記錄下由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

時間不早了,下班了 

相關文章
相關標籤/搜索