码迷,mamicode.com
首页 > Windows程序 > 详细

ASP.NET Web API 之一 入门篇

时间:2018-08-02 12:18:05      阅读:366      评论:0      收藏:0      [点我收藏+]

标签:file   Matter   logs   type   重写   net   不能   使用   返回   

一、基于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 之一 入门篇

标签:file   Matter   logs   type   重写   net   不能   使用   返回   

原文地址:https://www.cnblogs.com/xcsn/p/9406276.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!