最近一直急着在負責弄Asp.Net Web Api 與 Andriod 接口開發的對接工做!html
剛據說要用Asp.Net Web Api去跟 Andriod 那端作接口對接工做,本身也是第一次接觸Web Api,我就開始了邊學習邊開發,甚至連本身都沒有來得急去理解和消化一些知識,就得去作項目了,感受仍是挺趕,挺忙的,不少東西都是在地鐵上學習到的,很感謝 ( Artech 和 張善友 )大神的博文 給予的幫助與啓發 。web
項目目錄以下:api
因爲我這裏所作的web api提供的是一整套項目接口,不少 api 接口都須要登陸受權的,也有部分是匿名的。架構
==》 對於 對外開發 的 web api 接口,可能都具備 「匿名訪問」 或者 是 "CORS受權機制",或者是還要去限制 web api 調用的頻率。ide
【CORS受權機制-知識】:http://www.cnblogs.com/artech/tag/ASP.NET Web APIpost
【限制 Web Api 訪問頻率】:http://www.cnblogs.com/shanyou/p/3194802.html學習
對於哪些web api 須要 匿名開發,哪些須要登陸受權才能訪問,你們能夠作一個通用的Attribute去作這個事情。ui
以下面代碼,僅供參考:spa
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 }
==》【 OData 】
code
考慮到手機項目的限制,在針對(查詢分頁,查詢篩選,排序)方面,我用了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 }
但願,能對各位小夥伴不吝賜教。
祝各位小夥伴,元旦節快樂!