如何在部分视图中使用模型验证

时间:2012-08-18 04:17:04

标签: c# asp.net-mvc asp.net-mvc-3 partial-views

我有一个像这样的控制器:

public FooController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

使用索引视图:

@{ Html.RenderPartial("~/Views/Bar/Add", new Models.Bar()); }

Bar控制器是这样的:

public BarController : Controller
{
    public ActionResult Add()
    {
        var bar = new Bar();
        return View(bar);
    }

    [HttpPost]
    public ActionResult Add(Bar bar)
    {
        if(ModelState.IsValid)
        {
            _repository.AddBar(bar);
            return RedirectToAction("Index", "Foo");
        }

        // This will return only the partial view (No Layout, no outer view)
        return View("Add", bar);

        // This will not show validation errors
        // return RedirectToAction("Index", "Foo");
    }
}

添加视图如下所示:

@model Models.Bar

@using(Html.BeginForm("Add", "Bar", FormMethod.Post))
{
    Name: @Html.TextBoxFor(x => x.Name)

    <input type="submit" value="Add Bar" />

    @Html.ValidationSummary()
}

我的问题是,如果我返回View("Add", bar),我会得到局部视图,而不是其他任何东西(不是我想要的)。但是,如果我返回RedirectToAction("Index", "Foo")是否通过验证,我当然会丢失valiation摘要的任何验证错误。

有没有办法在像这样的局部视图中使用验证?

3 个答案:

答案 0 :(得分:4)

你可以:

    如果验证失败,则
  1. return View("~/Views/Home/Index.cshtml")
  2. 在TempData上保存ModelState并在Home.Index操作上恢复它。
  3. 发出AJAX请求。

答案 1 :(得分:1)

你应该使用@ Ajax.Begin而不是使用@ Html.BeginForm,它将使用ajax提交你的请求。

@model Models.Bar

<div id="targetId">
</div>

        @using(Ajax.BeginForm("Add", "Bar",new AjaxOptions{  HttpMethod ="POST",UpdateTargetId="targetId"}))
        {


            Name: @Html.TextBoxFor(x => x.Name)

            <input type="submit" value="Add Bar" />

            @Html.ValidationSummary()
        }

它在控制器中调用“添加”ajax。

[HttpPost]
public ActionResult Add(Bar bar)
{
    if(ModelState.IsValid)
    {
        _repository.AddBar(bar);
        return RedirectToAction("Index", "Foo");
    }

    return RenderPartialViewToString("Add",bar);
}



protected string RenderPartialViewToString(string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.RouteData.GetRequiredString("action");

        ViewData.Model = model;

        using (StringWriter sw = new StringWriter())
        {
            ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
            ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            return sw.GetStringBuilder().ToString();
        }
    }

然后添加“RenderPartialViewToString”方法,这将返回“ HtmlRenderString ”,您需要将View和model作为参数传递给此方法。 您也必须在AjxOption中指定“ UpdateTargetId ”,其结果将附加在其中。

答案 2 :(得分:0)

@{ Html.RenderPartial("~/Views/Bar/Add", new Models.Bar()); }替换为@{ Html.RenderPartial("~/Views/Bar/Add"); },就像你拥有它一样,它试图将新的Bar发布到[Post] Add或获取视图。

此外,我通常在控制器中使用PartialViewResultreturn PartialView作为部分视图。不确定它是否有所作为。

<强>更新

我刚刚启动了一个项目,我有一个部分表单,我使用@Html.Action()访问它,一切似乎都有效并且验证正常。试试@Html.RenderAction。这是一篇描述差异的好文章。 http://www.arrangeactassert.com/when-to-use-html-renderpartial-and-html-renderaction-in-asp-net-mvc-razor-views/