ASP.NET MVC技术分享,最新应用实例!为您介绍ASP.NET MVC各版本使用,模板使用,路由配置,常见web应用及错误处理!
Microsoft ASP.NET MVC官方网站:http://www.asp.net/mvc
Pages: 1/9 First page 1 2 3 4 5 6 7 8 9 Next page Final page [ View by Articles | List ]
Feb 8
隐式代码表达式

就是一个标识符,之后可以跟任意数量的方法调用("()")、索引表达式("[]")及成员访问表达式(".")。但是,除了在"()"或者"[]"里面,是不允许空格存在的。

例如,下面是一些合法的Razor隐式表达式:

下面是一些非法的表达式,这些表达式只有部分("==>"之后的部分)会被Razor认为是表达式。

这是我们为什么需要另一个表达式语法:"@(...)"的原因,通过这个语法我们可以把任何想要的东西放到"()"里面,上面的例子用这个语法来表示就是:

而这种表示方法就是 显示代码表达式。
Feb 8
Feb 8
本文目的
我们来看一个小例子,在一个ASP.NET MVC项目中创建一个控制器Home,只有一个Index:


创建对应的强类型视图


运行一下,如果你的RP不是非常不好的情况下,会出现下面的结果:

Highslide JS

生成的是一个Email的链接。看一下email部分对应的html源文件:


对于不求甚解的人来说,这很正常啊,正常的就像1+1=2一样。但对于勤学好问的同学来说,问题来了。

为什么生成的是一个email链接,不是一个纯文本?

因为我用DataType指明了它是email!

那DataType是如何指导Model生成html的?

如果你对这些问题感兴趣,请你看下去。



Model的兄弟--ModelMetadata
      在介绍Model如何能在View中正常显示之前,不得不提一下他的兄弟ModelMetadata这个类。ModelMetadata实现对Model的一些特征进行描述(如Model的类型、Model的值,Model要显示的模板 ),并且实现了对Model的所有属性值进行描述(递归结构)。有了这个兄弟,Model才能知道如何在View中正常显示【注意:这里特指的是用HtmlHelper的系列扩展方法(如Display/DiaplayFor/EditorFor等)方法在View中显示。如果你是在View中直接取Model的值用html显示,你可以暂不用关心ModelMetadata。但!!不要觉得这样你就不用了解ModelMetadata了,因为MVC中还有一个核心与它息息相关---Model绑定与验证,所以我建议你还是先认识一下这位好兄弟】,让我们来看看这个兄弟长什么样:


      然而在MVC中默认使用的却不是这个类,而是它的子类CachedDataAnnotationsModelMetadata(其实中间还隔着一个CachedModelMetadata类,因为该类只是做了简单的封装,为了方便读者理解,在此省略)。CachedDataAnnotationsModelMetadata做的最主要的一件事情就是通过一系列的Compute函数得到Model上注解特性的值,并把这些值赋值到对应的属性。如下:


      注意代码中两个红色的部分,把Model的注解特性存在PrototypeCache里面,这样就可以通过反射得到注解特性的值了。比如文章开始处的DemoModel的属性Email对应的CachedDataAnnotationsModelMetadata对象中 DataTypeName最终被赋值为“EmailAddress”,等介绍完下一位重量级人物后,会详解具体调用过程。

ModelMetadata的创建者ModelMetadataProvider
我们还要来认识一位重量级的人物:ModelMetadata的创建者:


      它是一个纯抽象类。该类的第一级子类非常重要,看一下代码:


      注意红色的部分,正是因为有这样一个处理,用户就可以通过自已自定义扩展实现IMetadataAware接口,对ModelMetadata进行再加工处理。



      根据上面ModelMetadata讲解,我们知道,MVC中默认使用的是CachedDataAnnotationsModelMetadata这个类,于是对应ModelMetadataProvider的最终子类CachedDataAnnotationsModelMetadataProvider。

      当外部想通过GetMetadataForType来得到ModelMetadata时,内部会调用CreateMetadata,再根据原型模式调用CreateMetadataPrototype或CraeteMetadataFromPrototype实现最终创建过程:


       同MVC的路由表RouteTable一样,ModelMetadataProvider也有一个静态的ModelMetadataProviders变量Current来提供默认的ModelMetadataProvider。简化代码如下:


