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
Related
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
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.
I have RedirectToAction as a return value in a controller and in my view I use ViewBag. While it's a well-known problem that ViewBag becomes empty after a RedirectToAction. I have a problem when I reinitialize ViewBag values in my overloaded controller in the OnActionExecuting method. ViewBag is empty again.
But the problem is that on my local PC (win7) it's working okay but on the web-hosting server (win 2008) it crashes. So can some one help saying what can cause that? Maybe it's a setting or something?
The ViewBag and ViewData only survives the current request. TempData is the thing to use when you use redirects (and only then): http://rachelappel.com/when-to-use-viewbag-viewdata-or-tempdata-in-asp.net-mvc-3-applications states this clearly:
[...] the TempData object works well in one basic scenario:
Passing data between the current and next HTTP requests
There was an exception deep inside data layer which was incorrectly captured and thereby prevented from propagation but caused ViewBag vanishing.
So be careful with exceptions catching.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateUser([Bind(Exclude = "Id")] User user)
{
...
db.SubmitChanges();
ViewData["info"] = "The account has been created.";
return RedirectToAction("Index", "Admin");
}
This doesnt keep the "info" text in the viewdata after the redirectToAction.
How would I get around this issue in the most elegant way?
My current idea is to put the stuff from the Index controlleraction in a [NonAction] and call that method from both the Index action and in the CreateUser action, but I have a feeling there must be a better way.
Thanks.
You can use TempData.
TempData["info"] = "The account has been created.".
TempData exists exactly for this situation. It uses Session as storage, but it will not be around after the second response.
From MSDN:
A typical use for a TempDataDictionary object is to pass data from an action method when it redirects to another action method. For example, an action method might store information about an error in the controller's TempData property (which returns a TempDataDictionary object) before it calls the RedirectToAction method. The next action method can then handle the error and render a view that displays an error message.
Use ViewData if your data should be accessible in View during "this" request. Use `TempData' if your data is for "next" request (for example POST-REDIRECT-GET design pattern).
If you need this more than once, a nice workaround would be creating ActionFilterAttributes which export/import the tempdata to viewdata and vice-versa. You can pass your ModelState in this way very nicely as well (demonstrated here - #13).
With a few adjustments to that piece of code you would have a clean solution, I think.
You could use the TempData controller property, but it has the disadvantage that it uses the session storage in the background. This means that you'll have extra work getting it to function on a web farm and you'll need to have sessions enabled in your application in the first place.
An alternative is to use cookies if you only need to transport a short message. This does require proper encryption of the cookie. Not relying on the TempData property also allows you to set messages in a non MVC context, for example in a classic ASHX page.
Take a look at FlashMessage which can save you some work implementing this yourself.
Since TempData appears to use storage, and any form of ITempDataProvider that is not "in-process", requires the object to be Serializable, TempData seems woefully inadequate in web farm situations... (ViewDataDictionary isn't itself serializable...) Does anyone have any suggestions for this?
The answer is TempData. The usage difference for clarification is as the following:
TempData = passing data from Action to another Action
ViewData = passing data from Action to a View
I'm using SQL state server for session variables. I'm also storing ViewData in TempData so I can access the ModelState across a redirect. The problem is that the ViewDataDictionary is not serializable. Is there a way to hook into the session storage logic to serialize the ViewDataDictionary when the Session variable is stored?
Thanks.
I think you're breaking a fundamental idea of the MVC pattern.
You shouldn't need the session variable. You pass the model to the view, then the model is passed back to the controller. It doesn't matter if it's a redirect or not.
Instead of storing the whole ViewData dictionary in TempData, I just stored the values I needed. A bit hacky, but it'll work for now.