@using (Html.BeginForm())和@{Html.BeginForm();}@{Html.EndForm();}对比
这样写报错
<body>
@using (Html.BeginForm())
{
form主体1
}
@{Html.BeginForm();}
form主体2
@{Html.EndForm();}
</body>
这样写正确
<body>
@using (Html.BeginForm())
{
<div>form主体1</div>
}
@{Html.BeginForm();}
form主体2
@{Html.EndForm();}
</body>
原因后续补上.
使用@:和text标签
在代码块中,要么是C#代码,要么是HTML标签,不能直接写纯文字,纯文字须包裹在HTML标签内。但如果需要在代码块中直接输出纯文字而不带HTML标签,则可以使用@:标签,在代码块中输出纯文本文字非常有用。如下代码所示:
@if (Model.Price > 5M)
{
@Model.Name@:太贵了 。
<br />
@: @@:后面可以是一行除@字符以外的任意文本,包括<、>和空格,怎么写的就怎么输出。
<br />
@: 如果要输出@符号,当@符号前后都有非敏感字符(如<、{、和空格等)时,可以直接使用@符号,否则需要使用两个@符号。
}
注意@符号的使用。上面代码运行效果如下:
使用@:标签在代码块中输出一行不带html标签的文本非常方便,但如果需要在代码块中输出续或不连续的多行纯文本,则使用text标签较为方便,如下代码所示:
@if (Model.Price > 5M)
{
<text>
名称:<b>@Model.Name</b><br />
分类:<b>@Model.Description</b><br />
价钱:<b>@Model.Price</b><br />
<pre>
测试行一: <a>aaaa</a>
测试行二: @@ fda@aaa
</pre>
</text>
}
运行结果:
参考内容:
运行结果就是生成form表单
一般我们的表单提交都涉及到强类型,所以一般需要@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方法代码很简单:
[csharp] view plaincopyprint?public static ScopeCache Get(IDictionary<object, object> scope, HttpContextBase httpContext) {
if (httpContext == null && System.Web.HttpContext.Current != null) {
httpContext = new HttpContextWrapper(System.Web.HttpContext.Current);
}
ScopeCache result = null;
scope = scope ?? ScopeStorage.CurrentScope;
if (httpContext != null) {
result = httpContext.Items[_cacheKey] as ScopeCache;
}
if (result == null || result._scope != scope) {
result = new ScopeCache(scope);
if (httpContext != null) {
httpContext.Items[_cacheKey] = result;
}
}
return result;
}
}
public static ScopeCache Get(IDictionary<object, object> scope, HttpContextBase httpContext) {
if (httpContext == null && System.Web.HttpContext.Current != null) {
httpContext = new HttpContextWrapper(System.Web.HttpContext.Current);
}
ScopeCache result = null;
scope = scope ?? ScopeStorage.CurrentScope;
if (httpContext != null) {
result = httpContext.Items[_cacheKey] as ScopeCache;
}
if (result == null || result._scope != scope) {
result = new ScopeCache(scope);
if (httpContext != null) {
httpContext.Items[_cacheKey] = result;
}
}
return result;
}
}
而ScopeStorage的CurrentScope属性是又是怎么来的了?
public static IScopeStorageProvider CurrentProvider {
get { return _stateStorageProvider ?? _defaultStorageProvider; }
set { _stateStorageProvider = value; }
}
public static IDictionary<object, object> CurrentScope {
get {
return CurrentProvider.CurrentScope;
}
}
默认来自于StaticScopeStorageProvider的CurrentScope,该属性默认返回的是一个没有成员的IDictionary<object, object>实例。那么这里的CurrentProvider 默认是个说明东西了,在System.Web.WebPages项目中的PreApplicationStartCode有这么一句 ScopeStorage.CurrentProvider = new AspNetRequestScopeStorageProvider(); 在AspNetRequestScopeStorageProvider的够着函数有这么一句ApplicationScope = new ApplicationScopeStorageDictionary(); 在ApplicationScopeStorageDictionary的构造函数中有 public ApplicationScopeStorageDictionary() : this(new WebConfigScopeDictionary()) { },WebConfigScopeDictionary的够着函数又有 public WebConfigScopeDictionary() :this(WebConfigurationManager.AppSettings) { }这么一句,
不知道大家是否还记得在ControllerBase的Execute方法中有这么一句 using (ScopeStorage.CreateTransientScope()) { ExecuteCore(); }
public static IDisposable CreateTransientScope() {
return CreateTransientScope(new ScopeStorageDictionary(baseScope: CurrentScope));
}
public static IDisposable CreateTransientScope(IDictionary<object, object> context) {
var currentContext = CurrentScope;
CurrentProvider.CurrentScope = context;
return new DisposableAction(() => CurrentProvider.CurrentScope = currentContext); // Return an IDisposable that pops the item back off
}
现在我们知道了IScopeStorageProvider 的CurrentProvider是什么东西了,是一个AspNetRequestScopeStorageProvider里面的数据实现从WebConfigurationManager.AppSettings这里取出来的。
我想大家现在该明白为什么这个ClientValidationEnabled 默认是true了吧。
@using (Html.BeginForm())和@{Html.BeginForm();}@{Html.EndForm();}对比的更多相关文章
- 爱上MVC3系列~Html.BeginForm与Ajax.BeginForm
Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...
- Html.BeginForm())与Ajax.BeginForm()
一.@using (Html.BeginForm())参数示例 1.指定表单提交方式和路径等 @using (Html.BeginForm("Index", "Home ...
- 转:MVC3系列:~Html.BeginForm与Ajax.BeginForm
Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...
- MVC3系列~Html.BeginForm与Ajax.BeginForm
Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...
- MVC小系列(十一)【Html.BeginForm与Ajax.BeginForm】
Html.BeginForm与Ajax.BeginForm都是mvc的表单元素,前者是普通的表单提交,而后者是支持异步的表单提交,直接用mvc自带的Ajax.BeginForm就可以很容易完成一个异步 ...
- Html.BeginForm() vs Ajax.BeginForm() in MVC3
我们知道,BeginForm()方法能创建一个Form标签,因此可以结合表单级的方法,在这个页面中.我一直在考虑Html.BeginForm()方法和Ajax.BeginForm()方法在MVC3中有 ...
- MVC Html.BeginForm 与 Ajax.BeginForm 使用总结
最近采用一边工作一边学习的方式使用MVC5+EF6做一个Demo项目, 期间遇到不少问题, 一直处于研究状态, 没能来得及记录. 今天项目进度告一段落, 得以有空记录学习中遇到的一些问题. 由于MVC ...
- Ajax.BeginForm VS Html.BeginForm
有的人说,AJAX一听,高大上,HTML一听,死老土,所以AJAX更好.其实这是错误的.每种方法有它不同的用途.现在做如下总结: @using (Ajax.BeginForm("Login& ...
- form表单和ajax表单提交(Html.BeginForm()、Ajax.BeginForm())的差别
有如下几种区别: 1. Ajax在提交.请求.接收时,都是异步进行的,网页不需要刷新: Form提交则是新建一个页面,哪怕是提交给自己本身的页面,也是需要刷新的: 2. A在提交时,是在后台新建一个请 ...
随机推荐
- Andriod 之数据获取
服务端Model using System; using System.Collections.Generic; using System.Linq; using System.Web; namesp ...
- 图形查询属性(IdentifyTask实现查询)//查询本地服务
主页代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...
- VR眼镜和AR眼镜的区别
VR眼镜是纯虚拟的世界建模,不结合现实世界.(VR一体机和手机VR眼镜是不同的,不只是是不是以手机为载体播放器的问题,而是它们结构上也有很大的区别:另外还有一点就是电脑端VR,这个主要是游戏:http ...
- kinect相机做扫描仪扫描人体模型
- python ghost.py使用笔记
ghost.py目前已更新到0.2版本,变化有点大,使用方法上跟0.1还是有点差别的,本文仅以0.1.1版本为例,因为我安装的是这个版本 我用ghost主要用来模拟在网站上的操作,比如登录之类的,当然 ...
- DI延伸
延迟初始化Bean 延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean. 配置方式很简单只需在<bean>标签上指定 “lazy-init” 属 ...
- Android-bindService本地服务-初步-Service返回对象
在Android开发过程中,Android API 已经有了startService方式,为什么还需要bindService呢? 答:是因为bindService可以实现Activity-->S ...
- long polling
Regular http: client 发出请求到server server 计算 response server 响应 response 给 client Polling: A client re ...
- java写入换行符
写入一个文件,生成文本文档,里面写入1000行字符,但是写出来的没有换行.所以纠结,百度了下,一行完事. String crlf=System.getProperty("line.separ ...
- IDEA配置spring
大半天都在看spring,以前总是看不下去,这次慢慢来,慢慢看. 看那些基础的,倒是还不错.好多都是关于helloworld的,写完helloworld,觉得不怎么形象.于是写了动物,作为接口. (1 ...