一次開放介面從需求分析到釋出sdk線上包

神牛003發表於2017-02-08

新年開場篇,歡迎來點贊;本篇和大家分享的是使用webapi做得介面服務驗證框架,需求來源是我打算把上篇提到的圖片驗證碼做成一種服務提供給大家,儘管我在上篇已經把程式碼打包開源了,但是如果有一種快速對接成功的服務,我想很多人也非常想使用吧,目前這服務已經上線並在nuget上釋出有sdk客戶端包(nuget包地址:Install-Package ShenNiuApi.SDK),值得慶幸的是僅上線一天就有46次的下載量(挺高興的),興許有感興趣的朋友可以去nuget官網地址檢視:神牛步行3的Nuget包;下面要分享的是在釋出服務時候涉及到的驗證呼叫方的架構,希望大家能夠喜歡,也希望各位多多"掃碼支援"和"推薦"謝謝(對了最近做了一個服裝店地址:神牛衣櫃3,希望需要買衣服鞋子的朋友多多捧場);

 

» 驗證架構的需求分析 和 表結構的設計

» 使用webapi的ActionFilterAttribute做賬號的統一驗證

» ShenNiuApi.SDK客戶端程式碼的分享

» 使用NuGet Package Explorer工具生成ShenNiuApi.SDK的nuget包併發布到nuget網站上

 

下面一步一個腳印的來分享:

» 驗證架構的需求分析 和 表結構的設計

. 驗證架構的需求分析

首先,對於一個介面服務來說通常會有一定的賬號限制,必須要呼叫方使用符合規定並正確的賬號傳遞給介面方才能呼叫成功介面,這裡我們就以網際網路行業一般介面驗證的來制定我們的需求:

1. 介面驗證需要:賬號,密碼,ip組,Token;通常密碼需要加密,市面上加密方式很多如Md5,3des等加密方式;ip組顧名思義就是用來驗證呼叫方請求的ip是否符合介面方新開賬號時候繫結的指定ip,對於現今網際網路行業來說分散式呼叫不是什麼新鮮事了,所以這裡需要的是ip組;Token一般都是由介面方制定的防篡改引數的保護措施,對於請求和接受雙方需要有同樣的Token值才能進行介面響應,通常需要有一個祕鑰來促成加密;

2. 除了賬號驗證外有些需要介面需要按照呼叫次數來收取費用,因此我們這裡有了次數限制的需求,但通常作為不同業務介面來說成本可能會高,儘管是同一個提供商提供的介面很有可能精細到每個介面的呼叫次數限制,所以我們這裡設計就按照這種方式來的,真實業務具體看需求而定;

3. 通常我們對方開放介面時,會直接提供sdk客戶端,方便呼叫方直接引用後直接可以呼叫方法不用再去管具體是什麼請求協議啊或者呼叫介面方法不對等問題,這種提供sdk的方式直接只需要賬號,密碼,祕鑰等就直接可以使用了,方便快捷而且在一定程度上避免了介面地址的暴露,可謂是好處多多;不好的第三就如同手機客戶端,只要服務端更新了一些必要性的引數屬性,那每次都需要呼叫方更新sdk包,不過這都不是事兒;

. 表結構的設計

有了上面的簡要分析,咋們來看下資料庫的表結構,這裡主要用資料庫來儲存對應開通的介面賬號,密碼等資訊和呼叫介面對應的次數:

表:MoApiUser(賬號表) MoApiManager(介面方法表) MoApiRelation(賬號與方法表關係表,其中包含有呼叫次數) MoLog(日誌表)

表資料:

 

» 使用ActionFilterAttribute做賬號的統一驗證

