示例#1
0
        private IHttpResponseHandler GetHttpResponseHandler(HttpFunctionDefinition httpFunctionDefinition)
        {
            IHttpResponseHandler httpResponseHandler = httpFunctionDefinition.HasHttpResponseHandler
                ? (IHttpResponseHandler)ServiceProvider.GetRequiredService(httpFunctionDefinition.HttpResponseHandlerType)
                : new DefaultHttpResponseHandler();

            return(httpResponseHandler);
        }
示例#2
0
 public SignalRFunctionConfigurationBuilder(
     ConnectionStringSettingNames connectionStringSettingNames,
     ISignalRFunctionBuilder httpFunctionBuilder,
     HttpFunctionDefinition definition)
 {
     _connectionStringSettingNames = connectionStringSettingNames;
     _httpFunctionBuilder          = httpFunctionBuilder;
     _definition = definition;
 }
示例#3
0
        private static void CompleteHttpFunctionDefinition(FunctionHostBuilder builder,
                                                           HttpFunctionDefinition httpFunctionDefinition, AuthorizationBuilder authorizationBuilder,
                                                           Type validationResultType)
        {
            if (!httpFunctionDefinition.Authorization.HasValue)
            {
                httpFunctionDefinition.Authorization = authorizationBuilder.AuthorizationDefaultValue;
            }

            if (httpFunctionDefinition.Authorization.Value == AuthorizationTypeEnum.TokenValidation)
            {
                httpFunctionDefinition.ValidatesToken = true;
            }

            if (httpFunctionDefinition.Verbs.Count == 0)
            {
                httpFunctionDefinition.Verbs.Add(HttpMethod.Get);
            }

            httpFunctionDefinition.ClaimsPrincipalAuthorizationType =
                httpFunctionDefinition.ClaimsPrincipalAuthorizationType ??
                httpFunctionDefinition.RouteConfiguration.ClaimsPrincipalAuthorizationType ??
                authorizationBuilder.DefaultClaimsPrincipalAuthorizationType;

            httpFunctionDefinition.HeaderBindingConfiguration =
                httpFunctionDefinition.HeaderBindingConfiguration ?? builder.DefaultHeaderBindingConfiguration;

            httpFunctionDefinition.HttpResponseHandlerType =
                httpFunctionDefinition.HttpResponseHandlerType ?? builder.DefaultHttpResponseHandlerType;

            httpFunctionDefinition.TokenHeader = httpFunctionDefinition.TokenHeader ?? authorizationBuilder.AuthorizationHeader ?? "Authorization";

            httpFunctionDefinition.IsValidationResult = httpFunctionDefinition.CommandResultType != null &&
                                                        validationResultType.IsAssignableFrom(httpFunctionDefinition
                                                                                              .CommandResultType);

            httpFunctionDefinition.IsStreamCommand =
                (typeof(IStreamCommand)).IsAssignableFrom(httpFunctionDefinition.CommandType);

            httpFunctionDefinition.TokenValidatorType = httpFunctionDefinition.TokenValidatorType ?? authorizationBuilder.TokenValidatorType;

            if (httpFunctionDefinition.ValidatesToken && httpFunctionDefinition.TokenValidatorType == null)
            {
                throw new ConfigurationException($"Command {httpFunctionDefinition.CommandType.Name} expects to be authenticated with token validation but no token validator is registered");
            }

            httpFunctionDefinition.Route = httpFunctionDefinition.Route?.TrimStart('/');

            ExtractRouteParameters(httpFunctionDefinition);

            ExtractPossibleQueryParameters(httpFunctionDefinition);

            ExtractPossibleFormParameters(httpFunctionDefinition);

            EnsureOpenApiDescription(httpFunctionDefinition);
        }
示例#4
0
        private IActionResult CreateResponse(int code, object content, HttpFunctionDefinition httpFunctionDefinition)
        {
            ISerializer   serializer = CreateSerializer(httpFunctionDefinition);
            ContentResult result     = new ContentResult
            {
                Content = serializer.Serialize(content), ContentType = "application/json", StatusCode = code
            };

            return(result);
        }
