我是ASP.NET的新手,刚刚在asp.net上启动了MVC教程。我到了http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-methods-and-edit-view
到目前为止,这个问题很好:
在我的视图中,我有以下代码 (使用@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>
}
我的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);
}
这就是问题 - 它如何将Movie对象传递给上面的POST方法?!当我观察客户端时有
<form action = "/Movie/Edit/1" ... />
这里我不明白为什么动作=同一个视图页面的网址?!1 另外在服务器端只有Html.BeginForm():( 它如何实现发布的操作方法和要传递的路由参数? 它有效,我只是不知道为什么
答案 0 :(得分:39)
代码中BeginForm
的版本,
如果没有参数,则将HTTP POST发送到当前URL,因此如果视图是响应
/Movie/Edit/5
,初始表单标记如下所示:
< form action="/Movie/Edit/5" method="post">
BeginForm HTML帮助器询问路由引擎如何到达的Edit操作 MovieController。在幕后,它使用Routes上名为GetVirtualPath的方法 RouteTable公开的属性 - 这是您的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>
你问过电影对象是如何传递的。这称为模型绑定。
当您使用参数执行操作时,MVC运行时使用模型绑定器来构建
参数。您可以在MVC运行时中为不同类型注册多个模型绑定器
模型,但默认的主力是DefaultModelBinder
。
以电影为例 对象,默认模型绑定器检查电影并查找所有可用的电影属性 用于绑定。按照您之前检查过的命名约定,默认模型绑定器可以自动将请求中的值转换并移动到电影对象中(模型绑定器可以 还要创建要填充的对象的实例)。 换句话说,当模型绑定器看到Movie具有Title属性时,它会查找值 在请求中命名为“标题”。请注意,模型绑定器看起来“在请求中”而不是“在表单中” “模型绑定器使用称为值提供程序的组件来搜索值 请求的不同区域。 模型绑定器可以查看路径数据,查询字符串和表单 集合,如果您愿意,可以添加自定义值提供者。
答案 1 :(得分:9)
当您在没有任何参数的情况下调用BeginForm()
时,默认使用与呈现当前页面相同的控制器/操作。它假设您将在控制器上使用正确的名称执行操作,该操作将接受回发(您执行此操作)。它使用RouteValues
来执行此操作。
它会自动将每个输入控件(按名称)绑定到接受回发的操作的参数 - 或者在您的情况下,是接受回发的操作的对象参数的属性。
答案 2 :(得分:4)
[HttpPost]
属性被赋予您希望在表单的POST提交中调用的操作。
要了解@using (Html.BeginForm())
的工作原理,您需要知道它已经在哪个页面上。在2个不同的视图中使用@using (Html.BeginForm())
将返回两个不同的控制器
答案 3 :(得分:0)
我们可以通过输入简单的html或html帮助器来创建表单。 其中一个是Html.BeginForm();它有点奇怪,因为你实际上可以将它包装在using语句中,因为这个特殊的帮助器返回一个在C#中实现IDisposable的对象。首先,它用开始标记写出来。在生成的代码调用dispose在该对象的底部,那时它将写出结束表单标记。所以BeginForm给了我一个对象,它将写出我的开始表单标签和我从标签关闭。之后,您不必担心任何可以只关注标签和输入的内容