13.2.2 编写HTML辅助方法
HTML辅助方法是用来在视图中生成HTML标记的方法。它们主要作为HtmlHelper、AjaxHelper或UrlHelper类的扩展方法来编写,具体作为哪一个类的扩展方法则根据想要生成的内容来定:是纯HTML,是支持Ajax的HTML还是URL。HTML和Ajax辅助方法可以访问ViewContext,因为它们只能从视图中调用,而URL辅助方法可以访问ControllerContext,因为它们既可以从控制器中调用,也可以从视图中调用。
扩展方法是静态类中的静态方法,它们通过其第一个参数上的this关键字来告知编译器它们提供的扩展类型。例如,如果想为HtmlHelper类提供一个没有参数的扩展方法,我们可能编写如下的代码:public static class MyExtensions {
public static string MyExtensionMethod(this HtmlHelper html) {
return "Hello, world!";
}
}
我们仍然可以使用传统的方式(即通过调用MyExtensions.MyExtensionMethod(Html))来调用该方法,但是使用扩展语法(即通过调用Html.MyExtensionMethod())可以更加方便地调用它。提供给该静态方法的任何其他参数也将变成扩展方法中的参数,而只有使用this关键字标记的扩展参数"消失"了。
ASP.NET MVC中的扩展方法都倾向于返回String类型的值,并使用类似于以下语句(Web Forms视图语法)的调用直接将返回的值放入输出流中:
但是,使用Web Forms旧版本语法存在一个问题:它很容易产生让人意想不到的HTML转义,从而产生错误。在20世纪90年代末21世纪初,ASP.NET刚刚开始它的"生命旅程",那时的Web世界与今天相比有很大的差别,那时的Web应用程序必须小心像跨站脚本攻击和跨站请求伪造攻击等常见的网络攻击。为了增加网络世界的安全系数,ASP.NET 4为Web Forms引入了自动编码HTML值的新语法,如下所示:
注意,这里用冒号取代了等号。这一改变对于数据安全来说意义重大,但是正如许多HTML辅助方法所做的,当我们真正需要返回HTML时会发生什么?ASP.NET 4也引入了一个任何类型都可以实现的新接口(IHtmlString)。当通过语法传递字符串时,系统能够识别出输入是已经保证安全的HTML,并直接输出而不进行编码处理。在ASP.NET MVC 2中,开发团队决定稍微打破向后的兼容性,使所有的HTML辅助方法都返回MvcHtmlString实例。
当编写生成HTML的HTML辅助方法时,我们几乎总是想返回IHtmlString而不是String,之所以这样,是因为我们不想让系统对返回的HTML进行编码。这对于Razor视图引擎是非常重要的,它只有一条输出语句,并且总是被编码:@Html.MyExtensionMethod()
为什么使用MvcHtmlString而不使用HtmlString?
ASP.NET 4除了引入IHtmlString接口以外还引入了HtmlString类,该类为用户提供了一个方便的方式来生成HTML字符串,而不需要实现IHtmlString接口。那么,为什么ASP.NET MVC 2还要创建MvcHtmlString类呢?
ASP.NET MVC 2的目标是能够在.NET 3.5 SP1和.NET 4平台上运行。为了实现这一目标,它不得不通过.NET 3.5 SP1编译,这就意味着ASP.NET MVC框架实际上没有HtmlString(和IHtmlString)类型。如果查看ASP.NET MVC的内部源代码,我们会发现MvcHtmlString并不是真正直接实现了IhtmlString接口。那么,.NET 4如何识别HTML字符串呢?
其实答案就在运行时代码生成部分。ASP.NET MVC框架在运行时环境中检测当前使用的.NET框架版本时采用了一项技术。当检测到.NET 4时,系统会自动创建一个派生于MvcHtmlString的新类,该类并且还实现了IHtmlString接口。这就是为什么通过调用MvcHtmlString.Create()来创建MvcHtmlString实例,而不是通过MvcHtmlString构造函数来创建的原因,这样就可以使ASP.NET MVC框架在合适的时刻返回一个新的自定义类型。
只要在.NET 4平台上开发,我们就可以使用内置的HtmlString类型;如果还需要在.NET 3.5 SP1上开发(因为HTML辅助方法需要支持ASP.NET MVC 2),那么我们还需要使用MvcHtmlString实例。
【责任编辑:book TEL:(010)68476606】
点赞 0