Actionresult 不会被路由链接调用。表单收集是罪魁祸首?

发布于 2024-08-22 15:41:30 字数 1868 浏览 7 评论 0原文

我对 MVC 还很陌生。我正在尝试设置一个搜索页面来搜索数据库并返回结果。搜索框位于我的视图中的 Html.BeginForm 内,如下所示:

   <% using (Html.BeginForm())
     { %>
      <%= Html.TextBox("searchBox", null, new { @id = "searchBox" })%>
       <div id="searchButtonsDiv">
        <input type="submit" value="Search" />
      </div>
  <% } %>

  //Results are returned in a ul and orgainized


   //Pagination below
   <% if (Model.HasPreviousPage)
      { %>
        <%= Html.RouteLink("Previous", "SearchResults", new { page = (Model.PageIndex - 1) })%>
   <% } %>
   <% if (Model.HasNextPage)
      {  %>
         <%= Html.RouteLink("Next", "SearchResults", new { formCollection = "", page = (Model.PageIndex + 1) })%>
   <% } %>

我正在使用 FormCollection 传递给我的控制器,如下所示:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(FormCollection formCollection, int? page)
    {
        var searchString = formCollection["searchBox"]; 
        var results = resultsRepository.GetResults();

        var paginatedResults = new PaginatedList<Driver>(results, page ?? 0, pageSize);

        return View(paginatedResults);
    }

到目前为止一切顺利。当我输入一个单词并按下提交按钮时,索引被调用并且数据库相应地返回。 ul 会填充结果,当结果超过 pageSize(在我的例子中为 10)时,会显示“下一个”链接。

当我单击“下一步”时,将加载默认页面。没有分页或类似的东西。我很确定这与我的 Index ActionResult 有一个 FormCollection 作为参数这一事实有关。我想我在某处读到只能处理字符串/整数?这是 MapRoute:

        routes.MapRoute(
            "SearchResults",
            "Drivers/Index/{formCollection}/{page}",
            new { controller = "Drivers", action = "Index", formCollection = "", page = "" }
        );

我完全错过了一些东西还是有办法处理这个问题?我知道我可以使用 jquery/ajax 发送搜索列表框中包含的字符串,但我不想这样做,因为稍后我计划添加复选框作为过滤搜索的手段等。

我尝试了几种不同的设置方式formCollection 的值,包括创建一个添加 searchBox 的新 FormCollection,以及仅传递字符串等。

I am fairly new to MVC. I am trying to set up a search page that searches a database and returns results. The search box is within a Html.BeginForm in my View, and looks like this:

   <% using (Html.BeginForm())
     { %>
      <%= Html.TextBox("searchBox", null, new { @id = "searchBox" })%>
       <div id="searchButtonsDiv">
        <input type="submit" value="Search" />
      </div>
  <% } %>

  //Results are returned in a ul and orgainized


   //Pagination below
   <% if (Model.HasPreviousPage)
      { %>
        <%= Html.RouteLink("Previous", "SearchResults", new { page = (Model.PageIndex - 1) })%>
   <% } %>
   <% if (Model.HasNextPage)
      {  %>
         <%= Html.RouteLink("Next", "SearchResults", new { formCollection = "", page = (Model.PageIndex + 1) })%>
   <% } %>

I am using a FormCollection to pass to my controller that looks like this:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(FormCollection formCollection, int? page)
    {
        var searchString = formCollection["searchBox"]; 
        var results = resultsRepository.GetResults();

        var paginatedResults = new PaginatedList<Driver>(results, page ?? 0, pageSize);

        return View(paginatedResults);
    }

So far so good. When I type a word and press the submit button, Index gets called and the database returns accordingly. The ul gets populated with the results, and when there are more than pageSize results (10 in my case), the Next link shows up.

When I click "Next", the default page just loads. No pagination or anything like that. I'm pretty sure it has to do with the fact that my Index ActionResult has a FormCollection as a paramater. I thought I read somewhere that only strings/ints can be handled? Here is the MapRoute:

        routes.MapRoute(
            "SearchResults",
            "Drivers/Index/{formCollection}/{page}",
            new { controller = "Drivers", action = "Index", formCollection = "", page = "" }
        );

Am I completely missing something or is there a way to handle this? I know I could just use jquery/ajax to send the string contained in the search listbox, but I don't want to do that because later I plan on adding checkbox's as means of filtering searches, etc.

I tried several different ways of setting the formCollection's value, including creating a new FormCollection that adds the searchBox, and just passing strings, etc.

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

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

发布评论

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

评论(1

揪着可爱 2024-08-29 15:41:30

操作中的 FormCollection 参数不是问题。这永远有效。

然而,它绝对不属于您的路线!只要摆脱它,你可能就会解决问题。表单元素不会出现在 URI 中,只有 URI 中的内容才应该出现在路由中。

然而,这不是我编写该动作签名的方式。我建议:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string searchBox, int? page)
{
    var results = resultsRepository.GetResults();

    var paginatedResults = new PaginatedList<Driver>(results, page ?? 0, pageSize);

    return View(paginatedResults);
}

最后:在这种情况下,您不应该从 POST 返回 View 。这会导致用户出现奇怪的行为;例如,当他们按下刷新时,浏览器会警告他们重新提交表单。

您应该:

  1. 使用 GET,而不是 POST 来获取搜索结果。
  2. 重定向而不是返回视图。

就我个人而言,我会选择第一个。

The FormCollection argument in the action isn't the problem. That will always work.

It absolutely does not belong in your route, however! Just get rid of that and you'll probably solve the problem. Form elements don't go in the URI, and only stuff in the URI should be in the route.

It's not how I'd write that action signature, however. I'd suggest:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string searchBox, int? page)
{
    var results = resultsRepository.GetResults();

    var paginatedResults = new PaginatedList<Driver>(results, page ?? 0, pageSize);

    return View(paginatedResults);
}

Finally: You shouldn't return a View from a POST in this case. This will cause weird behavior for the user; e.g., when they press refresh their browser will warn them about re-submitting the form.

You should either:

  1. Use a GET, not a POST for search results.
  2. Redirect instead of returning a view.

I'd pick the first, personally.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文