有了上面需求和表的設計,下面我們來看下怎麼使用Action的過濾器來統一做驗證,在這之前我們需要了解下:為什麼不弄一個父級的ApiController然後在裡面做驗證在來繼承呢,而用Action過濾器來做呢,其實這兩種方式都行,不過後者可以對那些不需要介面賬號的介面做開放,容易控制;好了咋們一起看下Action過濾器裡面著麼做驗證的,首先建立類 UserValidateAttribute 並繼承 ActionFilterAttribute ,然後在給她一個屬性ApiKeyId,這個屬性用來傳遞呼叫方呼叫的介面編號(也就是對應介面的Id,這裡對應資料庫表MoApiManager中的ApiKeyId),這樣做的目的是使用編號來方便資料庫中做呼叫某個介面的統計,針對我們上面需求分析說的次數限制到某個介面上,而不是限制在賬號上面(當然前者和必須和賬號關聯才行),因此我們定義一個這樣的列舉方便對應介面中的數字:

 1 /// <summary>
 2         /// 介面與資料庫關聯編號
 3         /// </summary>
 4         public enum ApiKeyId
 5         {
 6 
 7             文字驗證碼 = 1,
 8             圖片驗證碼 = 2
 9 
10         }

然後在過濾器中重新  public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) ,在OnActionExecuting中做非空驗證,賬號密碼是否匹配,Token的驗證,ip組的匹配,次數的對比,因此有了如下整體的自定義過濾器的程式碼:

  1  public class UserValidateAttribute : ActionFilterAttribute
  2     {
  3 
  4         /// <summary>
  5         /// 資料庫與程式關聯標號 
  6         /// </summary>
  7         public MoEnumHelper.ApiKeyId ApiKeyId { get; set; }
  8 
  9         public UserValidateAttribute(MoEnumHelper.ApiKeyId apiKeyId)
 10         {
 11             this.ApiKeyId = apiKeyId;
 12         }
 13 
 14         public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
 15         {
 16 
 17             var response = new MoShenNiuBaseResponse();
 18             var sbLog = new StringBuilder(string.Empty);
 19             try
 20             {
 21 
 22                 if (this.ApiKeyId <= 0) { response.Msg = "介面暫未開通,請聯絡管理員"; return; }
 23                 sbLog.AppendFormat("當前服務:{0};", this.ApiKeyId);
 24 
 25                 var request = actionContext.Request;
 26 
 27                 #region 驗證
 28 
 29                 #region 非空驗證  
 30                 if (actionContext.ActionArguments.Count <= 0) { response.Msg = "請求格式不正確,請檢查"; return; }
 31                 var moRequest = actionContext.ActionArguments["request"] as MoShenNiuBaseRequest;
 32 
 33                 dynamic httpContext = actionContext.Request.Properties["MS_HttpContext"];
 34                 var userIp = httpContext.Request.UserHostAddress;
 35                 sbLog.AppendFormat("UserName:{0};Ip:{1};Token:{2};UserPwd:{3};", moRequest.UserName, userIp, moRequest.Token, moRequest.UserPwd.ToUpper());
 36                 if (string.IsNullOrWhiteSpace(moRequest.UserName) || string.IsNullOrWhiteSpace(moRequest.UserPwd))
 37                 {
 38                     response.Msg = "介面賬號或密碼不能為空";
 39                     return;
 40                 }
 41                 else if (string.IsNullOrWhiteSpace(moRequest.Token))
 42                 {
 43                     response.Msg = "Token不能為空";
 44                     return;
 45                 }
 46                 #endregion
 47 
 48                 using (StageEntities db = new StageEntities())
 49                 {
 50 
 51                     #region 驗證賬號是否存在
 52 
 53                     var userInfo = db.MoApiUsers.Where(b => b.UserName.ToUpper() == moRequest.UserName.ToUpper() && b.UserPwd.ToUpper() == moRequest.UserPwd.ToUpper()).SingleOrDefault();
 54                     if (userInfo == null)
 55                     {
 56                         response.Msg = "介面賬號或密碼錯誤";
 57                         return;
 58                     }
 59                     #endregion
 60 
 61                     #region  獲取對應賬號祕鑰,驗證token
 62 
 63                     var newToken = Md5Extend.GetMd5Hash(string.Format("{0}_{1}_{2}",
 64                                                  moRequest.UserName.ToUpper(),
 65                                                  userInfo.TokenKey.ToUpper(),
 66                                                  moRequest.UserPwd.ToUpper()));
 67 
 68                     sbLog.AppendFormat("伺服器TokenKey:{0};Token:{1};", userInfo.TokenKey.ToUpper(), newToken);
 69 
 70                     if (!moRequest.Token.Equals(newToken, StringComparison.OrdinalIgnoreCase))
 71                     {
 72                         response.Msg = "Token驗證失敗";
 73                         return;
 74                     }
 75                     #endregion
 76 
 77                     #region 賬號可用性
 78                     if (userInfo.Status != (int)MoEnumHelper.EmStatus.啟用)
 79                     {
 80                         response.Msg = "介面賬號暫被停用";
 81                         return;
 82                     }
 83                     else if (!string.IsNullOrWhiteSpace(userInfo.Ips))
 84                     {
 85                         if (!userInfo.Ips.Contains(userIp))
 86                         {
 87                             response.Msg = "介面ip無效";
 88                             return;
 89                         }
 90                     }
 91 
 92                     var realationInfo = userInfo.MoApiRelations.Where(b => b.MoApiManager.ApiKeyId == (int)ApiKeyId && b.MoApiManager.Status == (int)MoEnumHelper.EmStatus.啟用).SingleOrDefault();
 93                     if (realationInfo == null)
 94                     {
 95                         response.Msg = "介面暫未啟用,請稍後重試";
 96                         return;
 97                     }
 98                     else if (realationInfo.MaxNum <= realationInfo.NowNum)
 99                     {
100                         response.Msg = "介面呼叫次數已滿,請聯絡管理員";
101                         return;
102                     }
103                     #endregion
104 
105                     //通過驗證
106                     response.Status = (int)MoEnumHelper.EmStatus.啟用;
107 
108                     #region 使用者通過驗證就增加次數
109 
110                     realationInfo.NowNum++;
111                     var result = db.SaveChanges();
112                     sbLog.AppendFormat("最大次數:{0};當前次數:{1};增加次數:{2};", realationInfo.MaxNum, realationInfo.NowNum, result);
113                     #endregion
114                 }
115 
116                 #endregion
117 
118 
119             }
120             catch (Exception ex)
121             {
122                 response.Msg = "500介面處理請求異常,請稍後重試";
123                 sbLog.AppendFormat("異常資訊:{0};", ex.Message);
124             }
125             finally
126             {
127 
128                 sbLog.AppendFormat("返回Status:{0};Msg:{1};", response.Status, response.Msg);
129                 //記錄日誌
130                 StageClass._WrigLog(sbLog.ToString());
131 
132                 //驗證失敗返回
133                 if (response.Status != (int)MoEnumHelper.EmStatus.啟用 || !string.IsNullOrWhiteSpace(response.Msg))
134                 {
135                     actionContext.Response = new HttpResponseMessage()
136                     {
137 
138                         StatusCode = System.Net.HttpStatusCode.OK,
139                         Content = new StringContent(JsonConvert.SerializeObject(response))
140                     };
141                 }
142             }
143         }
144     }

