zoukankan      html  css  js  c++  java
  • Asp.Net 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
        }
    View Code

    希望,能对各位小伙伴不吝赐教。

    祝各位小伙伴,元旦节快乐!

    在寂寞的日子里沉淀自己,在程序的日子里找到自己,我为梦想而坚持!

    如果对你有重要帮助,可以打赏一下!


  • 相关阅读:
    Rraspberry Pi 4B python3 安装opencv
    如何用arduion制作智能 垃圾桶
    MySQL(二)表结构的管理
    MySQL(一)基础操作
    vc++绘图基础
    网站签~
    (转)Oracle 知识日常积累
    利用反射判断bean属性不为空(null和空串)
    (转)Oracle 单字段拆分成多行
    svn 解决树冲突
  • 原文地址:https://www.cnblogs.com/Kummy/p/3499759.html
Copyright © 2011-2022 走看看