asp.net-mvc @Html.BeginForm() 如何工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16744191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 02:52:34  来源:igfitidea点击:

How does @Html.BeginForm() works?

asp.net-mvcasp.net-mvc-4razor

提问by Ivan Prodanov

I'm very new to ASP.NET, just started the MVC tutorial today on asp.net. I got here http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view

我对 ASP.NET 很陌生,今天刚开始在 asp.net 上学习 MVC 教程。我到了这里http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examing-the-edit-methods-and-edit-view

So far so good, the problem:

到目前为止一切顺利,问题是:

In my View I have the following code (Model is set to the view with @model MyFirstMVC4.Models.Movie)

在我的视图中,我有以下代码(模型设置为@model MyFirstMVC4.Models.Movie 的视图)

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Movie</legend>

        @Html.HiddenFor(model => model.ID)

        //... bla bla html input
        <p>
             <input type="submit" value="Save" />
        </p>
    </fieldset>
}

My MovieController

我的电影控制器

    // Shows the view
    public ActionResult Edit(int id = 0)
    {
        Movie movie = db.Movies.Find(id);
        if (movie == null)
        {
            return HttpNotFound();
        }
        return View(movie);
    }

    //
    // POST: /Movie/Edit/5

    [HttpPost] // Handles the view above
    public ActionResult Edit(Movie movie)
    {
        if (ModelState.IsValid)
        {
            db.Entry(movie).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(movie);
    }

And here is the question - How the heck does it pass the Movie object to the POST method above?! When I observe the client side there is

这里有一个问题——它到底是如何将 Movie 对象传递给上面的 POST 方法的?!当我观察客户端时

<form action = "/Movie/Edit/1" ... />

Here I don't understand why action = url of the very same view page?!1 Also on the server side there is just Html.BeginForm() :( How does it realize to what action method to post and what route parameters to pass? It works, I just don't know why

这里我不明白为什么 action = url 是同一个视图页面?!1 同样在服务器端只有 Html.BeginForm() :( 它是如何实现要发布的操作方法和要传递的路由参数的? 它有效,我只是不知道为什么

回答by Vlado Pand?i?

The version of BeginFormin the code, with no parameters, sends an HTTP POST to the current URL, so if the view is a response to /Movie/Edit/5, the opening form tag will look like the following: < form action="/Movie/Edit/5" method="post">

BeginForm代码中的 版本不带参数,向当前 URL 发送 HTTP POST,因此如果视图是对 的响应 /Movie/Edit/5,则打开表单标记将如下所示: < form action="/Movie/Edit/5" method="post">

The BeginForm HTML helper asks the routing engine how to reach the Edit action of the MovieController. Behind the scenes it uses the method named GetVirtualPath on the Routes property exposed by RouteTable — that's where your web application registered all its routes in global.asax. If you did all this without an HTML helper, you'd have to write all the following code:

BeginForm HTML 帮助程序询问路由引擎如何到达 MovieController 的 Edit 操作。在幕后,它在 RouteTable 公开的 Routes 属性上使用名为 GetVirtualPath 的方法——这是您的 Web 应用程序在 global.asax 中注册其所有路由的地方。如果您在没有 HTML 帮助程序的情况下完成所有这些操作,则必须编写以下所有代码:

  @{
 var context = this.ViewContext.RequestContext;
  var values = new RouteValueDictionary{
  { "controller", "movie" }, { "action", "edit" }
 };
  var path = RouteTable.Routes.GetVirtualPath(context, values);
 }
 <form action="@path.VirtualPath" method="get">
  ...
 </form>

You asked how is movie object is passed. That is called model binding. When you have an action with a parameter, the MVC runtime uses a model binder to build the parameter. You can have multiple model binders registered in the MVC runtime for different types of models, but the workhorse by default will be the DefaultModelBinder.

你问电影对象是如何传递的。这就是所谓的模型绑定。当您有一个带有参数的操作时,MVC 运行时使用模型绑定器来构建参数。您可以在 MVC 运行时为不同类型的模型注册多个模型绑定器,但默认情况下,主力将是DefaultModelBinder.

In the case of an Movie object, the default model binder inspects the Movie and finds all the movie properties available for binding. Following the naming convention you examined earlier, the default model binder can automatically convert and move values from the request into an movie object (the model binder can also create an instance of the object to populate). In other words, when the model binder sees an Movie has a Title property, it looks for a value named “Title” in the request. Notice the model binder looks “in the request” and not “in the form collection.” The model binder uses components known as value providers to search for values in different areas of a request. The model binder can look at route data, the query string, and the form collection, and you can add custom value providers if you so desire.

对于 Movie 对象,默认模型绑定器会检查 Movie 并找到所有可用于绑定的电影属性。遵循您之前检查过的命名约定,默认模型绑定器可以自动将请求中的值转换并移动到影片对象中(模型绑定器还可以创建要填充的对象实例)。换句话说,当模型绑定器看到 Movie 具有 Title 属性时,它会在请求中查找名为“Title”的值。请注意,模型绑定器看起来“在请求中”而不是“在表单集合中”。模型绑定器使用称为值提供程序的组件来搜索请求的不同区域中的值。模型绑定器可以查看路由数据、查询字符串和表单集合,并且您可以根据需要添加自定义值提供程序。

回答by Nick Albrecht

When you call BeginForm()without any parameters it default to using the same controller/action used to render the current page. It assumes you'll have an action with the correct name on your controller that will accept postbacks (which you do). It uses the RouteValuesto do this.

当您BeginForm()不带任何参数调用时,它默认使用用于呈现当前页面的相同控制器/操作。它假设您将在控制器上有一个具有正确名称的操作,该操作将接受回发(您这样做)。它使用RouteValues来做到这一点。

It automatically binds each input control (by name) to the parameters of the action accepting the postback - or in your case, the properties of the object parameter for the action accepting the postback.

它会自动将每个输入控件(按名称)绑定到接受回发的操作的参数 - 或者在您的情况下,是接受回发的操作的对象参数的属性。

回答by Scott Selby

[HttpPost]attribute is given to the action that you want to be called on the POST submit of the form.

[HttpPost]属性被赋予您想要在表单的 POST 提交上调用的操作。

to understand how @using (Html.BeginForm())works , you need to know what page it is already on . using @using (Html.BeginForm())in 2 different views will come back to two different controllers

要了解@using (Html.BeginForm())工作原理,您需要知道它已经在哪个页面上。使用@using (Html.BeginForm())在2个不同的视图会回来的两个不同的控制器

回答by Eldiyar Talantbek

We can create forms by typing simple html or by html helpers. One of them Html.BeginForm(); it is a little bit odd because you actually can wrap it in a using statement because this particular helper returns an object that implements IDisposable in C#. First it writes out with opening tag. And at the bottom when the generated code calls dispose on that object, that's when it will write out closing form tag . So BeginForm gives me an object that will write out my opening form tag and my closing from tag. After that you don't worry about anything you can just focus on labels and inputs

我们可以通过输入简单的 html 或通过 html 助手来创建表单。其中之一 Html.BeginForm(); 这有点奇怪,因为您实际上可以将它包装在 using 语句中,因为这个特定的帮助程序返回一个在 C# 中实现 IDisposable 的对象。首先它用开始标签写出。在底部,当生成的代码在该对象上调用 dispose 时,它​​会写出结束表单标记。所以 BeginForm 给了我一个对象,它将写出我的开始表单标签和我的结束标签。之后你不用担心任何事情,你可以专注于标签和输入