An Open Interface from Requirement Analysis to Publishing sdk Online Packages

Keywords: ASP.NET SDK Database JSON Attribute

New Year's opening, welcome to some praise; this article shares with you the use of Web API to do interface service verification framework, the source of demand is that I intend to make the picture authentication code mentioned above into a service for you, although I have packaged the code open source in the last, but if there is a fast docking service, I think many people would like to use it, at present. This service has been online and published on nuget with the sdk client package (nuget package address: Install-Package ShenNiuApi.SDK). Fortunately, there are 46 downloads in one day (very happy). Perhaps interested friends can visit the nuget official address: Nuget Pack of Shenniu Walking 3 Next, I want to share the architecture of the verification caller involved in publishing the service. I hope you like it. I also hope that you will have more "scanner support" and "recommendation" thanks (I have recently made a clothing store address: Shenniu Wardrobe 3 I hope that friends who need to buy clothes and shoes will be more popular.

 

Requirements analysis and table structure design of verification architecture

Unified verification of accounts using ActionFilterAttribute of webapi

Sharing of ShenNiuApi.SDK Client Code

NuGet Package Explorer tool is used to generate the nuget package of ShenNiuApi.SDK and publish it on the nuget website.

 

The next step is to share one footprint:

Requirements analysis and table structure design of verification architecture

Requirements analysis of verification architecture

First of all, for an interface service, there are usually some account restrictions. It is necessary for the caller to pass the correct account to the interface in order to call the successful interface. Here we use the general interface validation of the Internet industry to formulate our requirements:

1. Interface verification needs: account number, password, ip group, Token; password need to be encrypted generally, and there are many encryption methods on the market, such as Md5,3des and so on; ip group, as its name implies, is used to verify whether the ip requested by the caller meets the specified ip bound by the new account opening of the interface party. Distributed invocation is not a new thing for today's Internet industry, so it is needed here. Token is generally a tamper-proof parameter protection measures formulated by the interface side. For both requesters and recipients, the same Token value is needed to respond to the interface, usually a secret key is needed to facilitate encryption.

2. In addition to account validation, some interfaces need to be charged according to the number of calls. So we have the requirement to limit the number of calls. But as a different business interface, the cost may be high. Although the interface provided by the same provider is likely to be fine enough to limit the number of calls per interface, so we design it in this way. True. Business depends on demand.

3. Usually when the other side opens the interface, it will provide the sdk client directly. It is convenient for the caller to directly invoke the method after directly referring to it. It does not need to care about what the request protocol is or the interface method is not right. This way of providing sdk can be used directly only with account number, password, secret key and so on. It is convenient, fast and avoids to some extent. Exposure of interface addresses has many advantages; bad third is like mobile client, as long as the server updates some necessary parameter attributes, it needs the caller to update the sdk package every time, but this is not a matter of fact.

Design of table structure

With the above brief analysis, let's look at the table structure of the database. Here, the database is mainly used to store the corresponding open interface account, password and other information and the corresponding number of calls to the interface:

Table: MoApiUser (Account Table), MoApiManager (Interface Method Table), MoApiRelation (Account and Method Table Relation Table, which contains the number of calls) MoLog (Log Table)

Table data:

 

Use ActionFilterAttribute to Unify Account Verification

With the above requirements and table design, let's take a look at how to use Action filters to unify verification. Before that, we need to understand: Why not get a parent ApiController and do verification in it to inherit, and use Action filters to do both, but the latter can be used for interfaces that do not require interface accounts? Open, easy to control; Okay, let's look at what's validated in the Action filter, first create the class UserValidateAttribute and inherit the ActionFilterAttribute, and then give her an attribute ApiKeyId, which is used to pass the interface number (that is, the corresponding interface Id, which corresponds to the ApiKeyId in the database table MopiManager) The purpose of doing this is to use numbers to facilitate the statistics of calling an interface in the database, and to limit the number of times that we need to analyze to an interface, not to an account (of course, the former and must be associated with the account), so we define an enumeration that facilitates the number in the corresponding interface:

 1 /// <summary>
 2///Interface and Database Association Number
 3         /// </summary>
 4         public enum ApiKeyId
 5         {
 6 
 7 Text Verification Code = 1,
 8 Picture Verification Code = 2
 9 
10         }

