记录下由VSCode开发的WebApiCore

  今天星期六加班,事情早早作完没啥事;写个.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差很少的写法,新建个学习

   ModelStateFilter继承IActionFilter
 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 : "" });

        }
    }
View Code

这样的话,我写代码就比较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

时间不早了,下班了 

相关文章
相关标签/搜索