public IActionResult Invoke(RouteMatch match, TcpClient client, RequestContext context) { if (match is null) { throw new ArgumentNullException($"{nameof(match)} cannot be null.", nameof(match)); } if (match.ActionMatch.Action is null) { throw new ArgumentNullException($"match.HttpMethod.Template"); } if (match.ActionMatch.Action.ReturnType != typeof(IActionResult)) { throw new NotSupportedException($"Invalid Match: Invalid Action ReturnType:{match.ActionMatch.Action.ReturnType}. " + $"ReturnType must be {typeof(IActionResult)}"); } if (match.ActionMatch.HttpMethod == null) { throw new ArgumentNullException($"{nameof(match)}.{nameof(match.ActionMatch.HttpMethod)} cannot be null."); } if (match.ActionMatch.HttpMethod.Template == null) { throw new ArgumentNullException($"{nameof(match)}.{nameof(match.ActionMatch.HttpMethod)}.{nameof(match.ActionMatch.HttpMethod.Template)} cannot be null."); } if (client is null) { throw new ArgumentNullException($"{nameof(client)} cannot be null.", nameof(client)); } Assert.NotNull(context, nameof(context)); Assert.NotNull(context.Content, $"{nameof(context)}.{nameof(context.Content)}."); Assert.NotNull(match.MatchingActionPathSegments, $"{nameof(match)}.{nameof(match.MatchingActionPathSegments)}"); Assert.NotNull(match.TemplatePathSegments, $"{nameof(match)}.{nameof(match.TemplatePathSegments)}"); Assert.That(match.MatchingActionPathSegments.Length == match.TemplatePathSegments.Length, "Invalid match: actionPathLength must be equal to templatePathLength"); RequestBodyExtractor bodyExtractor = new RequestBodyExtractor(context); object controller = BuildController(match, client, context); List <object> invokeArguments = new List <object>(); foreach (ParameterInfo actionParameter in match.ActionMatch.Action.GetParameters()) { string correspondingParameter = string.Empty; int actionParameterIndex = Array.IndexOf(match.TemplatePathSegments, $"{{{actionParameter.Name}}}"); if (actionParameterIndex == -1) { if (context.Parameters.HeaderEntries.ContainsKey(actionParameter.Name)) { correspondingParameter = ExtractFromRequestHeader(context, actionParameter); } else { byte[] bodyContent = ExtractFromRequestBody(match, context, bodyExtractor, actionParameter); correspondingParameter = Encoding.UTF8.GetString(bodyContent); } } else { string routeParameter = match.MatchingActionPathSegments[actionParameterIndex]; correspondingParameter = ConvertToDeserializeableString(routeParameter, actionParameter); } try { if (actionParameter.ParameterType == typeof(Guid)) { if (Guid.TryParse(correspondingParameter, out Guid result)) { invokeArguments.Add(result); } else { throw new EndPointHandlerException( $"Error parsing expected Guid- Parameter: {actionParameter.Name}. " + $"Value: {correspondingParameter} could not be parsed." ); } } else { object result = JsonSerializer.Deserialize(correspondingParameter, actionParameter.ParameterType); invokeArguments.Add(result); } } catch (JsonException jsonEx) { throw BuildEndpointHandlerException( $"Could not Resolve Action Parameter:{actionParameter.Name} of Type: {actionParameter.ParameterType}.{Environment.NewLine}", match, jsonEx ); } } return((IActionResult)match.ActionMatch.Action.Invoke(controller, invokeArguments.ToArray())); }
private static byte[] ExtractFromRequestBody(RouteMatch match, RequestContext context, RequestBodyExtractor bodyExtractor, ParameterInfo actionParameter) { if (supportedContentTypes.Any(sct => sct.Equals(context.Content.ContentType, StringComparison.OrdinalIgnoreCase))) { if (bodyExtractor.BodyExtracted) { return(bodyExtractor.Cache.ToArray()); } else { try { return(bodyExtractor.Extract()); } catch (RequestBodyExtractorException bodyExtractorEx) { EndPointHandlerException error = BuildEndpointHandlerException( $"Could not Resolve Action Parameter:{actionParameter.Name} of Type: {actionParameter.ParameterType}.", match, bodyExtractorEx ); throw error; } } } else { NotSupportedException innerException = new NotSupportedException( $"Could not Resolve Action Parameter:{actionParameter.Name} of Type: {actionParameter.ParameterType}. " + $"Invalid Content-Type:{context.Content.ContentType}. " + $"Supported Contenttypes are: {string.Join(',', supportedContentTypes)}"); throw BuildEndpointHandlerException(match, innerException); } }