I have a view with model BlogPostViewModel
:
我对model BlogPostViewModel有一个看法:
public class BlogPostViewModel
{
public BlogPost BlogPost { get; set; }
public PostComment NewComment { get; set; }
}
This view is rendered when action method BlogPost
is hit. The view displays information regarding the blog post as well as a list of comments on the blog post by iterating over Model.BlogPost.PostComments
. Below that I have a form allowing users to post a new comment. This form posts to a different action AddComment
.
当单击action方法BlogPost时,将呈现此视图。视图通过遍历Model.BlogPost.PostComments显示关于博客文章的信息以及博客文章的评论列表。下面是一个表单,允许用户发布新的评论。此表单将发布到另一个动作AddComment。
[HttpPost]
public ActionResult AddComment([Bind(Prefix = "NewComment")] PostComment postComment)
{
postComment.Body = Server.HtmlEncode(postComment.Body);
postComment.PostedDate = DateTime.Now;
postCommentRepo.AddPostComment(postComment);
postCommentRepo.SaveChanges();
return RedirectToAction("BlogPost", new { Id = postComment.PostID });
}
My problem is with validation. How do I validate this form? The model of the view was actually BlogPostViewModel
. I'm new to validation and am confused. The form uses the strongly-typed helpers to bind to the NewComment
property of BlogPostViewModel
and I included the validation helpers as well.
我的问题是验证。我如何验证这个表单?视图的模型实际上是BlogPostViewModel。我对验证并不熟悉,也很困惑。表单使用强类型的助手绑定到BlogPostViewModel的NewComment属性,我还包括了验证助手。
@using (Html.BeginForm("AddComment", "Blog")
{
<div class="formTitle">Add Comment</div>
<div>
@Html.HiddenFor(x => x.NewComment.PostID) @* This property is populated in the action method for the page. *@
<table>
<tr>
<td>
Name:
</td>
<td>
@Html.TextBoxFor(x => x.NewComment.Author)
</td>
<td>
@Html.ValidationMessageFor(x => x.NewComment.Author)
</td>
</tr>
<tr>
<td>
Email:
</td>
<td>
@Html.TextBoxFor(x => x.NewComment.Email)
</td>
<td>
@Html.ValidationMessageFor(x => x.NewComment.Email)
</td>
</tr>
<tr>
<td>
Website:
</td>
<td>
@Html.TextBoxFor(x => x.NewComment.Website)
</td>
<td>
@Html.ValidationMessageFor(x => x.NewComment.Website)
</td>
</tr>
<tr>
<td>
Body:
</td>
<td>
@Html.TextAreaFor(x => x.NewComment.Body)
</td>
<td>
@Html.ValidationMessageFor(x => x.NewComment.Body)
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="submit" value="Add Comment" />
</td>
</tr>
</table>
</div>
}
How in the AddComment
action method do I implement validation? When I detect Model.IsValid == false
then what? What do I return? This action method is only binding to the PostComment
property of the pages initial BlogPostViewModel
object because I don't care about any other properties on that model.
如何在AddComment操作方法中实现验证?当我发现模型。IsValid == false,然后呢?我回报什么?此操作方法仅绑定到page initial BlogPostViewModel对象的PostComment属性,因为我不关心该模型上的任何其他属性。
Any help is appreciated.
任何帮助都是感激。
3 个解决方案
#1
2
You need to repopulate the model and send to view. However, you don't need to do this by hand, you can use action filters.
您需要重新填充模型并将其发送到view。但是,您不需要手工操作,您可以使用操作过滤器。
see:
看到的:
http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx#prg
http://weblogs.asp.net/rashid/archive/2009/04/01/asp网- mvc -最佳实践- 1. aspx # prg一部分
Specifically:
具体地说:
public abstract class ModelStateTempDataTransfer : ActionFilterAttribute
{
protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName;
}
public class ExportModelStateToTempData : ModelStateTempDataTransfer
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//Only export when ModelState is not valid
if (!filterContext.Controller.ViewData.ModelState.IsValid)
{
//Export if we are redirecting
if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))
{
filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;
}
}
base.OnActionExecuted(filterContext);
}
}
public class ImportModelStateFromTempData : ModelStateTempDataTransfer
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;
if (modelState != null)
{
//Only Import if we are viewing
if (filterContext.Result is ViewResult)
{
filterContext.Controller.ViewData.ModelState.Merge(modelState);
}
else
{
//Otherwise remove it.
filterContext.Controller.TempData.Remove(Key);
}
}
base.OnActionExecuted(filterContext);
}
}
Usage:
用法:
[AcceptVerbs(HttpVerbs.Get), ImportModelStateFromTempData]
public ActionResult Index(YourModel stuff)
{
return View();
}
[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]
public ActionResult Submit(YourModel stuff)
{
if (ModelState.IsValid)
{
try
{
//save
}
catch (Exception e)
{
ModelState.AddModelError(ModelStateException, e);
}
}
return RedirectToAction("Index");
}
#2
0
In your AddComment ActionResult, do this:
在你的AddComment ActionResult中,这样做:
if(ModelState.IsValid)
{
// Insert new comment
..
..
// Redirect to a different view
}
// Something is wrong, return to the same view with the model & errors
var postModel = new BlogPostViewModel { PostComment = postComment };
return View(postModel);
#3
0
After much time spent I have realized that I have to repopulate the view model and render the correct view, passing in the fully-populated model. Kind of a pain but at least I understand what's going on.
在花了很多时间之后,我意识到我必须重新填充视图模型并呈现正确的视图,传递完全填充的模型。有点痛苦,但至少我明白发生了什么。
#1
2
You need to repopulate the model and send to view. However, you don't need to do this by hand, you can use action filters.
您需要重新填充模型并将其发送到view。但是,您不需要手工操作,您可以使用操作过滤器。
see:
看到的:
http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx#prg
http://weblogs.asp.net/rashid/archive/2009/04/01/asp网- mvc -最佳实践- 1. aspx # prg一部分
Specifically:
具体地说:
public abstract class ModelStateTempDataTransfer : ActionFilterAttribute
{
protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName;
}
public class ExportModelStateToTempData : ModelStateTempDataTransfer
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//Only export when ModelState is not valid
if (!filterContext.Controller.ViewData.ModelState.IsValid)
{
//Export if we are redirecting
if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))
{
filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;
}
}
base.OnActionExecuted(filterContext);
}
}
public class ImportModelStateFromTempData : ModelStateTempDataTransfer
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;
if (modelState != null)
{
//Only Import if we are viewing
if (filterContext.Result is ViewResult)
{
filterContext.Controller.ViewData.ModelState.Merge(modelState);
}
else
{
//Otherwise remove it.
filterContext.Controller.TempData.Remove(Key);
}
}
base.OnActionExecuted(filterContext);
}
}
Usage:
用法:
[AcceptVerbs(HttpVerbs.Get), ImportModelStateFromTempData]
public ActionResult Index(YourModel stuff)
{
return View();
}
[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]
public ActionResult Submit(YourModel stuff)
{
if (ModelState.IsValid)
{
try
{
//save
}
catch (Exception e)
{
ModelState.AddModelError(ModelStateException, e);
}
}
return RedirectToAction("Index");
}
#2
0
In your AddComment ActionResult, do this:
在你的AddComment ActionResult中,这样做:
if(ModelState.IsValid)
{
// Insert new comment
..
..
// Redirect to a different view
}
// Something is wrong, return to the same view with the model & errors
var postModel = new BlogPostViewModel { PostComment = postComment };
return View(postModel);
#3
0
After much time spent I have realized that I have to repopulate the view model and render the correct view, passing in the fully-populated model. Kind of a pain but at least I understand what's going on.
在花了很多时间之后,我意识到我必须重新填充视图模型并呈现正确的视图,传递完全填充的模型。有点痛苦,但至少我明白发生了什么。