Then in the filter, the public override void OnAction Executing (System. Web. Http. Controllers. HttpActionContext actionContext) is re-constructed to do non-null verification in OnAction Executing, whether the account password matches, Token's verification, ip group matches, the number of comparisons, so there is the following overall custom filter code:

  1  public class UserValidateAttribute : ActionFilterAttribute
  2     {
  3 
  4         /// <summary>
  5         /// Database and Program Association Label 
  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 = "The interface is not open yet. Please contact the administrator."; return; }
 23                 sbLog.AppendFormat("Current services:{0};", this.ApiKeyId);
 24 
 25                 var request = actionContext.Request;
 26 
 27                 #region Verification
 28 
 29                 #region Non empty verification  
 30                 if (actionContext.ActionArguments.Count <= 0) { response.Msg = "The request format is incorrect. Please check it."; 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 = "Interface account or password cannot be empty";
 39                     return;
 40                 }
 41                 else if (string.IsNullOrWhiteSpace(moRequest.Token))
 42                 {
 43                     response.Msg = "Token Can not be empty";
 44                     return;
 45                 }
 46                 #endregion
 47 
 48                 using (StageEntities db = new StageEntities())
 49                 {
 50 
 51                     #region Verify that the account exists
 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 = "Interface account or password error";
 57                         return;
 58                     }
 59                     #endregion
 60 
 61                     #region  Get the corresponding account secret key and verify it 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("The server TokenKey: {0};Token: {1};", userInfo.TokenKey.ToUpper(), newToken);
 69 
 70                     if (!moRequest.Token.Equals(newToken, StringComparison.OrdinalIgnoreCase))
 71                     {
 72                         response.Msg = "Token Validation failed";
 73                         return;
 74                     }
 75                     #endregion
 76 
 77                     #region Account availability
 78                     if (userInfo.Status != (int)MoEnumHelper.EmStatus.Enable)
 79                     {
 80                         response.Msg = "Interface account suspended";
 81                         return;
 82                     }
 83                     else if (!string.IsNullOrWhiteSpace(userInfo.Ips))
 84                     {
 85                         if (!userInfo.Ips.Contains(userIp))
 86                         {
 87                             response.Msg = "Interface ip invalid";
 88                             return;
 89                         }
 90                     }
 91 
 92                     var realationInfo = userInfo.MoApiRelations.Where(b => b.MoApiManager.ApiKeyId == (int)ApiKeyId && b.MoApiManager.Status == (int)MoEnumHelper.EmStatus.Enable).SingleOrDefault();
 93                     if (realationInfo == null)
 94                     {
 95                         response.Msg = "Interface is not enabled yet. Please try again later.";
 96                         return;
 97                     }
 98                     else if (realationInfo.MaxNum <= realationInfo.NowNum)
 99                     {
100                         response.Msg = "The number of interface calls is full. Please contact the administrator.";
101                         return;
102                     }
103                     #endregion
104 
105                     //Through validation
106                     response.Status = (int)MoEnumHelper.EmStatus.Enable;
107 
108                     #region Users increase the number of times they authenticate
109 
110                     realationInfo.NowNum++;
111                     var result = db.SaveChanges();
112                     sbLog.AppendFormat("Maximum number of times:{0};Current times:{1};Increase the number of times:{2};", realationInfo.MaxNum, realationInfo.NowNum, result);
113                     #endregion
114                 }
115 
116                 #endregion
117 
118 
119             }
120             catch (Exception ex)
121             {
122                 response.Msg = "500 Interface handles request exceptions, please try again later";
123                 sbLog.AppendFormat("Exception information:{0};", ex.Message);
124             }
125             finally
126             {
127 
128                 sbLog.AppendFormat("Return Status: {0};Msg: {1};", response.Status, response.Msg);
129                 //Log
130                 StageClass._WrigLog(sbLog.ToString());
131 
132                 //Validation Failure Return
133                 if (response.Status != (int)MoEnumHelper.EmStatus.Enable || !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     }

You can read the instructions of the validation step module in the code. It is important to note that the way to get the object parameters passed to the interface by post in the Action filter is: var moRequest = actionContext.ActionArguments["request"] as MoShenNiuBaseRequest; this allows you to get the object data passed by the client directly; and then we can replace it with Controller. The filter defined in the code mainly adds the tag [User Validate (MoEnumHelper.ApiKeyId. Text Verification Code)] above the Action method, and passes the interface called by the caller through MoEnumHelper.ApiKeyId. Text Verification Code. Here I encapsulate the interface of Text Verification Code and Picture Verification Code. As for the code that generates the Verification Code, I have written the previous article. MVC Pseudo-12306 Picture Verification Code The Controller code for the entire web API interface is directly available.

 1 /// <summary>
 2     /// ShenNiuApi - Interface
 3     /// </summary>
 4     [RoutePrefix("shenniuapi")]
 5     public class ShenNiuController : ApiController
 6     {
 7 
 8         /// <summary>
 9         /// Text Verification Code
10         /// </summary>
11         /// <param name="request">Verification Code Request request</param>
12         /// <returns>Text Authentication Code Picture Stream</returns>
13         [Route("WenZiValidateCode")]
14         [HttpPost]
15         [UserValidate(MoEnumHelper.ApiKeyId.Text Verification Code)]
16         public MoValidateCodeResponse GetWenZiValidateCode(MoValidateCodeRequest request)
17         {
18 
19             var response = new MoValidateCodeResponse();
20 
21             try
22             {
23                 //The returned validation code text
24                 var code = string.Empty;
25                 //Picture flow
26                 response.CodeStream = ValidateCode.GetValidateCodeStream(ref code);
27                 if (string.IsNullOrWhiteSpace(code) || response.CodeStream.Length <= 0) { response.Msg = "Failed to get the authentication code. Please try again later."; return response; }
28 
29                 response.Code = code;
30                 response.Status = (int)MoEnumHelper.EmApiStatus.Success;
31             }
32             catch (Exception ex)
33             {
34                 response.Msg = "Failed to get the authentication code. Please try again later.";
35             }
36 
37             return response;
38         }
39 
40         /// <summary>
41         /// Picture Verification Code
42         /// </summary>
43         /// <param name="request">Verification Code Request request</param>
44         /// <returns>Picture Verification Code Picture Stream and Picture Coordinates to be Verified</returns>
45         [Route("TuPianValidateCode")]
46         [HttpPost]
47         [UserValidate(MoEnumHelper.ApiKeyId.Picture Verification Code)]
48         public MoValidateCodeResponse GetTuPianValidateCode(MoValidateCodeRequest request)
49         {
50 
51             var response = new MoValidateCodeResponse();
52 
53             try
54             {
55                 //Get the picture type
56                 var validateCode = ValidateCode.GetInitImgCode();
57                 if (validateCode == null || string.IsNullOrWhiteSpace(validateCode.IndexType)) { response.Msg = "Failed to get the authentication code. Please try again later."; return response; }
58 
59                 //Generate pictures
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 = "Failed to get the authentication code. Please try again later."; return response; }
63 
64                 //Getting the coordinates of the verification code to be matched
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.Success;
79             }
80             catch (Exception ex)
81             {
82                 response.Msg = "Failed to get the authentication code. Please try again later.";
83             }
84 
85             return response;
86         }
87 
88     }