示例#5
0
        /// <summary>
        /// Runs a command through the IActionResult ASP.Net pathways and returns a HTTP response.
        /// This is useful for testing end to end HTTP triggered functions without having to actually host the
        /// function app.
        /// A method only needs specifying in the function supports multiple methods.
        /// </summary>
        public async Task <HttpResponse> ExecuteHttpAsync <TResult>(ICommand <TResult> command, HttpMethod method = null)
        {
            HttpFunctionDefinition httpFunctionDefinition = FindHttpFunctionDefinition(command);
            ActionContext          actionContext          = _aspNetRuntime.PrepareToExecuteHttp(command, httpFunctionDefinition, method);
            IHttpResponseHandler   httpResponseHandler    = GetHttpResponseHandler(httpFunctionDefinition);
            HttpDispatcher         httpDispatcher         = new HttpDispatcher(Dispatcher, ServiceProvider);

            IActionResult actionResult = await httpDispatcher.DispatchAndConvertToActionResult(command, httpResponseHandler, httpFunctionDefinition);

            return(await _aspNetRuntime.CreateHttpResponse(actionContext, actionResult));
        }
示例#6
0
        private ISerializer CreateSerializer(HttpFunctionDefinition httpFunctionDefinition)
        {
            if (httpFunctionDefinition.SerializerNamingStrategyType != null)
            {
                NamingStrategy serializerNamingStrategy   = (NamingStrategy)Activator.CreateInstance(httpFunctionDefinition.SerializerNamingStrategyType);
                NamingStrategy deserializerNamingStrategy = (NamingStrategy)Activator.CreateInstance(httpFunctionDefinition.DeserializerNamingStrategyType);
                ISerializer    serializer = new NamingStrategyJsonSerializer(deserializerNamingStrategy, serializerNamingStrategy);
                return(serializer);
            }

            return((ISerializer)_serviceProvider.GetRequiredService(httpFunctionDefinition.CommandDeserializerType));
        }
示例#7
0
        private IHttpFunctionBuilderMetadataBuilder BuildHttpFunction <TCommand>(string route, AuthorizationTypeEnum?authorizationType, params HttpMethod[] method) where TCommand : ICommand
        {
            HttpFunctionDefinition definition = new HttpFunctionDefinition(typeof(TCommand))
            {
                SubRoute           = route,
                RouteConfiguration = _routeConfiguration,
                Route         = string.Concat(_routeConfiguration.Route, route),
                Verbs         = new HashSet <HttpMethod>(method),
                Authorization = authorizationType
            };

            _definitions.Add(definition);
            return(new HttpFunctionBuilderMetadataBuilder(this, definition));
        }
示例#8
0
 private static void ExtractPossibleFormParameters(HttpFunctionDefinition httpFunctionDefinition)
 {
     httpFunctionDefinition.PossibleFormProperties = httpFunctionDefinition
                                                     .CommandType
                                                     .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                     .Where(x => x.GetCustomAttribute <SecurityPropertyAttribute>() == null &&
                                                            x.SetMethod != null &&
                                                            (x.PropertyType == typeof(IFormCollection)))
                                                     .Select(x => new HttpParameter
     {
         Name = x.Name,
         Type = x.PropertyType
     })
                                                     .ToArray();
 }
示例#9
0
        private IHttpFunctionConfigurationBuilder <TCommand> BuildHttpFunction <TCommand>(string route,
                                                                                          AuthorizationTypeEnum?authorizationType,
                                                                                          params HttpMethod[] method)
        {
            HttpFunctionDefinition definition = new HttpFunctionDefinition(typeof(TCommand))
            {
                SubRoute           = route,
                RouteConfiguration = _routeConfiguration,
                Route         = _routeConfiguration.Route == null ? route : string.Concat(_routeConfiguration.Route, route).TrimStart('/'),
                Verbs         = new HashSet <HttpMethod>(method),
                Authorization = authorizationType,
                ClaimsPrincipalAuthorizationType = _routeConfiguration.ClaimsPrincipalAuthorizationType
            };

            _definitions.Add(definition);
            return(new HttpFunctionConfigurationBuilder <TCommand>(_connectionStringSettingNames, this, definition));
        }
