本章內容和大家分享的是Asp.NetCore元件寫法,在netcore中很多東西都以提供元件的方式來使用,比如MVC架構,Session,Cache,資料庫引用等; 這裡我也通過呼叫驗證碼介面來自定義個元件以此說明如何使用,以及使用時需要注意的場景;
Middleware之hello world
對於netcore來說,通常會在UseStartup<Startup>對應的Startup類中引用元件,這個Startup可以換成自己自定義的其實類,不過需要在UseStartup的時候指向她;這裡還是以Startup類為例,通過vs自動生成的檔案,在這個類中我們能看到Configure方法體裡面包含了:app.UseMvc(),app.UseStaticFiles(),app.xxx()等一些列自帶的元件,下面來看下自定義個hello world中元件例項,首先使用靜態擴充套件方法擴充套件IApplicationBuilder:
1 public static class MiddlewareExtends 2 { 3 /// <summary> 4 /// 測試用例中介軟體 5 /// </summary> 6 /// <param name="builder"></param> 7 /// <returns></returns> 8 public static IApplicationBuilder UseTest(this IApplicationBuilder builder) 9 { 10 return builder.UseMiddleware<TestMiddleware>(); 11 } 12 13 }
使用 builder.UseMiddleware<TestMiddleware>() 來新增自定義元件,元件實現程式碼如下:
1 public class TestMiddleware 2 { 3 private RequestDelegate _requestDelegate; 4 public TestMiddleware(RequestDelegate requestDelegate) 5 { 6 _requestDelegate = requestDelegate; 7 } 8 9 public Task Invoke(HttpContext context) 10 { 11 12 context.Items["TestMiddleware"] = "hello world,我是TestMiddleware。"; 13 14 return _requestDelegate(context); 15 } 16 }
以上是最基礎的元件格式;注:
1. 元件必須要有 public Task Invoke(HttpContext context) ,HttpContext是咋們http上下文,Invoke()委託方法,每次程式被訪問時就會進入Invoke;
2. 要有 public delegate Task RequestDelegate(HttpContext context); 委託方法,來響應http請求;
到這裡咋們hello world就完成了,為了測試方法,我們直接在action中寫入如下程式碼:
1 public IActionResult About() 2 { 3 4 ViewData["Message"] = HttpContext.Items["TestMiddleware"]; 5 return View(); 6 }
執行結果:
元件非同步寫法
1 public class TestMiddleware 2 { 3 private RequestDelegate _requestDelegate; 4 public TestMiddleware(RequestDelegate requestDelegate) 5 { 6 _requestDelegate = requestDelegate; 7 } 8 9 public async Task Invoke(HttpContext context) 10 { 11 12 context.Items["TestMiddleware"] = "hello world,我是asyncTestMiddleware。"; 13 14 await _requestDelegate(context); 15 } 16 }
僅僅需要async 和 await 組合修飾就行了;
.netcore自定義驗證碼元件
1 /// <summary> 2 /// 文字驗證碼 3 /// </summary> 4 public class WenZiCodeMiddleware 5 { 6 private RequestDelegate _requestDelegate; 7 public WenZiCodeMiddleware(RequestDelegate requestDelegate) 8 { 9 _requestDelegate = requestDelegate; 10 } 11 12 public async Task Invoke(HttpContext context) 13 { 14 15 var url = "http://localhost:1001/shenniuapi/WenZiValidateCode"; 16 using (HttpClient client = new HttpClient()) 17 { 18 client.Timeout = TimeSpan.FromSeconds(60); 19 20 var str = "{\"UserName\": \"神牛步行3\",\"UserPwd\": \"4297f44b13955235245b2497399d7a93\",\"Token\": \"008我是測試\"}"; 21 var content = new StringContent(str, Encoding.UTF8, "application/x-www-form-urlencoded"); 22 content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 23 var result01 = client.PostAsync(url, content).Result; 24 var stream = await result01.Content.ReadAsStreamAsync(); 25 using (var reader = new StreamReader(stream)) 26 { 27 var result02 = await reader.ReadToEndAsync(); 28 context.Items["codedata"] = result02; 29 } 30 } 31 32 await _requestDelegate(context); 33 } 34 }
我們同樣需要再靜態擴充套件方法裡面新增如下程式碼,來加入元件:
1 /// <summary> 2 /// 文字驗證碼中介軟體 3 /// </summary> 4 /// <param name="builder"></param> 5 /// <returns></returns> 6 public static IApplicationBuilder UseWenZiValidateCode(this IApplicationBuilder builder) 7 { 8 return builder.UseMiddleware<WenZiCodeMiddleware>(); 9 }
在Configure方法中,引用元件: app.UseWenZiValidateCode(); ;Action中,使用元件:
1 public FileResult GetCode() 2 { 3 var data = HttpContext.Items["codedata"].ToString(); 4 var code = JsonConvert.DeserializeObject<MoValidateCodeResponse>(data); 5 return File(code.CodeStream, "image/jpeg"); 6 }
View試圖中程式碼:
1 GetCode:<img src="/home/GetCode" data-src="/home/GetCode" />
效果展示:
這裡需要考慮場景是,我們上面提及到的Invoke方法是任意請求都會進入,那驗證碼這種功能做成元件是否不是很合理,因為驗證碼也只有在登陸介面或驗證的介面需要用到而已,如我們上面寫的驗證碼元件,每次都會被程式執行這顯然不合理,因此個人認為如果你需要自定義元件,那麼需要考量:是否每次請求都需要進入您的元件服務,如果不需要的話,那其實沒必要弄一個元件,當然感覺很高大上;因此這裡我不得不使用靜態擴充套件方法(當然還有其他方式)來重寫獲取驗證碼的方法;
靜態擴充套件方法重寫驗證碼元件
由於上面我們在新增元件時有一個靜態類了,那麼我們直接在上面補充擴充套件方法:
1 /// <summary> 2 /// 文字驗證碼 3 /// </summary> 4 /// <param name="context"></param> 5 /// <returns></returns> 6 public static async Task<MoValidateCodeResponse> WenZiCode(this HttpContext context) 7 { 8 var code = default(MoValidateCodeResponse); 9 try 10 { 11 var url = "http://localhost:1001/shenniuapi/WenZiValidateCode"; 12 using (HttpClient client = new HttpClient()) 13 { 14 client.Timeout = TimeSpan.FromSeconds(60); 15 16 var str = "{\"UserName\": \"神牛步行3\",\"UserPwd\": \"4297f44b13955235245b2497399d7a93\",\"Token\": \"008我是測試\"}"; 17 var content = new StringContent(str, Encoding.UTF8, "application/x-www-form-urlencoded"); 18 content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 19 var result01 = client.PostAsync(url, content).Result; 20 var stream = await result01.Content.ReadAsStreamAsync(); 21 using (var reader = new StreamReader(stream)) 22 { 23 var result02 = await reader.ReadToEndAsync(); 24 code = await JsonConvert.DeserializeObjectAsync<MoValidateCodeResponse>(result02); 25 } 26 } 27 } 28 catch (Exception ex) 29 { 30 } 31 return code; 32 }
對應的驗證碼實體類:
1 /// <summary> 2 /// 神牛介面返回基類 3 /// </summary> 4 public class MoShenNiuBaseResponse 5 { 6 /// <summary> 7 /// 返回狀態: 0:失敗 1:成功 8 /// </summary> 9 public int Status { get; set; } 10 11 /// <summary> 12 /// 錯誤資訊 13 /// </summary> 14 public string Msg { get; set; } 15 } 16 17 /// <summary> 18 /// 驗證碼返回類 19 /// </summary> 20 public class MoValidateCodeResponse : MoShenNiuBaseResponse 21 { 22 23 public MoValidateCodeResponse() 24 { 25 this.ImgCode = new List<MoImgCode>(); 26 } 27 28 /// <summary> 29 /// 驗證碼型別 30 /// </summary> 31 public string Code { get; set; } 32 33 /// <summary> 34 /// 驗證碼圖片流 35 /// </summary> 36 public byte[] CodeStream { get; set; } 37 38 /// <summary> 39 /// 圖片驗證座標 40 /// </summary> 41 public List<MoImgCode> ImgCode; 42 } 43 44 /// <summary> 45 /// 圖片驗證碼座標 46 /// </summary> 47 public class MoImgCode 48 { 49 public string Index { get; set; } 50 51 public string IndexType { get; set; } 52 53 public string ImgUrl { get; set; } 54 55 public Point Point_A { get; set; } 56 57 public Point Point_B { get; set; } 58 59 public bool IsChoice { get; set; } 60 } 61 62 public class Point 63 { 64 public int X { get; set; } 65 public int Y { get; set; } 66 }
這個時候同樣來到Action中:
1 public async Task<FileResult> GetCodeAsync() 2 { 3 var code = await HttpContext.WenZiCode(); 4 5 return File(code.CodeStream, "image/jpeg"); 6 }
修改view試圖程式碼,增加點選驗證碼圖片重新獲取新的驗證碼:
1 <style type="text/css"> 2 img{cursor:pointer} 3 </style> 4 <h3>@ViewData["Message"]</h3> 5 <h3>@ViewData["codedata"]</h3> 6 GetCode:<img src="/home/GetCode" data-src="/home/GetCode" /> 7 GetCodeAsync:<img src="/home/GetCodeAsync" data-src="/home/GetCodeAsync" /> 8 9 <script src="~/lib/jquery/dist/jquery.js"></script> 10 <script> 11 $(function () { 12 $("img").on("click", function () { 13 var img = this; 14 var nowTime = new Date().getTime(); 15 var src = $(img).attr("data-src") + "?t=" + nowTime; 16 $(img).attr("src", src); 17 }); 18 }) 19 </script>
效果圖:
以上就是本篇的所有內容,旨在分享怎麼寫一個元件和什麼時候用元件合適,謝謝大家支援和點贊。