Home  >  Article  >  Backend Development  >  Asp.net (2) Business processing interface project (Web Api)

Asp.net (2) Business processing interface project (Web Api)

PHPz
PHPzOriginal
2017-04-04 15:32:553142browse

Introduction

ApiAs a business logic provider, it carries the core logic of the project and therefore has relatively high logic complexity. Under such a premise, how to simplify code writing, how to standardize and unify the writing style and logic specifications, and how to improve the maintainability and scalability of the code. It becomes important to build projects with high cohesion and low coupling.
The example is an enterprise-level project, FrameworkThe picture is as follows

Asp.net (2) Business processing interface project (Web Api)

##api layer.jpg

Security: The Http request (Override DelegatingHan

dler) is rewritten, the validity of the request is judged, and the signature requirements are preprocessed. Client: defines a unified
interface calling method is used by the calling end, simplifying and unifying the use of the interface. Ctrl layer: As a direct provider of services, it directly provides an interface similar to RestFul style on the server (it feels strict RestFul style, requiring a complete domain
ModelDriver , the actual situation is always unsatisfactory, and the domain abstraction ability is not enough), obtain the request data, call FilterFilter on demand, make further judgments, and call
Model. Layer: As the business model layer, it provides the actual operation of business logic. Use a unified entity model and connect it to Ibatis for data operations. The specific code structure is as follows:

Asp.net (2) Business processing interface project (Web Api)
##Api-UML.jpg

The following is a detailed introduction and description of each module Code example:

Entity library project code example

The project structure is as follows:

Asp.net (2) Business processing interface project (Web Api)##entity.jpg

Do

main

module, as an entity model, the simple code is as follows

public class User
{
      public int Id { get; set; }
      public string NickName { get; set; }
      public string Avatar { get; set; }
}
Request, the request structure model, uses the generic interface to connect the request class and the return class, which achieves control inversion role.
public abstract class AbstractRequest
{
    public bool ValidateParameters()
    {
        //公用方法示例,验证参数合法性
    }
}
   public interface IRequest<T> where T:AbstractResponse
    {
        //获取接口名称
        string GetApiName();

        //获取接口编码
        string GetApiCode();
    }
//获取User信息的请求结构定义
  public class GetUserRequest:AbstractRequest,IRequest<GetUserResponse>
    {
        public int Id { get; set; }

        public string GetApiName()
        {
            return "User.GetUserDetail";
        }

        public string GetApiCode()
        {
            return "User001";
        }
    }
Response module, as the return type of the request, defines a unified return structure to facilitate consumers to judge and process consistent return codes.

public abstract class AbstractResponse
    {
        //返回码
        public int Code { get; set; }
        //报错信息
        public string Message { get; set; }
    }
 public class GetUserResponse:AbstractResponse
    {
        public User User { get; set; }
    }
Service project code example

The project structure is as follows:

Asp.net (2) Business processing interface project (Web Api)service.jpg

Code Example:

 public interface IUserService
    {
        GetUserResponse GetUser(int id);
    }
 public class BaseService
    {
        //protected SqlInstance sqlInstance;
        public BaseService()
        {
            //sqlInstance=new SqlInstance(); //实例化数据库连接
            //...
        }
        //...
    }
  public class UserService:BaseService,IUserService
    {
        public GetUserResponse GetUser(int id)
        {
            //链接数据库获取数据
            //...
            throw new NotImplementedException();
        }
    }
Security

Class library

Code example
The class library only handles security
issues and adds permission judgment at the api request entry . Use the method of rewriting Http requests.

Code example

public class MyHandler : DelegatingHandler
    {
        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            IEnumerable<string> keyEnumerable;
            var t1 = request.Headers.TryGetValues("key", out keyEnumerable);
            var key = keyEnumerable.FirstOrDefault();
            if (!true)//验证类似于token的权限
            {
                return await Task.Factory.StartNew<HttpResponseMessage>(
                            () => new HttpResponseMessage(HttpStatusCode.Forbidden)
                            {
                                Content = new StringContent("error message")
                            });
            }
            //如果有signature,判断,并加结果标志,没有的话,清除signature相关信息,防止伪造。
            //.....
            return await base.SendAsync(request, cancellationToken);
        }
    }
The abstracted permission judgment can be directly called to the webapi end and added to the
routing

configuration code.

WebApi project example

As the actual definition of the interface, webapi defines the actual rules of the interface file, and makes corresponding
security management
and interface permission control. To learn the permission control of WeChat, several interfaces have been roughly determined:

Asp.net (2) Business processing interface project (Web Api)Interface permissions.png

The judgments of these permissions are all placed Centralized management is done in Security. The interface definition only needs to be used to judge the legality of the corresponding logic.

Code example:

