读书人

asp.net mvc源码分析-BeginForm步骤 和

发布时间: 2012-11-23 00:03:43 作者: rapoo

asp.net mvc源码分析-BeginForm方法 和ClientValidationEnabled 属性

在上篇文章asp.net mvc源码分析-RenderAction和RenderPartial我们提到了一个常用的RenderAction方法,除了它我们还会经常遇到表单提交,这时我们通常会用到BeginForm。让我们来看看你BeginForm是如何使用的

asp.net mvc源码分析-BeginForm步骤 和ClientValidationEnabled 属性

运行结果就是生成form表单

asp.net mvc源码分析-BeginForm步骤 和ClientValidationEnabled 属性

一般我们的表单提交都涉及到强类型,所以一般需要@model MvcApp.Controllers.UserInfo指令,那我们来看看你用@using (Html.BeginForm()) 和Html.BeginForm();、Html.EndForm();这两种用法有什么区别。

我们找到BeginForm返回的是一个MvcForm,而MvcForm的一定如下: public class MvcForm : IDisposable

可见使用using最后调用的是MvcForm的Dispose方法:

protected virtual void Dispose(bool disposing) {
if (!_disposed) {
_disposed = true;
_writer.Write("</form>");
// output client validation and restore the original form context
if (_viewContext != null) {
_viewContext.OutputClientValidation();
_viewContext.FormContext = _originalFormContext;
}
}
}

这里的_disposed默认是false,_writer是viewContext.Writer或则httpResponse.Output都表示当前的输出流。那么我们再来看看EndForm吧:

public static void EndForm(this HtmlHelper htmlHelper) {
htmlHelper.ViewContext.Writer.Write("</form>");
htmlHelper.ViewContext.OutputClientValidation();
}

可见EndForm和MvcForm的Dispose方法完全等价。

我们来看看你BeginForm是如何实现的,

public static MvcForm BeginForm(this HtmlHelper htmlHelper) {
// generates <form action="{current url}" method="post">...</form>
string formAction = htmlHelper.ViewContext.HttpContext.Request.RawUrl;
return FormHelper(htmlHelper, formAction, FormMethod.Post, new RouteValueDictionary());
}

public static MvcForm BeginForm(this HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method, IDictionary<string, object> htmlAttributes) {
string formAction = UrlHelper.GenerateUrl(null /* routeName */, actionName, controllerName, routeValues, htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, true /* includeImplicitMvcValues */);
return FormHelper(htmlHelper, formAction, method, htmlAttributes);
}

这里的FormHelper方法比较简单,里面有一句需要注意一下 bool traditionalJavascriptEnabled = htmlHelper.ViewContext.ClientValidationEnabled && !htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled;这里ClientValidationEnabled 和UnobtrusiveJavaScriptEnabled默认都是true,所以traditionalJavascriptEnabled 为false。

上面有个GenerateUrl方法,这个方法也很简单,关键代码就3句。

RouteValueDictionary mergedRouteValues = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, requestContext.RouteData.Values, routeValues, includeImplicitMvcValues);
VirtualPathData vpd = routeCollection.GetVirtualPathForArea(requestContext, routeName, mergedRouteValues);
string modifiedUrl = PathHelpers.GenerateClientUrl(requestContext.HttpContext,vpd.VirtualPath);

看看这里我们就用到了VirtualPathData的VirtualPath属性了。

在FormExtensions中有一个BeginRouteForm方法,该方法的使用方式和BeginForm方法差不多,就跳过了。现在我们来看看ClientValidationEnabled 和UnobtrusiveJavaScriptEnabled默认为什么是true?这2个属性都是调用ScopeCache实例的对应属性,而获取ScopeCache时通过ScopeCache的Get方法来完成的。该Get方法代码很简单:

我想大家现在该明白为什么这个ClientValidationEnabled 默认是true了吧。


读书人网 >ASP

热点推荐