示例#10
0
 private static void ExtractPossibleQueryParameters(HttpFunctionDefinition httpFunctionDefinition)
 {
     httpFunctionDefinition.PossibleBindingProperties = httpFunctionDefinition
                                                        .CommandType
                                                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                        .Where(x => x.GetCustomAttribute <SecurityPropertyAttribute>() == null &&
                                                               x.SetMethod != null &&
                                                               (x.PropertyType == typeof(string) || x.PropertyType
                                                                .GetMethods(BindingFlags.Public | BindingFlags.Static).Any(y => y.Name == "TryParse")))
                                                        .Select(x => new HttpParameter
     {
         Name     = x.Name,
         TypeName = x.PropertyType.EvaluateType(),
         Type     = x.PropertyType
     })
                                                        .ToArray();
 }
示例#11
0
        public ActionContext PrepareToExecuteHttp(ICommand command,
                                                  HttpFunctionDefinition httpFunctionDefinition,
                                                  HttpMethod method)
        {
            HttpContext httpContext = new DefaultHttpContext()
            {
                RequestServices = ServiceProvider,
                Request         =
                {
                    Method = (method ?? httpFunctionDefinition.Verbs.Single()).Method
                },
                Response = { Body = new MemoryStream() }
            };
            RouteData        routeData        = new RouteData();
            ActionDescriptor actionDescriptor = new ActionDescriptor();

            return(new ActionContext(httpContext, routeData, actionDescriptor));
        }
示例#12
0
        public async Task <IActionResult> DispatchAndConvertToActionResult <TResult>(
            ICommand <TResult> command,
            IHttpResponseHandler httpResponseHandler,
            HttpFunctionDefinition httpFunctionDefinition)
        {
            IActionResult actionResult = null;

            try
            {
                TResult result = await _dispatcher.DispatchAsync(command);

                // TODO: Handle validation here
                Task <IActionResult> responseHandlerTask = httpResponseHandler.CreateResponse(command, result);
                if (responseHandlerTask != null)
                {
                    actionResult = await responseHandlerTask;
                }

                if (actionResult == null)
                {
                    actionResult = CreateResponse(200, result, httpFunctionDefinition);
                }
            }
            catch (ValidationException vex)
            {
                actionResult = await CreateValidationResponse(command, vex.ValidationResult, httpFunctionDefinition, httpResponseHandler);
            }
            catch (Exception ex)
            {
                Task exceptionResponseHandlerTask = httpResponseHandler.CreateResponseFromException(command, ex);
                if (exceptionResponseHandlerTask != null)
                {
                    actionResult = await httpResponseHandler.CreateResponseFromException(command, ex);
                }

                if (actionResult == null)
                {
                    actionResult = CreateResponse(500, "Unexpected error", httpFunctionDefinition);
                }
            }

            return(actionResult);
        }
        private static void CompleteHttpFunctionDefinition(FunctionHostBuilder builder,
                                                           HttpFunctionDefinition httpFunctionDefinition, AuthorizationBuilder authorizationBuilder,
                                                           Type validationResultType)
        {
            if (!httpFunctionDefinition.Authorization.HasValue)
            {
                httpFunctionDefinition.Authorization = authorizationBuilder.AuthorizationDefaultValue;
            }

            if (httpFunctionDefinition.Authorization.Value == AuthorizationTypeEnum.TokenValidation)
            {
                httpFunctionDefinition.ValidatesToken = true;
            }

            if (httpFunctionDefinition.Verbs.Count == 0)
            {
                httpFunctionDefinition.Verbs.Add(HttpMethod.Get);
            }

            if (string.IsNullOrWhiteSpace(httpFunctionDefinition.ClaimsPrincipalAuthorizationTypeName))
            {
                httpFunctionDefinition.ClaimsPrincipalAuthorizationType =
                    authorizationBuilder.DefaultClaimsPrincipalAuthorizationType;
            }

            httpFunctionDefinition.HeaderBindingConfiguration =
                httpFunctionDefinition.HeaderBindingConfiguration ?? builder.DefaultHeaderBindingConfiguration;

            httpFunctionDefinition.HttpResponseHandlerType =
                httpFunctionDefinition.HttpResponseHandlerType ?? builder.DefaultHttpResponseHandlerType;

            httpFunctionDefinition.TokenHeader = authorizationBuilder.AuthorizationHeader ?? "Authorization";

            httpFunctionDefinition.IsValidationResult = httpFunctionDefinition.CommandResultType != null &&
                                                        validationResultType.IsAssignableFrom(httpFunctionDefinition
                                                                                              .CommandResultType);

            ExtractPossibleQueryParameters(httpFunctionDefinition);

            ExtractRouteParameters(httpFunctionDefinition);

            EnsureOpenApiDescription(httpFunctionDefinition);
        }
