What is the best way to pass random data from a view to a controller.
I have a number of views that are identical except for a few pieces of state information. instead of creating a page for each webpage, I want to have one page and I just pass over these variables dynamically.
Although not the "recommended" approach, you can make your action method accept a FormCollection as the parameter. You can then write your own logic to pull whatever data you need from that object. Basically the FormCollection will contain all fields inside the form that is posted as a key-value pair.
The signature would look like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection form)
{
// logic here to
}
Not shure about the "random data" - but maybe the question is realy about "views that are identical"
Put the common parts into a partial and the differing parts into the page, if your layout allows it.
You would have a couple of pages then, but no duplicate code.
Or is your problem more on the controller/model side?
Related
I need to pass objects between ActionMethods and Views in an ASP.net MVC 5 app.
I'm using it for a multi page signup - and for a multi page payment.
Is this bad practice? I haven't seen a good way to pass objects between different controllers.
Code:
public ActionResult Join1()
{
//
return View("Join2", MyObject);
}
[HttpPost]
public ActionResult Join2(MyObject MyObj)
{
//manipulate object
//return
}
It seems to be an effective way to do it - though I haven't seen many people do it this way. I haven't seen objects being passed between action methods much at all.
Is there a flaw in this approach, a better way of passing models between Views - or should each ActionMethod stick to passing simple data with, say, TempData instead of objects?
Why haven't I seen any sample projects doing things like this?
I've seen return RedirectToAction("act"); plenty - but that is Get and passing an object in a URI is limiting - and I don't want users to be able to manipulate or see the data being passed.
thx.
Unless I have misunderstood the description, your code is not doing what you think it's doing. That first return View("Join2", MyObject); statement is not executing the second ActionMethod, it is only passing your data into the View that happens to have the same name as the second method. Therefore the code implied by //manipulate object will not run before that View is rendered and sent back to the user.
Assuming the View file Join2.cshtml exists, and it contains the default #using (Html.BeginForm()), then users submitting the form will cause the Join2 Action to be executed and the same view rendered with the manipulated data - unless, of course, you add another return View() statement that names a different View.
The reason you haven't seen this done much is that the MVC convention is to have a View named the same as the ActionMethod, this makes the code slightly simpler and also much easier for other ASP.NET developers to understand because it is what they are expecting to see.
If you want the form rendered by each View to then execute a different ActionMethod when it is posted back, the place to do that is in the View code, where Html.BeginForm() has several overloads that allow you to do just that, e.g. in Join.cshtml you could write:
#using (Html.BeginForm("Join2", "JoinController"))
{
// form fields and stuff
}
// Produces the following form element
// <form action="/JoinController/Join2" action="post">
To address the final part of your question, "I don't want users to be able to manipulate or see the data being passed", sorry to say it but your proposed code doesn't prevent that: users can see the data in the web form, before it is ever posted back to the Join2 method; they can manipulate the data by sending an HTTP POST containing any data they want back to the Join2 method.
If you absolutely, positively need to actually execute Join2() from within Join(), before anything is passed back to the user, then you can call it just like any other C# method:
var myResult = Join2(MyObject);
Then you have an ActionResult object that you can manipulate or return straight to the browser. But why you would want to do this, is beyond me.
I have 3 partialviews with 3 viewmodels on page:
List of accounts
Modal popup (you can modify multiple accounts here)
Search panel
I want to refresh 1. after doing POST on 2. This is straightforward, but what if I want to keep results I got after using Search Panel?
I can do this in 2 ways but both seems bad (correct me if I am wrong).
First (the one I chose and works) is to store viewmodel used in 3. in TempData. I do Search (POST) and save passed viewmodel in TempData. Then whenever I do POST on different partialview I can refresh 1. using data(search parametrs) from TempData.
private const string SearchDataKey = "SearchData";
[HttpGet]
public PartialViewResult RefreshData()
{
if (TempData[SearchDataKey] != null)
return PartialView("AccountListView", PrepareAccountListViewModelForSearchData(TempData[SearchDataKey] as AccountSearchViewModel));
else
return PartialView("AccountListView", PrepareAccountListViewModel());
}
and saving ViewModel:
public PartialViewResult Search(AccountSearchViewModel searchParameters)
{
...
TempData[SearchDataKey] = searchParameters;
return PartialView("AccountListView", databaseAccountListViewModel);}
Second approach is to always POST "big" viewmodel with all 3 viewmodels. This way I will have data from Search's viewmodel but I will send many not needed information instead just Modal Popup's viewmodel which I need to call procedure.
I asked few MVC folks with better experience and they said they never had to store viewmodel in TempData but it still seems more reasonable than having 1 Big form and passing everything in every POST.
Do you know any better ways to handle this or which one is correct?
PS. Topic had "Best Practice" but was removed cause of warning message. I hope asking about opinion is still allowed on SO.
PS2. Most of my POSTs & GETs after initial load are through Ajax.
I do Search (POST)
This seems semantically incorrect to me. Searching is an action that shouldn't modify any state on the server. So using GET seems more appropriate. And when you use GET you have the benefit that all parameters are already present in the query string and thus preserved upon successive POST actions (like modifying an account in your case). So your RefreshData action could take the AccountSearchViewModel as parameter and the model binder will take care of the rest.
I don't know if I'm doing this wrong, but here's my problem. I need to pass a View's data to another Controller/Action.
In my HTML Form, I have
#using (Html.BeginForm("Preprocess", "Item", FormMethod.Post))
{
...some html...
...loop for each item in Items collection
<button type="submit" name="itemInfo" value="#Model.someValue">Submit</submit>
}
I receive the Form's data on my Item/Preprocess Action (strongly-typed view). However, I need to pass this to a 'central processor' that process the data depending on a certain flag. How do I pass the values I receive on this controller to another controller? I'm a beginner in MVC and I'm not even sure if this is the right way to do it.
Basically, I have three HTML forms similar from the above form, but with different Controllers and Views. I need them to call a single central master-Controller/Action and of course pass the data from the Form to the master Controller via HTTPPOST. Of course, each Controller has to format its own data to a class the master Controller can accept. What should I put in place of Return View() or RedirectToAction(...)?
Can you guys suggest a way to do this?
Or maybe you guys can suggest another way. It may not follow what I want, but basically my requirement is a central Controller/Action (or some other Centralized code) can receive the data and do operations depending on a value
You can do this:
return RedirectToAction("SomeAction", "SomeController",new { id=someString} );
Not sure I follow exactly what you are trying to do here. But from your description it does sound like your design is wrong.
If you are trying to perform some common set of actions once data is received and processed by your controllers then you should promote your "central controller" to be some kind of service class that can be accessed by all three controllers. The service class could return a ActionResult if necessary:
return new ViewResult { ViewName = "MyForm" };
However if you want to intercept the data and perform some common actions you could write a custom ActionFilter to do whatever your central controller is doing and leave the other controllers clean.
I have seen a few other threads with the same question as mine but I don't understand them very much. Anyway, my scenario is this: I have a MainView which renders four different PartialViews in it. The reason is because each PartialView contains data that comes from different Tables(Models).
So my problem is this. My MainView accepts a parameter of type string which is an ID. I need to pass that ID to each of my PartialViews. This can be easily achieved but the problem is, each partial views also needs to accept parameter of type List<>.
My question is, how can I pass two parameters to my PartialView (ie string and List<>)?
Currently, my PartialViews accept only one parameter (List<>).
create an object containing both the string and the list<>, and pass that to your PartialViews.
You can use ViewModels. Create a Viewmodel that is the result of all objects you need to present in the view. Is more clean.
There are many articles with this information.
I'm in serious need of passing url params with View class. Here's code:
if (!ModelState.IsValid)
{
return View(model);
}
This should not only return model based view, but also add specific param to URL (param won't change view details, but is needed as it's one of few automatically generated SessionKeys (one for each tab/window used to view app) and I know no other way to get to it, different than passing as param (it can't be generated everytime, 'cos params will change; it can't be global variable because it'll reset its value each refresh; it can't be static, because static is evul).
Oh this action is called with use of form and submit button, not actionLink or something like this.
EDIT1: I need params to stay in URL after refresh, or I need some other form of keeping data that persists through refresh/validation fail.
If I understand you correctly you have data that you need to use in generating Urls on your page? This just forms part of your ViewModel - or at least it should, since it's data that the View needs in order to render.
You can use ViewData to add any extra data that isn't part of your view model. Or, better still, add the data as members to it. Equally, if different views with different View Models require this data, add a ViewModel base class and derive from that so you can share that data.
use
RedirectToAction("actionName","controller",
new RouteValueDictionary(new {param1="value",param2="value2"});
or you can use hidden field to store the values in your page and then pass this down as and when you need them..