终极解密
知道了这两位重量级的大员后,现在我们回到文章开始的代码:

Html.DisplayFor(model => model.Email)
当View中执行这句时,执行HtmlHelper的扩展函数,正式进入漫长的生成MvcString旅程:
Highslide JS
http://www.cnblogs.com/DotCpp/

     【注意,这个图中代码是经过N重简化而来,实际调用流程复杂无比(全是在TemplateHelpers中跳转),函数参数多如牛毛,实在不忍让大家看的痛苦】

      红色线是程序执行的主流程,后来的执行主场景都是在TemplateHelpers里面完成。

      从黄色线可以看出ModelMetadata是通过调用ModelMetadata本身的静态函数FromLambdExpression--->GetMetadataFromProvider,最终由ModelMetadataProviders完成创建。

     再来看看桔黄色部分。MVC中有一个DefaultDisplayTemplates的类,存储了诸如Boolean/String/Html/Email等等数据类型的模板,MVC最终根据ViewData中的ModelMetadata.DataType的值找到对应的模板,最终完成HTML字符串的输出,作为WebViewPage.ExecutePageHierarchy的一部分(WebViewPage请参看:仅此一文让你明白ASP.NET MVC 之View的显示(仅此一文系列二))。



结语
      本文只是用了ModelMetadata的一个DataType属性做为例子,让你了解在Model中添加注解特性是如何被ModelMetadata使用的。还有其它很多Model注解特性(如ReadOnlyAttribute/RequiredAttribute/UIHintAttribute等等)都和该原理类似。

      其实ModelMetadata在view显示中的作用是有限的,因为很多开发人员都不喜欢用这种前台显示方式,尤其随着json的大量使用,与JQUERY等前台的完美结合。但它有属于它的舞台----Model绑定与验证,敬请期待!

     希望新手看的明白,老手多提意见。如果你觉得对你有帮助,请让更多人知道它:)