程式碼中已經有了驗證步驟模組的說明各位可以讀一下,需要注意的地方是在Action過濾器中獲取post傳遞給介面的物件引數方式是:  var moRequest = actionContext.ActionArguments["request"] as MoShenNiuBaseRequest; 這樣就能直接獲取客戶端傳遞過來的物件資料了;然後咋們再Controller程式碼中使用定義的過濾器,主要是在Action方法上方增加 [UserValidate(MoEnumHelper.ApiKeyId.文字驗證碼)]標記,通過MoEnumHelper.ApiKeyId.文字驗證碼來傳遞呼叫方呼叫的介面,這裡我封裝的介面是:文字驗證碼圖片驗證碼的介面,至於生成驗證碼的程式碼已經在上一篇MVC偽一個12306圖片驗證碼已經開源出來了這裡不多說,直接上整個webapi介面的Controller程式碼:

 1 /// <summary>
 2     /// ShenNiuApi - 介面
 3     /// </summary>
 4     [RoutePrefix("shenniuapi")]
 5     public class ShenNiuController : ApiController
 6     {
 7 
 8         /// <summary>
 9         /// 文字驗證碼
10         /// </summary>
11         /// <param name="request">驗證碼Request請求</param>
12         /// <returns>文字驗證碼圖片流</returns>
13         [Route("WenZiValidateCode")]
14         [HttpPost]
15         [UserValidate(MoEnumHelper.ApiKeyId.文字驗證碼)]
16         public MoValidateCodeResponse GetWenZiValidateCode(MoValidateCodeRequest request)
17         {
18 
19             var response = new MoValidateCodeResponse();
20 
21             try
22             {
23                 //返回的驗證碼文字
24                 var code = string.Empty;
25                 //圖片流
26                 response.CodeStream = ValidateCode.GetValidateCodeStream(ref code);
27                 if (string.IsNullOrWhiteSpace(code) || response.CodeStream.Length <= 0) { response.Msg = "獲取驗證碼失敗,請稍後重試"; return response; }
28 
29                 response.Code = code;
30                 response.Status = (int)MoEnumHelper.EmApiStatus.成功;
31             }
32             catch (Exception ex)
33             {
34                 response.Msg = "獲取驗證碼失敗,請稍後重試";
35             }
36 
37             return response;
38         }
39 
40         /// <summary>
41         /// 圖片驗證碼
42         /// </summary>
43         /// <param name="request">驗證碼Request請求</param>
44         /// <returns>圖片驗證碼圖片流及待驗證圖片座標</returns>
45         [Route("TuPianValidateCode")]
46         [HttpPost]
47         [UserValidate(MoEnumHelper.ApiKeyId.圖片驗證碼)]
48         public MoValidateCodeResponse GetTuPianValidateCode(MoValidateCodeRequest request)
49         {
50 
51             var response = new MoValidateCodeResponse();
52 
53             try
54             {
55                 //獲取圖片型別
56                 var validateCode = ValidateCode.GetInitImgCode();
57                 if (validateCode == null || string.IsNullOrWhiteSpace(validateCode.IndexType)) { response.Msg = "獲取驗證碼失敗,請稍後重試"; return response; }
58 
59                 //生成圖片
60                 var imgCode = new List<Stage.Com.Extend.MoImgCode>();
61                 response.CodeStream = ValidateCode.CreateImgValidateStream(validateCode.IndexType, ref imgCode, strLen: 8);
62                 if (imgCode.Count <= 0 || response.CodeStream.Length <= 0 || imgCode.Count <= 0) { response.Msg = "獲取驗證碼失敗,請稍後重試"; return response; }
63 
64                 //得到待匹配驗證碼座標
65                 foreach (var item in imgCode.Where(b=>b.IsChoice))
66                 {
67                     response.ImgCode.Add(new Stage.Model.MoImgCode()
68                     {
69                         ImgUrl = item.ImgUrl,
70                         Index = item.Index,
71                         IndexType = item.IndexType,
72                         IsChoice = item.IsChoice,
73                         Point_A = item.Point_A,
74                         Point_B = item.Point_B
75                     });
76                 }
77                 response.Code = validateCode.IndexType;
78                 response.Status = (int)MoEnumHelper.EmApiStatus.成功;
79             }
80             catch (Exception ex)
81             {
82                 response.Msg = "獲取驗證碼失敗,請稍後重試";
83             }
84 
85             return response;
86         }
87 
88     }

