ITPub博客

首页 > Linux操作系统 > Linux操作系统 > ASP.NET MVC Unleashed (4)

ASP.NET MVC Unleashed (4)

原创 Linux操作系统 作者:geez 时间:2009-03-09 15:09:31 0 删除 编辑
Chapter 4 - Understanding Views
The set of views in an ASP.NET MVC application is the public face of the application. ASP.NET MVC views are responsible for rendering the HTML pages that people see when they visit your website.
In this chapter, you learn how to create and work with views. You learn how to pass information from a controller to a view. You also learn how to create both typed and untyped views. Finally, you learn strategies for testing your views.
Creating a View
The easiest way to create a new view is to create the view from an existing controller action. You can right-click any controller action within the Visual Studio Code Editor window and select the menu option Add View to create a new view automatically (see Figure 1).
第4章 – 深入理解视图
一个ASP.NET MVC应用程序视图的集合,是这个应用程序的外观。当人们访问您的站点时,由ASP.NET MVC视图绘制返回的HTML页面。
本章中,您将学习如何创建以及使用视图,学习如何从控制器传递信息给视图,以及如何创建强类型和无类型视图。最后,学习视图的测试策略。
创建视图
创建一个视图最简单的方法是通过现有的控制器行为来创建,在Visual Studio的代码编辑窗口中用鼠标右键单击任意的控制器行为,在弹出的上下文菜单中选择Add View菜单项,自动创建一个新的视图(见图1)

Figure 1 – Adding a new view from a controller action

clip_image002

 When you select the Add View menu option, the Add View dialog opens (see Figure 2). This dialog enables you to set various view options. For example, you can specify whether a view uses a view master page.
*** Begin Note ***
We discuss master pages in detail in Chapter 10, Understanding View Master Pages and View User Controls.
*** End Note ***
For example, if you open a controller named Customer controller and right-click the Index() action to add a view, and you leave the default options selected in the Add View dialog, then you’ll get the view in Listing 1.
当您选择Add View菜单项时,将弹出一个Add View对话框(见图2),您可以在该对话框中设定一些视图可选项。例如,您可以指定该视图是否使用Master页。
【注释】我们在第10章中详细讨论Master页面,深入理解视图Master页面及视图用户控件。

Figure 2 – Using the Add View dialog

clip_image004

例如,如果您打开Customer控制器并鼠标右键单击Index()行为来添加对应视图,并接受弹出的Add View对话框中的默认选项,那么你将得到Listing 1所示的视图
Listing 1 – Views\Customer\Index.aspx
1. <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>  
2.  
3.  
4.    Index  
5.  
6.  
7.  
8.  
9.    

Index

 
10.  
11.  

The file in Listing 1 looks almost like a standard HTML document. This view contains two tags. Any content that you place within the first tag appears in the tag of the resulting HTML document. Any content that you place within the second tag appears in the tag of the resulting HTML document.
For example, the modified Index view in Listing 2 has been modified to display the current time.
*** Begin Note ***
Notice that the first tag has been removed from the view in Listing 2. If you don’t need to modify anything in the tag, then there is no reason to keep the first tag.
*** End Note ***
Listing 1中显示的文件内容与标准HTML文档很相似,该视图内容中包含两个标记,放置在第一个标记中的所有内容将出现在最终生成的HTML文档的标记之处;放置在第二个标记中的所有内容将出现在最终生成的HTML文档的标记之处。
例如,Listing 2中显示了修改后的Index视图,它显示当前时间。
【注意】请留意第一个标记在Listing 2的视图中已被移除,如果您不需要修改标记处的任何东西,没有理由要保留那第一个标记。
Listing 2 – Views\Product\Index.aspx with time
1. <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>  
2.  
3.  
4.  
5.    

Time

 
6.  
7.    

 

8.    At the tone, the time will be  
9.    <%= DateTime.Now.ToString("T") %>.  
10.    

 
11.  
12.  

The view in Listing 2 contains familiar HTML tags such as the

, and