Is it very simple to feel, in fact, the key point lies in the steps of verification in the filter, to understand what needs to be verified as an interface in order to ensure the security of the interface?

 

Sharing of ShenNiuApi.SDK Client Code

We also said that the nuget mode of SDK is convenient, fast and secure for the caller to use. Let's first look at the entity classes used by the client.

  1 namespace ShenNiuApi.SDK
  2 {
  3 
  4     /// <summary>
  5     /// Three Enumerations of Shenniu Walking
  6     /// </summary>
  7     public class MoEnumHelper
  8     {
  9 
 10         public enum EmStatus
 11         {
 12             Prohibit = 0,
 13             Enable = 1
 14         }
 15     }
 16 
 17     /// <summary>
 18     /// Interface Verification Base Class
 19     /// </summary>
 20     public class MoShenNiuBaseRequest
 21     {
 22         /// <summary>
 23         /// Account number
 24         /// </summary>
 25         public string UserName { get; set; }
 26 
 27         /// <summary>
 28         /// Password
 29         /// </summary>
 30         public string UserPwd { get; set; }
 31 
 32         /// <summary>
 33         /// encryption Token(Method: Md5(Account number_Secret key_Password)
 34         /// </summary>
 35         public string Token { get; set; }
 36 
 37     }
 38 
 39     /// <summary>
 40     /// Shenniu interface returns base class
 41     /// </summary>
 42     public class MoShenNiuBaseResponse
 43     {
 44         /// <summary>
 45         /// Return status: 0: Failure 1: Success
 46         /// </summary>
 47         public int Status { get; set; }
 48 
 49         /// <summary>
 50         /// error message
 51         /// </summary>
 52         public string Msg { get; set; }
 53     }
 54 
 55     /// <summary>
 56     /// Verification Code Request Class
 57     /// </summary>
 58     public class MoValidateCodeRequest : MoShenNiuBaseRequest { }
 59 
 60     /// <summary>
 61     /// Verification code return class
 62     /// </summary>
 63     public class MoValidateCodeResponse : MoShenNiuBaseResponse
 64     {
 65 
 66         public MoValidateCodeResponse()
 67         {
 68             this.ImgCode = new List<MoImgCode>();
 69         }
 70 
 71         /// <summary>
 72         /// Verification code type
 73         /// </summary>
 74         public string Code { get; set; }
 75 
 76         /// <summary>
 77         /// Verification Code Picture Stream
 78         /// </summary>
 79         public byte[] CodeStream { get; set; }
 80 
 81         /// <summary>
 82         /// Picture Verification Coordinates
 83         /// </summary>
 84         public List<MoImgCode> ImgCode;
 85     }
 86 
 87     /// <summary>
 88     /// Picture Verification Code Coordinates
 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 }