Oct 8
[codes=c#]
MVC中HtmlHelper用法大全参考

解析MVC中HtmlHelper控件7个大类中各个控件的主要使用方法(1)
2012-02-27 16:25
HtmlHelper类在命令System.Web.Mvc.Html之中,主要由7个静态类组成,它们分别是FormExtensions类,InputExtensions类,LinkExtensions类,SelectExtensions类,TextExtensions类,ValidationExtensions类,RenderPartialExtensions类。
为了方便开发者使用HtmlHelper控件,在视图ViewPage类中设置了一个属性Html它就是HtmlHelper类型。
1.FormExtensions类
定义了3中类型的扩展方法BeginForm,BeginRouteForm,EndForm。
(1) BeginForm (实现表单定义的开始部分)
重载方法有13个:
BeginForm();
BeginForm(Object routeValues);
BeginForm(RouteValueDictionary routeValues);
BeginForm(string actionName,string controllerName);
BeginForm(string actionName,string controllerName,object routeValues);
BeginForm(string actionName,string controllerName,RouteValueDictionary routeValues);
BeginForm(string actionName,string controllerName,FormMethod method);
BeginForm(string actionName,string controllerName,object routeValues,FormMethod method);
BeginForm(string actionName,string controllerName,RouteValueDictionary routeVaues,FormMethod method);
BeginForm(string actionName,string controllerName,FormMethod method,object htmlAttributes);
BeginForm(string actionName,string controllerName,FormMethod method,IDictionary htmlAttributes);
BeginForm(string actionName,string controllerName,object routeValues,FormMethod method,object htmlAttributes);
BeginForm(string actionName,string controllerName,RouteValueDictionary routeValues,FormMethod method,IDictionary htmlAttributes);
对于第二个重载方法可以设置如下:
Html.BeginForm(new{action="action",controller="actroller",id="2"});
在上述代码中,设置了路由值的一个实例化对象,输出的HTML语句是:

对于最后一个第十三个方法的最后一个参数是实例化对象设置相关属性的值例如class,width等。
(2)BeginRouteForm (主要实现表单定义的开始部分,以路由的方法设置action的值)
有12个重载方法:
BeginRouteForm(object routeValues);
BeginRouteForm(RouteValueDictionary routeValues);
BeginRouteForm(string routeName);
BeginRouteForm(string routeName,object routeValues);
BeginRouteForm(string routeName,RouteValueDictionary routeValues);
BeginRouteForm(string routeName,FormMethod method);
BeginRouteForm(string routeName,object routeValues,FormMethod method);
……
对于第一个重载方法:
Html.BeginRouteForm(new {action="action"});
Home是页面所在的目录
BeginForm与BeginRouteForm的区别就在于第一个的action是action第二个的action是Home/action
(3)EndForm(实现表单的定义的结束部分)
Html.EndForm();
相当于


InputExtensions类有5种类型的扩展方法,可在视图中设置checkBox,hidden,password,radioButton,textBox控件。
(1)CheckBox 实现复选框控件有6个重载方法
CheckBox(string name);
CheckBox(string name,bool isChecked);
CheckBox(string name,bool isChecked,object htmlAttributes);
CheckBox(string name,object htmlAttributes);
CheckBox(string name,Idictionary htmlAttributes);
CheckBox(string name,bool isChecked,Idictionary htmlAttributes);
设置复选框的实现代码:
<%=Html.BeginForm("CheckBox","Home") %>

设置字体:
<%=Html.CheckBox("MyCheckBox1",true,new{id="checkBox1"})%>

<%=Html.CheckBox("MyCheckBox2",false,new{id="checkBox2"})%>






<%Html.EndForm();%>
运行上述代码,上述复选框的设置代码对应的HTML语句:




在后台检索checkBox
public ActionResult CheckBox (FormCollection formCollection)
{
bool MyCheckBox1=formCollection[0].Contains("true");//检索第一个复选框是否被选中
bool MyCheckBox2=formCollection["MyCheckBox2"].Contains("true");//检索名字是MyCheckBox2的复选框是否倍选中
ViewData["CheckBox1"]=MyCheckBox1;
ViewData["CheckBox2"]=MyCheckBox2;
return View();
}
(2)Hidden 表单中的隐藏数值,有4个重载方法。
Hidden(string name);
Hidden(string name,object value);
Hidden(string name,object value,object htmlAttributes);
Hidden(string name,object value,Idictionary htmlAttributes);
eg:
Html.Hidden("testName");对应输出的Html语句如下:

(3)Password 主要是输入密码的文本框,有4个重载方法。
Hidden(string name);
Password (string name,object value);
Password (string name,object value,object htmlAttributes);
Password (string name,object value,Idictionary htmlAttributes);
eg:
Html.Password ("MyPwd");对应输出的Html语句如下:

--------------------------------------------------------------------------------------------


HTML扩展类的所有方法都有2个参数:
以textbox为例子
public static string TextBox( this HtmlHelper htmlHelper, string name, Object value, IDictionary htmlAttributes )
public static string TextBox( this HtmlHelper htmlHelper, string name, Object value, Object htmlAttributes )
这2个参数代表这个html标签的属性集合。使用方法如下。

1.ActionLink
<%=Html.ActionLink("这是一个连接", "Index", "Home")%>
带有QueryString的写法
<%=Html.ActionLink("这是一个连接", "Index", "Home", new { page=1 },null)%>
<%=Html.ActionLink("这是一个连接", "Index", new { page=1 })%>
有其它Html属性的写法
<%=Html.ActionLink("这是一个连接", "Index", "Home", new { id="link1" })%>
<%=Html.ActionLink("这是一个连接", "Index",null, new { id="link1" })%>
QueryString与Html属性同时存在
<%=Html.ActionLink("这是一个连接", "Index", "Home", new { page = 1 }, new { id = "link1" })%>
<%=Html.ActionLink("这是一个连接", "Index" , new { page = 1 }, new { id = "link1" })%>

生成结果为:
这是一个连接
带有QueryString的写法
这是一个连接
这是一个连接
有其它Html属性的写法
这是一个连接
这是一个连接
QueryString与Html属性同时存在
这是一个连接
这是一个连接

2.RouteLink
跟ActionLink在功能上一样。
<%=Html.RouteLink("关于", "about", new { })%>
带QueryString
<%=Html.RouteLink("关于", "about", new { page = 1 })%>
<%=Html.RouteLink("关于", "about", new { page = 1 }, new { id = "link1" })%>

生成结果:
关于
关于
关于
3.Form 2种方法
<%using(Html.BeginForm("index","home",FormMethod.Post)){%>
<%} %>

<%Html.BeginForm("index", "home", FormMethod.Post);//注意这里没有=输出%>
<%Html.EndForm(); %>

生成结果:

4.TextBox , Hidden ,
<%=Html.TextBox("input1") %>
<%=Html.TextBox("input2",Model.CategoryName,new{ @style = "width:300px;" }) %>
<%=Html.TextBox("input3", ViewData["Name"],new{ @style = "width:300px;" }) %>
<%=Html.TextBoxFor(a => a.CategoryName, new { @style = "width:300px;" })%>

生成结果:






5.TextArea
<%=Html.TextArea("input5", Model.CategoryName, 3, 9,null)%>
<%=Html.TextAreaFor(a => a.CategoryName, 3, 3, null)%>

生成结果:
Oct 8
MVC三个组成部分:Model 、View、Controller。今天主要想和大家分享的是View这一块。微软的MVC摒弃了之前的aspx页面的拖拖控件就能搞定的理念,因为发现那样会把程序员惯成傻子,而做出来的网站毫无性能可言,慢的像猪头!所以在展示页面View这一部分的操作几乎就是纯手工写html代码了。这对于程序员来说也挺苦恼的,因为从轻松拖控件直接升级为纯手工写代码(当然,可能难度不大,但是其中的麻烦是不可言喻的)。幸好微软推出了HtmlHelper,方便了我们写html代码,大大提高了效率。

  何为HtmlHelper?HtmlHelper也好SQLHelper也好,说白了就是把很多代码封装起来,然后供我们调用,用于节省开发时间,降低错误率。好了闲言少叙,开始正题;如果我们用MVC做一个简单的文章回复功能,View层中写一个TextBox一个TextArea一个Submit按钮,TextBox写标题TextArea写内容然后一点Submit就可以搞定了,这样看起来没什么问题。但是想一想如果在提交回复时出现了错误,没提交成功。按道理说在TextBox和TextArea中应该还保存刚才我们写的内容的,但是可惜View层中已经没有了ViewState。于是乎悲催的事情发生了,我们写了半天的评论,一点按钮,一个小错误没成功,回来后啥都没了,傻眼了!这样该怎么办呢?好办啊!在Controller里面给控件赋值不就可以了吗?想法很好,但可惜MVC模式中Controller操作View中的控件是犯法的!这怎么办?于是乎htmlhelper应运而生! 在View中将手写的TextBox和TextArea删掉,然后用HtmlHelper,具体代码如下:标题: <%:Html.TextBox("txtTitle","txtTitle") %>评论内容: <%:Html.TextArea("txtContent") %>这两个尖括号里里面的东西就是HtmlHelper了。以第一个为例:先写尖括号百分号然后是冒号,但是我们知道啊在WebForm时代,我们也这样在html里面加C#代码但是百分号后面往往是等号,那冒号和百分号的区别是什么呢?诸位可以试一下,冒号包裹的内容如果含有尖括号等的html标签,会识别出来。而等号不识别而是直接把内容显示出来。Html.TextBox里面的参数,第一个是该TextBox的Name属性,第二个是Value属性,当然还可以设置它的样式了 <%:Html.TextBox("txtTitle", "txtTitle", new { disable="none",....})%>大括号里面写属性,多个时用逗号隔开。在Controller里面可以通过ViewData["txtTitle"]进行取值和赋值。这样子一个HtmlHelper基本上就出炉了。

  当然有很多公司都有自己的HtmlHelper,然后今天就研究了一下,应该怎样写出自己的HtmlHelper,然后查看代码发现了所谓的每一个控件的HtmlHelper其实就是分别写一个类然后对HtmlHelper进行扩展,然后便写了一个扩展的类实现了一个特殊的Span标签的展示。具体方法如下:新建一个类,命名为SpanExtensions这个类是一个静态类,Public Static Class SpanExtensions  里面写一个方法,GetSpan方法,当然这也是一个静态方法,同时实现对HtmlHelper的扩展,还需要传入一个里面显示内容的参数具体代码如下:

public static string GetLabel(this HtmlHelper helper, string txt)  

  {            

            return string.Format("{0}", txt);

}

  这样在前面的View里面用Htmlhelper调用的时候发现没有,怪了,明明写了的,后来发现原来是SpanExtensions类的命名空间和View不一样,我想引用然后发现如果以后用这个方法的地方很多就太麻烦了,然后就直接把SpanExtensions的命名空间改为View的命名空间,然后就找到了,写完后一运行!发现:亲娘来,连html标签都出来了,难不成还得转?后来看了看HtmlHelper里面的TextBox发现返回值不一样,它的返回值是一个MvcHtmlString类型,啥东西啊?没见过!于是我就想把MvcHtmlString这个东西和String能够联系起来,后来整出来了,代码如下:  MvcHtmlString mc = MvcHtmlString.Create(string.Format("{0}", txt)); 这样直接返回mc就可以搞定了!
Oct 8


在 controller 中可以使用 ControllerContext 取得:



在 view 中可以使用 ViewContext:
Apr 21
HttpContext
HttpContext是最原始的ASP.NET Context. MVC的目的之一是能够单元测试。HttpContext没有base class,并且不是virtual,所以不能用单元测试,因为没有办法mock.

HttpContextBase
HttpContextBase, 是用来在MVC中替代HttpContext.但是这是一个abstract类,是mockable的。

HttpContextWrapper
HttpContextWrapper是HttpContextBase的实现类,用来真正的替换HttpContext,可以用new HttpContextWrapper(HttpContext.Current)的方式来创建一个ttpContextWrapper.观察代码可以发现,HttpContext与HttpContextWrapper在属性方法设置上基本上是一样的,只是HttpContextWrapper不是virtual,有base class,因此可以进行单元测试。现在,关于使用到HttpContext的方法,可以通过HttpContextWrapper来进行单元测试。观察ASP.NET MVC的源码可以发现,在最终MVCHandler(ASP.NET MVC的HttpHandler)中,调用ProcessRequest(HttpContext context)方法的时候,其内部把HttpContext转为HttpContextWrapper,然后调用了ProcessRequest(HttpContext context)来进行后续的处理。
[csharp] view plaincopy
public ProcessRequest(HttpContext context)  
{  
    HttpContextWrapper _context = new HttpContextWrapper(context);  
    ProcessRequest(_context);  
}  
  
  
public ProcessRequest(HttpContextBase context)  
{  
    //进行相应的Controller,Action的调用  
}  
Jun 25
ASP.NET MVC5 网站开发实践系列,来自博客园“洞庭夕照”http://www.cnblogs.com/mzwhj/p/3537145.html
Pages: 1/9 First page 1 2 3 4 5 6 7 8 9 Next page Final page [ View by Articles | List ]