How to initialize field once for every client in MVC Controller? - c#

In ASP.NET MVC, a field which is declare outside a method, the field is initialize every-time.
There I am giving a demo example.
public class TestController : Controller
{
private List<object> ListItems;
// GET: /Test/Index
public ActionResult Index(int Id)
{
ModelSource _model = new ModelSource(Id);
ListItems = _model.GetItems();//coming info from Model
return View();
}
// GET: /Test/Demo
public ActionResult Demo()
{
int x = ListItems.Count;
//Do Something More
return View(x);
}
}
Is It possible for ListItems will be initialize for once for every client as Id parameter will be different on client's request.

As Patrick Hofman stated you can use Sessions or Cookies Here is an example for both:
Cookies:
string cookievalue ;
if ( Request.Cookies["cookie"] != null )
{
cookievalue = Request.Cookies["cookie"].ToString();
}
else
{
Response.Cookies["cookie"].Value = "cookie value";
}
//For removing cookie use following code
if (Request.Cookies["cookie"] != null)
{
Response.Cookies["cookie"].Expires = DateTime.Now.AddDays(-1);
}
Sessions:
HttpContext.Current.Session.Add("Title", "Data");
string foo = Session["Title"];

Related

List<int> from method parameters return 0 as default first value in C# MVC ActionResult

I have checked the parameters in chrome network inspection tool. and it's null.
but when I get the data from the actionResult it has a member and it's zero.
[HttpPost]
public ActionResult Index(MyInputDto input)
{
var data = input.ItemList;
//the data variable is a list with one member and that's zero;
return view();
}
and this is my MyInputDto:
public class MyInputDto
{
public MyInputDto()
{
this.ItemList = new List<int>();
}
public List<int> ItemList { get; set; }
}
and the request is something like this:
var itemList = ($('#input_selector').val() != null ? $('#input_selector').val() : []).map(x => parseInt(x));
$.post('#Url.Action("Index")'
, {
ItemList: itemList
})
.done((data) => {
$('[data-table-container]').html(data);
})
the reason I use parseInt(x) is that if I don't the data will be sent like this "1,2,3,4" and the ActionResult method doesn't recognize it as a list of integers
how can I fix it?

return to view after addModelError

