RedirectToAction not passing all parameters - asp.net-mvc

I have these two methods in the same Controller, the first passing two parameters to the second.
When debugging, the list (model.RequestedProducts) passed is correct (not empty) but on the second method, only idOR is read correctly, List<OCS> RequestedProducts is empty.
[HttpPost]
public ActionResult Index(int idOR, ViewModel model, string add, string remove, string send)
{
//...
return RedirectToAction("Done",
new { idOR = idOR,
RequestedProducts = model.RequestedProducts});
}
public ActionResult Done(int IdOR, List<OCS> RequestedProducts)
{ ...
What am I missing?
Is there maybe a better way to do it? (other than Redirect to Action)
Thank you

When you use RedirectToAction you are returning a message to the client to request a new URL probably something like /controller/action/id. You Routes will define how the URL is formed. I am guessing you have the default route defined and in your case MVC has no way of knowing how to deserialise your RequestedProducts type into a URL and then bind it back into a List type.
Instead you could use the TempData object to pass data between to Action requests.
The TempData property value is stored in session state. Any action method that is called after the TempDataDictionary value is set can get values from the object and then process or display them. The value of TempData persists until it is read or until the session times out.
This MSDN article explains it all.

Related

MVC 5 RouteConfig trouble

I have such action:
[ObjectRequired]
public ActionResult Campaign(int? id, SomeClass object = null)
{
...
}
What i need is to route to this action:
a) with only int parameter (.../Campaign/12345)
b) with no parametes (optionally) (.../Campaign)
MVC error says, that there is no nonparametric constructor (if delete "object" parameter - it's ok). But i cant delete "object" parameter, because i need to check some values and pass value from [ObjectRequired] attribute like this:
filterContext.ActionParameters["object"] = _someObject;
I don't want to use constructions like ViewData. Where's the right way?
I'm not 100% on what I'm about to say but I'll say it as if I am...
You can't pass an object through to a get. You could pass back parameters and use a custom route handler to build the object for you.
You could also hold the object in data and use Entity Framework to get the model.
You could also use TempData, but that's similar to ViewData.
You could also hold it in their Session.

Temp data is not being maintained between two controllers sitecore

I am just trying to implement Post-Redirect-Get pattern in my sitecore application.
I could see Tempdata is not maintained when i redirect from one controller to another controller.
[HttpPost]
public ActionResult Select()
{
TempData["SelectPost"] = "SomeValue";
var path = PaymentPath;
return RedirectToRoute(MvcSettings.SitecoreRouteName, new { pathInfo = path});
}
public ActionResult Payment()
{
var tempDataValue = TempData["SelectPost"];
//Value is coming as null always
}
I even tried with RedirectToAction and Redirect and also by explicitly calling TempData.keep()
All my pages are controller renderings.
Am i missing anything? I am using Sitecore.NET 7.0. (rev. 130424)
TempData is available to the current and next request only. So if you POST to /select and redirect to /payment (GET) the TempData value will be available.
In your example it looks like you are redirecting to the SitecoreRouteName and then redirecting to /payment, in which case your TempData value will no longer be available.
If you need to store something for longer than the current and next request I suggest you use Session, a cookie or a database to store your value.

How can ViewBag data be saved after a form post?

So I have a ViewBag.Something and this data is randomly generated. In my view, I set this to a label like so #Html.LabelFor(m => m.Something, (string)ViewBag.Something). This works out well but when I submit the form there could be errors and if there are errors, I need this label to remain the same, I don't want dynamic/random data anymore so I wouldn't call the controller method that generated this ViewBag. Is there a way to retain this value without having some private variable in my controller? Some nice way that MVC/Razor does it?
Option 1:
Pass the value of "ViewBag.Something" to the Controller by using route Values:
#Html.ActionLink("ButtonText", "ActionName", new { Something = #ViewBag.Something })
Option 2:
You can use TempData.
public ActionResult Index()
{
var Something = "YOURVALUE";
TempData["Something"] = Something;
.......
}
public ActionResult OtherAction()
{
var Something = TempData["Something "];
...........
}
Passing State Between Action Methods
Action methods might have to pass data to another action, such as if an error occurs when a form is being posted, or if the method must redirect to additional methods, as might occur when the user is directed to a login view and then back to the original action method.
An action method can store data in the controller's TempDataDictionary object before it calls the controller's RedirectToAction method to invoke the next action. The TempData property value is stored in session state. Any action method that is called after the TempDataDictionary value is set can get values from the object and then process or display them. The value of TempData persists until it is read or until the session times out. Persisting TempData in this way enables scenarios such as redirection, because the values in TempData are available beyond a single request.
In the get, set up a model, set it dynamically and when return view() is being executed, do return view(model). Then in the view, set up a hidden field that can keep on passing the value needed. I chose to go this route because I don't have to worry about any server code to make this work on a post and I don't have to worry about any sessions.
Displaying message in viewbag after posting (I user this method)
ActionResult SubmitUser(){
ViewBag.Msg =TempData["Msg"];
return view();
}
[HtttpPost]
ActionResult SubmitUser(){
TempData["Msg"] ="Submitted Successfully"];
return view();
}
The Value is send to get method..

