Session Problem? - asp.net-mvc

I have an MVC application that times out the session after 20 minutes. I store some values for a dropdown in a Session variable. If a user allows a page to timeout and then refreshes the page, I have no values in the dropdown.
What is the best way to deal with this?

Persist the information into some form of storage e.g. a Database.

I assume the dropdown data is from a database. If so, you'll need to repopulate the session. I assume you are using Windows authentication - otherwise, say if you were using form-based authentication, you would also have to get the user to log in again by redirecting to a login page.
If the dropdown data is not from a database, you could store it in Web.config and update it from there.
Exactly how you deal with this depends on specifics which you haven't mentioned. For example, on some of my projects, it's been sufficient to check if the session variable exists (on every non-post access to the page) and if absent, repopulate the session with that information.

You can try to use InMemory cache instead of Session (if it's really needed to store it somewhere and do not get from database). You need just to specify key (for each dd list) and expiration time
using System.Runtime.Caching;
public static dynamic Get(string key)
{
ObjectCache cache = MemoryCache.Default;
var item = cache.Get(key);
return item;
}
public static void Put(string key, dynamic ddResult)
{
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(1); // expiration in one minute
ObjectCache cache = MemoryCache.Default;
cache.Set(key, ddResult, policy);
}

Can I know whether it's a Windows application or a web-based application in the web-based application if you are going to use the database as source to display the data in the dropdown we give it as :
DropDownList3.DataSource = Class2.details().Tables[0];
DropDownList3.DataBind();
Here Class2 is the class having the function name called details in that we are going to have the SQL query to display the data from the database to the dropdown (SELECT query).
Then we will using that dropdownlist's data into the session as
session["anyname"]=dropdownlist3.selecteditem.text;
Then according to you we can give the timeout values in the web.config file also.

Related

How to store in cookie a list with objects MVC C#

I need to store the shopping list items in cookie.
I have the products page where each product has an "Add" button where it should be added to cookie.
I run into a problem, I observed that I can store in the cookie only one product. If the user wants to add the second product to the basket, the first product will be overwrite with the newly added product.
I didn't find any solution on the net which can help me, my question is: I can store a list of objects in the cookie.
I tried this way:
string myObjectJson = new JavaScriptSerializer().Serialize(cartItem);
var cookiea = new HttpCookie("myObjectKey", myObjectJson)
{
Expires = DateTime.Now.AddYears(1)
};
When I need the cookie value, I can get this way. It works:
var tttt = new JavaScriptSerializer().Deserialize<ShoppingCartVM>(myObjectJson);
How should I resolve the problem if the cookie already contains an item, to add a the new item to the same cookie, meaning the cookie had to store a list of objects, and when I need it to return me the entire list of the objects?
Could anyone help me on this? Thanks in advance!
You really shouldn't use Cookies for storing shopping cart items. Session is much better in this case. Cookies are stored on the client side whereas Session is stored on server. When you use cookies, you send whole serialized shopping cart back and forth between the client and server, that's not necessary. Also, Cookies's size is limited and Session does allow you to store complex objects.
To save the shopping cart, use (in controller):
ShoppingCartVM cart; // create instance of the shopping cart
this.Session["ShoppingCart"] = cart;
To get the values, use:
if (this.Session["ShoppingCart"] !== null)
{
ShoppingCartVM cart = (ShoppingCartVM)Session["NeededByDateTime"];
}
If you need something persistent. To make sure that the user will find their products in the cart even after couple months. You should consider saving their shopping cart in database.

Set a global parameters in Asp.Net MVC 3/4

I'm creating a MVC application with a CRUD. In the list view I have the PagedList helper. I set the pageSize variable in the code: pageSize= 5, so the list only show 5 files and allow go to the previous and next pages.
In the other side, I want to create an option called "Parameters" where the user can define yourself the "pageSize" value.
I'm confused about how to do it.
Thanks in advance.
Consider using a Profile provider
http://wiki.asp.net/page.aspx/1327/profile-provider-in-aspnet-mvc/
Or create a bespoke UserSettings table to store the setting yourself.
You can write pagesize that user choose in session variable and read it from it when you need:
To write to session you should call:
Session["pagesize"]=pagesize;
To read from session you can use:
var pagesize = (int)Session["pagesize"];
You should check that this value is in session before cast to avoid null reference exception.
Session variable can be used when you want keep it only during working period of user. If you want save it for long period, you should save it into database or in file.
If you are using Sql Sever, then do a simple table
Create Table UserProfile (
UserId Int Not null,
ProfileName Varchar(50) Not null
Value Varchar(50) Not Null
foreign key (UserId) references [UsersTable] (UserId)
)
You can save and retrieve PageSize or any other profile from this table.
What's common among modern web applications is a page size <select /> list:
What you want to do next is remember the user's choice in a cookie. The user experience (UX) is much better than the profile approach for 2 reasons:
both registered and anonymous users can select a page size
it is not necessary to navigate to a setting or profile page to select the page size
There are scenarios that call for a profile page but definitely not this one.

Instead of Session variable where i can save my temp data in mvc?

I have created a mvc3 application.
Currently saving submit form value into Session as i need to do some stuff on that before
save changes to database.
Is there any other good way to store temp data in mvc like ViewState?
I'm saving form input values into Session variable each time when data is entered and and when I clicked on submit button.
After every submit i'm populating my session variable with new added values and displaying all those values into webgrid.
Once i'm done with insertion finally clicked on update button which takes all values from webgrid and pass to one stored procedure as a parameter.
Now here i want to achieve 2 things
1.need to save all inserted data as clicked on submit it gets refresh all time.
so need to save all previous data to.
2.currently using session variable which sets to webgrid to show data into webgrid and once done with insertion passing those values to stored procedure.
So need to know any other good way to save data.
Else can use javascript to do this all on client side.
You should avoid schemes that attempt to make the stateless web seem stateful for two reasons.
Firstly, Session DOES NOT avoid a round-trip, it's only nominally different than storing values in the database. Yes, a fetch of memory is faster than a fetch from SQL but this doesn't scale well -- to scale (more than 1 server) you must add components and hops that reduce the gains and dramatically increase the complexity.
Secondly, Session values are likely to make it to a database anyway so why not just start with them there in the first place.
Thirdly (yes, another one), Session is not necessarily something to trust any more than a hidden form field would be.
In 13 years I've seen session used almost exclusively for the wrong things -- developers regress to using session for convenience and later regret it (as do the developers who replace them and have to maintain their code).
In short, use a database to store this information and be smart about how you fetch and cache it.
You can use TempData (http://msdn.microsoft.com/en-us/library/system.web.mvc.controllerbase.tempdata.aspx), but know that it persists only from one request to the next.
TempData["someKey"] = "";
if you need to persist the data across posts, Session is the proper place. If you need to write the data to a database, then the model should handle the data on post. In your controller:
[HttpPost]
public ActionResult Index(YourModel model)
{
if (ModelState.IsValid)
{
model.SaveToDataBase();
return View("Success");
}
return View("Index", model);
}
Then in the model:
[Serializable]
public class YourModel
{
[Required]
public string YourData { get; set; }
public void SaveToDataBase()
{
//TODO - add code to call stored procedure with data posted to model
}
}

asp.net mvc output cache, can i cache a result that will be different for different users?

i have read a few different things, it sounds like output cache will not cache a different copy of results for each user. so if user A has 3 menus and user B only has access to 1 of them, then caching the view result would show all 3?
how can i cache things for each user so that it's not shared?
thanks!
Use VaryByCustom and redefine HttpApplication.GetVaryByCustomString:
public virtual string GetVaryByCustomString(
HttpContext context,
string custom
)
{
//Return a value unique per user
//Change depending on the authentication of your site (f.e. make use of Session)
return context.User.Identity.Name;
}
http://msdn.microsoft.com/en-us/library/system.web.httpapplication.getvarybycustomstring.aspx
http://asp.net-tutorials.com/caching/more-output-cache/
One solution is to pass a parameter with the number of menus. Then configure outputcache to cache by all parameters except this one.
Also you can configure output cache to cache only on the client, not on the server It might be useful depending of your scenario.
You can always cache user specific information on the asp.net session.

When to use TempData vs Session in ASP.Net MVC

I am trying to get the hang of MVC framework so bear with me.
Right now, the only thing I'm using the session store for is storing the current logged in user. My website is simple. For this example, consider three domain objects, Person, Meeting, and File. Users can log in and view a "members only" profile of a meeting and can add files to it, or view a meeting's public "profile" if they aren't logged in.
So, from the meeting's private profile, with a logged in user, I have a "add files" link. This link routes to FileContoller.Add(int meetingId). From this action, I get the meeting the user want to add files to using the meeting id, but after the form is posted, I still need to know which meeting the user is adding files to. That's where my question lies, should I pass the "currently interacting with" meeting through TempData, or add it to the Session store?
This is how I currently have the Add action setup, but it's not working:
public ActionResult Add(int meetingId)
{
try
{
var meeting = _meetingsRepository.GetById(meetingId);
ViewData.Model = meeting;
TempData[TempDataKeys.CurrentMeeting] = meeting; /* add to tempdata here */
}
catch (Exception)
{
TempData[TempDataKeys.ErrorMessage] = "Unable to add files to this meeting.";
return RedirectToRoute("MeetingsIndex");
}
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(FormCollection form)
{
var member = Session[SessionStateKeys.Member] as Member;
var meeting = TempData[TempDataKeys.CurrentMeeting] as Meeting; /* meeting ends up null here */
if (member == null)
{
TempData[TempDataKeys.ErrorMessage] = "You must be logged in to add files to an meeting.";
return RedirectToRoute("LoginPage");
}
if (meeting == null)
{
TempData[TempDataKeys.ErrorMessage] = "An error occurred. No meeting selected.";
return RedirectToRoute("MeetingsIndex");
}
// add files to meeting
TempData[TempDataKeys.Notification] = "Successfully added.";
return RedirectToRoute("AddFiles", new {meetingId = meeting.MeetingId});
}
Edit:
Based on most of the answers, can any one provide any examples on what kind of data (other than messages) should be stored in TempData vs Session?
TempData is session, so they're not entirely different. However, the distinction is easy to understand, because TempData is for redirects, and redirects only. So when you set some message in TempData and then redirect, you are using TempData correctly.
However, using Session for any kind of security is extremely dangerous. Session and Membership are entirely separate in ASP.NET. You can "steal" sessions from other users, and yes, people do attack web sites this way. So if you want to selectively stop a post information based on whether a user is logged in, look at IsAuthenticated, and if you want to selectively show information based on what type of user is logged in, you use a Role provider. Because GETs can be cached, the only way to selectively allow access to an action in a GET is with AuthorizeAttribute.
Update In response to your edited question: You already have a good example of using TempData in your question, namely, returning a simple error message after a failed POST. In terms of what should be stored in Session (beyond "not much"), I just think of Session as a user-specific cache. Like the non-user-specific Cache, you should not put security-sensitive information there. But it's a good place to stick stuff which is relatively expensive to look up. For example, our Site.Master has the user's full name displayed on it. That is stored in a database, and we don't want to do a database query for it for every page we serve. (An installation of our application is used in a single company, so a user's full name is not considered "security-sensitive.") So if you think of Session as a cache which varies by a cookie which the user has, you won't be far wrong.
The default TempData provider uses the session so there really isn't much of a distinction, except that your TempData is cleared out at the end of the next request. You should use TempData when the data needs only to persist between two requests, preferably the second one being a redirect to avoid issues with other requests from the user -- from AJAX, for example -- deleting the data accidentally. If the data needs to persist longer than that, you should either repopulate the TempData or use the Session directly.
You can use it as per your requirement. A clarification can be,
TempData Vs Session
TempData
TempData allow us to persisting data for the duration of single subsequent request.
ASP.net MVC will automatically expire the value of tempdata once consecutive request returned the result (it means, it alive only till the target view is fully loaded).
It valid for only current and subsequent request only
TempData has Keep method to retention the value of TempData.
Example:
TempData.Keep(), TempData.Keep(“EmpName”)
TempData internally stored the value in to Session variable.
It is used to stored only one time messages like validation messages, error messages etc.
Session:
Session is able to store data much more long time, until user session is not expire.
Session will be expire after the session time out occurred.
It valid for all requests.
N/A
Session varible are stored in SessionStateItemCollection object (Which is exposed through the HttpContext.Session property of page).
It is used to stored long life data like user id, role id etc. which required throughout user session.
TempData and session, both required typecasting for getting data and check for null values to avoid run time exception.
"It doesn't work" isn't very descriptive, but let me offer a couple suggestions.
Under the hood, TempData uses Session to store values. So there isn't much difference in terms of storage mechanisms or anything like that. However, TempData only lasts until the next request is received.
If the user makes an ajax request in between form posts, TempData is gone. Any request whatsoever will clear TempData. So it's really only reliable when you're doing a manual redirect.
Why can't you just simply render the meeting ID to a hidden field in your View form? You're already adding it to the model. Alternately, add it to your route as a parameter.
I prefer to maintain that kind of data in the page itself. Render meetingID as a hidden input, so it gets submitted back to the controller. The controller handling the post can then feed that meeting ID back to whatever view will be rendered, so that the meetingID basically gets passed around as long as you need it.
It's kind of like the difference between storing a value in a global variable before calling a method that will operate on it, vs. passing the value directly to the method.
I would suggest MvcContrib's solution:
http://jonkruger.com/blog/2009/04/06/aspnet-mvc-pass-parameters-when-redirecting-from-one-action-to-another/
If you don't want full MvcContrib, the solution is only 1 method + 1 class that you can easily grab from MvcContrib sources.
The TempData property value is stored in session state. The value of TempData persists until it is read or until the session times out. If you want pass data one controller view to another controller view then you should use TempData.
Use Session when the data need for the throughout application

Resources