.NET中间件以及VUE拦截器联合使用

  • .NET中间件以及VUE拦截器联合使用已关闭评论
  • 232 次浏览
  • A+
所属分类:.NET技术
摘要

业务逻辑
特性


.NET中间件以及VUE拦截器联合使用

工作中遇见的问题,边学边弄,记录一下

Vue的UI库使用的是antvue 3.2.9版本的。

  • 业务逻辑
    .NET中间件以及VUE拦截器联合使用

  • 特性

//特性     public class ModelEsignNameAttribute : Attribute     {         public ModelEsignNameAttribute(string nameProp, string id, string reversion = "", ModelESignType eSignType = ModelESignType.Modeling, string middleModelId = "")         {          }     } 
  • 接口加上特性
        /// <summary>         ///  添加或者修改方法         /// </summary>         /// <param name="input"></param>         /// <returns></returns> 		//特性上添加参数的地址         [ModelEsignName("Bolg.BolgBaseEditDto.BolgName", "Document.Id", "Bolg.BolgRevision")]         public async Task<Output> CreateOrUpdate(CreateOrUpdateBolgInput input)         {             var doc = await _XXXXManager.FindRdoById(input.Bolg.Id.Value);              // 文档id为空,新增             if (doc == null || !input.Bolg.BolgBaseId.HasValue)             {                 return await this.Create(input.Bolg);             }              // 更新             return await this.Update(input.Bolg);         } 
  • 中间件代码