示例#14
0
        private static void ExtractPossibleQueryParameters(HttpFunctionDefinition httpFunctionDefinition)
        {
            Debug.Assert(httpFunctionDefinition.RouteParameters != null);

            httpFunctionDefinition.PossibleBindingProperties = httpFunctionDefinition
                                                               .CommandType
                                                               .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                               .Where(x => x.GetCustomAttribute <SecurityPropertyAttribute>() == null &&
                                                                      x.SetMethod != null &&
                                                                      x.PropertyType.IsSupportedQueryParameterType() &&
                                                                      httpFunctionDefinition.RouteParameters.All(y => y.Name != x.Name) // we can't be a query parameter and a route parameter
                                                                      )
                                                               .Select(x => new HttpParameter
            {
                Name       = x.Name,
                Type       = x.PropertyType,
                IsOptional = !x.PropertyType.IsValueType || Nullable.GetUnderlyingType(x.PropertyType) != null
            })
                                                               .ToArray();
        }
示例#15
0
        private static void ExtractRouteParameters(HttpFunctionDefinition httpFunctionDefinition1)
        {
            string lowerCaseRoute = httpFunctionDefinition1.Route.ToLower();

            httpFunctionDefinition1.RouteParameters = httpFunctionDefinition1
                                                      .CommandType
                                                      .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                      .Where(x => x.GetCustomAttribute <SecurityPropertyAttribute>() == null &&
                                                             x.SetMethod != null &&
                                                             (x.PropertyType == typeof(string) || x.PropertyType
                                                              .GetMethods(BindingFlags.Public | BindingFlags.Static).Any(y => y.Name == "TryParse")) &&
                                                             lowerCaseRoute.Contains("{" + x.Name.ToLower() + "}"))
                                                      .Select(x => new HttpParameter
            {
                Name     = x.Name,
                TypeName = x.PropertyType.EvaluateType(),
                Type     = x.PropertyType
            })
                                                      .ToArray();
        }
示例#16
0
        private static void EnsureOpenApiDescription(HttpFunctionDefinition httpFunctionDefinition)
        {
            // function definitions share route definitions so setting properties for one sets for all
            // but we set only if absent and based on the parent route
            // alternative would be to gather up the unique route configurations and set once but will
            // involve multiple loops
            Debug.Assert(httpFunctionDefinition.RouteConfiguration != null);
            if (string.IsNullOrWhiteSpace(httpFunctionDefinition.RouteConfiguration.OpenApiName))
            {
                string[] components = httpFunctionDefinition.RouteConfiguration.Route.Split('/');
                for (int index = components.Length - 1; index >= 0; index--)
                {
                    if (string.IsNullOrWhiteSpace(components[index]) || IsRouteParameter(components[index]))
                    {
                        continue;
                    }

                    httpFunctionDefinition.RouteConfiguration.OpenApiName = components[index];
                    break;
                }
            }
        }