public class UserController : ApiController
    {
        private IUserService userService;

        public UserController()
        {
            userService=new UserService();
        }

        [Signature]//安全签名过滤器判断
        [HttpPost]
        public GetUserResponse GetUser(GetUserRequest request)
        {
            //参数判断,安全性判断等等
            var ret = userService.GetUser(request.Id);
            return ret;
        }

    }

The above is an example interface for obtaining user information. As for the routing configuration as the interface entrance, you need to judge the legality of the request. The routing configuration code is as follows:
public static void Register(HttpConfiguration config)
{
            // Web API configuration and services
            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}",
                defaults: new { id = RouteParameter.Optional }
            );
            //添加的代码,添加http请求的入口处理
            config.MessageHandlers.Add(new MyHandler());
}
Client class library code example

Client class library defines the public methods called by the interface.
1. Use generic interfaces to encapsulate the request class and return class to simplify the writing of calling code.
2. And make consumers call the interface through the proxy class, avoiding cross-domain problems.

3. Consumer calls all agree to use a unified class library, so that the log processing is unified, and the returned errors can also be defined consistently.
Code examples are as follows:

 public interface IClient
 {
     T Execute<T>(IRequest<T> request) where T : AbstractResponse;
 }

public class DefaultClient:IClient
    {
        private readonly string appKey;
        private readonly string appSecret;
        private readonly string baseUrl = "http://localhost:16469/api/";
        private readonly bool isNeedLogFile = false;
        private readonly LogFile logFile;
        public static readonly string SecureHeaderAppKey = "secure_head_appkey";
        public static readonly string SecureHeaderSignature = "secure_head_signature";

        public DefaultClient()
        {
            baseUrl = ConfigurationManager.AppSettings["service_base_url"];
            appKey = ConfigurationManager.AppSettings["app_key"];
            appSecret = ConfigurationManager.AppSettings["app_secret"];
            isNeedLogFile = "1".Equals(ConfigurationManager.AppSettings["client_log_file"]);
            logFile = new LogFile("client_log_path");
            logFile.SubPath = appKey;
        }

        public DefaultClient(string serviceBase, string code, string key)
        {
            baseUrl = serviceBase;
            appKey = code;
            appSecret = key;
        }
        public T Execute<T>(IRequest<T> request) where T : AbstractResponse
        {
            var webRequest = (HttpWebRequest)WebRequest.Create(baseUrl + request.GetApiName());
            webRequest.Method = "POST";

            string reqJson;
            string sign;
            using (Stream rs = webRequest.GetRequestStream())
            {
                reqJson = JsonConvert.SerializeObject(request);

                byte[] reqBytes = Encoding.UTF8.GetBytes(reqJson);
                rs.Write(reqBytes, 0, reqBytes.Length);
                rs.Close();
            }

            webRequest.ContentType = "application/json";
            webRequest.Headers.Add(SecureHeaderAppKey, appKey);
            sign = ComputeHash(appKey, appSecret, reqJson);
            webRequest.Headers.Add(SecureHeaderSignature, sign);

            //记录日志
            if (isNeedLogFile)
            {
                logFile.Log(string.Format("[{0}] 请求内容: {1}", request.GetApiCode(), reqJson));
                logFile.Log(string.Format("[{0}] 请求签名: {1}", request.GetApiCode(), sign));
            }

            try
            {
                using (var resp = (HttpWebResponse)webRequest.GetResponse())
                {
                    try
                    {
                        Stream respStream = resp.GetResponseStream();

                        if (respStream == null)
                        {
                            throw new WebException("GetResponseStream returned null");
                        }
                        var streamReader = new StreamReader(respStream);
                        string respStr = streamReader.ReadToEnd();
                        //记录日志
                        if (isNeedLogFile)
                        {
                            logFile.Log(string.Format("[{0}] 响应内容: {1}", request.GetApiCode(), respStr));
                        }
                        return JsonConvert.DeserializeObject<T>(respStr);
                    }
                    catch (Exception e)
                    {
                        //记录日志
                        if (isNeedLogFile)
                        {
                            logFile.Log(string.Format("[{0}] 响应错误: {1}", request.GetApiCode(), e.Message));
                        }
                        throw new ApplicationException(e.Message, e);
                    }
                }
            }
            catch (WebException e)
            {
                var errMsg = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();
                //记录日志
                if (isNeedLogFile)
                {
                    logFile.Log(string.Format("[{0}] 请求错误: {1}", request.GetApiCode(), errMsg));
                }
                throw new APIServiceException(errMsg);
            }
        }
        private string ComputeHash(string key, string secret, string body)
        {
            return
                Convert.ToBase64String(
                    SHA1.Create().ComputeHash(Encoding.Default.GetBytes(string.Concat(key, secret, body.Trim()))));
        }
    }

以上就是Api项目端的各个核心环节的详细介绍。
接下来会对调用端即前端进行简单的介绍。Asp.net(三)Web端展示

The above is the detailed content of Asp.net (2) Business processing interface project (Web Api). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn