【问题标题】:MVC .NET "Edit" button choose right methodMVC .NET“编辑”按钮选择正确的方法
【发布时间】:2014-01-06 10:45:28
【问题描述】:

我正在关注本教程>>http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view

还有一个让我很困惑的问题!

在我的控制器类“MoviesController”中,我有一个方法 Edit 和一个重载,当用户开始编辑记录时使用其中一个方法,而另一个用于发布更改。

我的问题是页面如何知道它必须调用哪个方法,我知道它正在使用参数,但是查看代码我没有找到任何可以跟踪请求的东西。

代码如下:

Edit.cshtml

@model SmartJob.Models.Movie

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ReleaseDate)
                @Html.ValidationMessageFor(model => model.ReleaseDate)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Genre, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Genre)
                @Html.ValidationMessageFor(model => model.Genre)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Price)
                @Html.ValidationMessageFor(model => model.Price)
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>

MoviesContoller 类(仅限 Edit 方法)

 // GET: /Movies/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Movie movie = db.Movies.Find(id);
            if (movie == null)
            {
                return HttpNotFound();
            }
            return View(movie);
        }

        // POST: /Movies/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
        {
            if (ModelState.IsValid)
            {
                db.Entry(movie).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(movie);
        }

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-4


    【解决方案1】:

    默认情况下,任何没有 [HttpGet] 或 [HttpPost] 属性的请求都是 GET 方法。如果您针对该方法发布(也就是提交某种类型的表单),则必须指定该方法是 [HttpPost]

    请注意,您的第一个 Edit 方法中没有指定 [HttpGet][HttpPost]。因此它将默认为[HttpGet]

    // GET: /Movies/Edit/5
            public ActionResult Edit(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
                Movie movie = db.Movies.Find(id);
                if (movie == null)
                {
                    return HttpNotFound();
                }
                return View(movie);
            }
    

    现在注意这个方法的标签是[HttpPost]。如果需要,您还可以指定其他动词,例如 [HttpPut][HttpDelete] 等等,但这些是最常用的。另请注意,您有 [Bind()] 方法。当您可能只想更新对象的几个字段时,这用于防止发送“过多”数据。

            // POST: /Movies/Edit/5
            // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
            // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
            [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
            {
                if (ModelState.IsValid)
                {
                    db.Entry(movie).State = EntityState.Modified;
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                return View(movie);
            }
    

    【讨论】:

      【解决方案2】:

      它使用 Http 动词来知道调用哪个方法。当您提交表单时,它会查找具有HttpPost 属性的操作,因为它是POST 请求。第一个动作没有指定动词,所以它使用的默认动词是HttpGet,所以你可以使用你的路由定义的url(比如Movies/Edit/5)。

      【讨论】:

        【解决方案3】:

        [HttpPost] 是一个 ActionMethodSelectorAttribute,MVC 将利用它来根据请求中的 HTTP 动词确定要选择的正确操作方法。

        另外,如果你有相同的动作名称和不同的参数,基于 http 请求参数,MVC 会推断出正确的动作来调用...ex:

        [HttpGet]
        public ActionResult ActionName() {...}
        
        [HttpPost]
        public ActionResult ActionName(string aParameter) {...}
        

        【讨论】:

          【解决方案4】:

          它通过一些事情知道。

          第一个是在第二个Edit 操作上,它被标记为[HttpPost],这告诉ASP.NET 路由器如果请求是除POST 之外的任何其他方法,则完全忽略它。您可以将第一个方法标记为[HttpGet] 也可以使其更加明确。 (未明确标记的方法将响应对它们的所有请求,因此您可以使用POST 对带有 ID 字段的第一次编辑做出响应。)

          第二个是通过的模型。 ActionResult 重载与普通函数重载完全一样,即它会自动选择与输入匹配的函数。 ([Bind] 只是模型反序列化器的语法糖,因此您可以防止特定数据库字段通过特定表单更新。)

          如果它不能将模型反序列化为预期的类型,你会遇到运行时错误。

          【讨论】:

          • 以上代码,可以编译,但是在浏览器中访问url时,会抛出异常。
          • @czcz1024 谢谢,我对我写的东西很明显:-/
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-16
          • 2015-02-27
          • 2022-01-17
          • 2013-06-02
          • 1970-01-01
          • 2017-04-10
          • 1970-01-01
          相关资源
          最近更新 更多