为什么在使用 POST 动词提交表单时会再次调用 HttpGet 方法?

kis*_*pit 1 c# asp.net-mvc

控制器:

// other usings are removed for the sake of brevity
using MvcMovie.Models;

namespace MvcMovie.Controllers
{
    public class MoviesController : Controller
    {
        private MoviewDBContext db = new MoviewDBContext();

        public ActionResult SearchIndex(string searchString)
        {
            var movies = db.Movies.Select(x => x);
            if (!string.IsNullOrEmpty(searchString))
                movies = movies.Where(x => x.Title.Contains(searchString));

            return View(movies);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

看法:

// SearhcIndex.cshtml

@model IEnumerable<MvcMovie.Models.Movie>

@using (Html.BeginForm())
{
    <p>
        Title: @Html.TextBox("searchString")
        <br />
        <input type="submit" value="Filter" />
    </p>
}

<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Title)
        </th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            </td>
        </tr>
    }

</table>
Run Code Online (Sandbox Code Playgroud)

我第一次访问时localhost/Movies/SearchIndex,HttpGet SearchIndex将被调用并填充相应视图的模型。在浏览器上呈现视图后,我输入一个词来过滤列表,然后按下提交按钮Filter。

我的问题是:

Filter在我看来,单击将提交带有 POST 动词的表单。但是为什么再次HttpGet SearchIndex调用 get呢?我还没有实现(当然)。HttpPost SearchIndex

注意:我是新手,请不要在没有给出我可以学习的理由的情况下投票。我正在阅读本教程“检查编辑方法和编辑视图”。

Mik*_* C. 5

它这样做是因为你没有指定它应该只处理 get 请求,所以默认情况下它会同时处理这两个请求。如果您要添加该HttpGet属性,它将具有您期望的行为

    [HttpGet]
    public ActionResult SearchIndex(string searchString)
    {
        var movies = db.Movies.Select(x => x);
        if (!string.IsNullOrEmpty(searchString))
            movies = movies.Where(x => x.Title.Contains(searchString));

        return View(movies);
    }

    [HttpPost]
    public ActionResult SearchIndex(string searchString, string someOtherParam)
    {
        var movies = db.Movies.Select(x => x);
        if (!string.IsNullOrEmpty(searchString))
            movies = movies.Where(x => x.Title.Contains(searchString));
        //do something different than your get...
        return View(movies);
    }
Run Code Online (Sandbox Code Playgroud)

请注意,我在这里包含了另一种处理 Post 的方法,当然您仍然想要。正如评论中所提到的,如果这仍然失败,请在您的表单中明确指定 POST,尽管我从来没有这样做过,我不希望您在这里需要它。

另请注意,您的 post 方法要么需要不同的名称,要么需要与 get 不同的参数(以便 .net 可以区分它们)

由于您提到是新手,这里是我更喜欢的 MVC 教程,并且在启动 MVC 时让新开发人员阅读:http : //www.asp.net/mvc/tutorials/mvc-music-store

如果你还没有这样做,你应该检查一下!

更新:

根据您的评论,这是他们在您提供的链接中告诉您的内容。当请求路由到您的控制器时,MVC 将选择第一个与请求完全匹配的 Action Method。如果您不申请[HttpGet],[HttpPost]则该操作方法将同时接受两者。因此,假设您浏览到 /mysite/Movies/SearchIndex。使用我上面的示例,这是一个 GET 请求,因此 MVC 看到您使用 [HttpGet] 标记了 SearchIndex,这就是它将使用的内容。

现在假设您删除了[HttpGet]但保留[HttpPost]在另一个上(如您提供的文章中的示例)。如果您浏览到 /mysite/Movies/SearchIndex MVC 看到 SearchIndex() 标有 HTTPPost 并说,不能使用那个!然后它看到没有属性的 SearchIndex()(意味着它接受 Post 和 Get)并使用它。

类似地,如果您使用 POST 请求导致 /mysite/Movies/SearchIndex,MVC 会看到您有一个 SearchIndex() 标记,[HttpPost]因此它使用该标记,因为它是完全匹配的。

这篇文章没有说清楚的一点是,方法的默认行为是同时接受 GET 和 POST。文章当时实际上在说什么,给出了特定场景,其中一个标记为[HttpPost],另一个根本没有标记,默认行为将导致使用未标记的 Action 方法。

如果这令人困惑,我深表歉意,我重写了几次,但解释起来有点复杂。