in this project i create cardGroup. in httpGet Method we get some needed info and pass to view to fill dropdown. when httpPost trigger if some field Date has Problem we must return error with addModelError but after return View, all ViewData Clear and Return Exception. how can handle this. just show error in view.
[HttpGet]
[Route("CreateCardGroup")]
public ActionResult CreateCardGroup()
{
var discounts =
UnitOfWork.DiscountPatternRepository.GetNotExpireDiscountPattern();
var discountDtos = discounts?.Select(c => new SelectListItem
{
Text = c.PatternTitle,
Value = c.Id.ToString()
}).ToList();
ViewData["DiscountPatterns"] = discountDtos;
var serials =
UnitOfWork.ChargeCardSerialRepository.GetNotAssignedSerials();
var serialDtos = serials?.Select(c => new SelectListItem
{
Text = c.SerialNumber.ToString(),
Value = c.Id.ToString()
}).ToList();
ViewData["ChargeSerials"] = serialDtos;
ViewData["CardSerialCount"] =
UnitOfWork.GiftCardSerialRepository.GetNotUsedGiftSerials();
return View();
}
[HttpPost]
[Route("CreateCardGroup")]
public ActionResult CreateCardGroup(CardGroupCreateDto dto)
{
if (!ModelState.IsValid)
return View(dto);
if(!UnitOfWork.DiscountPatternRepository
.IsCardGroupDateInRange(dto.DiscountPatternId,
dto.ActiveFromDate, dto.ActiveToDate))
{
ModelState.AddModelError("ActiveFromDate", #"Error In Date.");
return View(dto); <---Problem Here
}
var group = dto.LoadFrom();
var insertedId = UnitOfWork.CardGroupRepository.Add(group);
foreach (var rangeDto in group.CardGroupGiftSerialRanges)
{
for (var i = rangeDto.GiftCardSerialBegin; i <=
rangeDto.GiftCardSerialEnd; i++)
{
var serial =
UnitOfWork.GiftCardSerialRepository.GetBySerial(i);
if (serial != null)
{
serial.CardGroupGiftSerialRangeId = rangeDto.Id;
serial.DiscountPatternId = group.DiscountPatternId;
UnitOfWork.Complete();
}
}
}
return Redirect("/CardGroup");
}
From this article:
ViewData
ViewData is a property of ControllerBase class.
ViewData is used to pass data from controller to corresponding view
Its life lies only during the current request. If redirection occurs, then its value becomes null. It’s required typecasting for getting data and check for null values to avoid error.
So what's happening is once you've done your post back to the server, you're now in a different request, meaning, that you need to repopulate your ViewData items so that their values are populated again, or else they'll be null.
So I'd recommend refactoring your Dropdown population method into a private method on your controller and then call that method in your post when you find a validation error or are just returning by calling return View(dto).
If they're used in other controllers, you can add them to a LookupService or LookupRepository or even a general helpers class that contains your lookup logic (whatever fits into your UnitofWork pattern the best for you), to make them available to those other controllers, instead of having it as a private method as per my example.
So something like this for example:
[HttpGet]
[Route("CreateCardGroup")]
public ActionResult CreateCardGroup()
{
PopulateCreateCardGroupLookups();
return View();
}
[HttpPost]
[Route("CreateCardGroup")]
public ActionResult CreateCardGroup(CardGroupCreateDto dto)
{
if (!ModelState.IsValid)
{
PopulateCreateCardGroupLookups();
return View(dto);
}
if(!UnitOfWork.DiscountPatternRepository
.IsCardGroupDateInRange(dto.DiscountPatternId,
dto.ActiveFromDate, dto.ActiveToDate))
{
ModelState.AddModelError("ActiveFromDate", #"Error In Date.");
PopulateCreateCardGroupLookups();
return View(dto); <---Problem Here
}
var group = dto.LoadFrom();
var insertedId = UnitOfWork.CardGroupRepository.Add(group);
foreach (var rangeDto in group.CardGroupGiftSerialRanges)
{
for (var i = rangeDto.GiftCardSerialBegin; i <=
rangeDto.GiftCardSerialEnd; i++)
{
var serial =
UnitOfWork.GiftCardSerialRepository.GetBySerial(i);
if (serial != null)
{
serial.CardGroupGiftSerialRangeId = rangeDto.Id;
serial.DiscountPatternId = group.DiscountPatternId;
UnitOfWork.Complete();
}
}
}
return Redirect("/CardGroup");
}
private void PopulateCreateCardGroupLookups()
{
var discounts =
UnitOfWork.DiscountPatternRepository.GetNotExpireDiscountPattern();
var discountDtos = discounts?.Select(c => new SelectListItem
{
Text = c.PatternTitle,
Value = c.Id.ToString()
}).ToList();
ViewData["DiscountPatterns"] = discountDtos;
var serials =
UnitOfWork.ChargeCardSerialRepository.GetNotAssignedSerials();
var serialDtos = serials?.Select(c => new SelectListItem
{
Text = c.SerialNumber.ToString(),
Value = c.Id.ToString()
}).ToList();
ViewData["ChargeSerials"] = serialDtos;
ViewData["CardSerialCount"] =
UnitOfWork.GiftCardSerialRepository.GetNotUsedGiftSerials();
}

Session sets the value successfully but gets null in MVC 5

I am developing an MVC 5 application and I have a specific Controller for Session variables in my application which has 6 sessions, and all are working fine. Now I wanted to use another session, so I have declared it in my Session controller as follows:
public int tempResult
{
get { return Convert.ToInt32(Session["tempResult"]); }
set { Session["tempResult"] = value; }
}
Now I have a Controller A which inherits from Session Controller and it is setting the session variable tempResult in method as:
[HttPPost]
public JsonResult COAcodelength(MST m)
{
var s = (from sets in db.ABCs where sets.name == "Name" && sets.pre.ToString() == m.house select sets.Id).Single().ToString();
tempResult = Convert.ToInt32(s);
}
Now Controller B which also inherits from Session Controller is calling a method of Controller A and in that method I am trying to access the session value of tempResult as:
[HttpPost]
public ActionResult New([Bind(Include = "Id,Name,House,Number")] MST tr)
{
tr.Name = r.Ccode(tr); // r is the instance of Controller A
db.MSTs.Add(tr);
db.SaveChanges();
return Json(tr);
}
And the Ccode method in Controller A is as:
public string Ccode (MST tr)
{
int q = tempResult;
tr.Name = q.ToString() + tr.House;
return tr.Name;
}
So, when Ccode method in Controller A tries to get the value of tempResult it returns null with Object reference error.
What could be the possible problem?
You cannot convert null to int 32, which meant that if your tempResult can be null, you should use it like this:
public int? tempResult
{
get { return Convert.ToInt32(Session["tempResult"]); }
set { Session["tempResult"] = value; }
}
Which will then allow the integer variable to accept null.
int? meaning the integer variable can be nullable.

backbone and mvc

I have a Backbone project where I have the following model that I want to pass on to .NET for database updating.
var myList = Backbone.Model.extend({
// Default attributes for the todo item.
defaults: function () {
return {
Name: "Default name"
};
},
url: "/my/myList",
"sync": mySyncFunction,
// Ensure that each todo created has `title`.
initialize: function () {
if (!this.get("Name")) {
this.set({ "Name": this.defaults.Name });
}
}
});
Using the following for overriding the sync
function mySyncFunction(method, model, options) {
if (method == 'GET') {
options.url = model.url;
}
else if (method == "create") {
options.url = model.url+"Post";
}
else {
options.url = model.url;
}
Backbone.emulateJSON = true
return Backbone.sync(method, model, options);
}
When creating a new item it is using the model.url+"Post" I assumed and the model.get("Name") contains the correct data. The correct section is executed and the entry in the database is created but the Name is empty.
Although when the .NET Controller handles the post the Name no longer contains any data.
My controller code looks like this.
public class myController : Controller
{
public ActionResult myList()
{
List<myCore.myList> l = new List<myCore.myList>();
l = myCore.myList.ListAll();
return Json(l, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult myListPost(myCore.myList doc)
{
doc.AccountGuid = Guid.NewGuid();
Boolean created = doc.Create();
return Json(doc);
}
[HttpPut]
public ActionResult myListPut(myCore.myList doc)
{
myCore.myList doc1 = new myCore.myList();
doc1.AccountGuid = Guid.Empty;
doc1.Name = "testPut";
Boolean created = doc1.Create();
return Json(doc1);
}
[HttpDelete]
public ActionResult myListDelete(myCore.myList doc)
{
//DeleteDoc(id);
myCore.myList doc1 = new myCore.myList();
doc1.id = Guid.NewGuid();
doc1.AccountGuid = Guid.Empty;
doc1.Name = "testDelete";
Boolean created = doc1.Create();
return Json(doc1);
}
}
Can anyone tell me what to do to get the model/class data into the controller.
The myList class looks like this.
public class myList
{
Guid _id = Guid.Empty;
String _name = String.Empty;
Guid _accountGuid = Guid.Empty;
public Guid id
{
get { return _id; }
set { _id = value; }
}
public String Name
{
get { return _name; }
set { _name = value; }
}
public Guid AccountGuid
{
get { return _accountGuid; }
set { _accountGuid = value; }
}
}
UPDATE
It now looks like it works after removing Backbone.emulateJSON = true
Although I still cant get my delete part to work. It comes up with a 404 error. Only Post and Get works.
It looks like this in the controller.
[ActionName("myList")]
[HttpDelete]
public ActionResult myListDelete(myCore.myList doc)
{
doc.Name += "-DELETE";
return Json(doc);
}
UPDATE
Figured that one out as well.
ASP.NET Handle PUT/DELETE verbs
Although i can seem to pass any model or paramters along with it on order to delete the correct entry in the database.
Change your defaults to
defaults: {
Name: "Default name"
},

ViewData set in an ActionFilter is coming out null on Master Page MVC3

My Original Issue here:
Help! I've got repository access in my MVC master page! Refactor time!
What originated as a re factoring job to improve performance has revealed new issues. If I should keep this in my original question - feel free to delete this one, and rename the old one to something more relevant. I'm using an ActionFilter applied to a base controller to load some user-customized settings. My issue is that I save these settings in the filterContext.Controller.ViewData object but its coming through as null on my master page. Here is the relevant code:
Action Filter
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class StoreSettingsActionFilter : ActionFilterAttribute
{
private readonly IResellerRepository _resellerRepository;
private readonly IStoreSettingsRepository _storeSettingsRepository;
public StoreSettingsActionFilter(
IResellerRepository resellerRepository,
IStoreSettingsRepository storeSettingsRepository
)
{
_resellerRepository = resellerRepository;
_storeSettingsRepository = storeSettingsRepository;
}
public StoreSettingsActionFilter()
: this(new ResellerRepository(), new StoreSettingsRepository())
{
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
var settingsViewModel = new StoreSettingsViewModel();
settingsViewModel.ThemeLocation = "~/Content/jquery-ui-1.8.9.custom.css";
var user = filterContext.HttpContext.User;
if (!user.Identity.IsAuthenticated || !user.IsInRole("Reseller"))
{
filterContext.Controller.ViewData["storeSettings"] = settingsViewModel;
return;
}
var session = filterContext.HttpContext.Session;
var reseller = session["reseller"] as Reseller;
if (reseller == null)
{
reseller = _resellerRepository.GetResellerByUsername(user.Identity.Name);
session["reseller"] = reseller;
}
if (reseller.StoreSettingsID != null && reseller.StoreSetting.Theme != null)
{
var storeSettings = session["storeSettings"] as StoreSettings;
if (storeSettings == null)
{
storeSettings = _storeSettingsRepository.GetStoreSettings((int)reseller.StoreSettingsID);
session["storeSettings"] = storeSettings;
}
// Using AutoMapper to convert between the model and the view model
//settingsViewModel = Mapper.Map<StoreSettings, StoreSettingsViewModel>(storeSettings);
settingsViewModel.ThemeLocation = storeSettings.Theme.StylesheetLocation;
settingsViewModel.Address1 = storeSettings.Address1;
settingsViewModel.Address2 = storeSettings.Address2;
settingsViewModel.City = storeSettings.City;
settingsViewModel.FooterImage = storeSettings.Image.FileName;
settingsViewModel.HeaderImage = storeSettings.Image1.FileName;
settingsViewModel.Phone = storeSettings.Phone;
settingsViewModel.PostalCode = storeSettings.PostalCode;
settingsViewModel.ProvinceCode = storeSettings.Province.Abbreviation;
settingsViewModel.StoreName = storeSettings.StoreName;
}
filterContext.Controller.ViewData["storeSettings"] = settingsViewModel;
}
}
Base Controller
[StoreSettingsActionFilter]
public abstract class BaseController : Controller
{
}
HomeController snippet
public class HomeController : BaseController
{
//
// GET: /Store/Home/
public ActionResult Index()
{
IProductRepository productRepository = new ProductRepository();
var products = new List<Product>();
IResellerRepository resellerRepository = new ResellerRepository();
var reseller = resellerRepository.GetResellerByUsername(User.Identity.Name);
IProductCategoryRepository categoryRepository = new ProductCategoryRepository();
var categories = categoryRepository.GetProductCategoriesFromStoreSettings(reseller.StoreSetting.Categories);
foreach(var category in categories)
{
products.AddRange(productRepository.GetProductsByCategory(category.CategoryId));
}
var viewModel = new StoreViewModel()
{
Products = products.ToList()
};
return View(viewModel);
}
}
Master Page snippet
<head id="Head1">
<%
var storeSettings = (StoreSettingsViewModel)ViewData["storeSettings"]; // This is always ending up null.
%>
<title>
<%: string.IsNullOrEmpty(storeSettings.StoreName) ? "My Store Name" : storeSettings.StoreName%>
</title>
I'm really stuck here, your help is greatly appreciated!
Try overriding OnActionExecuted instead of OnResultExecuting in the StoreSettingsActionFilter filter:
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
...
}

Categories

Resources