private static SeparatedSyntaxList <ParameterSyntax> AddAttributeToComplexTypeParameters(SeparatedSyntaxList <ParameterSyntax> wcfParameters)
        {
            // asp.net web api considers enums as 'simple types' and can be used in uri query string
            // however, unable to determine if a parameter is an enum type using roslyn parsing syntax api (instead this requires using rosyln's semantic model api to get type info)
            // hence the client needs to send enum values via the http request body instead of uri query string
            // therefore, enums will be treated as complex types but since can't identify them then must add explicit `FromBody` attribute to *all* complex types (even if unnecessary for classes)

            ParameterSyntax AddAttributeToParameter(string attributeName, ParameterSyntax parameter)
            {
                return(parameter.WithAttributeLists(SyntaxFactory.SingletonList(SyntaxFactory.AttributeList(
                                                                                    SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute(SyntaxFactory.IdentifierName(attributeName))))
                                                                                .WithOpenBracketToken(SyntaxFactory.Token(SyntaxKind.OpenBracketToken))
                                                                                .WithCloseBracketToken(SyntaxFactory.Token(SyntaxKind.CloseBracketToken)))));
            }

            // find complex type parameters
            var wcfComplexTypeParameters = ComplexTypesGenerator.FindComplexTypes(wcfParameters);

            // add attribute to complex type parameters
            var complexTypeParameters = wcfComplexTypeParameters
                                        .Select(parameter => AddAttributeToParameter("FromBody", parameter));

            var parameters = wcfParameters;

            // add modified complex type parameters back with other params
            foreach (var complexTypeParameter in complexTypeParameters)
            {
                var parameterName = complexTypeParameter.Identifier.ValueText;
                var oldParameter  = parameters.Single(param => param.Identifier.ValueText == parameterName);

                parameters = parameters.Replace(oldParameter, complexTypeParameter);
            }

            return(parameters);
        }
        private static string CreateRequestQueryString(MethodDeclarationSyntax serviceGenMethod)
        {
            string queryString;

            var simpleTypes = ComplexTypesGenerator.FindSimpleTypes(serviceGenMethod.ParameterList.Parameters);

            if (!simpleTypes.Any())
            {
                queryString = "";

                return(queryString);
            }

            var queryStringWithSimpleTypes = simpleTypes
                                             .Select(parameter =>
            {
                var parameterName  = parameter.Identifier.NormalizeWhitespace().ToFullString();
                var parameterType  = parameter.Type.NormalizeWhitespace().ToFullString();
                var parameterValue = CreateParameterValue(parameterName, parameterType);

                var queryStringParam = $"{parameterName}={{{parameterValue}}}";

                return(queryStringParam);
            })
                                             .Aggregate((parameter1, parameter2) => $"{parameter1}&{parameter2}");

            queryString = $"?{queryStringWithSimpleTypes}";

            return(queryString);
        }
Esempio n. 3
0
        private static (string startRequest, string endRequest) CreateHttpPostRequest(MethodDeclarationSyntax wcfClientMethod,
                                                                                      MethodDeclarationSyntax serviceGenMethod, IEnumerable <MethodDeclarationSyntax> wcfServiceMethods)
        {
            var serviceParameters               = serviceGenMethod.ParameterList.Parameters;
            var serviceComplexTypeParameter     = ComplexTypesGenerator.FindComplexTypes(serviceParameters).SingleOrDefault();
            var serviceComplexTypeParameterName = serviceComplexTypeParameter?.Identifier.ValueText;

            // create anon class instance if method has two or more (i.e. "multiple") complex types parameters
            var multipleComplexTypes = ClientCodeMultipleComplexTypesGenerator.CreateMultipleComplexTypesClassInstance(wcfClientMethod, serviceComplexTypeParameterName, wcfServiceMethods);

            // should only be one complex type parmeter for any service method
            // hence serialize it to json for http post
            var jsonRequest = CreateJsonRequest(serviceComplexTypeParameter, serviceComplexTypeParameterName);

            // create http post request
            var startHttpPostRequest = $@"
    {multipleComplexTypes}
    var json = {jsonRequest};
    var content = new StringContent(json, Encoding.UTF8, ""application/json"");
    var response = _httpClient.PostAsync(requestUri, content).Result;
";

            var httpPostRequest = (startRequest : startHttpPostRequest, endRequest : "response.Content.ReadAsStringAsync().Result");

            return(httpPostRequest);
        }
        private static string CreateHttpVerb(string wcfMethodName, SeparatedSyntaxList <ParameterSyntax> parameters)
        {
            bool methodNameStartsWithGet     = wcfMethodName.StartsWith("Get");
            bool hasAllSimpleTypesParameters = !ComplexTypesGenerator.FindComplexTypes(parameters).Any();
            bool isGetMethodWithSimpleTypes  = methodNameStartsWithGet && hasAllSimpleTypesParameters;

            var httpVerb = isGetMethodWithSimpleTypes
                ? "HttpGet"
                : "HttpPost";

            return(httpVerb);
        }
        private static SeparatedSyntaxList <ParameterSyntax> RemoveDefaultValuesFromComplexTypeParameters(SeparatedSyntaxList <ParameterSyntax> parameters)
        {
            // asp.net web api does not support controller method parameters that are:
            //  1) reference types with default values set to 'null'
            //  2) enums with any default values
            // therefore remove all default values from complex type parameters
            // also the auto gen client files will include the default values so ok to remove them for enums
            // otherwise perhaps need to auto gen enum as a string (and parse it) or as a nullable type

            bool IsComplexTypeWithDefaultValue(ParameterSyntax parameter)
            {
                var param           = new SeparatedSyntaxList <ParameterSyntax>().Add(parameter);
                var isComplexType   = ComplexTypesGenerator.FindComplexTypes(param).Any();
                var hasDefaultValue = parameter.Default != null;

                return(isComplexType && hasDefaultValue);
            }

            // split up complex type parameters into two lists: 1) has default values 2) all others
            var parametersGroupByDefaults = parameters.ToLookup(IsComplexTypeWithDefaultValue);
            var defaultValParameters      = parametersGroupByDefaults[true].ToList();
            var otherParameters           = parametersGroupByDefaults[false];

            if (!defaultValParameters.Any())
            {
                return(parameters);
            }

            // remove default values
            var removedDefaultParameters = defaultValParameters
                                           .Select(parameter =>
            {
                parameter = IsComplexTypeWithDefaultValue(parameter)
                        ? parameter.WithDefault(null)
                        : parameter;

                return(parameter);
            });

            // combine modified parameters no longer with default values back with other params
            var newParameters = new SeparatedSyntaxList <ParameterSyntax>();

            newParameters = newParameters.AddRange(otherParameters);
            var insertIndex = ParametersGenerator.FindIndexBeforeFirstOptionalParam(newParameters);

            newParameters = newParameters.InsertRange(insertIndex, removedDefaultParameters);

            return(newParameters);
        }