今天星期六加班,事情早早作完没啥事;写个.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
时间不早了,下班了