今天星期六加班,事情早早作完沒啥事;寫個.NetCore博客,若有不足之處,請你們指出;與君共勉。html
.NetCore做爲一個輕量級應用,是能夠用cli腳手架開發的,詳情能夠看這裏https://www.cnblogs.com/yilezhu/p/9926078.html;git
關於.NetCore爲啥不用倉儲模式,這個我也提過了,dudu稱這個是反模式,慎用;https://q.cnblogs.com/q/117108/github
話很少說,開整。json
1、Model反向工程生成。tomcat
若是你是CodeFirst,這步能夠直接跳過;但咱們大多數是Database First,因此仍是須要命令來生成下,app
dotnet ef dbcontext scaffold "Server=.;Database=sys;user id=sa;password=123456;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o EFCore --data-annotations
注意下參數--data-annotations,加了以後會生成咱們所熟悉的model,否則會自動生成 Fluent API(字段約束在dbcontext裏的那種);async
2、過濾器驗證Model有效性及統一返回結果集ide
反正我是不喜歡在控制器裏寫ModelState.IsValid的,索性搞個全局的吧,跟.NetFrameWork差很少的寫法,新建個學習
public void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { string ret = ""; foreach (var item in context.ModelState.Values) { foreach (var error in item.Errors) { ret += error.ErrorMessage + "|"; } } var data = new { code = 400, msg = "數據驗證失敗!", result = ret }; context.Result = new JsonResult(data); } }
那麼既然接受的有了全局的,返回的我也要統一;新建一個ResultFilter繼承ActionFilterAttributeui
public override void OnResultExecuting(ResultExecutingContext context) { //根據實際需求進行具體實現 if (context.Result is StatusCodeResult) { var objectResult = context.Result as StatusCodeResult; var msg = ""; if (objectResult.StatusCode == 200) { msg = "操做成功!"; } if (objectResult.StatusCode == 404) { msg = "未找到資源!"; } context.Result = new ObjectResult(new { code = objectResult.StatusCode, msg = msg, result = "" }); } else if (context.Result is EmptyResult) { context.Result = new ObjectResult(new { code = 404, msg = "未找到資源!", result = "" }); } else if (context.Result is ContentResult) { context.Result = new ObjectResult(new { Code = 200, Msg = "操做成功!", Result = (context.Result as ContentResult).Content }); } else if (context.Result is ObjectResult) { var objectResult = context.Result as ObjectResult; var msg = ""; if (objectResult.StatusCode == 200) { msg = "操做成功!"; } if (objectResult.StatusCode == 404) { msg = "未找到資源!"; } if (objectResult.StatusCode == 400) { msg = "數據驗證失敗!"; } context.Result = new ObjectResult(new { code = objectResult.StatusCode, msg = msg, result = objectResult.Value != null ? objectResult.Value : "" }); } }
這樣的話,我寫代碼就比較nice了,像這樣
/// <summary> /// 添加人員 /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] public async Task<IActionResult> AddPerson([FromBody]SysPerson model) { _context.Add(model); await _context.SaveChangesAsync(); return Ok(model); }
3、利用中間件進行全局異常攔截
在開發的時候不免程序會出錯,在.NetFramework上開發的時候也是用的過濾器進行攔截返回統一格式的model,並用log4net記錄日誌,同時給我發送QQ郵件(畢竟個人bug不能亂報>_<);.NetCore上用中間件來實現的,這裏我是在stack overflow上看到國際友人這樣實現的,後面我會加上郵件發送,具體代碼
public class ErrorHandlingMiddleware { private readonly RequestDelegate next; public ErrorHandlingMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context /* other dependencies */) { try { await next(context); } catch (Exception ex) { await HandleExceptionAsync(context, ex); } } private static Task HandleExceptionAsync(HttpContext context, Exception ex) { var code = HttpStatusCode.InternalServerError; // 500 if unexpected // if (ex is NotFoundException) code = HttpStatusCode.NotFound; // else if (ex is UnauthorizedException) code = HttpStatusCode.Unauthorized; // else if (ex is MyException) code = HttpStatusCode.BadRequest; code = HttpStatusCode.OK; var result = JsonConvert.SerializeObject(new { code = 500, msg = "程序錯誤", result = ex.Message }); context.Response.ContentType = "application/json"; context.Response.StatusCode = (int)code; return context.Response.WriteAsync(result); } }
4、.NetCore集成Swagger UI而且Swagger UI集成JWT
好的WebApi怎麼能少了交互文檔,Swagger應該是最nice的一個了;但在.Net平臺上的官方文檔沒找到,都是看的各位牛人的文檔集成的;此次.NetCore官方文檔上也有了,照着作就能夠了;可是我要在Swagger裏面集成個人JWT身份認證,我也是翻了些許博客,主要代碼以下
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); //啓用auth支持 c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() { Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey }); // Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); // 添加swagger對身份認證的支持 c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new string[] { } } }); });
5、修改數據
我以爲修改數據EntityFramework一直有個瑕疵,就是修改數據會修改所有字段,以前看到用擴展插件或是寫ForEach設置IsModified能夠解決這個問題,但我以爲這樣仍是欠妥,因此如今仍是用反射解決的,若有更好的@me。代碼以下
/// <summary> /// 修改人員 /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] public async Task<IActionResult> EditPerson([FromBody] SysPerson model) { if (model.Id == null) { return BadRequest("Id不能爲空!"); } if (await _context.SysPerson.FindAsync(model.Id) == null) { return NotFound(); } SysPerson sysPerson = await _context.SysPerson.FindAsync(model.Id); foreach (System.Reflection.PropertyInfo p in model.GetType().GetProperties()) { var pValue = p.GetValue(model); if (p.GetValue(model) != null) { sysPerson.GetType().GetProperty(p.Name).SetValue(sysPerson, pValue, null); } } await _context.SaveChangesAsync(); return Ok(model); }
6、發佈部署及驗證Swagger和JWT
如今只在IIS進行了部署,後面會學習在liux tomcat上進行部署,部署時應用程序池選擇無託管代碼部署;下圖演示JWT集成在Swagger中的身份認證,如圖
項目源碼github地址:https://github.com/Jame-Chen/WebApiCore
時間不早了,下班了