Asp.Net MVC 3【Controllers And Actions】
这里分享一下MVC框架里的Controller("控制器")和Action("动作/方法"),我将告诉你如何实现控制器和不同的方式,你可以使用控制器接收和生成输出。 MVC框架不限制您通过视图生成HTML,我们将讨论其他可用的选项。我们还将展示如何操作方法使易于单元测试,并演示如何测试每一种结果,只需要一个动作("Action")方法即可。
介绍控制器("Controller")
关于Controller("控制器")的代码,估计大家也看到不少了,今天我们深入的看看这个控制器的内幕吧!
首项我们准备一个项目("MvcControllers"),接下来我们创建一个 IController接口,并且让所有的Controller("控制器")都实现该接口。项目整体结构如下图1.
图1.IController的接口内容,大概为下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Routing; namespace MvcControllers.Interface { public interface IController { void Execute(RequestContext requestContext); } }
这是一个非常简单的接口。调用的唯一方法,当一个执行请求是针对控制器类。 MVC框架知道哪个控制器类已针对要求读取控制器路由数据所产生的属性的值。你可以选择创建控制器类通过实现IController,但它是一个相当低级接口,并且您必须做很多工作要完成什么有用的东西。我们搞一个简单的控制器('BasicController')提来供了一个演示。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MvcControllers.Controllers { public class BasicController : IController { public void Execute(RequestContext requestContext) { //Controller Info string controller = (string)requestContext.RouteData.Values["controller"]; //Action Info string action = (string)requestContext.RouteData.Values["action"]; //Out requestContext.HttpContext.Response.Write(string.Format("Controller:{0},Action:{1}", controller, action)); } } }
好的,实现这个简单接口后,我们来运行一下,结果如下图2.
图2.实现IController接口允许您创建一个类,MVC框架认识到作为一个控制器和发送请求,但是它将很难编写一个复杂的应用程序。但是你可以使用MVC框架实现更强大的你想要的结果。
创建一个控制器从控制器类派生出来的
MVC框架是无休止地自定义和扩展。您可以实现IController接口来创建你需要的任何类型的请求处理结果的产生。不喜欢行动的方法呢?渲染视图不关心?然后,你可以在你自己手中事项和写一个更好,更快,更优雅的方式处理请求。或者你可以使用的特点,即MVC框架团队,这是实现派生控制器System.Web.Mvc.Controller 类。
System.Web.Mvc.Controller的类提供支持,最MVC请求处理开发人员会很熟悉。这是我们在所有的例子在前面的章节中已经使用。控制器类中提供了三个主要特点:
- 操作方法:控制器的行为被划分为多个方法(而不是只是一个单一的Execute()方法)。每个操作方法暴露于不同的URL,并调用带参数的提取传入的请求。
- 行动结果:您可以描述一个动作的结果返回一个对象(例如,渲染视图,或重定向到一个不同的URL或操作方法),然后以您的名义进行的。指定结果之间的分离和执行简化单元测试。
- 过滤器:可以封装可重复使用的行为过滤器,每一个行为,然后标记上的一个或多个控制器或动作方法将在源代码中的[Attribute](属性)。
为了更好的推导出来Controller类,我们创建一个新的Controller类,叫"DerivedController",具体代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcControllers.Controllers { public class DerivedController : Controller { // // GET: /Derived/ public ActionResult Index() { this.ViewBag.Message = "Hello from the DerivedController Index method."; return this.View("MyView"); } } }
控制器基类实现调用Execute方法,并负责行动方法,其名称的动作值相匹配的路由数据。根据上面的代码返回,我们应该建立一个视图(View),'MyView'页面的具体代码如下:
@{ ViewBag.Title = "MyView"; } <h2>MyView</h2> Messag: @this.ViewBag.Message
然后运行我们的项目,可以看到如下图3所示的结果。
图3.我们的工作,作为一个派生的Controller的类,是实现操作方法,获得输入我们需要处理一个请求,并生成一个合适的响应。
接受输入数据
控制器经常需要访问传入的数据,比如查询字符串值,表单值,和参数解析从传入的URL的路由系统。这些数据主要有三种主要的方式来访问:
- 接受上下文对象
- 有数据作为参数传递给你的动作方法
- 显式地调用框架的模型绑定功能。
在这里,我们将看看方法获取输入你的行动方式,专注于当前项目上下文对象和动作方法参数。
从当前上下对象获取数据
保持数据的最直接的方式是自己把它拿来。当你创建一个控制器通过派生的ControllerBase类,您可以访问一组方便的属性访问信息的要求。这些属性包括请求,响应,RouteData,HttpContext的,和服务器。每提供的信息有关的请求的一个不同方面。我们参考这些方便的属性,因为它们每一个检索不同类型的数据的从请求的ControllerContext实例(可以进行访问通过Controller.ControllerContext属性)。
常用的上下文对象,大致如下表:
属性(Property) | 类型(Type) | 描述(Description) |
Request.QueryString | NameValueCollection | 这个请求发送GET变量 |
Request.Form | NameValueCollection | 这个请求发送POST变量 |
Request.Cookies | HttpCookieCollection | 这个浏览器发送的Cookie 要求 |
Request.HttpMethod | string | 用于这个请求的HTTP方法(动词,如GET或POST) |
Request.Headers | NameValueCollection | 发送的HTTP标题的全套申请 |
Request.Url | Uri | 请求的URL |
Request.UserHostAddress | string | 作出该请求的用户的IP地址 |
RouteData.Route | RouteBase | 选择RouteTable.Routesentry申请 |
RouteData.Values | RouteValueDictionary | 主动路由参数(或者提取的URL或默认值) |
HttpContext.Application | HttpApplicationStateBase | 应用程序状态存储 |
HttpContext.Cache | Cache | 应用程序缓存存储 |
HttpContext.Items | IDictionary | 状态存储当前请求 |
HttpContext.Session | HttpSessionStateBase | 状态存储为访问者的会话 |
User | IPrincipal | 对已登录的用户的身份验证信息 |
TempData | TempDataDictionary | 临时数据项存储为当前用户 |
一个动作方法可以使用任何的这些上下文对象,获取请求的信息,我们可以写一个方法/动作(Action)来获取当前上下文的对象的一些属性,例如下面:
public ActionResult RenameProduct() { //从上下文对象访问各种属性 string userName = this.User.Identity.Name; string serverName = this.Server.MachineName; string clientIP = this.Request.UserHostAddress; DateTime dateStamp = this.HttpContext.Timestamp; AuditRequest(userName, serverName, clientIP, dateStamp, "Rename Product"); //检索数据从请求表单数据 string oldProductName = this.Request.Form["OldName"]; string newProductName = this.Request.Form["NewName"]; bool result = AttemptProductRename(oldProductName, newProductName); this.ViewData["Rename"] = result; return this.View("RenameProduct"); }
您可以探索广阔的可用请求的上下文信息使用IntelliSense,并在Microsoft Developer Network(看看它的基类,System.Web.Mvc.Controllerand或System.Web.Mvc.ControllerContext)。
使用动作方法参数
这是一个简洁的方式接收输入的数据比手动提取从上下文对象,它使你的操作方法更容易来阅读。例如,假设我们有一个使用上下文对象的操作方法,想这样的:
public ActionResult ShowWeatherForecast() { string city = this.RouteData.Values["city"]; DateTime forDate = DateTime.Parse(this.Request.Form["forDate"]); ....... }
我们可以从写它成为带参数的形式,像这样:
public ActionResult ShowWeatherForecast(string city,DateTime forDate) { ....... }
这不仅是更容易阅读,但它也有利于单元测试,我们可以进行单元测试的操作方法,而不需要模拟控制器类的便利性。
了解参数对象被实例化
控制器基类获得使用MVC框架为您的操作方法参数的值一种名值的提供者和模型绑定。
值提供的一组数据项提供给您的控制器。有内置值供应商获取项目的Request.Form的Request.QueryString,Request.Files,RouteData.Values。该值将传递给模型的粘合剂的尝试将它们映射到的类型,您的操作方法需要的参数。可以创建默认的模型绑定和填充。
理解可选和强制参数
如果MVC框架无法找到一个引用类型参数的值(如字符串或对象),的操作方法将被调用,但使用该参数为空值。如果某个值不对于值类型参数(如int或double),那么一个异常被抛出,和动作方法将不会被调用。这里的另一种方式去思想它:
- 值类型参数是强制性的。称他们可选的,指定默认值,或更改的参数类型为可空类型(如int或DateTime),这样的MVC框架可以传递null,如果没有值可用。
- 引用类型参数是可选的。为了让他们强制(以确保一个非空值传递),添加一些代码顶部的操作方法拒绝空值。例如,如果该值等于null,则抛出一个ArgumentNull异常。
指定默认参数值
如果你想处理请求不包含的操作方法参数的值,但是你会不检查你的代码中的空值或抛出异常,你可以使用C#可选参数功能。使用c#可选参数特性在一个动作方法,如下:
public ActionResult Search(string query= "all", int page = 1) { // ... }
我们标记为可选的参数指定值时,我们将它们定义。在代码中,我们有提供的查询和页面参数的默认值。 MVC框架将尝试获取值从这些参数的要求,但如果没有可用的值,我们指定默认值
将被代替使用。对于字符串参数,查询,这意味着我们不需要检查空值。如果要求,我们正在处理未指定的查询,那么我们的操作方法将被调用的字符串所有。 int参数,我们并不需要担心导致错误的请求时,有没有页值。我们的方法就会被调用的默认值为1。可选参数可以用于文本类型,这是任何类型,你可以定义没有使用新的关键字,如字符串,整数和双精度。
产生的输出数据
控制器已经完成对请求的处理后,它通常需要产生一个响应。当我们创造了我们的裸机直接实现IController接口的控制器,我们需要采取的处理的请求,其中包括产生响应于客户端的每一个方面的责任。如果我们要发送一个HTML的响应,例如,我们必须创建和组装的HTML数据,使用Response.Write方法将其发送到客户端。同样,如果我们要重定向用户的浏览器到另一个URL,我们需要调用Response.Redirect方法,我们感兴趣的是通过URL直接。下面生成的结果在一个IController实现,例如:
public class BasicController : IController { public void Execute(RequestContext requestContext) { //Controller Info string controller = (string)requestContext.RouteData.Values["controller"]; //Action Info string action = (string)requestContext.RouteData.Values["action"]; //Out requestContext.HttpContext.Response.Write(string.Format("Controller:{0},Action:{1}", controller, action)); //....OR... requestContext.HttpContext.Response.Redirect("/Some/Other/Url"); } }
您可以使用同样的方法,当你从Controller类派生的控制器。当你阅读的HttpResponseBase类,则返回requestContext.HttpContext.Responseproperty在你的Execute方法可通过Controller.Responseproperty,如下:
using System.Web.Mvc; namespace MvcControllers.Controllers { public class DerivedController : Controller { // // GET: /Derived/ public ActionResult Index() { string controller = (string)RouteData.Values["controller"]; string action = (string)RouteData.Values["action"]; Response.Write(string.Format("Controller: {0}, Action: {1}", controller, action)); Response.Redirect("/Some/Other/Url"); //this.ViewBag.Message = "Hello from the DerivedController Index method."; return this.View("MyView"); } } }
这种方法的工作原理,但它有几个问题:
- 控制器类必须包含的HTML或URL结构的细节,类难以阅读和维护。
- 这是很难单元测试生成其响应的控制器,直接连接到输出。您需要创建模拟实现的Response对象,然后是能够处理,以确定您收到来自控制器的输出什么样的输出代表。这可能意味着解析HTML的关键字,例如,这是一个漫长的和痛苦的过程。
- 精致的细节处理每个响应这种方式繁琐和容易出错的。
幸运的是,MVC框架有一个很好的功能,能解决所有这些问题,称为动作结果。以下各节介绍了操作结果的概念,并告诉你不同的方式,它可以用来从控制器来产生响应。
理解动作结果
MVC框架使用操作结果的分离,说明我们的意图执行我们的意图。它的工作原理很简单。
我们的工作直接与Response对象,而是返回一个对象来自ActionResult类,描述了我们希望我们的控制器的响应,如渲染视图或重定向到另一个URL或操作方法。
当MVC框架接收到一个ActionResult对象的操作方法,它调用该类定义的ExecuteResult方法。作用的结果实现,那么处理Response对象,产生对应的输出,你的意图。 MVC框架的好处之一源是幕后是如何工作的,你可以看到的。我们简化了这个类,使其更容易阅读。一个简单的例子如下:
public class RedirectResult : ActionResult { public RedirectResult(string url): this(url, permanent: false) { } public RedirectResult(string url, bool permanent) { Permanent = permanent; Url = url; } public bool Permanent { get; private set; } public string Url { get; private set; } public override void ExecuteResult(ControllerContext context) { string destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext); if (Permanent) { context.HttpContext.Response.RedirectPermanent(destinationUrl, endResponse: false); } else { context.HttpContext.Response.Redirect(destinationUrl, endResponse: false); } } }
当我们创建的一个实例的RedirectResult类,我们通过在URL中,我们要重定向用户(可选),这是否是一个永久的或暂时的重定向。我们的操作方法结束时将要执行的MVC框架,ExecuteResult方法,得到了Responseobject通过ControllerContext对象框架提供的查询.
我们可以使用RedirectResult的类通过创建一个新的实例并返回它从我们的行动方法。下面演示我们的DerivedController类的更新,有两个动作方法之一,使用RedirectResult将请求重定向到其他。
using System.Web.Mvc; namespace MvcControllers.Controllers { public class DerivedController : Controller { public void Index() { string controller = (string)RouteData.Values["controller"]; string action = (string)RouteData.Values["action"]; Response.Write(string.Format("Controller: {0}, Action: {1}", controller, action)); //Response.Redirect("/Some/Other/Url"); //this.ViewBag.Message = "Hello from the DerivedController Index method."; //return this.View("MyView"); } public ActionResult Redirect() { return new RedirectResult("Derived/Index"); } } }
如果您启动应用程序和浏览 /Derived/Redirect,您的浏览器将被重定向到/Derived/Index。为了使我们的代码更简单,控制器类包括方便的方法,为产生不同种ActionResults。因此,举例来说,我们可以达到的效果在上面代码Redirect方法的返回结果。没有什么作用的结果,这是非常复杂的系统,你最终用更简单的,更清洁和更一致的代码。此外,还可以进行单元测试您的操作方法很容易重定向,例如,你可以简单的操作方法返回一个实例RedirectResult,Urlproperty包含您所期望的目标。MVC框架包含了一些内置的操作结果类型,它们如下表所示。来自所有这些类型的ActionResult,他们中有许多方便的帮手在控制器类中的方法。
类型(Type) | 描述(Description) | 控制器里助手方法(Controller Helper Methods) |
ViewResult | 呈现指定或者默认的视图模板 | View |
PartialViewResult | 呈现指定或者默认的部分视图模板 | PartialView |
RedirectToRouteResult |
分流一个HTTP301或302重定向到一个 操作方法或具体的路由条目,根据你的路 由生成一个网址组态 |
RedirectToAction RedirectToActionPermanent RedirectToRoute RedirectToRoutePermanent |
RedirectResult | 分流一个HTTP 301或302重定向到一个特定URL |
Redirect RedirectPermanent |
ContentResult | 原始文本数据返回给浏览器,可以设置Content-Type头 | Content |
FileResult | 直接向浏览器传输二进制数据(如文件从磁盘或一个字节数组在内存中) | File |
JsonResult | .NET对象在JSON格式序列化,并将其作为响应 | Json |
JavaScriptResult | 将应该由浏览器执行JavaScript源代码的一个片段 | JavaScript |
HttpUnauthorizedResult |
设置响应的HTTP状态代码401(意为“未授权”),这将导致有效的 认证机制(窗体身份验证或Windows身份验证),要求访问者登录 |
None |
HttpNotFoundResult | 返回一个HTTP 404 - 未找到错误 | HttpNotFound |
HttpStatusCodeResult | 返回一个指定的HTTP代码 | None |
EmptyResult | 什么都不做 | None |
通过渲染视图返回的HTML
最常见的一种是产生HTML响应的操作方法,并将其发送到浏览器。当使用作用的结果,你这样做的ViewResult类的一个实例指定呈现所需的视图,以便生成的HTML,比如下面的代码:
using System.Web.Mvc; namespace MvcControllers.Controllers { public class ExampleController : Controller { // // GET: /Example/ public ActionResult Index() { return View("HomePage"); } } }
我们使用的ViewHelper的方法来创建的ViewResult类的一个实例,然后返回结果的操作方法。
注意,返回类型的ViewResult。该方法将编译和运行一样好,如果我们有指定的更一般的ActionResult类型。事实上,一些MVC的程序员将定义的结果,每一个的ActionResult的操作方法,甚至当他们知道这将总是返回一个更具体的类型。
您可以指定你想呈现参数的查看方法。在这个例子中,我们已经指定了主页。
当MVC框架调用的的ExecuteResult方法的ViewResult对象,搜索开始为您所指定的视图。如果您使用的区域,然后在您的项目中,框架会
在以下位置:
- /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.aspx
- /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.ascx
- /Areas/<AreaName>/Views/Shared/<ViewName>.aspx
- /Areas/<AreaName>/Views/Shared/<ViewName>.ascx
- /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.cshtml
- /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.vbhtml
- /Areas/<AreaName>/Views/Shared/<ViewName>.cshtml
- /Areas/<AreaName>/Views/Shared/<ViewName>.vbhtml
从列表中可以看到,该框架看起来已创建的视图的引擎ASPX,尽管我们指定的Razor当我们创建的视图引擎(aspx和ascx文件扩展名)该项目。该框架像.NET Razor模板。MVC框架检查,看看是否每个这些文件的存在反过来当它找到一个匹配,它会使用该视图来呈现的结果的操作方法。
如果你不使用区域,或者您正在使用的地区,但没有前面的列表中的文件找到,那么框架继续搜索,使用下列地点:
- /Views/<ControllerName>/<ViewName>.aspx
- /Views/<ControllerName>/<ViewName>.ascx
- /Views/Shared/<ViewName>.aspx
- /Views/Shared/<ViewName>.ascx
- /Views/<ControllerName>/<ViewName>.cshtml
- /Views/<ControllerName>/<ViewName>.vbhtml
- /Views/Shared/<ViewName>.cshtml
- /Views/Shared/<ViewName>.vbhtml
再次,尽快MVC框架测试的位置,并找到一个文件,然后就会停止搜索,已被发现是习惯于渲染到客户端的响应。
MVC框架的视图搜索的目录序列是另一个例子,约定优于配置。你并不需要注册你的视图文件的框架。你只把它们中的一组已知的位置中的一个,并且该框架将找到它们。
我们可以把约定更进了一步,我们希望呈现的视图名称时省略我们所说的查看方法,如下面代码:
using System.Web.Mvc; namespace MvcControllers.Controllers { public class ExampleController : Controller { // // GET: /Example/ public ActionResult Index() { return this.View(); } } }
当我们这样做时,MVC框架的假设,我们要呈现一个视图具有相同的命名的操作方法。这意味着,上面代码的查看方法的调用开始搜索一个叫做指数。
有很多View方法的重写版本。它们对应设置不同的性能上的ViewResult对象被创建。例如,您可以覆盖所使用的布局查看通过明确命名的替代,这样的的例子如下:
using System.Web.Mvc; namespace MvcControllers.Controllers { public class ExampleController : Controller { // // GET: /Example/ public ActionResult Index() { return this.View("Index", "_AlternateLayoutPage"); } } }
提供一个视图模型对象
您可以将它作为一个参数传递到视图对象的查看方法,如下面代码所示:
public class ExampleController : Controller { // // GET: /Example/ public ActionResult Index() { DateTime date = DateTime.Now; return this.View(date); } }
我们通过一个DateTime对象的视图模型。我们可以访问该对象在视图中使用Razor关键字。如下面:
@{ ViewBag.Title = "Index"; } <h2>Index</h2> The day is:@(((DateTime)Model).DayOfWeek)
上面代码所示被称为作为一个untypedor弱typedview。视图不知道任何有关视图模型对象,并把它作为对象的一个实例。要获得DayOfWeek属性,我们需要把对象cast的DateTime的一个实例。整理这件事,我们可以通过创建强类型视图,在此我们告诉视图什么视图模型对象的类型。
传递数据的ViewBag
此功能允许您定义的任意属性在一个动态的对象,并在视图中访问它们。动态对象的访问是通过Controller.ViewBag属性.下面代码演示使用ViewBag属性:
using System.Web.Mvc; namespace MvcControllers.Controllers { public class ExampleController : Controller { // // GET: /Example/ public ActionResult Index() { this.ViewBag.Message = "Hello"; DateTime date = DateTime.Now; return this.View(); } } }
在代码中,我们已经定义了消息和日期的属性,简单地将值分配给它们。对在视图中读取数据,我们简单地得到相同的属性,我们设置的操作方法,具体代码如下:
@{ ViewBag.Title = "Index"; } <h2>Index</h2> The day is:@(((DateTime)Model).DayOfWeek) <br /> The message is: @this.ViewBag.Message
ViewBag有一个使用视图模型对象的优势,因为它很容易发送多个对象的观点。
查看数据和传递数据
视图数据功能类似于视图包特性,但它是采用的ViewDataDictionary类,而不是一个动态的对象。ViewDataDictionary的类类似的key/value键值对收集和是通过ViewData属性访问的控制器类。下面我们演示一个简单的查看数据和传递数据的例子:
using System.Web.Mvc; namespace MvcControllers.Controllers { public class ExampleController : Controller { // // GET: /Example/ public ActionResult Index() { this.ViewData["Message"] = "Hello"; this.ViewData["Date"] = DateTime.Now; return this.View(); } } }
你读的值在视图中,你会得到任何键/值集合,例如:
@{ ViewBag.Title = "Index"; } <h2>Index</h2> The day is:@(((DateTime)this.ViewData["Date"]).DayOfWeek) <br /> The message is: @this.ViewData["Message"]
我们必须把我们得到的对象从数据中读出,就像我们做的非类型化的观点。
执行重定向
一个共同的结果的操作方法是不产生任何输出,但重定向用户的浏览器到另一个URL。大多数时候,这个URL是另一种操作方法中的应用生成的用户可以看到你想要的输出。当您执行重定向,你将发送一两个HTTP代码到浏览器:
- 发送的HTTP代码302,这是一个临时重定向。这是最MVC 3经常使用的类型的重定向,直到是唯一的一种MVC框架的内置支持。使用Post/Redirect/Get重定向模式,这是您要发送的代码。
- 发送的HTTP代码301,这表示永久重定向。这应该是谨慎使用,因为它不指示收件人的HTTP代码要求原来的URL,并使用新的URL,包括旁边的重定向代码。如果您有任何疑问,请使用临时重定向即,发送代码302。
重定向到一个文字网址
你要重定向到的URL表示为一个字符串,并通过作为参数,在Redirect方法。 Redirect方法发送一个临时重定向。您可以发送一个永久重定向使用永久性重定向的方法.
重定向路由系统URL
如果您将用户重定向到一个不同的应用程序的一部分,你需要确保的URL你送在你的URL模式是有效的.这个问题与使用文字重定向的URL是在你的路由架构的任何变化意味着,你需要去通过您的代码和更新的URL。
作为一种替代方法,您可以使用路由系统,以产生有效的URL与RedirectToRoute的方法,该方法创建一个实例的RedirectToRouteResult.比如下面代码所示:
public RedirectToRouteResult Redirect() { return this.RedirectToRoute(new { controller = "Example", action = "Index", ID = "MyID" }); }
RedirectToRoute方法发出一个临时重定向。使用RedirectToRoutePermanent永久重定向的方法。这两种方法都需要一个匿名类型,其属性是传递的路由系统中生成一个URL。
重定向到一个Action方法
您可以重定向到更优雅的操作方法,使用RedirectToAction方法。这仅仅是一个包装周围的RedirectToRoute方法,可以让你指定值的操作方法和控制器,而无需创建一个匿名类型。例如下面代码所示:
public RedirectToRouteResult RedirectResult() { return this.RedirectToAction("Index"); }
如果你只是指定的操作方法,那么就假设你是指的操作方法当前控制器。如果你想重定向到另一个控制器,您需要提供的参数。
返回文本数据
除了HTML的,还有很多其他的基于文本的数据格式,你可能希望你的网站作为响应的应用程序来生成。这些措施包括以下内容:
- XML,RSS和Atom(这是特定的XML的子集)
- JSON(通常为AJAX应用程序)
- CSV(导出表格数据)
- 是简单的文本
下面实例返回文本数据的方法(Action):
public ContentResult Index() { string message = "This is plain text"; return this.Content(message, "text/plain", Encoding.Default); }
我们通过创建ContentResult的Controller.Content辅助方法,它需要三个参数:
- 首先是要发送的文本数据.
- 第二是HTTP响应的Content-Type头的值。您可以看看这些容易在网上,或使用的System.Net.Mime.MediaTypeNames,类获得一个值。对于纯文本,该值是text / plain。
- 最后一个参数指定将用于转换的编码方案成一个字节序列的文本.
您可以省略最后的两个参数,在这种情况下,该框架假定该数据是HTML(有内容类型为text / html)。它会尝试选择浏览器的编码格式宣布支持时.
事实上,你可以去远一点。如果您返回任何对象的操作方法,这是不是一个的ActionResult,MVC框架将尝试将数据序列化到一个字符串值,并将其发送到作为HTML的浏览器.
返回的XML数据
返回的XML数据的操作方法很简单,尤其是当你使用LINQ to XML和XDocument的API生成的XML对象。下面代码实例生成XML的动作(Action)方法:
public ContentResult XMLData() { StoryLink[] stories = GetAllStories(); XElement data = new XElement("StoryList", stories.Select(e => { return new XElement("Story", new XAttribute("title", e.Title), new XAttribute("description", e.Description), new XAttribute("link", e.Url)); })); return this.Content(data.ToString(), "text/html"); }
StoryLink类的用于生成XML是这样定义:
public class StoryLink { public string Title { get; set; } public string Description { get; set; } public string Url { get; set; } }
返回JSON数据
在Web应用程序中使用XML文档和XML片段已经减弱,有利于JavaScript对象符号(JSON)格式。 JSON是一个轻量级的,基于文本的格式来描述分层数据结构。 JSON数据是有效的JavaScript代码,这意味着它是原生支持所有的主流网络浏览器,使之更紧凑,更容易比XML。 JSON是最常用的数据从服务器发送到客户端AJAX查询。
MVC框架有一个内置的JsonResult类,它负责序列化.NET对象到JSON格式。您可以创建的JsonResult对象使用的Controller.Json的方便的方法,示例如下:
[HttpPost] public JsonResult JsonData() { StoryLink[] stories = GetAllStories(); return this.Json(stories); }
我们已经格式化的JSON数据,使其更具可读性。不要担心,如果你不熟悉JSON。后面我们一起学习!这里只做个简单的介绍!
返回文件和二进制数据
FileResult是一个抽象基类的所有有关行动的结果发送二进制数据浏览器。 MVC框架提供了三个供您使用的具体子类分别如下:
- FilePathResult直接发送一个文件从服务器的文件系统。
- FileContentResult将内存中的字节数组的内容。
- FileStreamResult一个System.IO.Stream对象,该对象是已经发送的内容打开。
您不必担心使用这些类型的,因为他们会为您创建自动的Controller.File辅助方法的不同重载。
发送文件
下面演示了如何从磁盘发送一个文件,具体代码如下:
public FileResult AnnualReport() { string filename = @"D:\huitai.pdf"; string contentType = "application/pdf"; string downloadName = "AnnualReport2012.pdf"; return this.File(filename, contentType, downloadName); }
这个动作方法使浏览器会提示用户保存文件,这里做个简单的介绍!
发送一个字节数组
如果您已经在内存中的二进制数据,你可以将它传送到浏览器中使用不同的过载文件的方法,下面用代码做个简单的描述(发送二进制数组):
public FileContentResult DownloadReport() { byte[] data = ... //生成或获取文件内容以某种方式 return this.File(data,"appliction/pdf","AnnualReport.pdf"); }
从检索到的图像数据发送数据库。再次,你必须指定的contentType,并可以选择指定fileDownloadName。浏览器会把它们在完全相同的方式,当你发送一个磁盘文件。
返回错误和HTTP代码
可以使用内置的ActionResult类,我们将期待在最后的发送特定的错误到客户端的消息和HTTP结果代码。大多数应用程序并不需要这些功能,因为MVC框架会自动生成这些结果自动。然而,他们可以是有用的,如果你需要采取更直接地控制发送给客户端的响应。
发送一个特定的HTTP结果代码
您可以发送一个特定的HTTP状态代码的浏览器使用HttpStatusCodeResult类。有没有控制器的辅助方法,所以你必须实例化类。
发送404结果
这里直接用简单的代码说明怎么生成一个404的结果,如下:
public HttpStatusCodeResult StatusCode() { return this.HttpNotFound(); }
有没有在控制器类中的辅助方法来创建实例的HttpUnauthorizedResult,所以你必须这样做的直接。返回这个类的一个实例的效果通常是将用户重定向到在验证页面。
OK!好久都没来更新博客,这边文章写的也比较仓促,肯定有描述错误的地方,还请路过的前辈和新学习的同学们多多指教和,对于之前提出问题的童鞋,我会抽时间解答大家!总之大家共同进步!