感覺是不是挺簡單的,其實關鍵點在於過濾器中驗證的步驟,要明白作為一個介面需要驗證哪些東西這樣才能保障介面的安全;

 

» ShenNiuApi.SDK客戶端程式碼的分享

我們需求分析的時候也說了通過SDK的nuget方式提供給呼叫方使用,方便快捷,有一定的安全性;下面我們先來看下客戶端所使用到的實體類:

  1 namespace ShenNiuApi.SDK
  2 {
  3 
  4     /// <summary>
  5     /// 神牛步行3列舉
  6     /// </summary>
  7     public class MoEnumHelper
  8     {
  9 
 10         public enum EmStatus
 11         {
 12             禁用 = 0,
 13             啟用 = 1
 14         }
 15     }
 16 
 17     /// <summary>
 18     /// 介面驗證基類
 19     /// </summary>
 20     public class MoShenNiuBaseRequest
 21     {
 22         /// <summary>
 23         /// 賬號
 24         /// </summary>
 25         public string UserName { get; set; }
 26 
 27         /// <summary>
 28         /// 密碼
 29         /// </summary>
 30         public string UserPwd { get; set; }
 31 
 32         /// <summary>
 33         /// 加密Token(方式:Md5(賬號_祕鑰_密碼))
 34         /// </summary>
 35         public string Token { get; set; }
 36 
 37     }
 38 
 39     /// <summary>
 40     /// 神牛介面返回基類
 41     /// </summary>
 42     public class MoShenNiuBaseResponse
 43     {
 44         /// <summary>
 45         /// 返回狀態: 0:失敗 1:成功
 46         /// </summary>
 47         public int Status { get; set; }
 48 
 49         /// <summary>
 50         /// 錯誤資訊
 51         /// </summary>
 52         public string Msg { get; set; }
 53     }
 54 
 55     /// <summary>
 56     /// 驗證碼請求類
 57     /// </summary>
 58     public class MoValidateCodeRequest : MoShenNiuBaseRequest { }
 59 
 60     /// <summary>
 61     /// 驗證碼返回類
 62     /// </summary>
 63     public class MoValidateCodeResponse : MoShenNiuBaseResponse
 64     {
 65 
 66         public MoValidateCodeResponse()
 67         {
 68             this.ImgCode = new List<MoImgCode>();
 69         }
 70 
 71         /// <summary>
 72         /// 驗證碼型別
 73         /// </summary>
 74         public string Code { get; set; }
 75 
 76         /// <summary>
 77         /// 驗證碼圖片流
 78         /// </summary>
 79         public byte[] CodeStream { get; set; }
 80 
 81         /// <summary>
 82         /// 圖片驗證座標
 83         /// </summary>
 84         public List<MoImgCode> ImgCode;
 85     }
 86 
 87     /// <summary>
 88     /// 圖片驗證碼座標
 89     /// </summary>
 90     public class MoImgCode
 91     {
 92         public string Index { get; set; }
 93 
 94         public string IndexType { get; set; }
 95 
 96         public string ImgUrl { get; set; }
 97 
 98         public Point Point_A { get; set; }
 99 
100         public Point Point_B { get; set; }
101 
102         public bool IsChoice { get; set; }
103     }
104 
105 }

