• ASP.NET Web API 之一 入门篇


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

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

      其实,使用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<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访问

     

    六、使用request form

    示例:https://www.cnblogs.com/FlowerThree/articles/10275476.html

      var token = HttpContext.Current.Request.Headers["token"];
      var uid = HttpContext.Current.Request.Form["uid"];
      var aa = HttpContext.Current.Request.Form["list[aa]"];

     

     

     

     

  • 相关阅读:
    初始化块:
    继承与组合:
    instanceof用法及本质:
    引用变量的强制类型转换:
    多态是如何产生的:
    program by the way......
    多层次继承,构造器之间的调用顺序!
    调用父类构造器:super
    子类覆写的变量被private隐藏,强制转换方式通过子类访问父类的被覆写变量:
    super限定,子类中系统查找变量的顺序:
  • 原文地址:https://www.cnblogs.com/xcsn/p/9406276.html
Copyright © 2020-2023  润新知