tags. You can put anything that you would put in a normal HTML page within a view including images, iframes, Java applets, Flash, and Silverlight.

The view also contains a script. that displays the time. The expression DateTime.Now.ToString(“T”) returns the current time (see Figure 3).
You embed a script. in a view by using the <% %> script. delimiters. For example, if for some bizarre reason you wanted to display the string “Hello World!” nine-hundred and ninety-nine times in a page then you could embed the following script. in a page (see Figure 4):
The <%= %> script. delimiters are shorthand for <% Response.Write %>. You can use the <%= %> script. delimiters to write the value of an expression to the browser. The following two scripts do exactly the same thing:
*** Begin Tip ***
You can create views that contain Visual Basic scripts in a C# ASP.NET MVC application and you can create views that contain C# scripts in a Visual Basic ASP.NET MVC application. However, you cannot mix both C# and Visual Basic scripts within the same view.
*** End Tip ***
Listing 2的视图中包含了一些熟知的HTML标记,如

,

标记等,可以在普通HTML页面上放置的任何事物,您都可以放到视图中,包括images, iframes, Java applets, Flash, 及Silverlight。

该视图也包含了显示当前时间的脚本,表达式DateTime.Now.ToString(“T”)返回当前时间(见图3)。

Figure 3 – Displaying the current time

clip_image006

