ASP.NET MVC2: Views, Viewmodels, and Post requests
I am having trouble following good object-oriented design in ASP.NET MVC2 and I think the problem is a poor understanding of how ViewModels and Views should interact when the user will be posting information.
I have implemented a forum that allows users to create replies to a thread using a Reply action. My ReplyViewModel contains an int for the threadId and a string for the reply's content. The Reply action creates a ReplyViewModel with the ThreadId so we'll know to which thread the user is replying. The Reply View is strongly typed to the ReplyViewModel and has a form allowing the user to edit the model's content. The user can then post to the Reply action with the threadId as a parameter.
It works, but I don't think I'm doing this the correct way. Each post involves two ReplyViewModels: one with the threadId but null content, and the other with content but a null ThreadId. The Reply View is creating a new ReplyViewModel, and I think it should just be editing the ReplyViewModel that was passed to the view--but I don't know how.
Here's a stripped-down version of the view:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<mvcForum.ViewModels.ReplyViewModel>" %>
<%: Html.TextAreaFor(model=> model.content, new{TextMode="multiline", id="postbox"})%>
<input type="submit" value="Reply" />
In case that's not enough to answer my question, here's the entire view: http://pastebin.com/BFGL4p67
The ViewModel is literally just a string (content) and an int (threadId).
The controller:
[Authorize]
public ActionResult Reply(int id)
{
ReplyViewModel reply = new ReplyViewModel
{
ThreadId = id
};
return View(reply);
}
[HttpPost]
public ActionResult Reply(int id, ReplyViewModel model)
{
/**TODO: Catch when no user*/
var newPost = new ForumPost
{
UserId = (Guid)Membership.GetUser(User.Identity.Name).ProviderUserKey,
ThreadId = id,
postContent = model.content
};
db.AddToForumPosts(newPost);
db.SaveChanges();
return RedirectToAction("Index");
}
So my question is "What's the best way to do what I'm trying to do? Can I use a single instance of t开发者_如何学Gohe ReplyViewModel to pass from the controller, to the view, and back to the controller?"
I think what you're doing is fine.
You're thinking about a problem that you haven't come across yet, which is when the data to populate the form differs greatly from the data that will be posted. Here the 'Get' view model is a subset of the 'Post' view model, so using one view model is fine, but if the data for the 'Get' and the data for the 'Post' differed greatly, you could use two different view models such as:
public class GetReplyFromViewModel //...
public class PostReplyFromViewModel //...
But I would suggest against this unless both view models were very different and sufficently complex to require their own view models.
One important thing to remeber: just because the view is strongly typed to type 'A' doesn't mean the type of the parameter in the post method can't be type 'B'.
- The type of the View will simply determine the compilation / intellisense in the view along with the type checking of the view whenever one is created.
- The type of the post method parameter will simply use the MVC Model Binding to convert the posted HTTP form to the type you specify.
In other words the type of your view could simply be
<%@ Page Title="" ... Inherits="System.Web.Mvc.ViewPage<int>" %>
Where the whole Model
variable is simply the ThreadId
if you like and the post method could still take the same parameter if your html fields were named properly.
but again, in this particular case I think the current implementation is just fine.
精彩评论