在视图页中@Html.xxx(...)是什么?如何被执行?
如下图所示:
视图页中@Html.xxx(...)涉及的内容有:
以@Html.TextBox(...)为例进行详细分析:
在ASP.NET MVC 中,视图页都被编译成继承自WebViewPage
public abstract class BuildManagerCompiledView : IView { public void Render(ViewContext viewContext, TextWriter writer) { if (viewCOntext== null) { throw new ArgumentNullException("viewContext"); } object instance = null; //获取被编译的视图页(cshtml文件)的类型 Type type = BuildManager.GetCompiledType(ViewPath); if (type != null) { //通过SingleServiceResolver利用反射和缓存的原理创建视图页的实例,过程类似SingleServiceResolver类对Controller的激活。 instance = ViewPageActivator.Create(_controllerContext, type); } if (instance == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.CshtmlView_ViewCouldNotBeCreated, ViewPath)); } //执行RenderView方法 RenderView(viewContext, writer, instance); } } public class RazorView : BuildManagerCompiledView { protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance) { if (writer == null) { throw new ArgumentNullException("writer"); } //将视图页实例转换为WebViewPage对象。 WebViewPage webViewPage = instance as WebViewPage; if (webViewPage == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, ViewPath)); } webViewPage.OverridenLayoutPath = LayoutPath;//母板路径(在第二步中,创建RazorView对象时,由构造函数导入) webViewPage.VirtualPath = ViewPath; //该视图路径 webViewPage.ViewCOntext= viewContext; //视图上下文,其中有TempData、controllerContext、ViewData等 webViewPage.ViewData = viewContext.ViewData; //WebViewPage对象初始化,执行创建3个xxHelper对象AjaxHelper、HtmlHelper、UrlHelper。 webViewPage.InitHelpers(); if (VirtualPathFactory != null) { webViewPage.VirtualPathFactory = VirtualPathFactory; } if (DisplayModeProvider != null) { webViewPage.DisplayModeProvider = DisplayModeProvider; } WebPageRenderingBase startPage = null; if (RunViewStartPages) { startPage = StartPageLookup(webViewPage, RazorViewEngine.ViewStartFileName, ViewStartFileExtensions); } //按层次结构处理视图页的内容。 webViewPage.ExecutePageHierarchy(new WebPageContext(context: viewContext.HttpContext, page: null, model: null), writer, startPage); } }
public abstract class WebViewPage : WebPageBase, IViewDataContainer, IViewStartPageChild { //省略其他代码... public AjaxHelper<object> Ajax { get; set; } public HtmlHelper<object> Html { get; set; } public UrlHelper Url { get; set; } public ViewContext ViewContext { get; set; } public virtual void InitHelpers() { this.Ajax = new AjaxHelper<object>(this.ViewContext, this); this.Html = new HtmlHelper<object>(this.ViewContext, this); this.Url = new UrlHelper(this.ViewContext.RequestContext); } }
“_Index.cshtml”经编译后的结果为:
如上图所示,“@Html.TextBox(‘txtUser’)” 经过编译后,就是去执行base.Html.TextBox("txtUser"),又由类继承关系可知,base.Html的值就是一个HtmlHelper对象(视图页对象转换为WebViewPage类型后,初始化时创建的)。而TextBox("txtUser"),则是HtmlHelper的扩展方法!
代码中,TextBox等扩展方法最终调用InputHelper方法,从而生成对应字符串类型的html标签(如:),并写入到Http响应内容中!
最终,将生成的html标签以字符串的形式写入到Http响应内容中!
以上只对HtmlHelper的扩展方法TextBox进行了介绍,其他的扩展方法童鞋们自行补脑了!上述如有不适之处,请指正!!!
扩展:
可以通过创建一个HtmlHelper的扩展方法,从而实现一个自定义控件!
在视图页中@Html.xxx(...)是什么?如何被执行?
如下图所示:
视图页中@Html.xxx(...)涉及的内容有:
以@Html.TextBox(...)为例进行详细分析:
在ASP.NET MVC 中,视图页都被编译成继承自WebViewPage
public abstract class BuildManagerCompiledView : IView { public void Render(ViewContext viewContext, TextWriter writer) { if (viewCOntext== null) { throw new ArgumentNullException("viewContext"); } object instance = null; //获取被编译的视图页(cshtml文件)的类型 Type type = BuildManager.GetCompiledType(ViewPath); if (type != null) { //通过SingleServiceResolver利用反射和缓存的原理创建视图页的实例,过程类似SingleServiceResolver类对Controller的激活。 instance = ViewPageActivator.Create(_controllerContext, type); } if (instance == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.CshtmlView_ViewCouldNotBeCreated, ViewPath)); } //执行RenderView方法 RenderView(viewContext, writer, instance); } } public class RazorView : BuildManagerCompiledView { protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance) { if (writer == null) { throw new ArgumentNullException("writer"); } //将视图页实例转换为WebViewPage对象。 WebViewPage webViewPage = instance as WebViewPage; if (webViewPage == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, ViewPath)); } webViewPage.OverridenLayoutPath = LayoutPath;//母板路径(在第二步中,创建RazorView对象时,由构造函数导入) webViewPage.VirtualPath = ViewPath; //该视图路径 webViewPage.ViewCOntext= viewContext; //视图上下文,其中有TempData、controllerContext、ViewData等 webViewPage.ViewData = viewContext.ViewData; //WebViewPage对象初始化,执行创建3个xxHelper对象AjaxHelper、HtmlHelper、UrlHelper。 webViewPage.InitHelpers(); if (VirtualPathFactory != null) { webViewPage.VirtualPathFactory = VirtualPathFactory; } if (DisplayModeProvider != null) { webViewPage.DisplayModeProvider = DisplayModeProvider; } WebPageRenderingBase startPage = null; if (RunViewStartPages) { startPage = StartPageLookup(webViewPage, RazorViewEngine.ViewStartFileName, ViewStartFileExtensions); } //按层次结构处理视图页的内容。 webViewPage.ExecutePageHierarchy(new WebPageContext(context: viewContext.HttpContext, page: null, model: null), writer, startPage); } }
public abstract class WebViewPage : WebPageBase, IViewDataContainer, IViewStartPageChild { //省略其他代码... public AjaxHelper<object> Ajax { get; set; } public HtmlHelper<object> Html { get; set; } public UrlHelper Url { get; set; } public ViewContext ViewContext { get; set; } public virtual void InitHelpers() { this.Ajax = new AjaxHelper<object>(this.ViewContext, this); this.Html = new HtmlHelper<object>(this.ViewContext, this); this.Url = new UrlHelper(this.ViewContext.RequestContext); } }
“_Index.cshtml”经编译后的结果为:
如上图所示,“@Html.TextBox(‘txtUser’)” 经过编译后,就是去执行base.Html.TextBox("txtUser"),又由类继承关系可知,base.Html的值就是一个HtmlHelper对象(视图页对象转换为WebViewPage类型后,初始化时创建的)。而TextBox("txtUser"),则是HtmlHelper的扩展方法!
代码中,TextBox等扩展方法最终调用InputHelper方法,从而生成对应字符串类型的html标签(如:),并写入到Http响应内容中!
最终,将生成的html标签以字符串的形式写入到Http响应内容中!
以上只对HtmlHelper的扩展方法TextBox进行了介绍,其他的扩展方法童鞋们自行补脑了!上述如有不适之处,请指正!!!
扩展:
可以通过创建一个HtmlHelper的扩展方法,从而实现一个自定义控件!