.NET中间件以及VUE拦截器联合使用
工作中遇见的问题,边学边弄,记录一下
Vue的UI库使用的是antvue 3.2.9版本的。
- 业务逻辑

- 特性
- //特性
- 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;
复制代码- //是否验证需求通过弹窗
- 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;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |