1. 程式人生 > >ASP.NET Web API 之一 入門篇

ASP.NET Web API 之一 入門篇

mda 處理 ssa 控制 講解 serve attr contex gis

一、基於RESTful標準的Web Api

  原文講解:https://www.cnblogs.com/lori/p/3555737.html

  微軟的web api是在vs2012上的mvc4項目綁定發行的,它提出的web api是完全基於RESTful標準的,完全不同於之前的(同是SOAP協議的)wcf和webService,它是簡單,代碼可讀性強的,上手快的,如果要拿它和web服務相比,我會說,它的接口更標準,更清晰,沒有混亂的方法名稱,有的只有幾種標準的請求,如get,post,put,delete等,它們分別對應的幾個操作,下面講一下:

  GET:生到數據列表(默認),或者得到一條實體數據

  POST:添加服務端添加一條記錄,記錄實體為Form對象

  PUT:添加或修改服務端的一條記錄,記錄實體的Form對象,記錄主鍵以GET方式進行傳輸

  DELETE:刪除 服務端的一條記錄

  自帶的示例

public class ValuesController : ApiController
    {
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2
" }; } // GET api/values/5 public string Get(int id) { return "value"; } // POST api/values public void Post([FromBody]string value) { } // PUT api/values/5 public void Put(int id, [FromBody]string
value) { } // DELETE api/values/5 public void Delete(int id) { } }

二、自定義的Web Api

  自定義這裏並沒有多高明,說白了就是習慣了mvc的寫法,不想用奇葩的restfull api

  修改WebApiConfig即可實現

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服務

            // Web API 路由
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.Filters.Add(new ValidataModelAttribute());
            config.Filters.Add(new WebApiExceptionFilterAttribute());
            // config.Filters.Add(new AuthFilterAttribute());//由於用java httpclient請求無法識別session,故而沒使用了

            config.Formatters.Remove(config.Formatters.XmlFormatter);
 
        }
    }

   WebApi沒有session的,可在Global.asax開啟session

 public class WebApiApplication : System.Web.HttpApplication
    {
        //省略....
        
        protected void Application_PostAuthorizeRequest()
        {
            if (isWebAPiRequest())
            {
                HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
            }
        }
        private bool isWebAPiRequest()
        {
            return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith("~/api");
        }
    }

三、使用模型驗證

  直接將步驟了,呵呵

  1. 定義特性過濾:ValidataModelAttribute

  響應結果:返回狀態200,和錯誤結果提示,而不是400等其他狀態,那樣返回格式不一致,狀態也不對

public class ValidataModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (!actionContext.ModelState.IsValid)
            {
                string error = string.Empty;
                foreach (var key in actionContext.ModelState.Keys)
                {
                    var state = actionContext.ModelState[key];
                    if (state.Errors.Any())
                    {
                        error = state.Errors.First().ErrorMessage;
                        break;
                    }
                }
                var result = new ErrorResult(error);
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, result);
                //actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
            }
        } 
    }

  2.定義模型類

   可參看:https://www.cnblogs.com/kexxxfeng/p/5602656.html

 public class PageModel : BaseModel
    {
        [Required(ErrorMessage = "當前頁不能為空")]
        [Range(1, 9999,ErrorMessage = "當前頁必須大於0")]
        public int Page { get; set; }
    }

  3.使用特性

    這樣就能自動驗證了

[ValidataModel]
        [HttpGet]
        public IHttpActionResult GetPage([FromUri]PageModel model)
        { 
            var dataGrid = xxx;
            return JsonDataResult(dataGrid);
        }

  這裏順便講下使用dynamic的問題,遇到 dynamic類型報錯:“object”不包含“xxx”的定義

  按網上的說法沒法解決:https://www.cnblogs.com/similar/p/6716320.html

四、異常攔截

  直接上代碼

  日誌組件自己去搞定哈,WebApiConfig裏面的配置註意配對

  Application_Start下增加過濾: GlobalConfiguration.Configuration.Filters.Add(new WebApiExceptionFilterAttribute()); 這個不確定是否真的需要

 public class WebApiExceptionFilterAttribute : ExceptionFilterAttribute
    {
        //重寫基類的異常處理方法
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            //1.異常日誌記錄(正式項目裏面一般是用log4net記錄異常日誌)
           var msg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "——" +
                              actionExecutedContext.Exception.GetType().ToString() + "" + actionExecutedContext.Exception.Message + "——堆棧信息:" +
                              actionExecutedContext.Exception.StackTrace;
            LogHelper.Fatal(msg);
             
            //2.返回調用方具體的異常信息
            if (actionExecutedContext.Exception is NotImplementedException)
            {
                actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
            else if (actionExecutedContext.Exception is TimeoutException)
            {
                actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.RequestTimeout);
            }
            //.....這裏可以根據項目需要返回到客戶端特定的狀態碼。如果找不到相應的異常,統一返回服務端錯誤500
            else
            {
                actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }

            base.OnException(actionExecutedContext);
        }
    }

五、TOKEN機制

  這部分沒做成功,這裏只是記錄下

  

 public class AuthFilterAttribute : AuthorizeAttribute
    { 
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            //取出區域的控制器controller,Action
            string controller = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string action = actionContext.ActionDescriptor.ActionName;
            if (controller.ToLower() == "account" && action.ToLower() == "login")
            { 
                base.OnAuthorization(actionContext);
            }
            else
            { 
                var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase;
                var token = content.Request.QueryString["Token"];
                if (!string.IsNullOrEmpty(token))
                {
                    //URL路徑
                    string filePath = HttpContext.Current.Request.FilePath;
                    //校驗用戶名密碼是否匹配
                    if (ValidateTicket(token) && ValiddatePermission(token, controller, action, filePath))
                    {
                        base.IsAuthorized(actionContext);
                    }
                    else
                    {
                        HandleUnauthorizedRequest(actionContext);
                    }
                }
                //如果取不到身份驗證信息,並且不允許匿名訪問,則返回未驗證401
                else
                {
                    var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
                    bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute);
                    if (isAnonymous)
                    {
                        base.OnAuthorization(actionContext);
                    }
                    else
                    {
                        HandleUnauthorizedRequest(actionContext);
                    }
                }
            } 
        }
         
        private bool ValidateTicket(string encryptToken)
        {
            if (UserProvider.CurrentUser != null && UserProvider.CurrentUser.LoginToken == encryptToken)
            {
                return true;
            }

            return false; 
        }

        public bool ValiddatePermission(string token, string controller, string action, string filePath)
        {
            //bool isPass = false;
            //TODO 權限驗證


            return true;
        }
    }

另外,推薦幾篇相關的文章

WebApi系列~StringContent參數需要添加MetaType對象

WebApi系列~HttpClient的性能隱患

WebApi系列~通過HttpClient來調用Web Api接口

WebApi系列~通過HttpClient來調用Web Api接口~續~實體參數的傳遞

WebApi系列~在WebApi中實現Cors訪問

ASP.NET Web API 之一 入門篇