ASP.NET MVC表单验证。你如何在非模型对象上做到这一点?

时间:2011-03-17 22:17:44

标签: c# asp.net asp.net-mvc validation asp.net-mvc-3

我有一个模型BlogPostViewModel的视图:

public class BlogPostViewModel
{
    public BlogPost BlogPost { get; set; }
    public PostComment NewComment { get; set; }
}

当操作方法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 });
    }

我的问题在于验证。我如何验证此表单?视图的模型实际上是BlogPostViewModel。我是验证的新手,很困惑。表单使用强类型帮助器绑定到NewComment的{​​{1}}属性,并且我也包含了验证助手。

BlogPostViewModel

如何在@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> } 操作方法中实现验证?当我发现AddComment然后是什么?我该怎么回事?此操作方法仅绑定到页面初始Model.IsValid == false对象的PostComment属性,因为我不关心该模型上的任何其他属性。

感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

您需要重新填充模型并发送到视图。但是,您不需要手动执行此操作,可以使用操作过滤器。

见:

http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx#prg

具体做法是:

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);
    }
}

用法:

[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");
}

答案 1 :(得分:0)

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);

答案 2 :(得分:0)

花了很多时间后,我意识到我必须重新填充视图模型并渲染正确的视图,传入完全填充的模型。有点痛,但至少我明白发生了什么。