其中包含了賬號實體,驗證碼請求實體和返回實體,挺簡單的,因為這裡介面目前只有兩個嘛,當以後我不斷開放介面後相信客戶端的實體程式碼遠不止於此;再來看方法,作為一個客戶端肯定會有登陸賬號,密碼等傳入的地方,我這裡不是以配置檔案傳入的方式獲取,而是直接通過客戶端類建構函式來傳遞(建構函式上有預設引數是方便各位朋友使用介面的賬號,如果有希望單獨開放賬號的合作伙伴可以聯絡我);客戶端類中利用泛型T構造了一個統一的賬號非空驗證方法Validate和密碼及Token構造的GetBaseRequest方法,對已程式碼:

 1  /// <summary>
 2         /// 得到基礎請求格式
 3         /// </summary>
 4         /// <returns></returns>
 5         private T GetBaseRequest<T>() where T : MoShenNiuBaseRequest, new()
 6         {
 7             var baseRequest = new T();
 8 
 9             baseRequest.UserName = this.UserName;
10             baseRequest.UserPwd = Md5Extend.GetMd5Hash(this.UserPwd);
11             baseRequest.Token = Md5Extend.GetMd5Hash(string.Format("{0}_{1}_{2}",
12                                                    this.UserName.ToUpper(),
13                                                    this.TokenKey.ToUpper(),
14                                                    baseRequest.UserPwd.ToUpper()));
15 
16             return baseRequest;
17         }
18 
19         /// <summary>
20         /// 非空驗證
21         /// </summary>
22         /// <typeparam name="T"></typeparam>
23         /// <param name="t"></param>
24         public void Validate<T>(T t)
25             where T : MoValidateCodeResponse
26         {
27             if (string.IsNullOrWhiteSpace(this.UserName) ||
28                 string.IsNullOrWhiteSpace(this.UserPwd)) { t.Msg = "賬號或密碼不能為空"; }
29             else if (string.IsNullOrWhiteSpace(this.TokenKey))
30             {
31                 t.Msg = "祕鑰不能為空";
32             }
33         }

