问题
I have been working on this MVC 3 Razor app and typically utilize view models for my views.
A fair number of my view models contain more information than just the particular entity that I am interacting with in my form. So my GET action handler will init the view model and provide each property with the intended value etc..
In my POST action handler I check to see if the model state is valid, if not I redisplay the form/view with errors.
In my POST action handler I find myself having to copy the code from my GET action handler in order to re-render the view again. How can I implement my controller actions so that I am not having to copy the code that is responsible for gathering the data for the view model?
I have tried allowing my action handler to handle both POST and GET but then I have the input params to deal with. My POST action handler will have the view model as an input parameter but for the GET action handler will not.
回答1:
In situations like these we create builders for our view models.
Take a look at option 3 under this post.
回答2:
Your POST handler can return the ActionResult from the GET handler, as follows:
public ActionResult SomePageGet() {
var model = new SomePageViewModel();
// Populate ViewModel:
...
return View("SomePageGet", model);
}
[HttpPost]
public ActionResult SomePagePost(SomePageViewModel input) {
// Validate the model:
...
if (!ModelState.IsValid) {
// Return the GET page, with error messages:
return SomePageGet();
}
return View("Success");
}
Since the ModelState holds all error messages (and invalid input), the GET page will show them normally.
回答3:
You can simply refactor the common code into an extension method on the main entity you're working on.
Then call it as many times as you wish while staying DRY
.
I don't precisely know what's the function of that common code, but mostly it will be related data for rich presentation.
In that case the solution which I prefer, is to let the view load the extra data from another action using RenderAction which can be later refactored to AJAX page update staying DRY
and separating concerns of actions.
回答4:
"...I find myself having to copy the code..."
I don't understand why; why can't you simply create a member in your controller and call it? Not everything in your controller has to be an Action. But you might want to look at builders instead as @ataddeini suggested.
回答5:
Your POST action method should be able to just the the viewmodel type as the parameter, instead of all the individual pieces of data. If the viewmodel is more complex to build, you may want to write a modelbinder for your view model that can do that more complex work (your action method would still take the VM type as the parameter).
[HttpPost]
public ViewResult MyAction(MyViewModel model) {
// model should now be fully populated; check ModelState.IsValid though in case there are errors (such as the user entering "abc" for an int property)
}
来源:https://stackoverflow.com/questions/4940509/mvc-controller-actions-handle-post-and-get-with-out-duplicate-code