Asp.net mvc @Html.BeginForm()是如何工作的?

Asp.net mvc @Html.BeginForm()是如何工作的?,asp.net-mvc,asp.net-mvc-4,razor,Asp.net Mvc,Asp.net Mvc 4,Razor,我对ASP.NET非常陌生,今天刚开始在ASP.NET上学习MVC教程。我来了 到目前为止,问题是: 在我看来,我有以下代码 (模型设置为带有@Model MyFirstMVC4.Models.Movie的视图) 这里有一个问题-它是如何将电影对象传递给上面的POST方法的?!当我观察客户端时,会发现 <form action = "/Movie/Edit/1" ... /> 在这里我不明白为什么action=url是同一个查看页面?!1. 在服务器端也只有Html.Begin

我对ASP.NET非常陌生,今天刚开始在ASP.NET上学习MVC教程。我来了

到目前为止,问题是:

在我看来,我有以下代码 (模型设置为带有@Model MyFirstMVC4.Models.Movie的视图)

这里有一个问题-它是如何将电影对象传递给上面的POST方法的?!当我观察客户端时,会发现

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

在这里我不明白为什么action=url是同一个查看页面?!1. 在服务器端也只有Html.BeginForm():( 它如何实现发布什么动作方法和传递什么路由参数?
它是有效的,我只是不知道为什么在表单提交后要调用的操作会被赋予

[HttpPost]
属性


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

代码中的
BeginForm
版本, 如果没有参数,则向当前URL发送HTTP POST,因此如果视图是对
/Movie/Edit/5
,开始表单标签如下所示:

BeginForm HTML助手询问路由引擎如何达到 MovieController。在幕后,它在路由上使用名为GetVirtualPath的方法 RouteTable公开的属性-您的web应用程序在其中注册其所有路由 如果您在没有HTML助手的情况下完成了所有这些,那么您必须编写以下所有内容 代码:

@{
var context=this.ViewContext.RequestContext;
var值=新的RouteValueDictionary{
{“控制器”、“电影”}、{“动作”、“编辑”}
};
var path=RouteTable.Routes.GetVirtualPath(上下文,值);
}
...
您询问了电影对象是如何传递的,这称为模型绑定。 当您有一个带有参数的操作时,MVC运行时使用模型绑定器来构建 可以在MVC运行时中为不同类型注册多个模型绑定 的模型,但默认情况下,主力将是
DefaultModelBinder

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

当您调用
BeginForm()
而不使用任何参数时,它默认使用用于呈现当前页面的同一控制器/操作。它假定您的控制器上有一个名称正确的操作,该操作将接受回发(您可以这样做)。它使用
routeValue
来执行此操作


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

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

玩转
@Html.BeginForm
-我提供了
Html.BeginForm(“编辑”,“电影”,FormMethod.Post)
。注意,我没有提供路由的第三个
id
部分。但是在生成的标记中,它在那里:
/Movies/Edit/4
。它是如何做到的?如果我提供
Html.BeginForm(“Delete”,“Movies”,FormMethod.Post)
,则生成的Html没有
id
/Movies/Delete
    // 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);
    }
<form action = "/Movie/Edit/1" ... />
  @{
 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>