namespace GCT.MedPro.Middleware {     public class ModelESignCheckMiddleware : IMiddleware     {           		#region 依赖注入等内容 			....         #endregion                   public async Task InvokeAsync(HttpContext context, RequestDelegate next)         {              if (await ShouldCheckESign(context))             {                 // 不需要电子签名                 await next(context);             }          }         /// <summary>         /// 是否需要拦截         /// </summary>         /// <param name="actionContext"></param>         /// <returns></returns>         private async Task<bool> ShouldCheckESign(HttpContext actionContext)         {             var whetherSignature = true;              var request = actionContext.Request;//获取请求值             var currentUser = actionContext.User.Identity.Name;             var serviceAction = actionContext                     .GetEndpoint()?                     .Metadata                     .GetMetadata<ControllerActionDescriptor>();             if (serviceAction == null)             {                 return whetherSignature;             }              //通过接口特性来筛选是否需要进行拦截             var attrObj = serviceAction.MethodInfo.CustomAttributes                 .FirstOrDefault(x => x.AttributeType == typeof(ModelEsignNameAttribute));              if (attrObj == null)             {                 return whetherSignature;             }                          string inputbody = default;             actionContext.Request.EnableBuffering();                          //Post请求获取请求参数,转换JSON             if (request.Method.ToLower().Equals("post"))             {                 var requestReader = new StreamReader(actionContext.Request.Body);                 var body = await requestReader.ReadToEndAsync();                 inputbody = UpperFirst(body); //首字母大写    全局搜索可得下方有             }             else   //GET请求以及其他方式获取             {                 var reqString = request.QueryString.Value.Remove(0, 1);                 string[] parts = reqString.Split("&");                 JObject json = new JObject();                  foreach (string part in parts)                 {                     String[] keyVal = part.Split("=");                     json.Add(keyVal[0], keyVal[1]);                 }                 inputbody = JsonConvert.SerializeObject(json);                 inputbody = UpperFirst(inputbody);             }                          var inputObj = JObject.Parse(inputbody);//转换JObject                                       #region 获取特性传入的参数,,总五位参数 			var actionName = serviceAction.ActionName;             var namePath = attrObj.ConstructorArguments[0].Value.ToString();             var idPath = attrObj.ConstructorArguments[1].Value.ToString();             var revsionPath = attrObj.ConstructorArguments[2].Value.ToString();             var typePath = (ModelESignType)attrObj.ConstructorArguments[3].Value;             var middlePath = attrObj.ConstructorArguments[4].Value.ToString();         	#endregion                          var middleModelId = GetValueName(inputObj, middlePath);//通过JObject获取对应值             //接口控制器名称             var typeName = serviceAction.ControllerTypeInfo.FullName;             //重置请求Body指针               actionContext.Request.Body.Position = 0;             //验证方法,自己写个,自已业务的处理验证             var output = await CheckSign(middleModelId);                          if (!output.SignStatus)             {                 actionContext.Request.EnableBuffering();                 Stream originalBody = actionContext.Response.Body;                 try                 {                     using (var ms = new MemoryStream())                     {                         //修改响应状态麻420                         actionContext.Response.Body = ms;                         actionContext.Response.StatusCode = 420;                         ms.Position = 0;                         //写入数据                         var responseBody = TextJosn.JsonSerializer.Serialize(output);                         var memoryStream = new MemoryStream();                                                 var sw = new StreamWriter(memoryStream);                          //自己编辑的实体写入响应体                         sw.Write(responseBody);                         sw.Flush(); 		                         //重置响应指针                         memoryStream.Position = 0;                         //复制到原body上                         await memoryStream.CopyToAsync(originalBody);                     }                 }                 finally                 {                     actionContext.Response.Body = originalBody;                     actionContext.Request.Body.Position = 0;                 }                  whetherSignature = false;              }             else             {                 if (!string.IsNullOrWhiteSpace(output.ErrorMessage))                 {                     var serializerSettings = new JsonSerializerSettings                     {                         // 设置为驼峰命名                         ContractResolver = new Newtonsoft.Json.Serialization                             .CamelCasePropertyNamesContractResolver()                     };                     //错误友好提示,适配中间件中抛出错误,修改响应体                     var exception = new UserFriendlyException(output.ErrorMessage);                     actionContext.Response.StatusCode = 500;                     actionContext.Response.ContentType = "application/json; charset=utf-8";                     //写入                     await actionContext.Response.WriteAsync(                     JsonConvert.SerializeObject(                         new AjaxResponse(                             _errorInfoBuilder.BuildForException(exception),                             true                              ), serializerSettings                          )                     );                     whetherSignature = false;                 }             }              return whetherSignature;         }                   		//取出json的Name值         private string GetValueName(JObject inputObj, string path)         {             string result = null;             if (!string.IsNullOrWhiteSpace(path))             {                 result = inputObj.SelectToken(path).ToObject<string>();             }             return result;         }          /// <summary>         /// Json字符串首字母转大写         /// </summary>         /// <param name="strJsonData">json字符串</param>         /// <returns></returns>         public static string UpperFirst(string strJsonData)         {             MatchCollection matchCollection = Regex.Matches(strJsonData, "\"[a-zA-Z0-9]+\"\s*:");             foreach (Match item in matchCollection)             {                 string res = Regex.Replace(item.Value, @"b[a-z]w+", delegate (Match match)                 {                     string val = match.ToString();                     return char.ToUpper(val[0]) + val.Substring(1);                 });                 strJsonData = strJsonData.Replace(item.Value, res);             }             return strJsonData;         }     } }  
  • Vue拦截器,拦截失败的响应,状态码为420的,中间件修改的响应的状态码
import { AppConsts } from '/@/abpPro/AppConsts'; import { abpService } from '/@/shared/abp'; import { Modal } from 'ant-design-vue'; import axios, { AxiosResponse } from 'axios'; import abpHttpConfiguration from './abp-http-configuration.service';  const apiHttpClient = axios.create({   baseURL: AppConsts.remoteServiceBaseUrl,   timeout: 300000, });  // 请求拦截器 apiHttpClient.interceptors.request.use(   (config: any) => {      // ....     return config;   },   (error: any) => {     return Promise.reject(error);   }, );  // 响应拦截器 apiHttpClient.interceptors.response.use(   (response: AxiosResponse) => {     // 响应成功拦截器     if (response.data.__abp) {       response.data = response.data.result;     }     return response;   },   (error: any) => {     // 响应失败拦截器    	//方法里存在异步,使用一个Promise包裹起来     return new Promise((resolve, reject) => {       // 关闭所有模态框       Modal.destroyAll();       const errorResponse = error.response;       const ajaxResponse = abpHttpConfiguration.getAbpAjaxResponseOrNull(error.response);       if (ajaxResponse != null) {         abpHttpConfiguration.handleAbpResponse(errorResponse, ajaxResponse);         reject(error);       } else {         if (errorResponse.status == 420) {           //abpHttpConfiguration中自己写的一个模态框弹窗,把响应数据传入其中           abpHttpConfiguration.needIntercept(errorResponse.data)             .toPromise()//Observable转Promise             .then((value) => {               if (value) {                 // resolve 原先的请求地址,重发请求                 resolve(apiHttpClient(errorResponse.config));               } else {                 reject(error);               }             });         } else {           abpHttpConfiguration.handleNonAbpErrorResponse(errorResponse);           reject(error);         }       }     });   }, );  export default apiHttpClient;  
  • 模态框弹窗,返回的bool类型
//是否验证需求通过弹窗   needIntercept(error): Observable<Boolean> {     return new Observable<Boolean>((obs) => {       if (error != undefined && error.SignStatus != null && !error.SignStatus) {         //弹出模态框         this.modalCreate(error).subscribe(           (b) => {             obs.next(b);             obs.complete();           },           (error) => console.log(error, 123),           () => {             obs.next(false);             obs.complete();           },         );       } else {         obs.next(false);         obs.complete();       }     });   }   //电子签名弹窗   modalCreate(responseBody: any): Observable<Boolean> {     let sub;     if (!responseBody.IsAccountSign) {       //弹出模态框,指定的组件GESignNameComponent ,传入参数       sub = modalHelper.create(         GESignNameComponent,         {           relationId: responseBody.ModelSignNameId,           listEsignRequirementId: responseBody.ListSignRequirementId,         },       );     } else {       //弹出模态框,GESignNameAccountComponent ,传入参数       sub = modalHelper.create(         GESignNameAccountComponent,         {           relationId: responseBody.ModelSignNameId,           listEsignRequirementId: responseBody.ListSignRequirementId,         },       );     }      return sub;   }