Home > Article > Backend Development > Asp.net (2) Business processing interface project (Web Api)
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
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:
##Api-UML.jpg
##entity.jpg
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 exampleThe project structure is as follows:
service.jpg
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 exampleCode examplepublic 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
Interface permissions.png
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; } }
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 exampleClient class library defines the public methods called by the interface.
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!