private RpcParameterInfo[] GetSignatureInfo(IExposedMethodInformation exposedMethodInformation) { return(exposedMethodInformation.Parameters.Select(parameterInfo => { var fromServices = false; var httpContext = parameterInfo.ParameterType == typeof(HttpContext); var serviceProvider = parameterInfo.ParameterType == typeof(IServiceProvider); if (!httpContext && !serviceProvider) { fromServices = _fromService.ParameterIsFromServices(parameterInfo.ParameterInfo); } return new RpcParameterInfo { ParameterIndex = parameterInfo.Position, ParameterName = parameterInfo.Name, ParameterType = parameterInfo.ParameterType, DefaultValue = parameterInfo.DefaultValue, HasDefaultValue = parameterInfo.HasDefaultValue, FromServices = fromServices, HttpContext = httpContext, ServiceProvider = serviceProvider }; }).ToArray()); }
public ParamsDeserializer BuildDeserializer(IExposedMethodInformation exposedMethod) { DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object[]), new[] { typeof(HttpContext), typeof(RpcJsonReader), typeof(JsonSerializer) }, GetType().GetTypeInfo().Module); var ilGenerator = dynamicMethod.GetILGenerator(); GenerateMethod(exposedMethod, ilGenerator); return(dynamicMethod.CreateDelegate(typeof(ParamsDeserializer)) as ParamsDeserializer); }
protected virtual void GenerateMethod(IExposedMethodInformation exposedMethod, ILGenerator ilGenerator) { var parameters = exposedMethod.Parameters.ToArray(); ilGenerator.EmitInt(parameters.Length); ilGenerator.Emit(OpCodes.Newarr, typeof(object)); var parameterIndex = 0; for (var index = 0; index < parameters.Length; index++) { var parameter = parameters[index]; ilGenerator.Emit(OpCodes.Dup); ilGenerator.EmitInt(index); if (_fromServicesManager.ParameterIsFromServices(parameter.ParameterInfo)) { GenerateIlForFromServices(parameter.ParameterInfo, ilGenerator); } else if (parameter.ParameterType == typeof(HttpContext)) { GenerateIlForHttpContext(parameter.ParameterInfo, ilGenerator); } else if (parameter.ParameterType == typeof(IServiceProvider)) { GenerateIlForServiceProvider(parameter.ParameterInfo, ilGenerator); } else { GenerateIlForParameter(parameter.ParameterInfo, ilGenerator, parameterIndex); parameterIndex++; } if (!parameter.ParameterType.IsByRef) { ilGenerator.Emit(OpCodes.Box, parameter.ParameterType); } ilGenerator.Emit(OpCodes.Stelem_Ref); } ilGenerator.Emit(OpCodes.Ret); }
private RpcMethodInfo GenerateInfoForMethod(string route, IExposedMethodInformation methodInformation) { var method = methodInformation.MethodInfo; string displayString; string parameterString = " "; var parameters = methodInformation.Parameters.ToArray(); var parameterList = new List <JsonParameterInfo>(); if (parameters.Length > 0) { parameterString = ""; foreach (var parameter in parameters) { if (parameter.ParameterType == typeof(IServiceProvider) || parameter.ParameterType == typeof(HttpContext) || _fromServicesManager.ParameterIsFromServices(parameter.ParameterInfo)) { continue; } if (parameterString.Length > 0) { parameterString += ", "; } var friendlyName = TypeUtilities.GetFriendlyTypeName(parameter.ParameterType, out var currentType, out var isArray); parameterString += $"{friendlyName} {parameter.Name}"; bool stringify = !(currentType == typeof(string) || currentType.GetTypeInfo().IsEnum || currentType == typeof(DateTime) || currentType == typeof(DateTime?)); var htmlType = "text"; var type = Nullable.GetUnderlyingType(parameter.ParameterType) ?? parameter.ParameterType; if (type == typeof(int) || type == typeof(uint) || type == typeof(short) || type == typeof(ushort) || type == typeof(long) || type == typeof(ulong) || type == typeof(double) || type == typeof(float) || type == typeof(decimal)) { htmlType = "number"; } else if (type == typeof(DateTime)) { htmlType = "datetime-local"; } parameterList.Add(new JsonParameterInfo { Name = parameter.Name, ParameterType = TypeUtilities.CreateTypeRef(parameter.ParameterType), Array = isArray, Stringify = stringify, Optional = parameter.HasDefaultValue, DefaultValue = parameter.HasDefaultValue ? parameter.DefaultValue : null, HtmlType = htmlType }); } } if (methodInformation.MethodAuthorizations != null && methodInformation.MethodAuthorizations.Length > 0) { _hasAuthorization = true; } displayString = $"{TypeUtilities.GetFriendlyTypeName(method.ReturnType,out var unusedType, out var unused)} {methodInformation.MethodName}({parameterString})"; return(new RpcMethodInfo { Path = route, Name = methodInformation.MethodName, Signature = displayString, ReturnType = TypeUtilities.CreateTypeRef(methodInformation.MethodInfo.ReturnType), Parameters = parameterList, Method = methodInformation, ObsoleteMessage = methodInformation.ObsoleteMessage }); }
public ParamsDeserializer BuildDeserializer(IExposedMethodInformation exposedMethod) { var signatureInfo = GetSignatureInfo(exposedMethod); return((context, reader, serializer) => DeserializeParameters(context, reader, serializer, signatureInfo)); }
private async Task <ResponseMessage> ExecuteMethod(HttpContext context, IServiceProvider serviceProvider, RpcRequestMessage requestMessage, IExposedMethodInformation exposedMethod) { CallExecutionContext callExecutionContext = new CallExecutionContext(context, exposedMethod.InstanceType, exposedMethod.MethodInfo, requestMessage); if (exposedMethod.MethodAuthorizations.Length > 0) { for (var i = 0; i < exposedMethod.MethodAuthorizations.Length; i++) { if (!await exposedMethod.MethodAuthorizations[i].AsyncAuthorize(callExecutionContext)) { if (_debugLogging) { _logger?.LogDebug($"Unauthorized access to {context.Request.Path} {requestMessage.Method}"); } return(ReturnUnauthorizedAccess(context, requestMessage.Version, requestMessage.Id)); } } } object newInstance = null; try { newInstance = exposedMethod.InstanceProvider(context, serviceProvider); callExecutionContext.Instance = newInstance; } catch (Exception exp) { _logger?.LogError(EventIdCode.ActivationException, exp, $"Exception thrown while creating instance {exposedMethod.InstanceType.Name} for {context.Request.Path} {requestMessage.Method} - " + exp.Message); // log error return(ReturnInternalServerError(requestMessage.Version, requestMessage.Id, $" Could not activate type {exposedMethod.InstanceType.FullName}\n{exp.Message}")); } if (newInstance == null) { return(ReturnInternalServerError(requestMessage.Version, requestMessage.Id, $"Could not locate type {exposedMethod.InstanceType.FullName}")); } List <ICallFilter> filters = null; bool runFilters = false; var exposedFilters = exposedMethod.Filters; if (exposedFilters.Length > 0) { filters = new List <ICallFilter>(); try { for (var i = 0; i < exposedFilters.Length; i++) { filters.AddRange(exposedFilters[i](callExecutionContext)); } } catch (Exception exp) { _logger?.LogError(EventIdCode.ActivationException, exp, $"Exception thrown while activating filters for {exposedMethod.InstanceType.Name} {context.Request.Path} {requestMessage.Method} - " + exp.Message); return(ReturnInternalServerError(requestMessage.Version, requestMessage.Id, "Could not activate filters")); } runFilters = filters.Count > 0; } try { object[] parameterValues = requestMessage.Parameters ?? NoParamsArray; if (runFilters) { callExecutionContext.Parameters = parameterValues; for (var i = 0; i < filters.Count; i++) { if (callExecutionContext.ContinueCall && filters[i] is ICallExecuteFilter executeFilter) { executeFilter.BeforeExecute(callExecutionContext); } } parameterValues = callExecutionContext.Parameters; } ResponseMessage responseMessage; if (callExecutionContext.ContinueCall) { responseMessage = await exposedMethod.InvokeMethod(newInstance, parameterValues, requestMessage.Version, requestMessage.Id); } else { return(callExecutionContext.ResponseMessage); } if (runFilters && callExecutionContext.ContinueCall) { callExecutionContext.ResponseMessage = responseMessage; for (var i = 0; i < filters.Count; i++) { if (callExecutionContext.ContinueCall && filters[i] is ICallExecuteFilter executeFilter) { executeFilter.AfterExecute(callExecutionContext); } } return(callExecutionContext.ResponseMessage); } return(responseMessage); } catch (Exception exp) { return(ExecuteMethodErrorHandler(context, requestMessage, exp, runFilters, filters, callExecutionContext)); } }