使用<% %>脚本分隔符,可以将脚本嵌入到视图中,例如,由于某种奇异原因您希望在页面上显示999次“Hello World!”串,那么可以将以下脚本嵌入到页面中(见图4):
[C#]
<%
for (var i = 1; i < 999; i++)
Response.Write("Hello World!");
%>

Figure 4 – Displaying 999 Hello Worlds!

clip_image008

<%= %>脚本分隔符是<% Response.Write %>的简写,您可以用<%= %>脚本分隔符将一个表达式的值写入浏览器页面。以下两个脚本正是这么做的:
[C#]
<%= DateTime.Now.ToString(“T”) %>
<% Response.Write(DateTime.Now.ToString(“T”)); %>
【提示】您可以在C# ASP.NET MVC程序中创建包含Visual Basic脚本的视图,也可以在Visual Basic ASP.NET MVC程序中创建包含C#脚本的视图,然而,您不能在同一个视图中混用C# 和Visual Basic。

Using View Data
You pass information between a controller and a view by taking advantage of something called view data. You can use view data to represent any type of information including strings, objects, and database records.
For example, imagine that you want to display a set of database records in a view. In that case, you would use view data to pass the set of records from a controller action to a view.
*** Begin Note ***
I like to think of view data as a UPS Truck delivering a package from a controller to a view.
*** End Note ***
You add an item to view data within a controller by adding the item to the view data dictionary exposed by the controller’s ViewData property. For example, you could add the following code to a controller action to add a new item to view data named message:
View data works like a dictionary. You can add any key and value pair that you want to the view data dictionary. The key must be a string, but the value can be any type of data whatsoever.
After you add one or more items to view data, you can display these items in a view by accessing the view data dictionary exposed by the view’s ViewData property. For example, the view in Listing 3 displays the value of the message item from view data.
使用View Data
利用view data机制,您可以在控制器和视图间传递信息。您可以使用view data来传递任意类型的信息,包括字符串、对象、以及数据库记录。
例如,想像一下您希望在某个视图中显示一组数据库记录,在这种情形下,您可以在某个控制器行为中使用view data来向视图传递这组记录。
【注意】我喜欢把view data想象成一个递送包裹的UPS卡车,将数据从控制器传递到视图。
通过控制器的ViewData属性,在控制器类的方法中将数据项添加到view data字典里,例如,可以在控制器行为中加入以下代码来在view data中添加一个名为message的数据项:
[C#]
ViewData["message"] = "Hello World!";
View data的工作方式类似与字典,您可以向其中添加您希望的任何“键-值”对。键必须是一个字符串,但是值可以是任何类型的数据。
在向view data中添加多个数据项后,通过在视图的ViewData属性访问view data字典,您可以在视图中显示它们。例如,Listing 3中的视图显示view data中的message项。
Listing 3 – Views\Person\Index.aspx [C#]
1. <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>  
2.  
3.  
4.  
5.    <%= ViewData["message"] %>  
6.  
7.  
8.  

Typed and Untyped Views
In the previous section, you learned how to add items to the view data dictionary. One problem with the view data dictionary is that it represents everything as untyped objects. This means that you must cast items to a particular data type before you can use the items in a view.
Consider, for example, the controller action in Listing 4. This action adds a set of database records representing products to view data.
类型化视图和无类型视图
前一节里,您学会了如何向view data字典中添加数据项,view data字典存在的一个问题是,它将所有数据均表示为无类型的对象,这意味着必须将它们的类型强制转换为特定类型后才可以在视图中使用。
考虑一下,例如Listing 4中的控制器行为,该行为向view data中添加了代表产品的一组数据库记录。
Listing 4 – Controllers\HomeController.cs [C#]
1. public ActionResult Index()  
2. {  
3.    ViewData["products"] = _dataModel.ProductSet.ToList();   
4.    return View();  
5.
 
The view in Listing 5 illustrates how you can display the records from the database table in an HTML table.
Listing 5中的视图向您展示了如何使用HTML表来显示这些数据库表中的记录。
Listing 5 – Views\Home\Index.aspx [C#]
1. <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>  
2. <%@ Import Namespace="ToyStore.Models" %>  
3.  
4.  
5.  
6.  
7.      
8.  
9.    <% foreach (var item in (IEnumerable)ViewData["products"]) { %>  
10.      
11.        
 
12.            
 
15.            
 
18.            
 
21.            
 
24.        
 
25.      
26.    <% } %>  
27.  
28.    
 
13.                <%= Html.Encode(item.Id) %>  
14.            
 
16.                <%= Html.Encode(item.Name) %>  
17.            
 
19.                <%= Html.Encode(item.Description) %>  
20.            
 
22.                <%= Html.Encode(item.Price) %>  
23.            
 
29.  
30.  

In Listing 5, notice that the products item from view data is cast to an IEnumerable of Product. An IEnumerable is something that you can enumerate over – something you can loop through. If you write your view with C# then you must cast the products item to an IEnumerable or you will get an error (see Figure 5). Regardless of whehter you are using C# or VB.NET, you won’t get Intellisense for Product properties unless you cast.
*** Begin Note ***
If you have Option Strict enabled then Visual Basic, like C#, will generate an error when you don’t cast the product item to an IEnumerable.
*** End Note ***
If you don’t want to clutter your views by casting the view data, you can create a strongly typed view.
The view data dictionary exposes a property named Model. Within a controller you can assign anything you want to the view data model. For example, the controller action in Listing 6 assigns the Product database records to the Model property.
在Listing 5中,请留意view data中的产品列表被转换为IEnumerable类型。IEnumerable类型的意义是您可以遍历它 – 可以循环遍历其内容。如果视图用C#编写,您必须将产品列表转换为IEnumerable,否则将得到一个错误(见图5)。无论您使用C#还是VB.NET,只有做了强制类型转换才能获得Product属性的智能感知提示。
【注意】如果选择了Strict选项,则Visual Basic和C#一样,如果没将产品列表转换为IEnumerable,也会生成一个错误。

Figure 5 – Failing to cast to IEnumerable

clip_image010

如果您不希望因为强制类型转换而把视图弄的看起来很凌乱,可以创建强类型视图。
view data字典是通过名为Model属性来访问的,在控制器(代码)内您可以将任何值赋给view data的Model属性。例如在Listing 6中的控制器行为将Product数据库记录集赋给Model属性。
Listing 6 – Controllers\HomeController.cs using model [C#]
1. public ActionResult Index()  
2. {  
3.    ViewData.Model = _dataModel.ProductSet.ToList();   
4.    return View();  
5. }  

*** Begin Note ***
The following code does the exact same thing as the code in Listing 6:
【注意】以下代码与Listing 6中代码实现同样功能
[C#]
public ActionResult Index()
{
return View(_dataModel.ProductSet.ToList());
}
*** End Note ***

The advantage of assigning a value to the ViewData.Model property is that you can cast the Model property automatically in a view. In a view, you can specify the type of object that the Model represents with the <%@ Page %> directive Inherits attribute.
For example, the strongly typed view in Listing 6 renders the exact same page as the previous untyped view.
向ViewData.Model属性赋值的好处是您能够在视图中自动对Model属性进行类型转换。在视图里,您可以通过<%@ Page %>指示字的Inherits属性来指定Model属性所代表的对象类型。
例如,Listing 6中的强类型视图的显示结果与前面的无类型视图完全一致。
Listing 6 – Views\Home\Index.aspx with Model [C#]
1. <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage>" %>  
2. <%@ Import Namespace="ToyStore.Models" %>  
3.  
4.  
5.  
6.      
7.  
8.    <% foreach (var item in ViewData.Model) { %>  
9.      
10.        
 
11.            
 
14.            
 
17.            
 
20.            
 
23.        
 
24.      
25.    <% } %>  
26.  
27.    
 
12.                <%= Html.Encode(item.Id) %>  
13.            
 
15.                <%= Html.Encode(item.Name) %>  
16.            
 
18.                <%= Html.Encode(item.Description) %>  
19.            
 
21.                <%= Html.Encode(item.Price) %>  
22.            
 
28.  
29.  

Notice the Inherits attribute in Listing 6. The view inherits from the following class:
[C#]
System.Web.Mvc.ViewPage>
This Inherits attribute casts the ViewData.Model property to an IEnumerable of Product. For this reason, in the body of the view, you do not need to cast the ViewData.Model property before looping through its items.
请留意Listing 6里的Inherits属性,该视图继承自如下类:
[C#]
System.Web.Mvc.ViewPage>
该Inherits属性将ViewData.Model属性转换为IEnumerable,因此在视图的内容里,您可以直接遍历产品列表而不需要再对ViewData.Model进行类型转换。

Creating Strongly Typed Views
Providing the proper value for the Inherits attribute for a typed view can be tricky. Because you don’t get any Intellisense for the Inherits attribute, you can easily make a mistake and your view will generate an error.
Instead of creating a strongly typed view by hand, you can take advantage of the Visual Studio Add View dialog to create a strongly typed view automatically (see Figure 6). You open this dialog by right-clicking a controller action and selecting the menu option Add View. Alternatively, you can right click a folder located in the Views folder and select the menu option Add, View.
The Add View dialog includes a checkbox labeled Create a strongly-typed view. If you check this checkbox, you can specify the View data class and the View content.
*** Begin Warning ***
The View data class dropdown list will be empty until you successfully build your application. It is a good idea to select the menu option Build, Build Solution before opening the Add View dialog.
*** End Warning ***
The View data class dropdown enables you to pick a class from your project. The Inherits directive will use this class. For example, you can pick the Product class.
The View content dropdown enables you to pick the type of view that you want to create. Your options are Create,Details, Edit, List, Empty, and List. If you pick List then your vide data model is cast to an IEnumerable of Products. Otherwise, if you pick any of the other options, your view data model is cast to a Product.
Add View对话框包含了一个Create a strongly-typed view复选框。如果您选中该复选框,便能继续指定View data class和View content。
创建强类型视图
为一个强类型视图指定Inherits属性的正确值有时会比较麻烦。由于在输入Inherits属性值时得不到任何智能提示,您可能会很轻易地弄错并且视图将会生成一个错误信息。
您可以利用Visual Studio的Add View对话框来自动创建一个强类型视图(见图6),而不是手工创建。用鼠标右击某个控制器行为并在弹出的上下文菜单中选择Add View菜单项,便会打开该对话框;或者您也可以鼠标右击Views文件夹并选择上下文菜单项Add,View。

Figure 6 – Creating a strongly typed view

clip_image012

【注意】除非您的应用程序编译成功,否则View data class下拉列表将会是空的,因此在打开Add View dialog对话框前,在上下文菜单中选择Build, Build Solution进行生成是个好办法。
您可以从View data class下拉列表框中选择项目中的某个类,Inherits指示字将使用该类。例如,您可以选择Product类。
您可以在View content下拉列表框中选择希望创建的视图类型,包括Create、Details、Edit、List、Empty、和List。如果您选择List,则您的数据模型将被转换为IEnumerable;选择其他任何选项会将数据模型转换为Product类型。

Preventing JavaScript. Injection Attacks
When you submit form. data using a view, the ASP.NET MVC framework validates the form. data automatically. If the framework identifies potentially malicious markup, the framework will throw an exception (see Figure 7).
What counts as malicious markup? Anything that could potentially open your website to a JavaScript. injection attack. For example, submitting the following text will generate an error:
alert(‘Boo!’)
*** Begin Note ***
JavaScript. injection attacks include cross-site scripting (XSS) attacks.
*** End Note ***
In some situations, you don’t want to perform. this validation. For example, if you are hosting a discussion forum on building websites then you most likely will want to enable users to post messages that contain HTML tags.
You disable request validation with the [ValidateInput] attribute. You apply this attribute to the controller action that accepts the HTML form. input. For example, the Create() action in Listing 7 has request validation disabled.
防止Javascript注入攻击
当您通过某个视图提交表单数据时,ASP.NET MVC框架将自动验证表单数据。如果框架发现可疑代码,则会抛出一个异常(见图7)。

Figure 7 – Preventing an attacking JavaScript

clip_image014

什么才算是有危害的代码?就是那些可能会导致您的站点遭受JavaScript注入攻击的任何代码。例如,提交以下文本将会生成一个错误:
alert(‘Boo!’)
【注意】JavaScript注入攻击包括cross-site scripting (XSS) 跨站点脚本攻击。
在某些情形下,您不希望执行这些验证,例如,如果您托管一个关于创建站点的论坛,则很有可能您会允许用户发送包含HTML标记的消息。
您可以使用[ValidateInput]属性来禁止对请求进行验证,将该属性应用到接受HTML表单输入请求的控制器行为。例如,Listing 7中的Create()行为就禁用了请求验证。
Listing 7 – Controllers\HomeController.cs [C#]
1. //  
2. // POST: /Home/Create  
3. [ValidateInput(false)]  
4. [AcceptVerbs(HttpVerbs.Post)]  
5. public ActionResult Create([Bind(Exclude="Id")]Product productToCreate)  
6. {  
7.    if (!ModelState.IsValid)  
8.        return View();  
9.  
10.    try  
11.    {  
12.        _dataModel.AddToProductSet(productToCreate);  
13.        _dataModel.SaveChanges();  
14.  
15.        return RedirectToAction("Index");  
16.    }  
17.    catch  
18.    {  
19.        return View();  
20.    }  
21. }  

*** Begin Note ***
Unlike ASP.NET Web Forms, you cannot disable request validation with the <%@ Page ValidateRequest=”false” %> directive and you cannot disable request validation in the web configuration (web.config) file. In an ASP.NET MVC application, the only way to disable request validation is with the ValidateInput attribute.
*** End Note ***
If you disable request validation, ensure that you never display user submitted content without first HTML encoding the content. HTML encoding text converts potentially dangerous characters such as < and > into safe entities such as < and >. Use the Html.Encode() helper to HTML encode all user submitted content in your views.
【注意】不像ASP.NET Web Form,您无法通过<%@ Page ValidateRequest=”false” %>禁用请求验证,并且您不能在web配置文件(web.config)中禁用请求验证。在一个ASP.NET MVC应用里,禁用请求验证的唯一途径是使用ValidateInput属性。
如果禁用请求验证,请确保您在对用户提交的内容进行HTML编码后再显示它们。HTML编码将某些可能会造成危害的字符,如<和>等,加以编码,转换为安全的<和>实体标记。请在您的视图中,用Html.Encode()对用户提交的所有内容进行HTML编码。

Using Alternative View Engines
The default view engine for the ASP.NET MVC framework is the Web Forms View Engine. The Web Forms View Engine uses ASP.NET pages as views.
The ASP.NET MVC framework was designed to support alternative view engines and there are already several open source alternatives to the Web Forms View Engine. Here’s a list of some of the more interesting and popular ones:
• NHaml – (pronounced enamel) is an implementation of the popular RAILS Haml view engine for the ASP.NET MVC framework. Distributed under the open source MIT license.
http://code.google.com/p/nhaml/
• Spark – The idea behind the Spark view engine is to allow “the html to dominate the flow and the code to fit seamlessly.”
http://dev.dejardin.org/
• Brail – A port of the Brail view engine from MonoRail to the ASP.NET MVC framework. The Brail view engine is part of the MVCContrib project.
http://www.codeplex.com/MVCContrib
• nVelocity – The nVelocity view engine is a port of the Java Apache Software Foundation Velocity project to the .NET framework. The nVelocity view engine is part of the MVCContrib project.
http://www.codeplex.com/MVCContrib
The different view engines enable you to write your views in radically different ways. For example, Listing 8 contains a sample of a view written with the NHaml view engine.
使用其他视图引擎
ASP.NET MVC框架的默认视图引擎是Web Forms视图引擎,Web Forms视图引擎使用ASP.NET页面作为视图。
ASP.NET MVC框架被设计为支持其他视图引擎,并且已经有数个开源视图引擎可以用来替换Web Forms视图引擎。下面列出了一些有趣、流行的视图引擎:
• NHaml – (发音为enamel)是流行的RAILS Haml视图引擎在ASP.NET MVC框架上的实现。开源并受MIT license约束.
http://code.google.com/p/nhaml/
• Spark – Spark视图引擎的设计思想是: html控制页面流,代码无缝集成.”
http://dev.dejardin.org/
• Brail – MonoRail开源项目中Brail视图引擎移植到ASP.NET MVC 框架. Brail视图引擎是MVCContrib项目的一部分.
http://www.codeplex.com/MVCContrib
• nVelocity – nVelocity视图引擎是Java Apache Software Foundation的Velocity项目的.NET框架的移植。nVelocity视图引擎是MVCContrib项目的一部分。
http://www.codeplex.com/MVCContrib
这些视图引擎让您能用完全不同的方式编写视图。例如,Listing 8包含了一个用NHaml视图引擎编写的视图样本。
Listing 8 – Views\Home\Index.haml
1. !!!  
2. %html{xmlns="http://www.w3.org/1999/xhtml"}  
3.  %head  
4.    %title My Index View  
5.  %body  
6.  %h1 Product List  
7.  %ul  
8.    - foreach (var p in ViewData.Model)  
9.      %li =m.Name  

The NHaml view in Listing 8 loops through all of the products represented by the ViewData.Model property and renders the value of the Product Name property. Just like the Web Forms View Engine, the NHaml View Engine renders HTML. However, notice the terseness of the syntax. You are able to render a valid and complete HTML page that displays a set of database records with a minimum of effort.
You can use multiple view engines in the same ASP.NET MVC application by registering multiple engines in the Global.asax file. Each view engine can handle a file with a different extension. For example, all .aspx files can be rendered by the Web Forms View Engine while all .haml files can be rendered by the NHaml view engine.
Listing 8中的NHaml视图遍历ViewData.Model属性里存放的所有产品,并显示Product.Name属性值。和Web Forms视图引擎一样,NHaml视图引擎绘制HTML。然而,请注意NHaml构造的简洁性:您可以很容易地显示一个完整有效的HTML页面并显示一组数据库记录。
通过在Global.asax文件中注册多个视图引擎,您可以在同一个ASP.NET MVC应用程序中使用多个视图引擎,每个视图引擎可以处理某个扩展名的请求。例如,所有的.aspx文件可以用Web Forms视图引擎处理,而所有.haml文件由NHaml视图引擎处理。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/740297/viewspace-564935/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2009-02-03

  • 博文量
    21
  • 访问量
    65360