示例#17
0
        private static void PatchHeaderBindings(FunctionHostBuilder builder, HttpFunctionDefinition httpFunctionDefinition)
        {
            if (httpFunctionDefinition.HeaderBindingConfiguration == null)
            {
                httpFunctionDefinition.HeaderBindingConfiguration = builder.DefaultHeaderBindingConfiguration;
            }
            else
            {
                if (builder.DefaultHeaderBindingConfiguration != null)
                {
                    foreach (KeyValuePair <string, string> kvp in builder.DefaultHeaderBindingConfiguration
                             .PropertyFromHeaderMappings)
                    {
                        if (!httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings.ContainsKey(
                                kvp.Key))
                        {
                            httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings
                            .Add(kvp.Key, kvp.Value);
                        }
                    }
                }
            }

            if (httpFunctionDefinition.HeaderBindingConfiguration == null)
            {
                httpFunctionDefinition.HeaderBindingConfiguration = new HeaderBindingConfiguration()
                {
                    PropertyFromHeaderMappings = new Dictionary <string, string>()
                };
            }

            if (httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings == null)
            {
                httpFunctionDefinition.HeaderBindingConfiguration.PropertyFromHeaderMappings = new Dictionary <string, string>();
            }
        }
示例#18
0
        private static void ExtractPossibleQueryParameters(HttpFunctionDefinition httpFunctionDefinition)
        {
            Debug.Assert(httpFunctionDefinition.RouteParameters != null);

            httpFunctionDefinition.PossibleBindingProperties = httpFunctionDefinition
                                                               .CommandType
                                                               .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                               .Where(x => x.GetCustomAttribute <SecurityPropertyAttribute>() == null &&
                                                                      x.SetMethod != null &&
                                                                      (x.PropertyType == typeof(string) ||
                                                                       x.PropertyType.GetMethods(BindingFlags.Public | BindingFlags.Static).Any(y => y.Name == "TryParse") ||
                                                                       x.PropertyType.IsEnum ||
                                                                       x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) &&
                                                                      httpFunctionDefinition.RouteParameters.All(y => y.Name != x.Name) // we can't be a query parameter and a route parameter
                                                                      )
                                                               .Select(x => new HttpParameter
            {
                Name       = x.Name,
                TypeName   = x.PropertyType.EvaluateType(),
                Type       = x.PropertyType,
                IsOptional = !x.PropertyType.IsValueType
            })
                                                               .ToArray();
        }
示例#19
0
        private SyntaxTree CreateController(string namespaceName, DirectoryInfo directoryInfo, HttpFunctionDefinition httpFunctionDefinition)
        {
            string startupTemplateSource    = TemplateProvider.GetTemplate("controller", "csharp");
            Func <object, string> template  = Handlebars.Compile(startupTemplateSource);
            string filenameWithoutExtension = $"{httpFunctionDefinition.Name}Controller";

            string outputCode = template(httpFunctionDefinition);

            OutputDiagnosticCode(directoryInfo, filenameWithoutExtension, outputCode);

            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(outputCode, path: $"{filenameWithoutExtension}.cs");

            return(syntaxTree);
        }
示例#20
0
        private async Task <IActionResult> CreateValidationResponse(ICommand command, ValidationResult validationResult, HttpFunctionDefinition httpFunctionDefinition, IHttpResponseHandler responseHandler)
        {
            IActionResult        actionResult = null;
            Task <IActionResult> validationResponseHandlerTask = responseHandler.CreateValidationFailureResponse(command, validationResult);

            if (validationResponseHandlerTask != null)
            {
                actionResult = await validationResponseHandlerTask;
            }

            return(actionResult ?? (CreateResponse(400, validationResult, httpFunctionDefinition)));
        }
 public HttpFunctionConfigurationBuilder(IHttpFunctionBuilder httpFunctionBuilder,
                                         HttpFunctionDefinition definition)
 {
     _httpFunctionBuilder = httpFunctionBuilder;
     _definition          = definition;
 }
