/// <summary> /// 执行Action /// </summary> /// <param name="context">上下文</param> /// <param name="arguments">参数值</param> /// <returns></returns> public async Task <TResult> InvokeAsync(ServiceContext context, object?[] arguments) { try { using var httpContext = new HttpContext(context); var requestContext = new ApiRequestContext(httpContext, this.ApiAction, arguments); return(await this.InvokeAsync(requestContext).ConfigureAwait(false)); } catch (HttpRequestException) { throw; } catch (Exception ex) { throw new HttpRequestException(ex.Message, ex); } }
/// <summary> /// 处理请求上下文 /// </summary> /// <returns></returns> private static async Task HandleRequestAsync(ApiRequestContext context) { // 参数验证 var validateProperty = context.HttpContext.HttpApiOptions.UseParameterPropertyValidate; foreach (var parameter in context.ApiAction.Parameters) { var parameterValue = context.Arguments[parameter.Index]; DataValidator.ValidateParameter(parameter, parameterValue, validateProperty); } // action特性请求前执行 foreach (var attr in context.ApiAction.Attributes) { await attr.OnRequestAsync(context).ConfigureAwait(false); } // 参数特性请求前执行 foreach (var parameter in context.ApiAction.Parameters) { var ctx = new ApiParameterContext(context, parameter); foreach (var attr in parameter.Attributes) { await attr.OnRequestAsync(ctx).ConfigureAwait(false); } } // Return特性请求前执行 foreach (var @return in context.ApiAction.Return.Attributes) { await @return.OnRequestAsync(context).ConfigureAwait(false); } // GlobalFilter请求前执行 foreach (var filter in context.HttpContext.HttpApiOptions.GlobalFilters) { await filter.OnRequestAsync(context).ConfigureAwait(false); } // Filter请求前执行 foreach (var filter in context.ApiAction.FilterAttributes) { await filter.OnRequestAsync(context).ConfigureAwait(false); } }
/// <summary> /// 发送http请求 /// </summary> /// <param name="context"></param> /// <exception cref="HttpRequestException"></exception> /// <returns></returns> public static async Task<ApiResponseContext> SendAsync(ApiRequestContext context) { var actionCache = await GetCaheAsync(context).ConfigureAwait(false); if (actionCache != null && actionCache.Value != null) { context.HttpContext.ResponseMessage = actionCache.Value; } else { var client = context.HttpContext.Client; using var tokenLinker = new CancellationTokenLinker(context.CancellationTokens); var response = await client.SendAsync(context.HttpContext.RequestMessage, tokenLinker.Token).ConfigureAwait(false); context.HttpContext.ResponseMessage = response; await SetCacheAsync(context, actionCache?.Key, response).ConfigureAwait(false); } return new ApiResponseContext(context); }
/// <summary> /// 更新响应到缓存 /// </summary> /// <param name="context"></param> /// <param name="cacheKey">缓存键</param> /// <param name="response">响应消息</param> /// <returns></returns> private static async Task SetCacheAsync(ApiRequestContext context, string? cacheKey, HttpResponseMessage? response) { var attribute = context.ApiAction.CacheAttribute; if (attribute == null) { return; } if (response == null) { return; } if (attribute.GetWritePolicy(context) == CachePolicy.Ignore) { return; } if (string.IsNullOrEmpty(cacheKey) == true) { cacheKey = await attribute.GetCacheKeyAsync(context).ConfigureAwait(false); } if (cacheKey == null) { return; } var provider = context.HttpContext.Services.GetService<IResponseCacheProvider>(); if (provider == null) { return; } var cacheEntry = await ResponseCacheEntry.FromResponseMessageAsync(response).ConfigureAwait(false); await provider.SetAsync(cacheKey, cacheEntry, attribute.Expiration).ConfigureAwait(false); }
/// <summary> /// Api参数上下文 /// </summary> /// <param name="context">上下文</param> /// <param name="parameterIndex">参数索引</param> public ApiParameterContext(ApiRequestContext context, int parameterIndex) : base(context.HttpContext, context.ApiAction, context.Arguments, context.Properties) { this.index = parameterIndex; }
/// <summary> /// 执行Api方法 /// </summary> /// <param name="context"></param> /// <returns></returns> private async Task <TResult> InvokeAsync(ApiRequestContext context) { #nullable disable
/// <summary> /// 尝试根据参数名获取参数值 /// </summary> /// <param name="context"></param> /// <param name="parameterName">参数名</param> /// <param name="value">值</param> /// <returns></returns> public static bool TryGetArgument(this ApiRequestContext context, string parameterName, out object?value) { return(context.TryGetArgument(parameterName, StringComparer.Ordinal, out value)); }
/// <summary> /// 尝试根据参数名获取参数值 /// </summary> /// <typeparam name="TValue"></typeparam> /// <param name="context"></param> /// <param name="parameterName">参数名</param> /// <param name="value">值</param> /// <returns></returns> public static bool TryGetArgument <TValue>(this ApiRequestContext context, string parameterName, [MaybeNullWhen(false)] out TValue value) { return(context.TryGetArgument(parameterName, StringComparer.Ordinal, out value)); }
/// <summary> /// Api参数上下文 /// </summary> /// <param name="context">上下文</param> /// <param name="parameter">参数描述</param> public ApiParameterContext(ApiRequestContext context, ApiParameterDescriptor parameter) : base(context.HttpContext, context.ApiAction, context.Arguments, context.Properties) { this.Parameter = parameter; }
/// <summary> /// Api参数上下文 /// </summary> /// <param name="context">上下文</param> /// <param name="parameterIndex">参数索引</param> public ApiParameterContext(ApiRequestContext context, int parameterIndex) : this(context, context.ApiAction.Parameters[parameterIndex]) { }
/// <summary> /// 执行上下文 /// </summary> /// <param name="request">请求上下文</param> /// <returns></returns> public static Task <ApiResponseContext> InvokeAsync(ApiRequestContext request) { return(handler(request)); }
/// <summary> /// Api参数上下文 /// </summary> /// <param name="context">上下文</param> /// <param name="parameterIndex">参数索引</param> public ApiParameterContext(ApiRequestContext context, int parameterIndex) : base(context.HttpContext, context.ApiAction, context.Arguments, context.UserDatas, context.CancellationTokens) { this.index = parameterIndex; }
/// <summary> /// Api缓存 /// </summary> /// <param name="context">上下文</param> public ApiCache(ApiRequestContext context) { this.context = context; this.attribute = context.ApiAction.CacheAttribute; }