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 }
不難看出,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 33
(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 }
測試結果
總之,大家在使用時,可以把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 }
(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 }
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 }
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 }
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 { get; set; } 59 }
(3)總結
JsonResult首先將指定的對象序列化為Json字符串,然后將字符串寫入到HTTP輸出流。
1.2.7 RedirectResult
功能:通過重定向到指定的 URI 來控制對應用程序操作的處理。
(1)定義
(2)完整定義

1 public class RedirectResult : ActionResult 2 { 3 // Methods 4 public RedirectResult(string url) : this(url, false) 5 { 6 } 7 8 public RedirectResult(string url, bool permanent) 9 { 10 if (string.IsNullOrEmpty(url)) 11 { 12 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "url"); 13 } 14 this.Permanent = permanent; 15 this.Url = url; 16 } 17 18 public override void ExecuteResult(ControllerContext context) 19 { 20 if (context == null) 21 { 22 throw new ArgumentNullException("context"); 23 } 24 if (context.IsChildAction) 25 { 26 throw new InvalidOperationException(MvcResources.RedirectAction_CannotRedirectInChildAction); 27 } 28 string url = UrlHelper.GenerateContentUrl(this.Url, context.HttpContext); 29 context.Controller.TempData.Keep(); 30 if (this.Permanent) 31 { 32 context.HttpContext.Response.RedirectPermanent(url, false); 33 } 34 else 35 { 36 context.HttpContext.Response.Redirect(url, false); 37 } 38 } 39 40 // Properties 41 public bool Permanent { get; private set; } 42 43 public string Url { get; private set; } 44 }
1.2.8 RedirectToRouteResult
功能:表示使用指定的路由值字典來執行重定向的結果。
(1)定義
(2)完整定義

1 public class RedirectToRouteResult : ActionResult 2 { 3 // Fields 4 private RouteCollection _routes; 5 6 // Methods 7 public RedirectToRouteResult(RouteValueDictionary routeValues) : this(null, routeValues) 8 { 9 } 10 11 public RedirectToRouteResult(string routeName, RouteValueDictionary routeValues) : this(routeName, routeValues, false) 12 { 13 } 14 15 public RedirectToRouteResult(string routeName, RouteValueDictionary routeValues, bool permanent) 16 { 17 this.Permanent = permanent; 18 this.RouteName = routeName ?? string.Empty; 19 this.RouteValues = routeValues ?? new RouteValueDictionary(); 20 } 21 22 public override void ExecuteResult(ControllerContext context) 23 { 24 if (context == null) 25 { 26 throw new ArgumentNullException("context"); 27 } 28 if (context.IsChildAction) 29 { 30 throw new InvalidOperationException(MvcResources.RedirectAction_CannotRedirectInChildAction); 31 } 32 string str = UrlHelper.GenerateUrl(this.RouteName, null, null, this.RouteValues, this.Routes, context.RequestContext, false); 33 if (string.IsNullOrEmpty(str)) 34 { 35 throw new InvalidOperationException(MvcResources.Common_NoRouteMatched); 36 } 37 context.Controller.TempData.Keep(); 38 if (this.Permanent) 39 { 40 context.HttpContext.Response.RedirectPermanent(str, false); 41 } 42 else 43 { 44 context.HttpContext.Response.Redirect(str, false); 45 } 46 } 47 48 // Properties 49 public bool Permanent { get; private set; } 50 51 public string RouteName { get; private set; } 52 53 internal RouteCollection Routes 54 { 55 get 56 { 57 if (this._routes == null) 58 { 59 this._routes = RouteTable.Routes; 60 } 61 return this._routes; 62 } 63 set 64 { 65 this._routes = value; 66 } 67 } 68 69 public RouteValueDictionary RouteValues { get; private set; } 70 }
1.2.9 ViewResultBase
功能:表示一個用於為視圖提供模型並向響應呈現視圖的基類。
(1)定義
(2)完整定義

1 public abstract class ViewResultBase : ActionResult 2 { 3 // Fields 4 private DynamicViewDataDictionary _dynamicViewData; 5 private TempDataDictionary _tempData; 6 private ViewDataDictionary _viewData; 7 private ViewEngineCollection _viewEngineCollection; 8 private string _viewName; 9 10 // Methods 11 protected ViewResultBase() 12 { 13 } 14 15 public override void ExecuteResult(ControllerContext context) 16 { 17 if (context == null) 18 { 19 throw new ArgumentNullException("context"); 20 } 21 if (string.IsNullOrEmpty(this.ViewName)) 22 { 23 this.ViewName = context.RouteData.GetRequiredString("action"); 24 } 25 ViewEngineResult result = null; 26 if (this.View == null) 27 { 28 result = this.FindView(context); 29 this.View = result.View; 30 } 31 TextWriter output = context.HttpContext.Response.Output; 32 ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output); 33 this.View.Render(viewContext, output); 34 if (result != null) 35 { 36 result.ViewEngine.ReleaseView(context, this.View); 37 } 38 } 39 40 protected abstract ViewEngineResult FindView(ControllerContext context); 41 42 // Properties 43 public object Model => 44 this.ViewData.Model; 45 46 public TempDataDictionary TempData 47 { 48 get 49 { 50 if (this._tempData == null) 51 { 52 this._tempData = new TempDataDictionary(); 53 } 54 return this._tempData; 55 } 56 set 57 { 58 this._tempData = value; 59 } 60 } 61 62 public IView View { get; set; } 63 64 [Dynamic] 65 public object ViewBag 66 { 67 [return: Dynamic] 68 get 69 { 70 Func<ViewDataDictionary> viewDataThunk = null; 71 if (this._dynamicViewData == null) 72 { 73 if (viewDataThunk == null) 74 { 75 viewDataThunk = () => this.ViewData; 76 } 77 this._dynamicViewData = new DynamicViewDataDictionary(viewDataThunk); 78 } 79 return this._dynamicViewData; 80 } 81 } 82 83 public ViewDataDictionary ViewData 84 { 85 get 86 { 87 if (this._viewData == null) 88 { 89 this._viewData = new ViewDataDictionary(); 90 } 91 return this._viewData; 92 } 93 set 94 { 95 this._viewData = value; 96 } 97 } 98 99 public ViewEngineCollection ViewEngineCollection 100 { 101 get => 102 (this._viewEngineCollection ?? ViewEngines.Engines); 103 set 104 { 105 this._viewEngineCollection = value; 106 } 107 } 108 109 public string ViewName 110 { 111 get => 112 (this._viewName ?? string.Empty); 113 set 114 { 115 this._viewName = value; 116 } 117 } 118 }
1.2.10 FileContentResult
功能:將二進制文件的內容發送到響應
定義:

1 public class FileContentResult : FileResult 2 { 3 // Methods 4 public FileContentResult(byte[] fileContents, string contentType) : base(contentType) 5 { 6 if (fileContents == null) 7 { 8 throw new ArgumentNullException("fileContents"); 9 } 10 this.FileContents = fileContents; 11 } 12 13 protected override void WriteFile(HttpResponseBase response) 14 { 15 response.OutputStream.Write(this.FileContents, 0, this.FileContents.Length); 16 } 17 18 // Properties 19 public byte[] FileContents { get; private set; } 20 }
1.2.11 FilePathResult
功能:將文件的內容發送到響應。
定義:

1 public class FilePathResult : FileResult 2 { 3 // Methods 4 public FilePathResult(string fileName, string contentType) : base(contentType) 5 { 6 if (string.IsNullOrEmpty(fileName)) 7 { 8 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "fileName"); 9 } 10 this.FileName = fileName; 11 } 12 13 protected override void WriteFile(HttpResponseBase response) 14 { 15 response.TransmitFile(this.FileName); 16 } 17 18 // Properties 19 public string FileName { get; private set; } 20 }
1.2.12 FilestreamResult
功能:使用Stream實例將二進制內容發送到響應。
定義:

1 public class FileStreamResult : FileResult 2 { 3 // Fields 4 private const int BufferSize = 0x1000; 5 6 // Methods 7 public FileStreamResult(Stream fileStream, string contentType) : base(contentType) 8 { 9 if (fileStream == null) 10 { 11 throw new ArgumentNullException("fileStream"); 12 } 13 this.FileStream = fileStream; 14 } 15 16 protected override void WriteFile(HttpResponseBase response) 17 { 18 Stream outputStream = response.OutputStream; 19 using (this.FileStream) 20 { 21 byte[] buffer = new byte[0x1000]; 22 while (true) 23 { 24 int count = this.FileStream.Read(buffer, 0, 0x1000); 25 if (count == 0) 26 { 27 return; 28 } 29 outputStream.Write(buffer, 0, count); 30 } 31 } 32 } 33 34 // Properties 35 public Stream FileStream { get; private set; } 36 }
1.2.13 ViewResult
功能:表示一個類,該類用於使用由IViewEngine對象返回的IView實例來呈現視圖。
(1)定義:

1 public class ViewResult : ViewResultBase 2 { 3 // Fields 4 private string _masterName; 5 6 // Methods 7 protected override ViewEngineResult FindView(ControllerContext context) 8 { 9 ViewEngineResult result = base.ViewEngineCollection.FindView(context, base.ViewName, this.MasterName); 10 if (result.View != null) 11 { 12 return result; 13 } 14 StringBuilder builder = new StringBuilder(); 15 foreach (string str in result.SearchedLocations) 16 { 17 builder.AppendLine(); 18 builder.Append(str); 19 } 20 throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.Common_ViewNotFound, new object[] { base.ViewName, builder })); 21 } 22 23 // Properties 24 public string MasterName 25 { 26 get => 27 (this._masterName ?? string.Empty); 28 set 29 { 30 this._masterName = value; 31 } 32 } 33 }
1.2.14 PartialResult
功能:表示一個用於將分部視圖發送到響應的基類。
(1)定義:

1 public class PartialViewResult : ViewResultBase 2 { 3 // Methods 4 protected override ViewEngineResult FindView(ControllerContext context) 5 { 6 ViewEngineResult result = base.ViewEngineCollection.FindPartialView(context, base.ViewName); 7 if (result.View != null) 8 { 9 return result; 10 } 11 StringBuilder builder = new StringBuilder(); 12 foreach (string str in result.SearchedLocations) 13 { 14 builder.AppendLine(); 15 builder.Append(str); 16 } 17 throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.Common_PartialViewNotFound, new object[] { base.ViewName, builder })); 18 } 19 }
2 ActionResult自定義擴展
關於ActionResult的自定義擴展,滿足兩個條件
(1)繼承ActionResult
(2)重寫ExecuteResult()方法
2.1 XMLResult
public class XmlResult : ActionResult { private object _data; public XmlResult(object data) { _data = data; } public override void ExecuteResult(ControllerContext context) { var serializer = new XmlSerializer(_data.GetType()); var response = context.HttpContext.Response; response.ContentType = "text/xml"; serializer.Serialize(response.Output, _data); } }
Controller
public XmlResult GetEmpInfo() { EmpInfo empInfo = new EmpInfo() { Name = "Alan_beijing", Address = "China-ShangHai", Age=40 }; return new XmlResult(empInfo); }
Test Result
2.2 CsvResult
public class CsvResult : FileResult { private IEnumerable _data; public CsvResult(IEnumerable data, string fileName) : base("text/csv") { _data = data; FileDownloadName = fileName; } protected override void WriteFile(HttpResponseBase response) { var builder = new StringBuilder(); var strWriter = new StringWriter(builder); foreach (var item in _data) { var properties = item.GetType().GetProperties(); foreach (var prop in properties) { strWriter.Write(GetValue(item, prop.Name)); strWriter.Write(", "); } strWriter.WriteLine(); } response.Write(builder); } public static string GetValue(object item, string propName) { return item.GetType().GetProperty(propName).GetValue(item, null).ToString() ?? ""; } }
Controller
public CsvResult DownCsvEmpInfo() { EmpInfo empInfo = new EmpInfo() { Name = "Alan_beijing", Address = "China-ShangHai", Age = 40 }; return new CsvResult(new List<EmpInfo>() { empInfo }, "empInfo"); }
測試結果
四 推薦網址
【01】https://msdn.microsoft.com/zh-cn/library/system.web.mvc.actionresult(v=vs.118).aspx
五 后續
敬請等待下一篇......
六 服務區
有喜歡的朋友,可以看一下,不喜歡的的朋友,勿噴,謝謝!!