Asp.net mvc @Html.BeginForm()是如何工作的?
我对ASP.NET非常陌生,今天刚开始在ASP.NET上学习MVC教程。我来了 到目前为止,问题是: 在我看来,我有以下代码 (模型设置为带有@Model MyFirstMVC4.Models.Movie的视图) 这里有一个问题-它是如何将电影对象传递给上面的POST方法的?!当我观察客户端时,会发现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
<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>