public async Task CallApi(SignalCall call) { await Clients.Caller.Trace($"Client call [{call.Method}] received"); var data = call.Parameters == null ? new ApiRequest() : JsonSerializer.Deserialize <ApiRequest>(((JsonElement)call.Parameters).GetRawText()); data.Headers.Add(HeaderKeys.ConnectionId, new[] { Context.ConnectionId }); try { var request = CreateRequest(call.Method, data.HttpMethod, data.Headers, data.Body); var response = await GetResponse(request); await Clients.Caller.Trace($"Client call [{call.Method}] done: {response.StatusCode}"); if (response.IsSuccessStatusCode) { if (!string.IsNullOrEmpty(call.Callback)) { await Clients.Caller.Handle(new SignalResult { Method = call.Callback, Data = new { Headers = response.Headers.ToDictionary(_ => _.Key, _ => _.Value), Body = await response.Content.ReadAsStringAsync(), }, }); } } else { await Clients.Caller.Error(response.StatusCode.ToString(), (int)response.StatusCode); } } catch (Exception ex) { await Clients.Caller.Error(ex.Message, ex.HResult); } }
async Task <ApiCallContext> BuildContextAsync(SignalCall call) { var apiDescriptor = apiRegistration.ApiCollections.SingleOrDefault(_ => _.Name == call.Method); if (apiDescriptor == null) { throw new Exception($"Could not find descriptor by method \"{call.Method}\""); } var apiMetadata = new ApiMetadata( apiDescriptor, apiDescriptor.FilterTypes .Select(_ => ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, _)) .Where(_ => _ is IFilterMetadata) .Cast <IFilterMetadata>() .Union(apiRegistration.GlobalFilters) ); var user = await serviceProvider.GetRequiredService <IAuthenticationProvider>().GetUserAsync(call.AccessToken); return(new ApiCallContext(Context.ConnectionId, apiMetadata, user)); }
/// <summary> /// /// </summary> /// <param name="call"></param> /// <returns></returns> public async Task CallApi(SignalCall call) { await Clients.Caller.Trace($"Client call [{call.Method}] received"); var context = await BuildContextAsync(call); var authorizationProvider = serviceProvider.GetRequiredService <IAuthorizationProvider>(); if (!await authorizationProvider.CheckAuthorizedAsync(context)) { await Clients.Caller.Error("UnAuthorized"); return; } var parameters = context.ApiMetadata.ApiDescriptor.Info.GetParameters() .Select(_ => #if NETCOREAPP3_0 || NET5_0 System.Text.Json.JsonSerializer.Deserialize(((System.Text.Json.JsonElement)call.Parameters).GetRawText(), _.ParameterType) #else (call.Parameters as Newtonsoft.Json.Linq.JObject)?.ToObject(_.ParameterType) #endif ) .ToArray(); var validationProvider = serviceProvider.GetService <IValidationProvider>(); if (validationProvider != null) { if (!await validationProvider.ValidateAsync(parameters)) { await Clients.Caller.Error("ValidationError", errors : validationProvider.Errors); return; } } try { var service = ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, context.ApiMetadata.ApiDescriptor.Info.DeclaringType) as ApiServiceBase; service.CallContext = context; var excutingContext = new ApiExecutingContext(context, service, parameters); if (!await OnExecutingAsync(excutingContext)) { return; } var result = await ExecuteAsync(excutingContext); var executedContext = new ApiExecutedContext(excutingContext, result); if (!await OnExecutedAsync(executedContext)) { return; } if (!string.IsNullOrEmpty(call.Callback)) { await Clients.Caller.Handle(new SignalResult { Method = call.Callback, Data = executedContext.Result, }); } } catch (Exception exception) { var exceptionContext = new ApiExceptionContext(context, exception); if (await HandleExceptionAsync(exceptionContext)) { await Clients.Caller.Error(exception.Message, exception.HResult); } } }