打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【译著】12.2 接收输入 — 精通 MVC 3 框架

【译著】12.2 接收输入 — 精通 MVC 3 框架

Receiving Input
接收输入

Controllers frequently need to access incoming data, such as query string values, form values, and parameters parsed from the incoming URL by the routing system. There are three main ways to access that data:
控制器经常需要访问输入数据,如查询字串值、表单值、以及通过路由系统从输入URL解析所得到的参数。有三个主要的办法来访问这些数据:

  • Extract it from a set of context objects.
    通过一组上下文对象进行提取。
  • Have the data passed as parameters to your action method.
    拥有作为参数被传递到动作方法的数据。
  • Explicitly invoke the framework’s model binding feature.
    明确地调用框架的模型绑定特性。

Here, we’ll look at the approaches for getting input for your action methods, focusing on using context objects and action method parameters. In Chapter 17, we’ll cover model binding in depth.
以下,我们将考查为动作方法获取输入的途径,关注于使用上下文对象以及动作方法参数。在第17章中,我们将深度涉及模型绑定。

Getting Data from Context Objects
通过上下文获取数据

The most direct way to get hold of data is to fetch it yourself. When you create a controller by deriving from the Controller base class, you get access to a set of convenience properties to access information about the request. These properties include Request, Response, RouteData, HttpContext, and Server. Each provides information about a different aspect of the request. We refer to these as convenience properties, because they each retrieve different types of data from the request’s ControllerContext instance (which can be accessed through the Controller.ControllerContext property). We have described some of the most commonly used context objects in Table 12-1.
抓取数据最直接的办法是你自己去拿。当你的控制器是通过Controller基类派生而来的时候,你便得到了一组便利属性来访问与请求相关的信息。这些便利属性包括Request、Response、RouteData、HttpContext、以及Server。每一个都包含了请求的不同方面的信息。我们把这些称为便利属性,是因为它们每一个都从请求的ControllerContext实例(可以通过Controller.ControllerContext属性对它进行访问)接受了不同类型的数据。我们在表12-1中描述了一些最常用的上下文对象。

Table 12-1. Commonly Used Context Objects
表12-1. 常用的上下文对象

Property
属性

Type
类型

Description
描述

Request.QueryString

NameValueCollection

GET variables sent with this request
用这个请求发送的GET变量

Request.Form

NameValueCollection

POST variables sent with this request
用这个请求发送的POST变量

Request.Cookies

HttpCookieCollection

Cookies sent by the browser with this request
由浏览器用这个请求发送的Cookies

Request.HttpMethod

string

The HTTP method (verb, such as GET or POST) used for this request
用于这个请求的HTTP方法(动词,如GET或POST)

Request.Headers

NameValueCollection

The full set of HTTP headers sent with this request
用这个请求发送的整个HTTP头

Request.Url

Uri

The URL requested
所请求的URL

Request.UserHostAddress

string

The IP address of the user making this request
发送请求的用户的IP地址

RouteData.Route

RouteBase

The chosen RouteTable.Routes entry for this request
为这个请求所选择的RouteTable.Routes条目

RouteData.Values

RouteValueDictionary

Active route parameters (either extracted from the URL or default values)
当前路由的参数(或是从URL提取的,或是默认值)

HttpContext.Application

HttpApplicationStateBase

Application state store
应用程序状态库

HttpContext.Cache

Cache

Application cache store
应用程序缓存库

HttpContext.Items

IDictionary

State store for the current request
当前请求的状态库

HttpContext.Session

HttpSessionStateBase

State store for the visitor’s session
访问者的会话状态库

User

IPrincipal

Authentication information about the logged-in user
已登录用户的认证信息

TempData

TempDataDictionary

Temporary data items stored for the current user
为当前用户存储的临时数据项

An action method can use any of these context objects to get information about the request, as Listing12-5 demonstrates.
在一个动作方法中,可以用这些上下文对象的任意一个来获取与请求相关的信息,如清单12-5所示(有些未在表12-1中说明,比如Server — 译者注)。

Listing 12-5. An Action Method Using Context Objects to Get Information About a Request
清单12-5. 使用上下文对象获取请求相关信息的一个动作方法