好了下面直接貼出對應的客戶端中呼叫文字驗證碼圖片驗證碼的程式碼:

  1 namespace ShenNiuApi.SDK
  2 {
  3     public class ShenNiuApiClient
  4     {
  5         #region 屬性
  6 
  7         public string ApiUrl { get; set; }
  8 
  9         /// <summary>
 10         /// 賬號
 11         /// </summary>
 12         public string UserName { get; set; }
 13 
 14         /// <summary>
 15         /// 密碼
 16         /// </summary>
 17         public string UserPwd { get; set; }
 18 
 19         /// <summary>
 20         /// 祕鑰
 21         /// </summary>
 22         public string TokenKey { get; set; }
 23         #endregion
 24 
 25         public ShenNiuApiClient() { }
 26         public ShenNiuApiClient(string userName = "神牛步行3", string userPwd = "123123", string tokenKey="程式碼改變世界,需求決定一切", string apiUrl = "http://www.lovexins.com:1001/shenniuapi")
 27         {
 28 
 29             this.UserName = userName;
 30             this.UserPwd = userPwd;
 31             this.TokenKey = tokenKey;
 32             this.ApiUrl = apiUrl;
 33         }
 34 
 35         /// <summary>
 36         /// 得到基礎請求格式
 37         /// </summary>
 38         /// <returns></returns>
 39         private T GetBaseRequest<T>() where T : MoShenNiuBaseRequest, new()
 40         {
 41             var baseRequest = new T();
 42 
 43             baseRequest.UserName = this.UserName;
 44             baseRequest.UserPwd = Md5Extend.GetMd5Hash(this.UserPwd);
 45             baseRequest.Token = Md5Extend.GetMd5Hash(string.Format("{0}_{1}_{2}",
 46                                                    this.UserName.ToUpper(),
 47                                                    this.TokenKey.ToUpper(),
 48                                                    baseRequest.UserPwd.ToUpper()));
 49 
 50             return baseRequest;
 51         }
 52 
 53         /// <summary>
 54         /// 非空驗證
 55         /// </summary>
 56         /// <typeparam name="T"></typeparam>
 57         /// <param name="t"></param>
 58         public void Validate<T>(T t)
 59             where T : MoValidateCodeResponse
 60         {
 61             if (string.IsNullOrWhiteSpace(this.UserName) ||
 62                 string.IsNullOrWhiteSpace(this.UserPwd)) { t.Msg = "賬號或密碼不能為空"; }
 63             else if (string.IsNullOrWhiteSpace(this.TokenKey))
 64             {
 65                 t.Msg = "祕鑰不能為空";
 66             }
 67         }
 68 
 69         /// <summary>
 70         /// 獲取文字驗證碼
 71         /// </summary>
 72         /// <returns></returns>
 73         public async Task<MoValidateCodeResponse> GetWenZiValidateCodeAsync()
 74         {
 75 
 76             var response = new MoValidateCodeResponse();
 77             try
 78             {
 79                 //非空驗證
 80                 Validate(response);
 81                 if (!string.IsNullOrWhiteSpace(response.Msg)) { return response; }
 82 
 83                 //獲取基礎請求設定
 84                 var request = this.GetBaseRequest<MoValidateCodeRequest>();
 85 
 86                 //json化
 87                 var requestStr = JsonConvert.SerializeObject(request);
 88                 //傳送請求
 89                 var returnStr = string.Empty;
 90                 using (HttpClient client = new HttpClient())
 91                 {
 92                     client.Timeout = TimeSpan.FromSeconds(60);
 93                     var stringContent = new StringContent(requestStr, Encoding.UTF8, "application/x-www-form-urlencoded");
 94                     stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
 95 
 96                     var httpResponseMessage = client.PostAsync(this.ApiUrl + "/WenZiValidateCode", stringContent).Result;
 97                     var stream = await httpResponseMessage.Content.ReadAsStreamAsync();
 98                     using (StreamReader reader = new StreamReader(stream))
 99                     {
100                         returnStr = await reader.ReadToEndAsync();
101                     }
102                 }
103                 if (string.IsNullOrWhiteSpace(returnStr))
104                 {
105 
106                     return response;
107                 }
108                 //解析
109                 response = JsonConvert.DeserializeObject<MoValidateCodeResponse>(returnStr);
110             }
111             catch (Exception ex)
112             {
113                 response.Msg = ex.Message;
114             }
115             return response;
116         }
117 
118        
119         /// <summary>
120         /// 獲取圖片驗證碼
121         /// </summary>
122         /// <returns></returns>
123         public async Task<MoValidateCodeResponse> GetTuPianValidateCodeAsync()
124         {
125 
126             var response = new MoValidateCodeResponse();
127             try
128             {
129                 //非空驗證
130                 Validate(response);
131                 if (!string.IsNullOrWhiteSpace(response.Msg)) { return response; }
132 
133                 //獲取基礎請求設定
134                 var request = this.GetBaseRequest<MoValidateCodeRequest>();
135 
136                 //json化
137                 var requestStr = JsonConvert.SerializeObject(request);
138                 //傳送請求
139                 var returnStr = string.Empty;
140                 using (HttpClient client = new HttpClient())
141                 {
142                     client.Timeout = TimeSpan.FromSeconds(60);
143                     var stringContent = new StringContent(requestStr, Encoding.UTF8, "application/x-www-form-urlencoded");
144                     stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
145 
146                     var httpResponseMessage = client.PostAsync(this.ApiUrl + "/TuPianValidateCode", stringContent).Result;
147                     var stream = await httpResponseMessage.Content.ReadAsStreamAsync();
148                     using (StreamReader reader = new StreamReader(stream))
149                     {
150                         returnStr = await reader.ReadToEndAsync();
151                     }
152                 }
153                 if (string.IsNullOrWhiteSpace(returnStr))
154                 {
155 
156                     return response;
157                 }
158                 //解析
159                 response = JsonConvert.DeserializeObject<MoValidateCodeResponse>(returnStr);
160             }
161             catch (Exception ex)
162             {
163                 response.Msg = ex.Message;
164             }
165             return response;
166         }
167  
168     }
169 }
View Code

 

