博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Web API 之一 入门篇
阅读量:7112 次
发布时间:2019-06-28

本文共 7904 字,大约阅读时间需要 26 分钟。

一、基于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
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机制

  这部分没做成功,这里只是记录下

  其实,使用postman可以,客户端是别人做的,使用的是java httpclient,请求后,后台得不到当前用户session

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
().OfType
(); 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; } }

 

另外,推荐几篇相关的文章

 

你可能感兴趣的文章
简单聊聊DOM
查看>>
【JavaScript】JavaScript Array 对象(数组)
查看>>
github 上有趣又实用的前端项目(持续更新,欢迎补充)
查看>>
opencv python 直方图均衡化
查看>>
HotFrameLearning 热门框架学习(前言)
查看>>
git团队开发流程
查看>>
【Under-the-hood-ReactJS-Part6】React源码解读
查看>>
深入理解css之vertical-align
查看>>
Laravel事件
查看>>
matlab绘制peano(皮亚诺)曲线和koch(科赫曲线,雪花曲线)分形曲线
查看>>
使用pipenv代替virtualenv管理python包
查看>>
Docker零基础入门指南(四):Docker容器使用
查看>>
React 深入系列4:组件的生命周期
查看>>
Mybatis之设计模式之迭代器模式
查看>>
房间号生成器
查看>>
CentOS 6.8 安装vsftpd
查看>>
js设计模式 --- 装饰设计模式
查看>>
Flask源代码阅读笔记(一)——应用启动
查看>>
IOS精品源码,仿探探UIButton封装iOS提示弹框迅速引导页自定义导航栏
查看>>
setState的一个Synthetic Event Warning
查看>>