来自不同控制器操作和ModelState的HTTP Post请求

时间:2012-02-13 08:47:32

标签: asp.net-mvc asp.net-mvc-3 modelstate asp.net-mvc-validation

我在ASP.NET MVC 3应用程序中有一个奇怪的需求阻止了我当前的进展。情况就是这样:

我有一些产品的搜索引擎,我在多个页面上渲染这个搜索引擎。此SE向product控制器的search操作发出HTTP POST请求。它很好,直到这里。

我们假设我在home控制器的index操作(/ home / index)上。我进行搜索并检查是否ModelState.IsValid。因此,它无效。所以,我应该使用输入的模型返回它(这样用户不会丢失值)和模型状态错误。但是当我这样做时,我最终得到了不同的URL(/ product / search)。

如果我进行重定向,则会丢失ModelState并且无法显示错误消息。

到目前为止我有不同的解决方案,它们看起来都很脏。有什么想法吗?

修改

这是一个小项目,展示了这一点:

这是ProductController

public class ProductController : Controller {

    [HttpPost]
    public ActionResult Search(SearchModel searchModel) {

        if (ModelState.IsValid) { 
            //Do some stuff...

            return RedirectToAction("Index", "SearchResult");
        }
        return View(searchModel);
    }
}

这是SearchModel

public class SearchModel {

    [Required]
    public string ProductCategory { get; set; }

    [Required]
    public string ProductName { get; set; }
}

这是* _SearchPartial *:

@model MvcApplication20.SearchModel

@using (Html.BeginForm("search", "product"))
{
    @Html.EditorForModel()

    <input type="submit" value="Search" />
}

最后这是Home控制器Index操作视图,它呈现* _SearchPartial *:

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>

@Html.Partial("_SearchPartialView")

在这里,当我提交表单并且模型状态失败时,我应该如何处理Product控制器Search操作?

2 个答案:

答案 0 :(得分:2)

  

在这里,当我提交表单时,如果模型状态失败,应该怎么做   我继续进行产品控制器搜索操作?

通常情况下,在这种情况下,您应该呈现_SearchPartialView但不是部分的,而是作为带有布局的完整视图,以便用户可以修复他的错误。在这种情况下无需留在家/索引:

[HttpPost]
public ActionResult Search(SearchModel searchModel) {

    if (ModelState.IsValid) { 
        //Do some stuff...

        return RedirectToAction("Index", "SearchResult");
    }
    // since we are returning a view instead of a partial view,
    // the _SearchPartialView template should be displayed with the layout
    return View("_SearchPartialView", searchModel);
}

如果您想在出错时保持同一页面,可以使用AJAX调用来执行搜索。因此,您将AJAXify此搜索表单,然后在成功回调测试中搜索操作的结果,并根据它决定是否刷新部分以显示错误或使用window.location.href重定向到结果操作:< / p>

类似于:

$(document).on('submit', '#searchForm', function() {
    $.ajax({
        url: this.action,
        type: this.method,
        data: $(this).serialize(), 
        success: function(result) {
            if (result.redirectTo) {
                // no validation errors we can redirect now:
                window.location.href = result.redirectTo;
            } else {
                // there were validation errors, refresh the partial to show them
                $('#searchContainer').html(result);

                // if you want to enable client side validation
                // with jquery unobtrusive validate for this search form
                // don't forget to call the .parse method here 
                // since we are updating the DOM dynamically and we
                // need to reattach client side validators to the new elements:
                // $.validator.unobtrusive.parse(result);
            }
        }
    });
    return false;
});

这显然假设您现在已将部分调用包含在id="searchContainer"的div中,并且在生成搜索表单时提供了id="searchForm"

<div id="searchContainer">
    @Html.Partial("_SearchPartialView")
</div>

现在搜索操作:

[HttpPost]
public ActionResult Search(SearchModel searchModel) {

    if (ModelState.IsValid) { 
        //Do some stuff...

        return Json(new { redirectTo = Url.Action("Index", "SearchResult") });
    }
    return PartialView("_SearchPartialView", searchModel);
}

答案 1 :(得分:1)

据我所知,当执行RedirectToAction时ModelState丢失了,解决方案是将模型状态保存在TempData的一个例子中,我正在使用的是:

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

这也在各种帖子中进行了讨论,例如MVC Transfer Data Between Views