这样写报错

<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();}对比的更多相关文章

  1. 爱上MVC3系列~Html.BeginForm与Ajax.BeginForm

    Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...

  2. Html.BeginForm())与Ajax.BeginForm()

     一.@using (Html.BeginForm())参数示例 1.指定表单提交方式和路径等 @using (Html.BeginForm("Index", "Home ...

  3. 转:MVC3系列:~Html.BeginForm与Ajax.BeginForm

    Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...

  4. MVC3系列~Html.BeginForm与Ajax.BeginForm

    Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...

  5. MVC小系列(十一)【Html.BeginForm与Ajax.BeginForm】

    Html.BeginForm与Ajax.BeginForm都是mvc的表单元素,前者是普通的表单提交,而后者是支持异步的表单提交,直接用mvc自带的Ajax.BeginForm就可以很容易完成一个异步 ...

  6. Html.BeginForm() vs Ajax.BeginForm() in MVC3

    我们知道,BeginForm()方法能创建一个Form标签,因此可以结合表单级的方法,在这个页面中.我一直在考虑Html.BeginForm()方法和Ajax.BeginForm()方法在MVC3中有 ...

  7. MVC Html.BeginForm 与 Ajax.BeginForm 使用总结

    最近采用一边工作一边学习的方式使用MVC5+EF6做一个Demo项目, 期间遇到不少问题, 一直处于研究状态, 没能来得及记录. 今天项目进度告一段落, 得以有空记录学习中遇到的一些问题. 由于MVC ...

  8. Ajax.BeginForm VS Html.BeginForm

    有的人说,AJAX一听,高大上,HTML一听,死老土,所以AJAX更好.其实这是错误的.每种方法有它不同的用途.现在做如下总结: @using (Ajax.BeginForm("Login& ...

  9. form表单和ajax表单提交(Html.BeginForm()、Ajax.BeginForm())的差别

    有如下几种区别: 1. Ajax在提交.请求.接收时,都是异步进行的,网页不需要刷新: Form提交则是新建一个页面,哪怕是提交给自己本身的页面,也是需要刷新的: 2. A在提交时,是在后台新建一个请 ...

随机推荐

  1. python之使用API(WEB应用编程接口)

    1.处理API响应 import requests #执行API调用并存储响应 url = "https://api.github.com/search/repositories?q=lan ...

  2. .NET基础 (15)委托

    委托1 请解释委托的基本原理2 委托回调静态方法和实例方法有何区别3 什么是链式委托4 链式委托的执行顺序是怎么样的5 可否定义拥有返回值的方法的委托链6 委托通常可以应用在哪些场合 委托1 请解释委 ...

  3. android虚拟机的垃圾收集

    Dalvik :http://zh.wikipedia.org/wiki/Dalvik%E8%99%9A%E6%8B%9F%E6%9C%BA ART :http://source.android.co ...

  4. MFC中的DLL、LIb文件的创建、使用

     动态链接库Dynamic-Linked Lib 的创建与使用 动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),是微软公司在微软 ...

  5. 【树状DP】星象仪

    题目描述 在寂寞的夜里,星象仪是非常浪漫的东西.但是,你作为一个精神稍微有点不太正常的Geek,把原本正常的星象仪改造得像电报发送器一样.当然,你这个的构造还要更加奇葩一点.具体来说,你的星象仪是一棵 ...

  6. 20145233计算机病毒实践九之IDA的使用

    20145233计算机病毒实践之IDA的使用 PSLIST导出函数做了什么 这个函数是一个export函数,所以在view中选择export 查到后,双击打开这个函数的位置 仔细看这个函数可以发现这个 ...

  7. 分布式流式计算平台——S4

    本文是作者在充分阅读和理解Yahoo!最新发布的技术论文<S4:Distributed Stream Computing Platform>的基础上,所做出的知识分享. S4是Yahoo! ...

  8. solr介绍一:Analyzer(分析器)、Tokenizer(分词器)

    首先,不知道大家在前面的例子中没有试着搜索文本串,就是在第二节,我们添加了很多文档.如果字段值是一个文本.你如果只搜索这个字段的某个单词,是不是发现搜不到? 这就是因为我们没有配置Analyzer,因 ...

  9. 对java位运算之异或运算的一点记录

    首先,异或运算是,每个位上的数不同为1,相同为0. 其次,对两个数值变量的值进行三次异或运算就等于是交换了两个变量的值. 例如: int a = 4; int b = 10; a = a ^ b; b ...

  10. WP8.1StoreApp(WP8.1RT)---MessageBox与MessageDialog

    在WP7和WP8中,MessageBox是跟WinForm中一样常用的对话框,但是有一个显著的缺点,就是WP7/8中默认的MessageBox是阻塞线程的.也许是由于这个原因,WP8.1/Win8中采 ...