It includes account entity, verification code request entity and return entity, which is very simple, because there are only two interfaces at present, when I continue to open the interface later, I believe that the client's entity code is far more than this; Look at the method, as a client, there will certainly be entry account, password and other places, I am not here by the way of configuration file input. Instead, it is passed directly through the client class constructor (the default parameter on the constructor is to facilitate friends to use the interface account, if there is a partner who wishes to open the account separately, he can contact me); the client class uses generic T to construct a unified non-empty account verification method, Validate, password and GetBaseRequest method constructed by Token, for the coded account. :

 1  /// <summary>
 2         /// Get the underlying request format
 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         /// Non empty verification
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 = "Account or password cannot be empty"; }
29             else if (string.IsNullOrWhiteSpace(this.TokenKey))
30             {
31                 t.Msg = "The secret key cannot be empty";
32             }
33         }

Well, the following code is directly posted to the corresponding client to invoke the text validation code and image validation code:

  1 namespace ShenNiuApi.SDK
  2 {
  3     public class ShenNiuApiClient
  4     {
  5         #region attribute
  6 
  7         public string ApiUrl { get; set; }
  8 
  9         /// <summary>
 10         /// Account number
 11         /// </summary>
 12         public string UserName { get; set; }
 13 
 14         /// <summary>
 15         /// Password
 16         /// </summary>
 17         public string UserPwd { get; set; }
 18 
 19         /// <summary>
 20         /// Secret key
 21         /// </summary>
 22         public string TokenKey { get; set; }
 23         #endregion
 24 
 25         public ShenNiuApiClient() { }
 26         public ShenNiuApiClient(string userName = "Shenniu Walking 3", string userPwd = "123123", string tokenKey="Code changes the world, demand decides everything.", 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         /// Get the underlying request format
 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         /// Non empty verification
 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 = "Account or password cannot be empty"; }
 63             else if (string.IsNullOrWhiteSpace(this.TokenKey))
 64             {
 65                 t.Msg = "The secret key cannot be empty";
 66             }
 67         }
 68 
 69         /// <summary>
 70         /// Getting Text Verification Codes
 71         /// </summary>
 72         /// <returns></returns>
 73         public async Task<MoValidateCodeResponse> GetWenZiValidateCodeAsync()
 74         {
 75 
 76             var response = new MoValidateCodeResponse();
 77             try
 78             {
 79                 //Non empty verification
 80                 Validate(response);
 81                 if (!string.IsNullOrWhiteSpace(response.Msg)) { return response; }
 82 
 83                 //Get the basic request settings
 84                 var request = this.GetBaseRequest<MoValidateCodeRequest>();
 85 
 86                 //json turn
 87                 var requestStr = JsonConvert.SerializeObject(request);
 88                 //Send request
 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                 //analysis
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         /// Getting Picture Verification Code
121         /// </summary>
122         /// <returns></returns>
123         public async Task<MoValidateCodeResponse> GetTuPianValidateCodeAsync()
124         {
125 
126             var response = new MoValidateCodeResponse();
127             try
128             {
129                 //Non empty verification
130                 Validate(response);
131                 if (!string.IsNullOrWhiteSpace(response.Msg)) { return response; }
132 
133                 //Get the basic request settings
134                 var request = this.GetBaseRequest<MoValidateCodeRequest>();
135 
136                 //json turn
137                 var requestStr = JsonConvert.SerializeObject(request);
138                 //Send request
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                 //analysis
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 }

 

NuGet Package Explorer tool is used to generate the nuget package of ShenNiuApi.SDK and publish it on the nuget website.

Because we want to publish Sdk's nuget package, we need to pack it. Instead of using the nuget command, we use the NuGet Package Explorer tool to pack it. After installing the tool first, we open a screen like this:

We select the options as shown in the figure above, and then select "Edit Options":

Then enter the following information, you can also enter more information about dependencies and other options:

This information is my published sdk, you can not fill in so detailed haha, remember to fill in and then click on the green hook (save) just in the position, well the next focus is on the right side of the tool in the "Package Contents" area ="right mouse =" select the options shown in the following figure:

This option means adding class library dll. After clicking on it, a "Lib" appears. Then right-click Lib and select "Add.Net Folder"="and"V4.5", which is the version of your packaged project. My version is applicable to 4.5, as follows:

Then directly drag the dll generated under your project bin (ShenNiuApi.SDK.dll here) to the "Package Contents" area and to the "V4.5" level. The effect is as follows:

The last step is to "save" our nuget file. First, click "File" = "Save" in the upper left corner of the tool. If you have a hint about where to save the package file, you can see your nuget package under the folder you saved.

How to use the tool is not very simple, you successfully generated your own nuget package; if you want to package your package to be published to nuget all over the world. net apes use it, or use the tool "File" = "publish" = "figure:"?

It's not a bad surprise that your nuget package was released, and you can see it through search package in vs. For example, my package here:

Would it be very exciting to receive your own nuget package? Haha, I also downloaded 51 sdk downloads in two days when the screenshot was released at the moment. Good. Description on the website:?

At this point, the content of this chapter is over, I hope to bring you learning help. If you thank me and consider buying a pair of shoes and clothes, you might as well come to my younger brother's clothing store to see: Shenniu Wardrobe 3 Thank you very much for your support and for your many compliments.

Posted by CerealBH on Sun, 24 Mar 2019 19:21:31 -0700