wcf雖然功能多、擴展性強可是也面臨配置忒多,並且restful的功能至關怪異,而且目前無法移植。asp.net core雖然支持webapi,可是功能也相對繁多、配置複雜。就沒有一個能讓碼農們安安心心的寫webapi,無需考慮性能、配置、甚至根據問題場景自行設計、改造等問題的方案麼?html
固然不是,特別是在dnc2.0已經至關強大的此時,徹底能夠自行設計一套簡潔、高效的webapi框架!說到自行寫一套框架,不少碼農們就可能會想到開發工做量難以想像,事實真的如此麼?java由於開源衆多,不少對mvc稍有了解的均可以拿這個拿那個拼出一個自已的mvc框架;而面對日益強大的dnc,本人以爲C#根本無需東拼西湊這麼麻煩,徹底能夠根據自已的需求簡單快速的寫出一個來,不服就開幹!java
設計的編碼思路就是仿asp.net mvc,緣由就是asp.net mvc成功發展了這麼多年,有着大量的C#碼農習慣了這套優良的編碼方式;至於spring mvc、spring boot那些,站在使用者的角度來講,光配置和註解都能敲死人,如要要說簡潔快速,asp.net mvc比他強多了,更別提ruby on rails。不扯遠了,下面就按C#經典來。那麼須要考慮的問題有tcp、http、request、response、server、controller、actionresult、routetable等,下面就一一來解決這個問題。git
1、Tcp:這個是實現傳輸通訊的底層,固然採用IOCP來提升吞吐量和性能,本人以前在作Redis Client等的時候就使用這個IOCP Socket的框架,此時正好也能夠用上github
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPI.Http.Net 7 *文件名: ServerSocket 8 *版本號: V1.0.0.0 9 *惟一標識:ab912b9a-c7ed-44d9-8e48-eef0b6ff86a2 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/8 17:11:15 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/8 17:11:15 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 using SAEA.Sockets.Core; 25 using SAEA.Sockets.Interface; 26 using System; 27 using System.Collections.Generic; 28 using System.Net; 29 using System.Text; 30 31 namespace SAEA.WebAPI.Http.Net 32 { 33 class ServerSocket : BaseServerSocket 34 { 35 public event Action<IUserToken, string> OnRequested; 36 37 public ServerSocket(int bufferSize = 1024 * 100, int count = 10000) : base(new HContext(), bufferSize, true, count) 38 { 39 40 } 41 42 protected override void OnReceiveBytes(IUserToken userToken, byte[] data) 43 { 44 HCoder coder = (HCoder)userToken.Coder; 45 46 coder.GetRequest(data, (result) => 47 { 48 OnRequested?.Invoke(userToken, result); 49 }); 50 } 51 52 public void Reply(IUserToken userToken, byte[] data) 53 { 54 base.Send(userToken, data); 55 base.Disconnected(userToken); 56 } 57 } 58 }
2、Http:這個是個應用協議,本人瞭解下來至少有3個版本,徹底熟悉的話估計沒個半年都搞不定;可是隻須要關鍵,好比說http1.1的工做模式、傳輸格式、常見異常code、常見mime類型、js跨域支持等,這些基本能覆蓋絕大部分平常場景,至於更多的那些細枝末節的理它做甚,本人的作法就是用Chrome的開發人員工具來查看相關network詳情,這樣的話就能夠清楚http這個協議的具體編碼解碼了。web
1 public void GetRequest(byte[] data, Action<string> onUnpackage) 2 { 3 lock (_locker) 4 { 5 var str = Encoding.UTF8.GetString(data); 6 7 var index = str.IndexOf(ENDSTR); 8 9 if (index > -1) 10 { 11 var s = str.Substring(0, index); 12 13 _result.Append(s); 14 15 onUnpackage.Invoke(_result.ToString()); 16 17 _result.Clear(); 18 19 if (str.Length > index + 4) 20 { 21 _result.Append(str.Substring(index + 4)); 22 } 23 } 24 else 25 { 26 _result.Append(str); 27 } 28 } 29 }
通過分析後http的內容格式其實就是字符回車分隔,再加上一些約定生成的分隔符bound完成的。spring
1 public HttpRequest(Stream stream) 2 { 3 this._dataStream = stream; 4 var data = GetRequestData(_dataStream); 5 var rows = Regex.Split(data, Environment.NewLine); 6 7 //Request URL & Method & Version 8 var first = Regex.Split(rows[0], @"(\s+)") 9 .Where(e => e.Trim() != string.Empty) 10 .ToArray(); 11 if (first.Length > 0) this.Method = first[0]; 12 if (first.Length > 1) 13 { 14 this.Query = first[1]; 15 16 if (this.Query.Contains("?")) 17 { 18 var qarr = this.Query.Split("?"); 19 this.URL = qarr[0]; 20 this.Params = GetRequestParameters(qarr[1]); 21 } 22 else 23 { 24 this.URL = this.Query; 25 } 26 27 var uarr = this.URL.Split("/"); 28 29 if (long.TryParse(uarr[uarr.Length - 1], out long id)) 30 { 31 this.URL = this.URL.Substring(0, this.URL.LastIndexOf("/")); 32 this.Params.Set("id", id.ToString()); 33 } 34 } 35 if (first.Length > 2) this.Protocols = first[2]; 36 37 //Request Headers 38 this.Headers = GetRequestHeaders(rows); 39 40 //Request "GET" 41 if (this.Method == "GET") 42 { 43 this.Body = GetRequestBody(rows); 44 } 45 46 //Request "POST" 47 if (this.Method == "POST") 48 { 49 this.Body = GetRequestBody(rows); 50 var contentType = GetHeader(RequestHeaderType.ContentType); 51 var isUrlencoded = contentType == @"application/x-www-form-urlencoded"; 52 if (isUrlencoded) this.Params = GetRequestParameters(this.Body); 53 } 54 }
看到上面,有人確定會說你這個傳文件咋辦?一個呢本人這個是針對webapi;另一個,如真有這個場景,能夠用Chrome的開發人員工具來查看相關network詳情,也可使用httpanalyzerstd、httpwatch等衆多工具分析下,其實也就是使用了一些約定的分隔符bound完成,每一個瀏覽器還不同,有興趣的徹底能夠自行擴展一個。json
3、Reponse這個是webapi服務端至關重要的一個組件,本人也是儘量方便而且按儘可能按asp.net mvc的命名來實現,另外這裏加入支持js跨域所需大部分場景heads,若是還有特殊的heads,徹底能夠自已添加。api
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPI.Http 7 *文件名: HttpResponse 8 *版本號: V1.0.0.0 9 *惟一標識:2e43075f-a43d-4b60-bee1-1f9107e2d133 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/8 16:46:40 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/8 16:46:40 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 using SAEA.Commom; 25 using SAEA.Sockets.Interface; 26 using SAEA.WebAPI.Http.Base; 27 using SAEA.WebAPI.Mvc; 28 using System.Collections.Generic; 29 using System.Net; 30 using System.Text; 31 32 namespace SAEA.WebAPI.Http 33 { 34 public class HttpResponse : BaseHeader 35 { 36 public HttpStatusCode Status { get; set; } = HttpStatusCode.OK; 37 38 public byte[] Content { get; private set; } 39 40 41 42 internal HttpServer HttpServer { get; set; } 43 44 internal IUserToken UserToken { get; set; } 45 /// <summary> 46 /// 建立一個HttpRequest實例 47 /// </summary> 48 /// <param name="httpServer"></param> 49 /// <param name="userToken"></param> 50 /// <param name="stream"></param> 51 /// <returns></returns> 52 internal static HttpResponse CreateInstance(HttpServer httpServer, IUserToken userToken) 53 { 54 HttpResponse httpResponse = new HttpResponse(""); 55 httpResponse.HttpServer = httpServer; 56 httpResponse.UserToken = userToken; 57 return httpResponse; 58 } 59 60 /// <summary> 61 /// 設置回覆內容 62 /// </summary> 63 /// <param name="httpResponse"></param> 64 /// <param name="result"></param> 65 internal static void SetResult(HttpResponse httpResponse, ActionResult result) 66 { 67 httpResponse.Content_Encoding = result.ContentEncoding.EncodingName; 68 httpResponse.Content_Type = result.ContentType; 69 httpResponse.Status = result.Status; 70 71 if (result is EmptyResult) 72 { 73 return; 74 } 75 76 if (result is FileResult) 77 { 78 var f = result as FileResult; 79 80 httpResponse.SetContent(f.Content); 81 82 return; 83 } 84 85 httpResponse.SetContent(result.Content); 86 } 87 88 89 public HttpResponse(string content) : this(content, "UTF-8", "application/json; charset=utf-8", HttpStatusCode.OK) 90 { 91 92 } 93 94 public HttpResponse(string content, string encoding, string contentType, HttpStatusCode status) 95 { 96 this.Content_Encoding = encoding; 97 this.Content_Type = contentType; 98 this.Status = status; 99 this.SetContent(content); 100 } 101 102 internal HttpResponse SetContent(byte[] content, Encoding encoding = null) 103 { 104 this.Content = content; 105 this.Encoding = encoding != null ? encoding : Encoding.UTF8; 106 this.Content_Length = content.Length.ToString(); 107 return this; 108 } 109 110 internal HttpResponse SetContent(string content, Encoding encoding = null) 111 { 112 //初始化內容 113 encoding = encoding != null ? encoding : Encoding.UTF8; 114 return SetContent(encoding.GetBytes(content), encoding); 115 } 116 117 118 public string GetHeader(ResponseHeaderType header) 119 { 120 return base.GetHeader(header); 121 } 122 123 public void SetHeader(ResponseHeaderType header, string value) 124 { 125 base.SetHeader(header, value); 126 } 127 128 /// <summary> 129 /// 構建響應頭部 130 /// </summary> 131 /// <returns></returns> 132 protected string BuildHeader() 133 { 134 StringBuilder builder = new StringBuilder(); 135 builder.Append(Protocols + SPACE + Status.ToNVString() + ENTER); 136 builder.AppendLine("Server: Wenli's Server"); 137 builder.AppendLine("Keep-Alive: timeout=20"); 138 builder.AppendLine("Date: " + DateTimeHelper.Now.ToFString("r")); 139 140 if (!string.IsNullOrEmpty(this.Content_Type)) 141 builder.AppendLine("Content-Type:" + this.Content_Type); 142 143 //支持跨域 144 builder.AppendLine("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); 145 builder.AppendLine("Access-Control-Allow-Origin: *"); 146 builder.AppendLine("Access-Control-Allow-Headers: Content-Type,X-Requested-With,Accept,yswenli");//可自行增長額外的header 147 builder.AppendLine("Access-Control-Request-Methods: GET, POST, PUT, DELETE, OPTIONS"); 148 149 if (this.Headers != null && this.Headers.Count > 0) 150 { 151 foreach (var key in Headers.Names) 152 { 153 builder.AppendLine($"{key}: {Headers[key]}"); 154 } 155 } 156 157 return builder.ToString(); 158 } 159 160 /// <summary> 161 /// 生成數據 162 /// </summary> 163 private byte[] ToBytes() 164 { 165 List<byte> list = new List<byte>(); 166 //發送響應頭 167 var header = BuildHeader(); 168 byte[] headerBytes = this.Encoding.GetBytes(header); 169 list.AddRange(headerBytes); 170 171 //發送空行 172 byte[] lineBytes = this.Encoding.GetBytes(System.Environment.NewLine); 173 list.AddRange(lineBytes); 174 175 //發送內容 176 list.AddRange(Content); 177 178 return list.ToArray(); 179 } 180 181 182 public void Write(string str) 183 { 184 SetContent(str); 185 } 186 187 public void BinaryWrite(byte[] data) 188 { 189 SetContent(data); 190 } 191 192 public void Clear() 193 { 194 this.Write(""); 195 } 196 197 public void End() 198 { 199 HttpServer.Replay(UserToken, this.ToBytes()); 200 HttpServer.Close(UserToken); 201 } 202 203 204 205 } 206 }
4、HttpServer:這個就是承載webapi的容器;有人說不是有IIS和Apache麼?本人想說的是:有self-host方便麼?有無需安裝,無需配置、隨便高性能開跑好麼?asp.net core裏面都有了這個,沒這個就沒有逼格....(此處省略一萬字),前面還研究tcp、http這個固然不能少了跨域
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPI.Http 7 *文件名: HttpServer 8 *版本號: V1.0.0.0 9 *惟一標識:914acb72-d4c4-4fa1-8e80-ce2f83bd06f0 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/10 13:51:50 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/10 13:51:50 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 using SAEA.Sockets.Interface; 25 using SAEA.WebAPI.Common; 26 using SAEA.WebAPI.Http.Net; 27 using System; 28 using System.Collections.Generic; 29 using System.IO; 30 using System.Text; 31 32 namespace SAEA.WebAPI.Http 33 { 34 class HttpServer 35 { 36 ServerSocket _serverSocket; 37 38 public HttpServer() 39 { 40 _serverSocket = new ServerSocket(); 41 _serverSocket.OnRequested += _serverSocket_OnRequested; 42 } 43 44 public void Start(int port = 39654) 45 { 46 _serverSocket.Start(port); 47 } 48 49 50 private void _serverSocket_OnRequested(IUserToken userToken, string htmlStr) 51 { 52 var httpContext = HttpContext.CreateInstance(this, userToken, htmlStr); 53 54 var response = httpContext.Response; 55 56 response.End(); 57 } 58 59 internal void Replay(IUserToken userToken, byte[] data) 60 { 61 _serverSocket.Reply(userToken, data); 62 } 63 64 internal void Close(IUserToken userToken) 65 { 66 _serverSocket.Disconnected(userToken); 67 } 68 69 70 } 71 }
5、Controller:爲了實現相似於mvc的效果Controller這個大名鼎鼎的固然不能少了,其在C#中使用很是少許的代碼便可實現瀏覽器
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPI.Mvc 7 *文件名: Controller 8 *版本號: V1.0.0.0 9 *惟一標識:a303db7d-f83c-4c49-9804-032ec2236232 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/10 13:58:08 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/10 13:58:08 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 25 using SAEA.WebAPI.Http; 26 27 namespace SAEA.WebAPI.Mvc 28 { 29 /// <summary> 30 /// WebApi控制器 31 /// </summary> 32 public abstract class Controller 33 { 34 public HttpContext HttpContext { get; set; } 35 36 /// <summary> 37 /// 返回Json 38 /// </summary> 39 /// <param name="data"></param> 40 /// <returns></returns> 41 protected JsonResult Json(object data) 42 { 43 return new JsonResult(data); 44 } 45 /// <summary> 46 /// 自定義內容 47 /// </summary> 48 /// <param name="data"></param> 49 /// <returns></returns> 50 protected ContentResult Content(string data) 51 { 52 return new ContentResult(data); 53 } 54 55 56 /// <summary> 57 /// 小文件 58 /// </summary> 59 /// <param name="filePath"></param> 60 /// <returns></returns> 61 protected FileResult File(string filePath) 62 { 63 return new FileResult(filePath); 64 } 65 66 /// <summary> 67 /// 空結果 68 /// </summary> 69 /// <returns></returns> 70 protected EmptyResult Empty() 71 { 72 return new EmptyResult(); 73 } 74 } 75 }
6、ActionResult:是mvc裏面針對reponse結果進行了一個http格式的封裝,本人主要實現了ContentResult、JsonResult、FileResult三個,至於其餘的在WebAPI裏基本上用不到。
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPI.Mvc 7 *文件名: JsonResult 8 *版本號: V1.0.0.0 9 *惟一標識:340c3ef0-2e98-4f25-998f-2bb369fa2794 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/10 16:48:06 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/10 16:48:06 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 using SAEA.WebAPI.Common; 25 using System; 26 using System.Collections.Generic; 27 using System.Net; 28 using System.Text; 29 30 namespace SAEA.WebAPI.Mvc 31 { 32 public class JsonResult : ActionResult 33 { 34 public JsonResult(object model) : this(SerializeHelper.Serialize(model)) 35 { 36 37 } 38 public JsonResult(string json) : this(json, Encoding.UTF8) 39 { 40 41 } 42 43 public JsonResult(string json, HttpStatusCode status) 44 { 45 this.Content = json; 46 this.ContentEncoding = Encoding.UTF8; 47 this.ContentType = "application/json; charset=utf-8"; 48 this.Status = status; 49 } 50 51 public JsonResult(string json, Encoding encoding, string contentType = "application/json; charset=utf-8") 52 { 53 this.Content = json; 54 this.ContentEncoding = encoding; 55 this.ContentType = contentType; 56 } 57 } 58 }
7、RouteTable:MVC裏面有一個至關重要的概念叫約定優先,即爲Controller、Action的名稱是按某種規則來寫編碼的,其中將URL與自定義Controller對應起來的緩存映射就是RouteTable,而且做爲緩存,也能極大的提高訪問性能。固然這裏並無嚴格按照asp.net mvc裏面的routetable來設計,而是根據只是實現webapi,並使用緩存反射結構能來實現的,而且只有約定,沒有配置。
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPI.Mvc 7 *文件名: RouteTable 8 *版本號: V1.0.0.0 9 *惟一標識:1ed5d381-d7ce-4ea3-b8b5-c32f581ad49f 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/12 10:55:31 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/12 10:55:31 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 using System; 25 using System.Collections.Generic; 26 using System.Linq; 27 using System.Reflection; 28 using System.Text; 29 30 namespace SAEA.WebAPI.Mvc 31 { 32 /// <summary> 33 /// SAEA.WebAPI路由表 34 /// </summary> 35 public static class RouteTable 36 { 37 static object _locker = new object(); 38 39 static List<Routing> _list = new List<Routing>(); 40 41 42 /// <summary> 43 /// 獲取routing中的緩存 44 /// 若不存在則建立 45 /// </summary> 46 /// <param name="controllerType"></param> 47 /// <param name="controllerName"></param> 48 /// <param name="actionName"></param> 49 /// <param name="isPost"></param> 50 /// <returns></returns> 51 public static Routing TryGet(Type controllerType, string controllerName, string actionName, bool isPost) 52 { 53 lock (_locker) 54 { 55 var list = _list.Where(b => b.ControllerName.ToLower() == controllerName.ToLower() && b.ActionName.ToLower() == actionName.ToLower() && b.IsPost == isPost).ToList(); 56 57 if (list == null || list.Count == 0) 58 { 59 var routing = new Routing() 60 { 61 ControllerName = controllerName, 62 ActionName = actionName, 63 IsPost = isPost 64 }; 65 66 var actions = controllerType.GetMethods().Where(b => b.Name.ToLower() == actionName.ToLower()).ToList(); 67 68 if (actions == null || actions.Count == 0) 69 { 70 throw new Exception($"{controllerName}/{actionName}找不到此action!"); 71 } 72 else if (actions.Count > 2) 73 { 74 throw new Exception($"{controllerName}/{actionName}有多個重複的的action!"); 75 } 76 else 77 { 78 routing.Instance = System.Activator.CreateInstance(controllerType); 79 80 //類上面的過濾 81 var attrs = controllerType.GetCustomAttributes(true); 82 83 if (attrs != null) 84 { 85 var attr = attrs.Where(b => b.GetType().BaseType.Name == "ActionFilterAttribute").FirstOrDefault(); 86 87 routing.Atrr = attr; 88 89 } 90 else 91 { 92 routing.Atrr = null; 93 } 94 95 routing.Action = actions[0]; 96 97 //action上面的過濾 98 if (routing.Atrr == null) 99 { 100 attrs = actions[0].GetCustomAttributes(true); 101 102 if (attrs != null) 103 { 104 var attr = attrs.Where(b => b.GetType().BaseType.Name == "ActionFilterAttribute").FirstOrDefault(); 105 106 routing.Atrr = attr; 107 108 } 109 else 110 { 111 routing.Atrr = null; 112 } 113 } 114 } 115 _list.Add(routing); 116 return routing; 117 } 118 else if (list.Count > 1) 119 { 120 throw new Exception("500"); 121 } 122 return list.FirstOrDefault(); 123 } 124 } 125 } 126 127 }
在MVC的思想裏面ActionFilterAtrribute的這個AOP設計也一直伴隨左右,好比記日誌、黑名單、權限、驗證、限流等等功能,因此路由的時候也會緩存這個。至此一些關鍵性的地方都已經弄的差很少了,爲了更好的瞭解上面說的這些,下面是vs2017中項目的結構截圖:
純粹乾淨單碼,無任何晦澀內容,若是對mvc有必定了解的,這個差很少能夠NoNotes,接下來就是按asp.net mvc命名方式,寫個測試webapi看看狀況,首先仍是測試項目結構圖:
HomeController裏面按asp.net mvc的習慣來編寫代碼:
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPITest.Controllers 7 *文件名: HomeController 8 *版本號: V1.0.0.0 9 *惟一標識:e00bb57f-e3ee-4efe-a7cf-f23db767c1d0 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/10 16:43:26 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/10 16:43:26 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 using SAEA.WebAPI.Mvc; 25 using SAEA.WebAPITest.Attrubutes; 26 using SAEA.WebAPITest.Model; 27 28 namespace SAEA.WebAPITest.Controllers 29 { 30 /// <summary> 31 /// 測試實例代碼 32 /// </summary> 33 //[LogAtrribute] 34 public class HomeController : Controller 35 { 36 /// <summary> 37 /// 日誌攔截 38 /// 內容輸出 39 /// </summary> 40 /// <returns></returns> 41 //[Log2Atrribute] 42 public ActionResult Index() 43 { 44 return Content("Hello,I'm SAEA.WebAPI!"); 45 } 46 /// <summary> 47 /// 支持基本類型參數 48 /// json序列化 49 /// </summary> 50 /// <param name="id"></param> 51 /// <returns></returns> 52 public ActionResult Get(int id) 53 { 54 return Json(new { Name = "yswenli", Sex = "男" }); 55 } 56 /// <summary> 57 /// 底層對象調用 58 /// </summary> 59 /// <returns></returns> 60 public ActionResult Show() 61 { 62 var response = HttpContext.Response; 63 64 response.Content_Type = "text/html; charset=utf-8"; 65 66 response.Write("<h3>測試一下那個response對象使用狀況!</h3>參考消息網4月12日報道外媒稱,法國一架「幻影-2000」戰機意外地對本國一家工廠投下了..."); 67 68 response.End(); 69 70 return Empty(); 71 } 72 73 [HttpGet] 74 public ActionResult Update(int id) 75 { 76 return Content($"HttpGet Update id:{id}"); 77 } 78 /// <summary> 79 /// 基本類型參數、實體混合填充 80 /// </summary> 81 /// <param name="isFemale"></param> 82 /// <param name="userInfo"></param> 83 /// <returns></returns> 84 [HttpPost] 85 public ActionResult Update(bool isFemale, UserInfo userInfo = null) 86 { 87 return Json(userInfo); 88 } 89 [HttpPost] 90 public ActionResult Test() 91 { 92 return Content("httppost test"); 93 } 94 /// <summary> 95 /// 文件輸出 96 /// </summary> 97 /// <returns></returns> 98 public ActionResult Download() 99 { 100 return File(HttpContext.Server.MapPath("/Content/Image/c984b2fb80aeca7b15eda8c004f2e0d4.jpg")); 101 } 102 } 103 }
增長一個LogAtrribute打印一些內容:
1 /**************************************************************************** 2 *Copyright (c) 2018 Microsoft All Rights Reserved. 3 *CLR版本: 4.0.30319.42000 4 *機器名稱:WENLI-PC 5 *公司名稱:Microsoft 6 *命名空間:SAEA.WebAPITest.Common 7 *文件名: LogAtrribute 8 *版本號: V1.0.0.0 9 *惟一標識:2a261731-b8f6-47de-b2e4-aecf2e0e0c0f 10 *當前的用戶域:WENLI-PC 11 *建立人: yswenli 12 *電子郵箱:wenguoli_520@qq.com 13 *建立時間:2018/4/11 13:46:42 14 *描述: 15 * 16 *===================================================================== 17 *修改標記 18 *修改時間:2018/4/11 13:46:42 19 *修改人: yswenli 20 *版本號: V1.0.0.0 21 *描述: 22 * 23 *****************************************************************************/ 24 using SAEA.Commom; 25 using SAEA.WebAPI.Http; 26 using SAEA.WebAPI.Mvc; 27 28 namespace SAEA.WebAPITest.Attrubutes 29 { 30 public class LogAtrribute : ActionFilterAttribute 31 { 32 /// <summary> 33 /// 執行前 34 /// </summary> 35 /// <param name="httpContext"></param> 36 /// <returns>返回值true爲繼續,false爲終止</returns> 37 public override bool OnActionExecuting(HttpContext httpContext) 38 { 39 return true; 40 } 41 42 /// <summary> 43 /// 執行後 44 /// </summary> 45 /// <param name="httpContext"></param> 46 /// <param name="result"></param> 47 public override void OnActionExecuted(HttpContext httpContext, ActionResult result) 48 { 49 ConsoleHelper.WriteLine($"請求地址:{httpContext.Request.Query},回覆內容:{result.Content}"); 50 } 51 } 52 }
program.cs Main中啓動一下服務:
1 MvcApplication mvcApplication = new MvcApplication();
2
3 mvcApplication.Start();
最後F5跑起來看看效果:
使用Apache ab.exe壓測一下性能如何:
至此,一個簡潔、高效的WebApi就初步完成了!
轉載請標明本文來源:http://www.cnblogs.com/yswenli/p/8858669.html
更多內容歡迎star做者的github:https://github.com/yswenli/SAEA若是發現本文有什麼問題和任何建議,也隨時歡迎交流~