示例#22
0
        private static void ExtractRouteParameters(HttpFunctionDefinition httpFunctionDefinition1)
        {
            List <HttpParameter> routeParameters = new List <HttpParameter>();

            if (httpFunctionDefinition1.Route == null)
            {
                httpFunctionDefinition1.RouteParameters = routeParameters;
                return;
            }

            PropertyInfo[] candidateCommandProperties = httpFunctionDefinition1.CommandType
                                                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                                        .Where(x => x.GetCustomAttribute <SecurityPropertyAttribute>() == null &&
                                                               x.SetMethod != null &&
                                                               (x.PropertyType == typeof(string) ||
                                                                Nullable.GetUnderlyingType(x.PropertyType) != null ||
                                                                x.PropertyType.GetMethods(BindingFlags.Public | BindingFlags.Static).Any(y => y.Name == "TryParse"))).ToArray();
            Regex           regex   = new Regex("{(.*?)}");
            MatchCollection matches = regex.Matches(httpFunctionDefinition1.Route);

            foreach (Match match in matches)
            {
                string   routeParameter      = match.Groups[1].Value;
                bool     isOptional          = routeParameter.EndsWith("?");
                string[] routeParameterParts = routeParameter.Split(':');
                if (routeParameterParts.Length == 0)
                {
                    throw new ConfigurationException($"Bad route parameter in route {httpFunctionDefinition1.Route} for command type {httpFunctionDefinition1.CommandType.FullName}");
                }

                string         routeParameterName  = routeParameterParts[0].TrimEnd('?');
                PropertyInfo[] candidateProperties = candidateCommandProperties
                                                     .Where(p => p.Name.ToLower() == routeParameterName.ToLower()).ToArray();
                PropertyInfo matchedProperty = null;
                if (candidateProperties.Length == 1)
                {
                    matchedProperty = candidateProperties[0];
                }
                else if (candidateProperties.Length > 1)
                {
                    matchedProperty = candidateProperties.SingleOrDefault(x => x.Name == routeParameterName);
                }

                if (matchedProperty == null)
                {
                    throw new ConfigurationException($"Unable to match route parameter {routeParameterName} to property on command type {httpFunctionDefinition1.CommandType}");
                }

                bool isPropertyNullable = !matchedProperty.PropertyType.IsValueType ||
                                          Nullable.GetUnderlyingType(matchedProperty.PropertyType) != null;

                string routeTypeName;
                if (isOptional && matchedProperty.PropertyType.IsValueType &&
                    Nullable.GetUnderlyingType(matchedProperty.PropertyType) == null)
                {
                    routeTypeName = $"{matchedProperty.PropertyType.EvaluateType()}?";
                }
                else
                {
                    routeTypeName = matchedProperty.PropertyType.EvaluateType();
                }

                routeParameters.Add(new HttpParameter
                {
                    Name           = matchedProperty.Name,
                    Type           = matchedProperty.PropertyType,
                    IsOptional     = isOptional,
                    IsNullableType = Nullable.GetUnderlyingType(matchedProperty.PropertyType) != null,
                    RouteName      = routeParameterName,
                    RouteTypeName  = routeTypeName
                });
            }

            httpFunctionDefinition1.RouteParameters = routeParameters;

            /*string lowerCaseRoute = httpFunctionDefinition1.Route.ToLower();
             * httpFunctionDefinition1.RouteParameters = httpFunctionDefinition1
             *  .CommandType
             *  .GetProperties(BindingFlags.Instance | BindingFlags.Public)
             *  .Where(x => x.GetCustomAttribute<SecurityPropertyAttribute>() == null
             *              && x.SetMethod != null
             *              && (x.PropertyType == typeof(string) || x.PropertyType
             *                      .GetMethods(BindingFlags.Public | BindingFlags.Static).Any(y => y.Name == "TryParse"))
             *              && lowerCaseRoute.Contains("{" + x.Name.ToLower() + "}"))
             *  .Select(x => new HttpParameter
             *  {
             *      Name = x.Name,
             *      TypeName = x.PropertyType.EvaluateType(),
             *      Type = x.PropertyType
             *  })
             *  .ToArray();*/
        }
 public HttpFunctionBuilderMetadataBuilder(IHttpFunctionBuilder httpFunctionBuilder,
                                           HttpFunctionDefinition definition)
 {
     _httpFunctionBuilder = httpFunctionBuilder;
     _definition          = definition;
 }
 public HttpFunctionOptionsBuilder(HttpFunctionDefinition functionDefinition)
 {
     _functionDefinition = functionDefinition;
 }
