Persist data in MVC Razor without using TempData between requests - asp.net-mvc

How do I can persist data in MVC Razor without using TempData between requests?
I see when we can use TempData from this, but don't want to TempData as it creates a state on the machine.
Thanks, Anish
EDIT: I want to persist the previous sort direction in a View page where a user is allowed to sort fields such as Name, Age etc.
FIX: I fixed it using ViewBag. Previous sort field/direction sent to View from Controller using ViewBag and then passed it back as query string in the next click.
Good FIX: I handled the everything in .js file such as checking and then in setting the previous sort field and previous sort dir in Controller.
This is what I finally did. I used ViewBag to send previous details to ViewPage and did the validation in a .js based on the current user action and passed it back to the controller in form-data.

Maintaining State in client page is something which is breaking the concept of HTTP which is stateless. Why do you want to maintain state ? If you are looking for some solution for Passing some data from your controller action to corresponding view, i would suggest you to go with a ViewModel where you fill the data for the dropdown and send that ViewModel object to the strongly typed view. You will have your data available there. Also you should grab data from your DataLayer ( from tables/ or Cache or etc..) in every request if you want some data.
You may pass a relevant id in the query string to get the corresponding data.
As RTigger mentioned, you may store some data in session. That will be available across all the pages till the life time of that session.

I haven't done a lot of ASP.NET MVC 3 recently, but I think the only real way you can persist data across requests is either with session state, cookies, or by posting data to the server every request.
ViewData, ViewBag, and TempData are all effectively killed at the end of each request, whereas session state, cookies, and post data is made available at the beginning of every request based on information from the client browser.
What particular scenario are you trying to persist data for?

You could pass those values as query string parameters when redirecting.

You can set parameters to hidden input fields if you post the form. But if you gonna call action by HTTPGET then you can pass values by using QueryString parameters.

Related

asp.net mvc post data and page refresh (session variable vs tempData vs detect F5)

i am teaching myself MVC and am struggling to work out the best solution to my problem. I have a search controller with a large amount of input fields. I will also have multiple overloads of the search fields eg basic search advanced search searchByCategory etc.
When the search form is posted i redirect to another action that displays the search results. If i press f5 the get action is fired again as opposed to the search results being refreshed in the action that my post redirects to. Ideally i would like to redirect to a search results Action Method without using the query string, or detect when refresh is hit and requery the database and just use different actions within the same search controller. I have read a lot of posts about this and the only 2 solutions i can find is using a session variable or TempData.Can anybody advise as to what is the best practice
From the Comments
Most of the time I prefer to use TempData in place of QueryString. This keeps the Url clean.
Question
Can anybody advise as to what is the best practice
Answer
Once the data is sent to Action Method to get the results from Database after then As per my knowledge you can use TempData to store the posted data. It is like a DataReader Class, once read, Data will be lost. So that stored data in TempData will become null.
var Value = TempData["keyName"] //Once read, data will be lost
So to persist the data even after the data is read you can Alive it like below
var Value = TempData["keyName"];
TempData.Keep(); //Data will not be lost for all Keys
TempData.Keep("keyName"); //Data will not be lost for this Key
TempData works in new Tabs/Windows also, like Session variable does.
You could use Session Variable also, Only major problem is that Session Variable are very heavy comparing with TempData. Finally you are able to keep the data across Controllers/Area also.
Hope this post will help you alot.
I think there is no need to even call Get Method after performing search although its good habit in case of if your are performing any add/update/delete operation in database. But in your case you can just return the View from your post method and no need to store data in tempdata or session until you really don't need them again. So do something like this:
[HttpPost]
public virtual ActionResult PerformSearch(SearchModel model)
{
// Your code to perform search
return View(model);
}
Hope this will help.
Hi thanks
I have had a chance to revisit this. the problem was i neglected to mention that i am using jQuery mobile which uses Ajax by default even for a normal Html.BeginForm. I was also returning a view which i have since learned will not updated the URL but only render new html for the current controller. my solution is to set the action, controller and html attributes in the Html.Beginformas follows :
#Html.BeginForm("Index", "SearchResults", FormMethod.Post, new { data_ajax = "false" })
inside the parameters for the index action of the searchResults controller I have a viewModel that represents the fieldset of the form that i am posting. The data-ajax="false" disables the Ajax on the form post and MVC takes care of matching the form post parameters to my model. This allows the url to update and when i press f5 to refresh the controller re-queries the database and updates the search results.
Thanks everybody for your help. I was aware of TempData but it is good to know that this is preferred over session data so i voted up your answer