» 使用NuGet Package Explorer工具生成ShenNiuApi.SDK的nuget包併發布到nuget網站上

因為我們要釋出Sdk的nuget包,所以需要打包才行,這裡就不用nuget命令了而是使用NuGet Package Explorer工具來打包,首先安裝好工具後,我們開啟有這樣的畫面:

我們選中如上圖所示的選項,然後選中"編輯選項":

然後錄入如下資訊即可,您也可以錄入更多的依賴等選項的資訊:

這些資訊是我釋出的sdk,您們自己的可以不用填寫這麼詳細哈哈,記得填完後再點選剛才位置的綠色鉤鉤(儲存),好了接下來重點是在工具的右邊的"Package Contents"區域=》右鍵滑鼠=》選中如下圖所示選項:

這裡選項的意思新增類庫dll,點選完後會有一個"Lib"出現,再右鍵Lib選中"Add .Net Folder"=》"V4.5"後面這個4.5是您打包專案的版本,我的是適用於4.5的,如下圖:

然後再直接把您專案bin下面生成的dll(我這裡是ShenNiuApi.SDK.dll)直接拖到"Package Contents"區域並且是在"V4.5"的下級,效果如下:

最後一步"儲存"我們的nuget檔案,先點選工具左上角的"File"=》"Save",有提示包檔案儲存在哪裡,確定後就可以在您儲存的資料夾下面看到您的nuget包了:

怎麼樣使用工具是不是很簡單,您成功生成自己的nuget包了麼;如果您想包您的包釋出到nuget共全世界.net程式猿使用那麼還是使用此工具“File”=》“publish”=》如圖:

不錯意外您的nuget包就釋出上去了,並且在vs中通過搜尋包也能看到,例如我這裡的包:

如果能收到您自己的nuget包是不是感覺很興奮呢哈哈,我也是當截圖此刻釋出兩天的sdk已經有51次下載量了,不錯啦;網站上的描述:

到此本章的內容就結束了,希望給您帶來了學習的幫助,如果感謝我的話並且考慮要買雙鞋子和衣服,不妨來小弟衣服店看看:神牛衣櫃3非常感謝您的支援也感謝多多點贊。

程式碼資源包:使用ShenNiuApi.SDK的nuget包

相關文章