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

发布于 2025-01-04 23:16:17 字数 1644 浏览 0 评论 0原文

我对 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" />
}

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

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

<h2>@ViewBag.Message</h2>

@Html.Partial("_SearchPartialView")

在这里,当我提交表单时,如果模型状态失败,我应该如何继续 <代码>产品控制器搜索操作?

I have a weird need in an ASP.NET MVC 3 application which blocks my current progress. Here is the case:

I have a little search engine for the products and I render this search engine on multiple pages. This SE makes a HTTP POST request to product controller's search action. It fine till here.

Let's assume that I am on home controller's index action (/home/index). I make a search and check if ModelState.IsValid. As a result, it is not valid. So, I should return this back with the entered model (so that user won't lose the values) and model state errors. But when I do that I ended up with different URL (/product/search) as expected.

If I do a redirect, I lose the ModelState and cannot display error messages.

I have different solutions so far and they all look dirty. Any idea?

Edit

Here is a little project which demonstrates this:

This is the ProductController:

public class ProductController : Controller {

    [HttpPost]
    public ActionResult Search(SearchModel searchModel) {

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

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

This is the SearchModel:

public class SearchModel {

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

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

This is the *_SearchPartial*:

@model MvcApplication20.SearchModel

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

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

And finally this is the Home controller Index action view which renders the *_SearchPartial*:

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

<h2>@ViewBag.Message</h2>

@Html.Partial("_SearchPartialView")

Here, when I submit the form and if the model state fails, how should I proceed at the Product controller Search action?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜是你 2025-01-11 23:16:18

据我所知,在执行 RedirectToAction 时 ModelState 会丢失,解决方案是将 modelstate 保存在 TempData 中,我正在使用的一个示例是:

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

这也在各种例如帖子 MVC 在视图之间传输数据

As far as I know the ModelState is lost when doing a RedirectToAction, the solution would be to save the modelstate in the TempData one example of this, that I'm using is this:

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

This is also discussed in various posts for instance MVC Transfer Data Between Views

披肩女神 2025-01-11 23:16:17

在这里,当我提交表单时,如果模型状态失败,应该如何处理
我继续执行产品控制器搜索操作吗?

通常在这种情况下,您应该渲染 _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 调用来执行搜索。因此,您可以 AJAX 化此搜索表单,然后在成功回调中测试搜索操作的结果,并根据结果决定是否刷新部分内容以显示错误或使用 window.location 重定向到结果操作。 href:

大致如下:

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

Here, when I submit the form and if the model state fails, how should
I proceed at the Product controller Search action?

Normally in this case you should render the _SearchPartialView but not as a partial but as a full view with layout so that the user can fix his errors. No need to stay at Home/Index in this case:

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

And if you wanted to stay on the same page upon error you could use an AJAX call to perform the search. So you would AJAXify this search form and then in the success callback test the result of the Search action and based on it decide whether to refresh the partial in order to show the error or redirect to the results action using window.location.href:

something along the lines of:

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

This obviously assumes that you have now wrapped the partial call in a div with id="searchContainer" and that you provided an id="searchForm" when generating the search form:

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

and now the search action:

[HttpPost]
public ActionResult Search(SearchModel searchModel) {

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

        return Json(new { redirectTo = Url.Action("Index", "SearchResult") });
    }
    return PartialView("_SearchPartialView", searchModel);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文