MVC checkbox checked state issue

Good morning,
I have a view that display's search results for customers. On top of the view i have a filter that has a few checkboxes. The user can select multiple checkbox items and press the filter results button. When the user presses the button it calls an action that filters the result. The page is also refreshed. My question now, how can i make the page remember what checkboxes are checked. Because when the results are returned the filter elements are reset.
Thanks in advance.
you can use TempData. TempData VS ViewBag VS ViewData
you used ViewData, After the redirect, the ViewBag & ViewData objects are no longer available
TempData is also a dictionary derived from TempDataDictionary class
and stored in short lives session and it is a string key and object
value. The difference is that the life cycle of the object. TempData
keep the information for the time of an HTTP Request. This mean only
from one page to another. This also work with a 302/303 redirection
because it’s in the same HTTP Request. Helps to maintain data when you
move from one controller to other controller or from one action to
other action. In other words when you redirect, “Tempdata” helps to
maintain data between those redirects. It internally uses session
variables. Temp data use during the current and subsequent request
only means it is use when you are sure that next request will be
redirecting to next view. It requires typecasting for complex data
type and check for null values to avoid error. generally used to store
only one time messages like error messages, validation messages.
TempData["CheckedList"] = YourCheckBoxListValues; //in your controller
in your View
#{
var tempchkboxList = TempData["CheckedList"] as yourStronglyTypeClass;
//or
var tempchkboxList = TempData["CheckedList"].ToString();
}
Depends on how long the input criteria should be remembered.
You could also save it in your session via Session["customerCriteria"] = yourCriteria, but it would be easier to give an example if you had provided some code.
You can keep your selected/checked checkbox details in session variable when you post the form (by clicking on the search button). In the HttpPost action,read the checkboxes which were checked and add that to a collection property of your viewmodel and send it back to the view. set the session variable values to null once you are done with it (after reading). in the view, use your viewmodel value to set the checked status of those checkboxes.
Another option is using ajax. When you click on search.Read your search criteria and make an ajax request to the action method. Return a partial view back and update only the div/table which shows the results of the search.

How do I STOP model data appearing in the URL

How can I pass a viewmodel to a view without the model's data showing up in the URL?
public ActionResult MyView(MyModel model)
{
model.memberId = "Secret Id"
return View("MyView", model)
}
URL shows up as
http://localhost:1234/MyView?memberId=Secret Id
The data is not critically secret but having it show up in the URL is not really acceptable.
I don't know what you are up to, you should never set anything secret in a viewmodel - because the viewmodel is as the name says to be seen...
But to answer your question: To avoid the memberId occuring in the url you can submit your form by post - but that is of course not secure as well.
You should better store that in the session for example.
As already mentioned, view models are exactly that - models for your view. You should never store any data in a view model that should not be exposed to the client in one shape or form (whether it be a hidden form value, part of the url or in an ajax call).
If you really need data to be secret, and you want to pass it between actions, use TempData, or the ASPNet Session. That way, it goes nowhere near the client.
I wrote a CAPTCHA generator that uses TempData to store the actual CAPTCHA string, as sending it to the client would mean that any automated system would be able to read the string. I'd recommend using TempData over the session, though, as it's only persisted for one request - whereas the session needs managing by yourself.
TempData["MyDataIdentifier"] = "MyObjectOrValue";

Where to initialize TempData

I need a variable that will be used everywhere (controller, view, master page, ...). I was thinking of putting it in the TempData. Where is the best place to put an object there?
I thought of Page_Load but that's done after the controller.
I thought of the controller Initialize but the TempData seems to be cleared after that.
I couldn't use a session because the data could change on every request. I decided to initialize everything in the OnActionExecuting of the controller and it's working great.
You should use a Session variable rather than TempData. Variables stored in TempData will be destroyed after one request: Difference Between ViewData and TempData?
Here is a link documenting the various Client and Server side storage options in Asp.net
http://www.dotnetfunda.com/articles/article61.aspx

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