public ActionResult RenameProduct() {    // Access various properties from context objects    string userName = User.Identity.Name;    string serverName = Server.MachineName;    string clientIP = Request.UserHostAddress;    DateTime dateStamp = HttpContext.Timestamp;    AuditRequest(userName, serverName,clientIP, dateStamp, "Renaming product");    // Retrieve posted data from Request.Form    string oldProductName =Request.Form["OldName"];    string newProductName =Request.Form["NewName"];    bool result =AttemptProductRename(oldProductName, newProductName);    ViewData["RenameResult"] =result;    return View("ProductRenamed");}

You can explore the vast range of available request context information using IntelliSense (in an action method, type this. and browse the pop-up), and the Microsoft Developer Network(look up System.Web.Mvc.Controller and its base classes, or System.Web.Mvc.ControllerContext).
你可以用智能感应(在一个动作方法中,输入this.,并浏览弹出的内容)、和微软开发者网络(查看System.Web.Mvc.Controller及其基类,或System.Web.Mvc.ControllerContext)来浏览这些大量可用的请求上下文信息。

Using Action Method Parameters
使用动作方法参数

As you’ve seen in previous chapters, action methods can take parameters. This is a neater way to receive incoming data than extracting it manually from context objects, and it makes you action methods easier to read. For example, suppose we have an action method that uses context objects like this:
正如在前面一些章节你已经看到的,动作方法可以有参数。这是一种比通过上下文对象提取数据更灵活的接收输入数据的办法,而且这使你的动作方法更易于阅读。例如,假设我们有一个像下面这样使用上下文对象的动作方法:

public ActionResult ShowWeatherForecast(){    string city = RouteData.Values["city"];    DateTime forDate = DateTime.Parse(Request.Form["forDate"]);    // ...implement weather forecast here ...}

We can rewrite it to useparameters, like this:
我们可以把它重写成使用参数的形式,像这样:

public ActionResult ShowWeatherForecast(stringcity, DateTime forDate){    // ...implement weather forecast here ...}

Not only is this easier to read, but it also helps with unit testing—we can unit test the action method without needing to mock the convenience properties of the controller class.
这不仅更易于阅读,而且它也有助于单元测试 — 我们不需要模仿控制器类的便利属性就能够单元测试这个动作方法。

For completeness, it’sworth noting that action methods aren’t allowed to have out or ref parameters. It wouldn’t make any sense if they did. ASP.NET MVC will simply throw an exception if it sees such a parameter.
出于完整性,值得注意的是,动作方法不允许有out或ref参数。如果这么做,没有任何意义。ASP.NET MVC如果看到这种参数会简单地弹出一个异常。

The MVC Framework will provide values for our parameters by checking context objects on our behalf, including Request.QueryString, Request.Form, and RouteData.Values. The names ofour parameters are treated case-insensitively, so that an action method parameter called city can be populated by a value from Request.Form["City"].
MVC框架将通过检查上下文对象的办法自动地给我们的参数提供值,包括Request.QueryString、Request.Form、以及RouteData.Values。对参数名的处理是大小写敏感的,以便一个名为city的动作方法参数能够被Request.Form["City"]的值所填充。

Understanding How Parameters Objects Are Instantiated
理解参数对象是如何被实例化的

The base Controller class obtains values for your action method parameters using MVC Framework components called value providers and model binders.
底层Controller类使用叫做值提供器模型绑定器的MVC框架组件,为你的动作方法参数获取值。

Value providers represent the set of data items available to your controller. There are built-in valueproviders that fetch items from Request.Form, Request.QueryString, Request.Files, and RouteData.Values. The values are then passed to model binders that try to map them to the types that your action methods require asparameters.
值提供器表现一组可用于控制器的数据项。有内建的值提供器,它们从Request.Form、Request.QueryString、Request.Files以及RouteData.Values获得各数据项。这些值然后被传递给模型绑定器,它试图把它们映射到你的动作方法参数的数据类型。

The default model binders can create and populate objects of any .NET type, including collections and project-specific custom types. You saw an example of this in Chapter 9 when form posts from administrators were presented to our action method as a single Product object, even though the individual values were dispersed among the elements of the HTML form.
默认的模型绑定器能够生成并填充任何.NET类型的对象,包括集合以及项目专用的自定义类型。你在第9章看到过它的一个例子,在管理员递交表单时,作为一个单一的Product对象被表现给了我们的动作方法,即使各个值被分散在HTML表单的各个元素之中也没问题。

We cover value providers and model binders in depth in Chapter 17.
我们将在第17章深度涉及值提供器和模型绑定器。

Understanding Optional and Compulsory Parameters
理解可选参数和强制参数

If the MVC Framework cannot find a value for a reference type parameter (such as a string or object), the action method will still be called, but using a null value for that parameter. If a value cannot be found for a value type parameter (such as int or double), then an exception will be thrown, and the action method will not be called. Here’s another way to think about it:
如果MVC框架找不到一个参考类型参数(如一个string或object)的值,动作方法仍然会被调用,但对该参数会使用一个null值。如果找不到一个值类型参数(如int或double)的值,那么会弹出一个异常,该动作方法不会被调用。以下是考虑了这一情况的另一种办法。

  • Value-type parameters are compulsory. To make them optional, either specify a default value (see the next section) or change the parameter type to a nullable type (such as int? or DateTime?), so the MVC Framework can pass null if no value is available.
    值类型参数是强制的。为了使它们成为可选的,或者指定一个默认值(参见下一小节),或是把参数类型改为可空(nullable)类型(如int? 或DateTiem?),于是,如果没有可用的值,MVC框架可以传递null。
  • Reference-type parameters are optional. To make them compulsory (to ensure that a non-null value is passed), add some code to the top of the action method to reject null values. For example, if the value equals null, throw an ArgumentNullException.
    引用类型参数是可选的。为了使它们成为强制的(以保证传递一个非空值),把一些代码添加到该动作方法的顶部,以拒绝null值。例如,如果该值等于null,则弹出一个ArgumentNullException异常。

■ Note We are not referring to UI validation. If your goal is to provide the user with feedback about required form fields, see Chapter 18.
注:我们并不是在指UI校验。如果你的目的是给用户提供所需表单字段的反馈,请参阅第18章。

Specifying Default Parameter Values
指定默认参数值

If you want to process requests that don’t contain values for action method parameters, but you would rather not check for null values in your code or have exceptions thrown, you can use the C# optional parameter feature instead. Listing 12-6 provides a demonstration.
如果你想处理不含动作方法参数值的请求,但你又不想在代码中检查null值或弹出异常,你可以代之以使用C#的可选参数特性。清单12-6提供了一个演示。

Listing 12-6. Using the C# Optional Parameter Feature in an Action Method

public ActionResult Search(string query= "all",int page = 1) {    // ...}

We mark parameters as optional by assigning values when we define them. In the listing, we have provided default values for the query and page parameters. The MVC Framework will try to obtain values from the request for these parameters, but if there are no values available, the defaults we have specified will be used instead.
我们在定义参数时,通过对参数赋值的办法把参数标记为可选的。在上述清单中,我们给query和page参数提供了默认值。MVC框架将试图通过请求为这些参数获取值,但如果无值可用,那么将用我们所指定的默认值来替代。

For the string parameter, query, this means that we don’t need to check for null values. If the request we are processing didn’t specify a query, then our action method will be called with the string all. For the int parameter, we don’t need to worry about requests resulting in errors when there is no page value. Our method will be called with the default value of 1.
对于字符串型参数,query,这意味着我们不需要检查null值。如果我们所处理的请求没有查询字串,那么,我们的动作方法将用字符串all进行调用。对于int型参建,在没有page值时,我们不需要担心请求会导致错误。我们的方法将以默认值1进行调用。

Optional parameters can be used for literal types, which are any type that you can define without using the new keyword, such as string, int, and double.
可选参数可以被用于字面(literal)类型,所谓字面类型是不需要用new关键词定义的任何类型,如string、int、以及double等。

■ Caution If a request does contain a value for a parameter but it cannot be converted to the correct type (for example, if the user gives a nonnumeric string for an int parameter), then the framework will pass the default value for that parameter type (for example, 0for an int parameter), and will register the attempted value as a validation error in a special context object called ModelState. Unless you check for validation errors in ModelState, you can get into odd situations where the user has entered bad data into a form, but the request is processed as though the user had not entered any data or had entered the default value. See Chapter 18for details of validation and ModelState, which can be used to avoid such problems.
注意:如果一个请求包含了一个参数的值,但又不能把它转换成正确的类型(例如,如果用户对一个int参数给了一个非数值字符串),那么框架将给这个参数类型传递默认值(例如,对int参数给0值),并在一个名为ModelState的特殊的上下文对象中把这个尝试值注册为一个校验错误。除非你检查ModelState中的校验错误,否则你可能会陷入奇怪的境况,此时用户在表单中输入了错误数据,但该请求仍然被处理了,就好像用户还没有输入任何数据,或输入了默认数据。参阅第18章的校验和ModelState细节,可以用来避免这类问题。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
spring mvc3获取请求参数的方法
ABAP方法的exporting类型参数,需要在方法实现最开始显式初始化么
Json相关功能块
filter 练习代码 敏感字
重构-改善既有代码的设计(三):编写代码22宗罪
深入了解MyBatis参数
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服