zoukankan      html  css  js  c++  java
  • Web Api 与 Andriod 接口对接开发经验

    最近一直急着在负责弄Asp.Net Web Api 与 Andriod 接口开发的对接工作!

    刚听说要用Asp.Net Web Api去跟 Andriod 那端做接口对接工作,自己也是第一次接触Web Api,我就开始了边学习边开发,甚至连自己都没有来得急去理解和消化一些知识,就得去做项目了,感觉还是挺赶,挺忙的,很多东西都是在地铁上学习到的,很感谢 ( Artech 和 张善友 )大神的博文 给予的帮助与启发 。

    项目目录如下:

     由于我这里所做的web api提供的是一整套项目接口,很多 api 接口都需要登录授权的,也有部分是匿名的。

    ==》 对于 对外开发 的 web api 接口,可能都具有  “匿名访问” 或者 是 "CORS授权机制",或者是还要去限制 web api 调用的频率。

               【CORS授权机制-知识】:http://www.cnblogs.com/artech/tag/ASP.NET Web API

           【限制 Web Api 访问频率】:http://www.cnblogs.com/shanyou/p/3194802.html

    对于哪些web api 需要 匿名开发,哪些需要登录授权才能访问,大家可以做一个通用的Attribute去做这个事情。

    如下面代码,仅供参考:

     1 /// <summary>   
     2     /// 基本验证Attribtue,用以WebApi请求的权限处理   
     3     /// </summary>   
     4     public class BasicAuthenticationAttribute : ActionFilterAttribute
     5     {
     6         private static Uni2uni.Framework.Cache.ICache cache = CacheFactory.Redis(RedisDb.User);
     7 
     8         /// <summary>   
     9         /// 检查用户是否有该WebApi请求执行的权限   
    10         /// </summary>   
    11         /// <param name="actionContext"></param>   
    12         public override void OnActionExecuting(HttpActionContext actionContext)
    13         {
    14             if (actionContext.Request.Headers.Contains("Set-Cookie"))
    15             {
    16                 var accessToken = actionContext.Request.Headers.GetValues("Set-Cookie");
    17                 Dictionary<string, string> item = new Dictionary<string, string>();
    18                 accessToken.FirstOrDefault().ToString().Split('&').Each(i =>
    19                 {
    20                     var itemLine = i.Split('=');
    21                     item.Add(itemLine[0], itemLine[1]);
    22                 });
    23                 //解密用户token值,看有没有登录
    24                 string tokenValue = System.Web.HttpUtility.UrlDecode(item["access_token"]);
    25                 if (ValidateToken(tokenValue))
    26                 {
    27                     base.OnActionExecuting(actionContext);
    28                 }
    29                 else
    30                 {
    31                     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
    32                     actionContext.Response.Content = new StringContent("The request has no token or toke id expired,is invalid !",
    33                                                           Encoding.UTF8, "text/plain");
    34                 }
    35             }
    36             else
    37             {
    38                 //检查web.config配置是否要求权限校验   
    39                 bool isRquired = (WebConfigurationManager.AppSettings["WebApiAuthenticatedFlag"].ToString() == "true");
    40                 if (isRquired)
    41                 {
    42                     //如果请求Header不包含token,则判断是否是匿名调用   
    43                     var attr = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
    44                     bool isAnonymous = attr.Any(a => a is AllowAnonymousAttribute);
    45 
    46                     //是匿名用户,则继续执行;非匿名用户,抛出“未授权访问”信息   
    47                     if (isAnonymous)
    48                     {
    49                         base.OnActionExecuting(actionContext);
    50                     }
    51                     else
    52                     {
    53                         actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
    54                         actionContext.Response.Content = new StringContent("The request is Unauthorized,is nto allow!",
    55                                                         Encoding.UTF8, "text/plain");
    56                     }
    57                 }
    58                 else
    59                 {
    60                     base.OnActionExecuting(actionContext);
    61                 }
    62             }
    63         }
    64 
    65         /// <summary>
    66         /// 验证是否登录授权
    67         /// </summary>
    68         /// <param name="token"></param>
    69         /// <returns></returns>
    70         public bool ValidateToken(string token)
    71         {
    72             if (!string.IsNullOrEmpty(token))
    73             {
    74                 var model = cache.Get<LoginMember>(token);
    75                 Logger.Error("2:请求中的。。。:model:" + model == null ? "不存在" : model.UserName);
    76                 return model != null ? true : false;
    77             }
    78             return false;
    79         }
    80     }
    View Code

    ==》【 OData 】

    考虑到手机项目的限制,在针对(查询分页,查询筛选,排序)方面,我用了Asp.Net Web Api OData,由于咋们的项目架构只支持.Net 4.0,最新的已经到 Asp.Net Web Api 2 OData了。

    OData相关知识链接:

    http://www.cnblogs.com/Kummy/p/3486097.html

    http://www.cnblogs.com/shanyou/archive/2013/06/11/3131583.html

    ==》【 Web Api Post [FromBody] 支持简单的数据类型。】 

    在Web Api 开发中,我们会发现一个问题, Post 已经不支持简单的数据类型了。

    如下面例子:  

    [AllowAnonymous]
    [HttpPost]
    public string Test([FromBody]string Name)
    {
         return null;
    }

    我们会发现,这个Post过来的类型怎么都是null

    于是我找了很久,发现了解决这个问题的办法。

     地址: http://weblog.west-wind.com/posts/2012/Sep/11/Passing-multiple-simple-POST-Values-to-ASPNET-Web-API

    ==》【 Web Api , 简单的( 通用上传 以及 通用分页 )】

    仅供参考代码,如下:

       [BasicAuthentication]
        public abstract class ApiControllerBase : ApiController
        {
            #region  Common Pager
            /// <summary>
            ///  给结果集扩展一个分页
            /// </summary>
            /// <typeparam name="T">实体</typeparam>
            /// <param name="_defaultSetting">页面设置</param>
            /// <param name="options">筛选条件集合</param>
            /// <param name="_list">待分页集合</param>
            /// <returns></returns>
            public PageResult<TEntity> GetPager<TEntity>(ODataQueryOptions<TEntity> options, IEnumerable<TEntity> _list, int PageSizeCount = 6) where TEntity : class
            {
                ODataQuerySettings settings = new ODataQuerySettings
                {
                    PageSize = PageSizeCount
                };
                IQueryable results = options.ApplyTo(_list.AsQueryable(), settings);
                Request.GetInlineCount();
                return new PageResult<TEntity>(
                    results as IEnumerable<TEntity>,
                    Request.GetNextPageLink(),
                    Request.GetInlineCount());
            }
            #endregion
    
            #region Common Upload
            /// <summary>
            /// 通用上传图片-操作
            /// </summary>
            /// <typeparam name="T">上传实体</typeparam>
            /// <param name="dirPath">上传路劲</param>
            /// <param name="fileNameAction">文件名自定义扩展</param>
            /// <param name="Entity">实体名字</param>
            /// <returns>图片上传是否成功</returns>
            [NonAction]
            public Hashtable CommonUpload<T>(string dirPath, Action<string> fileNameAction, out T Entity) where T : class
            {
                var queryp = Request.GetQueryNameValuePairs(); //获得查询字符串的键值集合 
                Entity = GetUploadEntity<T>(queryp); //实体赋值操作
    
                // 检查是否是 multipart/form-data 
                if (!Request.Content.IsMimeMultipartContent("form-data"))
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                //文件保存目录路径 
                string SaveTempPath = dirPath;
                String dirTempPath = HttpContext.Current.Server.MapPath(SaveTempPath);
                Logger.Error("文件路径:" + dirTempPath);
                // 设置上传目录 
                var provider = new MultipartFormDataStreamProvider(dirTempPath);
    
                //Logger.Error("queryp参数:" + param);
                var task = Request.Content.ReadAsMultipartAsync(provider).
                    ContinueWith<Hashtable>(o =>
                    {
                        Hashtable hash = new Hashtable();
                        hash["error"] = 1;
                        hash["errmsg"] = "上传出错";
                        var file = provider.FileData[0];//provider.FormData 
                        string orfilename = file.Headers.ContentDisposition.FileName.TrimStart('"').TrimEnd('"');
                        FileInfo fileinfo = new FileInfo(file.LocalFileName);
    
                        Logger.Error("最大文件大小:" + fileinfo.Length);
                        Logger.Error("最大格式:" + orfilename);
                        //最大文件大小 
                        int maxSize = 10000000;
                        if (fileinfo.Length <= 0)
                        {
                            hash["error"] = 1;
                            hash["errmsg"] = "请选择上传文件。";
                        }
                        else if (fileinfo.Length > maxSize)
                        {
                            hash["error"] = 1;
                            hash["errmsg"] = "上传文件大小超过限制。";
                        }
                        else
                        {
                            string fileExt = orfilename.Substring(orfilename.LastIndexOf('.'));
                            //定义允许上传的文件扩展名 
                            String fileTypes = "gif,jpg,jpeg,png,bmp";
                            if (String.IsNullOrEmpty(fileExt) || Array.IndexOf(fileTypes.Split(','), fileExt.Substring(1).ToLower()) == -1)
                            {
                                hash["error"] = 1;
                                hash["errmsg"] = "上传文件扩展名是不允许的扩展名。";
                            }
                            else
                            {
                                //String ymd = DateTime.Now.ToString("yyyyMMdd", System.Globalization.DateTimeFormatInfo.InvariantInfo);
                                //String newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", System.Globalization.DateTimeFormatInfo.InvariantInfo);
                                //String finalFileName = newFileName + fileExt;
                                string excute_FileName = string.Empty;
                                fileNameAction = (i) => { excute_FileName = i; };
                                fileinfo.CopyTo(Path.Combine(dirTempPath, excute_FileName), true);
                                fileinfo.Delete();
                                hash["error"] = 0;
                                hash["errmsg"] = "上传成功";
                                hash["filePathUrl"] = excute_FileName;
                            }
                        }
                        return hash;
                    });
                return null;
            }
    
            /// <summary>
            /// 反射动态的实体赋值-操作
            /// </summary>
            /// <typeparam name="Entity"></typeparam>
            /// <param name="queryp"></param>
            /// <returns></returns>
            [NonAction]
            public Entity GetUploadEntity<Entity>(IEnumerable<KeyValuePair<string, string>> queryp) where Entity : class
            {
                var entity = typeof(Entity);
                Object model = entity.Assembly.CreateInstance(entity.FullName, true);
                var props = entity.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                foreach (PropertyInfo propertyInfo in typeof(Entity).GetProperties())
                {
                    queryp.Each(i =>
                    {
                        if (i.Key.Equals(propertyInfo.Name.ToString()))
                        {
                            propertyInfo.SetValue(model, i.Value, null);
                        }
                    });
                }
                return (Entity)model;
            }
            #endregion
        }
  • 相关阅读:
    LeetCode 326. Power of Three
    LeetCode 324. Wiggle Sort II
    LeetCode 322. Coin Change
    LeetCode 321. Create Maximum Number
    LeetCode 319. Bulb Switcher
    LeetCode 318. Maximum Product of Word Lengths
    LeetCode 310. Minimum Height Trees (DFS)
    个人站点大开发!--起始篇
    LeetCode 313. Super Ugly Number
    LeetCode 309. Best Time to Buy and Sell Stock with Cooldown (DP)
  • 原文地址:https://www.cnblogs.com/marsli/p/5264965.html
Copyright © 2011-2022 走看看