示例#25
0
        public static Func <object, ClaimsPrincipal, object> Build(
            HttpFunctionDefinition functionDefinition,
            IReadOnlyCollection <AbstractClaimsMappingDefinition> claimsMappings)
        {
            if (functionDefinition.ImmutableTypeConstructorParameters.Count == 0)
            {
                return((o, cp) => o);
            }

            IReadOnlyCollection <CommandPropertyClaimsMappingDefinition> commandMappings = claimsMappings
                                                                                           .Where(t => t is CommandPropertyClaimsMappingDefinition).Cast <CommandPropertyClaimsMappingDefinition>()
                                                                                           .ToList();
            IReadOnlyCollection <SharedClaimsMappingDefinition> sharedMappings = claimsMappings
                                                                                 .Where(t => t is SharedClaimsMappingDefinition).Cast <SharedClaimsMappingDefinition>()
                                                                                 .ToList();

            bool didBuildAMappingFunc           = false;
            List <Expression> constructorClaims = new List <Expression>();

            ParameterExpression claimsPrincipalParameter = Expression.Parameter(typeof(ClaimsPrincipal));
            ParameterExpression commandParameter         = Expression.Parameter(typeof(object));

            foreach (ImmutableTypeConstructorParameter constructorParameter in functionDefinition
                     .ImmutableTypeConstructorParameters)
            {
                // there could be a shared mapping and a command -> property mapping - we use the latter first
                // in order of precedence
                CommandPropertyClaimsMappingDefinition commandPropertyDefinition = commandMappings.SingleOrDefault(
                    x => x.CommandType == functionDefinition.CommandType &&
                    x.PropertyInfo.Name == constructorParameter.Name);
                if (commandPropertyDefinition != null)
                {
                    constructorClaims.Add(BuildExpressionForPropertyName(
                                              commandPropertyDefinition.ClaimName,
                                              constructorParameter.Type,
                                              claimsPrincipalParameter,
                                              functionDefinition.CommandType,
                                              constructorParameter.Name,
                                              commandParameter)
                                          );
                    didBuildAMappingFunc = true;
                }
                else
                {
                    SharedClaimsMappingDefinition sharedDefinition = sharedMappings.SingleOrDefault(
                        x => x.PropertyPath == constructorParameter.Name);
                    if (sharedDefinition != null)
                    {
                        constructorClaims.Add(BuildExpressionForPropertyName(
                                                  sharedDefinition.ClaimName,
                                                  constructorParameter.Type,
                                                  claimsPrincipalParameter,
                                                  functionDefinition.CommandType,
                                                  constructorParameter.Name,
                                                  commandParameter));
                        didBuildAMappingFunc = true;
                    }
                    else
                    {
                        constructorClaims.Add(BuildExpressionForPreviousValue(functionDefinition.CommandType, constructorParameter.Name, commandParameter));
                    }
                }
            }

            if (!didBuildAMappingFunc)
            {
                return((o, cp) => o);
            }

            ConstructorInfo constructorInfo = functionDefinition.CommandType.GetConstructor(
                functionDefinition.ImmutableTypeConstructorParameters.Select(x => x.Type).ToArray());

            return(BuildConstructorFunc(constructorInfo, constructorClaims, commandParameter, claimsPrincipalParameter));
        }