Bear with me as I describe the issue.
An MVC3 application making use of partial views. Having trouble posting a Comments form in a partial view from its parent-model’s Details view.
For reference ArticleViewModel has a collection of CommentsViewModel so there is a OTM relationship.
Details View
@model ArticleViewModel
// Renders the Article and its Comments - no forms, just display markup
// A nested _Comments partial is used to render the article's comments.
@Html.Partial("_Article", Model)
// Renders HTML and Javascript for the Pagedown editor - POST form inside.
@Html.Partial("_CommentEditor", new CommentViewModel())
@section scripts { /* code here for validation and the javascript editor */ }
_CommentEditor Partial View
@model CommentViewModel
@using (Html.BeginForm("Comment","Article",FormMethod.Post)) {
@Html.TextAreaFor(m => m.Content)
<input type="submit" value="Submit" />
<input type="reset" value="Clear" />
}
Article Controller
public ActionResult Details(string slug) {
return View(_articleService.Get(slug));
}
[HttpPost]
public ActionResult Comment(string slug, CommentViewModel comment) {
if(ModelState.IsValid) {
_articleService.AddComment(comment, slug);
}
return RedirectToAction("Details", new { Slug = slug });
}
Scenario / Issue
-
Http Request for
/Article/Details/{slug}renders the article, its comments, and the editor form correctly. -
The editor works as intended, but on clicking Submit, I noticed the Details action on my controller being called rather than the HttpPost Comment action.
As you can see the Razor Form helper specifies the Comment action on the Article controller using POST.
Question
Why is this happening? What am I missing?
Chump Award!
The answer is Routing.
Looking closer with Fiddler, I was actually sending a
POSTrequest to/article/comment, so I checked my routing… how I missed this, I don’t know:There is no explicit route for the Comment action. There is a catch-all REST-ish route for fetching an article (
article/{slug}). So the Comment POST was being handled by it before hitting the default route…My specific solution (i like explicit routing – even when it gets me in trouble) was to add a route for comments, just about the catch-all
article/{slug}pattern:Problem solved. Embarrassing.