wcf雖然功能多、擴充性強但是也面臨配置忒多,而且restful的功能相當怪異,并且目前沒法移植。asp.net core雖然支援webapi,但是功能也相對繁多、配置複雜。就沒有一個能讓碼農們安安心心的寫webapi,無需考慮性能、配置、甚至根據問題場景自行設計、改造等問題的方案麼?
當然不是,特别是在dnc2.0已經相當強大的此時,完全可以自行設計一套簡潔、高效的webapi架構!說到自行寫一套架構,很多碼農們就可能會想到開發工作量難以想像,事實真的如此麼?java因為開源衆多,很多對mvc稍有了解的都可以拿這個拿那個拼出一個自已的mvc架構;而面對日益強大的dnc,本人覺得C#根本無需東拼西湊這麼麻煩,完全可以根據自已的需求簡單快速的寫出一個來,不服就開幹!
設計的編碼思路就是仿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等,下面就一一來解決這個問題。
一、Tcp:這個是實作傳輸通信的底層,當然采用IOCP來提高吞吐量和性能,本人之前在做
Redis Client 等的時候就使用這個 IOCP Socket 的架構,此時正好也可以用上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 *電子郵箱:[email protected]
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 }
二、Http:這個是個應用協定,本人了解下來至少有3個版本,完全熟悉的話估計沒個半年都搞不定;但是隻需要關鍵,比如說http1.1的工作模式、傳輸格式、常見異常code、常見mime類型、js跨域支援等,這些基本能覆寫絕大部分日常場景,至于更多的那些細枝末節的理它作甚,本人的做法就是用Chrome的開發人員工具來檢視相關network詳情,這樣的話就可以清楚http這個協定的具體編碼解碼了。
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完成的。
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完成,每個浏覽器還不一樣,有興趣的完全可以自行擴充一個。
三、Reponse這個是webapi服務端相當重要的一個元件,本人也是盡可能友善并且按盡量按asp.net mvc的命名來實作,另外這裡加入支援js跨域所需大部分場景heads,如果還有特殊的heads,完全可以自已添加。

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 *電子郵箱:[email protected]
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 }
View Code
四、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 *電子郵箱:[email protected]
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 }
五、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 *電子郵箱:[email protected]
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 }
六、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 *電子郵箱:[email protected]
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 }
七、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 *電子郵箱:[email protected]
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 *電子郵箱:[email protected]
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 *電子郵箱:[email protected]
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如果發現本文有什麼問題和任何建議,也随時歡迎交流~
感謝您的閱讀,如果您對我的部落格所講述的内容有興趣,請繼續關注我的後續部落格,我是yswenli 。