lASP.NET MVC系列文章 【01】淺談Google Chrome瀏覽器(理論篇) 【02】淺談Google Chrome瀏覽器(操作篇)(上) 【03】淺談Google Chrome瀏覽器(操作篇)(下) 【04】淺談ASP.NET框架 【05】淺談ASP.NET MVC運行過程 【06】淺 ...
lASP.NET MVC系列文章
【02】淺談Google Chrome瀏覽器(操作篇)(上)
【03】淺談Google Chrome瀏覽器(操作篇)(下)
【04】淺談ASP.NET框架
【07】淺談ASP.NET MVC 路由
【08】淺談ASP.NET MVC 視圖
【10】淺談jqGrid 在ASP.NET MVC中增刪改查
【13】淺談NuGet在VS中的運用
【14】淺談ASP.NET 程式發佈過程
一 引入背景
我們知道,MVC基架為我們提供了很多基礎類,當需要使用時,只需調用即可,以ActionResult為例,其有很多子類,如ContentResult,EmptyResult,FileResult,HttpStatusCodeResult,JavaScriptResult,JsonResult,RedirectResult,RedirectToRouteResult,ViewResultBase,FileContentResult,FilePathResult,FileStreamResult,ViewResult,PartialResult,
然而,儘管MVC基架提供了眾多類供我們調用,但卻並不是包括所有功能的類,比如,我需要返回XML格式的數據,或下載CSV格式的數據,此時,MVC基架就沒提供相應的類。因此,MVC類的擴展就迫在眉睫了。
在本篇文章中,主要講解MVC比較核心的八大擴展類,一共分為兩篇,即淺談ASP.NET MVC八大類擴展(上篇)和淺談ASP.NET MVC八大類擴展(下篇)。
其中,本篇文章主要講解MVC基架提供的ActionResult及其子孫類,自定義擴展XMLResult和CsvResult,下篇文章將講解剩下的七大類自定義擴展:Filter擴展,RazorViewEngine擴展,HtmlHelper擴展,Validator擴展,ModelBinder擴展,ControllerFactory註入擴展,Lambda 樹擴展。
二 ASP.NET MVC擴展概述
但凡涉及到架構,我們首先都會關心安全性,穩定性,可擴展性等特征,當然,ASO.NET MVC也不例外,MVC之所以比WebForm流行,不僅僅在於其實現前後端的松耦合,而且其也支持強大的自定義擴展,在本篇文章中,我們就是運用MVC支持自定義擴展這一特性來進行自定義擴展,從而實現個性化項目需求。
三 代碼實例
(一) ActionResult擴展
1 AtionResult內置擴展
ASP.NET MVC提供瞭如下內置擴展類.
1.1 上圖簡要概述
(1)ActionResult類繼承Object類;
(2)ContentResult,EmptyResult,FileResult,HttpStatusCodeResult,JavaScriptResult,JsonResult,ViewResultBase,RedirectToRouteResult,RedirectResult 九大類繼承類ActionResult;
(3)FileContentResult,FilePathResult,FileStreamResult 三大類繼承類FileResult;
(4)ViewResult,PartialViewResult兩大類繼承類ViewResultBase;
1.2 ActionResult講解
功能:封裝一個操作方法的結果並用於代表該操作方法執行框架級操作。
在Mvc中,我們對如下代碼再熟悉不過了。
public ActionResult Index() { return View();
}
F12查看ActionResult定義
1 namespace System.Web.Mvc 2 { 3 // 4 // 摘要: 5 // 表示操作方法的結果。 6 public abstract class ActionResult 7 { 8 // 9 // 摘要: 10 // 初始化 System.Web.Mvc.ActionResult 類的新實例。 11 protected ActionResult(); 12 13 // 14 // 摘要: 15 // 通過從 System.Web.Mvc.ActionResult 類繼承的自定義類型,啟用對操作方法結果的處理。 16 // 17 // 參數: 18 // context: 19 // 用於執行結果的上下文。上下文信息包括控制器、HTTP 內容、請求上下文和路由數據。 20 public abstract void ExecuteResult(ControllerContext context); 21 } 22 }View Code
不難看出,ActionResult具有如下特征:
(1)抽象類;
(2)一個只可繼承的構造函數;
(3)一個未實現的抽象方法;
1.2.1 ContentResult講解
功能:表示用戶定義的內容類型,該類型是操作方法的結果。
定義:查看定義
不難看出,ContentResult具有如下特征:
(1)繼承自類ActionResult
(2)包含一個構造方法,一個重寫ActionResultl類的抽象方法ExecuteResult(ControllerContext context),和三個屬性;
(3)完整定義
1 public class ContentResult : ActionResult 2 { 3 // Methods 4 public override void ExecuteResult(ControllerContext context) 5 { 6 if (context == null) 7 { 8 throw new ArgumentNullException("context"); 9 } 10 HttpResponseBase response = context.HttpContext.Response; 11 if (!string.IsNullOrEmpty(this.ContentType)) 12 { 13 response.ContentType = this.ContentType; 14 } 15 if (this.ContentEncoding != null) 16 { 17 response.ContentEncoding = this.ContentEncoding; 18 } 19 if (this.Content != null) 20 { 21 response.Write(this.Content); 22 } 23 } 24 25 // Properties 26 public string Content { get; set; } 27 28 public Encoding ContentEncoding { get; set; } 29 30 public string ContentType { get; set; } 31 } 32 33View Code
(4)我們來看看具體例子:
如我們向頁面輸出“Alan_beijing”,可採取如下兩種方式。
方式一:
1 public ContentResult ContextResultTest() 2 { 3 return Content("Alan_beijing"); 4 }
測試結果
方式二
1 public ContentResult ContextResultTest() 2 { 3 //string str = "<html>" + "<head></head>" + "<body>" + "Alan_beijing" + "</body>" + "</html>"; 4 string str = "<html><head></head></body>Alan_beijing</body></html>"; 5 return Content(str); 6 }View Code
測試結果
總之,大家在使用時,可以把ContentResult當作Responce.Write()使用。
1.2.2 EmptyResult
功能:表示一個不執行任何操作的結果,如不返回任何內容的控制器操作方法。
(1)查看定義
(2)完整定義
1 public class EmptyResult : ActionResult 2 { 3 // Fields 4 private static readonly EmptyResult _singleton = new EmptyResult(); 5 6 // Methods 7 public override void ExecuteResult(ControllerContext context) 8 { 9 } 10 11 // Properties 12 internal static EmptyResult Instance => 13 _singleton; 14 }View Code
(3)總結
EmptyResult不執行任何操作,相當於如下功能。
1 public ContentResult ContextResultTest() 2 { 3 return Content(""); 4 }
1.2.3 FileResult
功能:表示一個用於將二進位文件內容發送到響應的基類。
(1)查看定義
(2)完整定義
1 public abstract class FileResult : ActionResult 2 { 3 // Fields 4 private string _fileDownloadName; 5 6 // Methods 7 protected FileResult(string contentType) 8 { 9 if (string.IsNullOrEmpty(contentType)) 10 { 11 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "contentType"); 12 } 13 this.ContentType = contentType; 14 } 15 16 public override void ExecuteResult(ControllerContext context) 17 { 18 if (context == null) 19 { 20 throw new ArgumentNullException("context"); 21 } 22 HttpResponseBase response = context.HttpContext.Response; 23 response.ContentType = this.ContentType; 24 if (!string.IsNullOrEmpty(this.FileDownloadName)) 25 { 26 string headerValue = ContentDispositionUtil.GetHeaderValue(this.FileDownloadName); 27 context.HttpContext.Response.AddHeader("Content-Disposition", headerValue); 28 } 29 this.WriteFile(response); 30 } 31 32 protected abstract void WriteFile(HttpResponseBase response); 33 34 // Properties 35 public string ContentType { get; private set; } 36 37 public string FileDownloadName 38 { 39 get => 40 (this._fileDownloadName ?? string.Empty); 41 set 42 { 43 this._fileDownloadName = value; 44 } 45 } 46 47 // Nested Types 48 internal static class ContentDispositionUtil 49 { 50 // Fields 51 private const string HexDigits = "0123456789ABCDEF"; 52 53 // Methods 54 private static void AddByteToStringBuilder(byte b, StringBuilder builder) 55 { 56 builder.Append('%'); 57 int num = b; 58 AddHexDigitToStringBuilder(num >> 4, builder); 59 AddHexDigitToStringBuilder(num % 0x10, builder); 60 } 61 62 private static void AddHexDigitToStringBuilder(int digit, StringBuilder builder) 63 { 64 builder.Append("0123456789ABCDEF"[digit]); 65 } 66 67 private static string CreateRfc2231HeaderValue(string filename) 68 { 69 StringBuilder builder = new StringBuilder("attachment; filename*=UTF-8''"); 70 foreach (byte num in Encoding.UTF8.GetBytes(filename)) 71 { 72 if (IsByteValidHeaderValueCharacter(num)) 73 { 74 builder.Append((char) num); 75 } 76 else 77 { 78 AddByteToStringBuilder(num, builder); 79 } 80 } 81 return builder.ToString(); 82 } 83 84 public static string GetHeaderValue(string fileName) 85 { 86 foreach (char ch in fileName) 87 { 88 if (ch > '\x007f') 89 { 90 return CreateRfc2231HeaderValue(fileName); 91 } 92 } 93 ContentDisposition disposition = new ContentDisposition { 94 FileName = fileName 95 }; 96 return disposition.ToString(); 97 } 98 99 private static bool IsByteValidHeaderValueCharacter(byte b) 100 { 101 if ((0x30 <= b) && (b <= 0x39)) 102 { 103 return true; 104 } 105 if ((0x61 <= b) && (b <= 0x7a)) 106 { 107 return true; 108 } 109 if ((0x41 <= b) && (b <= 90)) 110 { 111 return true; 112 } 113 switch (b) 114 { 115 case 0x3a: 116 case 0x5f: 117 case 0x7e: 118 case 0x24: 119 case 0x26: 120 case 0x21: 121 case 0x2b: 122 case 0x2d: 123 case 0x2e: 124 return true; 125 } 126 return false; 127 } 128 } 129 }View Code
1.2.4 HttpStatusCodeResult
功能:提供一種用於返回帶特定 HTTP 響應狀態代碼和說明的操作結果的方法。
(1)定義
(2)完整定義
1 public class HttpStatusCodeResult : ActionResult 2 { 3 // Methods 4 public HttpStatusCodeResult(int statusCode) : this(statusCode, null) 5 { 6 } 7 8 public HttpStatusCodeResult(HttpStatusCode statusCode) : this(statusCode, null) 9 { 10 } 11 12 public HttpStatusCodeResult(int statusCode, string statusDescription) 13 { 14 this.StatusCode = statusCode; 15 this.StatusDescription = statusDescription; 16 } 17 18 public HttpStatusCodeResult(HttpStatusCode statusCode, string statusDescription) : this((int) statusCode, statusDescription) 19 { 20 } 21 22 public override void ExecuteResult(ControllerContext context) 23 { 24 if (context == null) 25 { 26 throw new ArgumentNullException("context"); 27 } 28 context.HttpContext.Response.StatusCode = this.StatusCode; 29 if (this.StatusDescription != null) 30 { 31 context.HttpContext.Response.StatusDescription = this.StatusDescription; 32 } 33 } 34 35 // Properties 36 public int StatusCode { get; private set; } 37 38 public string StatusDescription { get; private set; } 39 }View Code
1.2.5 JavaScriptResult
功能:將 JavaScript 內容發送到響應。
(1)定義
(2)完整定義
1 public class JavaScriptResult : ActionResult 2 { 3 // Methods 4 public override void ExecuteResult(ControllerContext context) 5 { 6 if (context == null) 7 { 8 throw new ArgumentNullException("context"); 9 } 10 HttpResponseBase response = context.HttpContext.Response; 11 response.ContentType = "application/x-javascript"; 12 if (this.Script != null) 13 { 14 response.Write(this.Script); 15 } 16 } 17 18 // Properties 19 public string Script { get; set; } 20 }View Code
1.2.6 JsonResult
功能:表示一個類,該類用於將 JSON 格式的內容發送到響應。
(1)定義
(2)完整定義
1 public class JsonResult : ActionResult 2 { 3 // Methods 4 public JsonResult() 5 { 6 this.JsonRequestBehavior = JsonRequestBehavior.DenyGet; 7 } 8 9 public override void ExecuteResult(ControllerContext context) 10 { 11 if (context == null) 12 { 13 throw new ArgumentNullException("context"); 14 } 15 if ((this.JsonRequestBehavior == JsonRequestBehavior.DenyGet) && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) 16 { 17 throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed); 18 } 19 HttpResponseBase response = context.HttpContext.Response; 20 if (!string.IsNullOrEmpty(this.ContentType)) 21 { 22 response.ContentType = this.ContentType; 23 } 24 else 25 { 26 response.ContentType = "application/json"; 27 } 28 if (this.ContentEncoding != null) 29 { 30 response.ContentEncoding = this.ContentEncoding; 31 } 32 if (this.Data != null) 33 { 34 JavaScriptSerializer serializer = new JavaScriptSerializer(); 35 if (this.MaxJsonLength.HasValue) 36 { 37 serializer.MaxJsonLength = this.MaxJsonLength.Value; 38 } 39 if (this.RecursionLimit.HasValue) 40 { 41 serializer.RecursionLimit = this.RecursionLimit.Value; 42 } 43 response.Write(serializer.Serialize(this.Data)); 44 } 45 } 46 47 // Properties 48 public Encoding ContentEncoding { get; set; } 49 50 public string ContentType { get; set; } 51 52 public object Data { get; set; } 53 54 public JsonRequestBehavior JsonRequestBehavior { get; set; } 55 56 public int? MaxJsonLength { get; set; } 57 58 public int? RecursionLimit {