.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 = ""){}}

接口加上特性:
/// ///添加或者修改方法/// /// 【.NET中间件与VUE拦截器联合使用详情】/// //特性上添加参数的地址[ModelEsignName("Bolg.BolgBaseEditDto.BolgName", "Document.Id", "Bolg.BolgRevision")]public async Task 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 依赖注入等内容....#endregionpublic async Task InvokeAsync(HttpContext context, RequestDelegate next){if (await ShouldCheckESign(context)){// 不需要电子签名await next(context); }}/// /// 是否需要拦截/// /// /// private async Task ShouldCheckESign(HttpContext actionContext){var whetherSignature = true; var request = actionContext.Request; //获取请求值var currentUser = actionContext.User.Identity.Name; var serviceAction = actionContext.GetEndpoint()?.Metadata.GetMetadata(); 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请求获取请求参数,转换JSONif (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(); #endregionvar 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()){//修改响应状态麻420actionContext.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(); }return result; }/// /// Json字符串首字母转大写/// /// json字符串/// 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 = https://www.it610.com/article/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 = https://www.it610.com/article/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 {return new Observable((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 {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; }

到此这篇关于.NET中间件与VUE拦截器联合使用详情的文章就介绍到这了,更多相关.NET VUE拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    推荐阅读