Completely not understanding View Data for MVC right now, need some serious help & code examples

I really need to maintain this string called "filterParams" in my MVC application. After the user enters some search parameters he clicks submit, and the grid is rebinded with that parameter. That works great. I also save the filterParams data in a Javascript variable, so when the user pages, and the OnDataBinding event is raised, the filter is also passed through that ajax call as well. this is all well and good however there is a huge issue, because when the user updates a question, all the results dissapear because it returns to the View and it does not have any data there. The way I'm using ViewData isn't working, and I could use your help, because if I can store it in ViewData and access it, it would fix my problems. I cannot use TempData because there are a number of other Actions that can be called in between Select and Update...Long question short, how do I implement ViewData correctly to store and retrieve a string in my controller?
Here are some code snippets.
[GridAction]
public ActionResult GetAllQuestion(string filterParams)
{
var _filterParams = new List<string>();
_filterParams.Add(filterParams);
ViewData["filterParams"] = _filterParams;
return View(new GridModel(QuestionManager.Instance.GetQuestion(filterParams)));
}
[GridAction]
public ActionResult EditQuestion(int id, QuestionDTO pQuestion)
{
// var _question = QuestionManager.Instance.GetQuestion(id,false).FirstOrDefault();
// TryUpdateModel(_question);
var _filterParams = (List<string>)ViewData["filterParams"];
var filterParams = _filterParams[0];
QuestionManager.Instance.UpdateQuestion(pQuestion);
// return View(new GridModel(QuestionManager.Instance.GetQuestion(id, false)));
return View(new GridModel(QuestionManager.Instance.GetQuestion(filterParams)));
}
in my aspx page
Html.Telerik().Grid<QuestionDTO>()
.DataBinding(dataBinding => dataBinding.Ajax().Select("GetAllQuestion", "Question", new { filterParams = string.Empty }).Update("EditQuestion", "Question").Insert("CreateQuestion", "Question"))
How can I get this to work please? Help is appreciated
ViewBag/ViewData only works for sending data from an action to a view. It does not get populated by the Model Binder when a request is made to an action, and its state is not saved between requests because ASP.net MVC is entirely stateless. In other words, the ViewData dictionary is always empty at the start of a request.
Meaning this line in your EditQuestion action will not work:
var _filterParams = (List<string>)ViewData["filterParams"];
ViewData is empty, so _filterParams will be null.
You have to manually send filterParams to the EditQuestion action just as you do for the GetAllQuestions action.
Perhaps a better alternative would simply be to persist filterParams using a temp cookie on the client side.
So, just to defy all the misinformation I've read on the subject, TempData infact does persist through multiple action calls in the controller and was able to be used to implement the functionality I needed.
Why just not store the data in Session?
Here's a good explanation with examples
http://rachelappel.com/when-to-use-viewbag-viewdata-or-tempdata-in-asp.net-mvc-3-applications

How to re-use model data on post back with MVC

I'm passing structured data to my MVC page when it loads initially. After the user submits a contact form, I want to re-use the same data (I just "leave" the same page up) so I don't have to hit the database again. I declared a variable global to the controller to store the model data, but it's null at the end of the post back, so it looks like I can't re-use it there.
Seems like this would be a typical scenario. How do I handle it?
If you are wanting to reuse viewmodel or other retrieved data that is not going to be part of the postback, you can either
a) Output it in hidden fields so that it is posted back to your action (meh) or
b) Store the object(s) in Session so that it will be available to any other controllers/actions in your application. If you are worried about memory, you could delete that session variable after you reuse it if you are not going to need to use it again.
On your initial page load, check if the session variable exists, if it does, you are good - else populate it.
Oh and why the global variable thing isn't working -> a controller is new'd up for each request (assuming using the default controller factory) and as such any global variables in the controller will be reset on each request.
public ActionResult Foo()
{
var model = GetModelFromDB();
Return View(model);
}
[HttpPost]
public ActionResult Foo(Entity model)
{
Return View(model);
}
Asp.net-mvc is stateless so each HTTP request has a different context, and each time you hit the controller all it's data reset in the constructor, this why you get null.
You can get the model in the post if it's properties are within the submitted form .
If you really don't want to leave the page you are on, and don't want to post all the other data back as KMan suggests, but still want to capture the users contact information/data you could post the contact info using ajax.
If you have your view model as an argument to your method, you can just return it to the view on postback. Ex:
public ActionResult TestAction(MyViewModelType testViewModel)
{
//Do logic
return View("view",testViewModel);
}
Note that you have to have the data inside the form you are posting.

Resources