コード例 #1
0
        private ParameterBase GetParameter(TypeFormat typeFormat,
                                           MethodInfo declaration,
                                           MethodInfo implementation,
                                           ParameterInfo parameter,
                                           SwaggerWcfParameterAttribute settings,
                                           string uriTemplate,
                                           bool wrappedRequest,
                                           IList <Type> definitionsTypesList,
                                           InType inType)
        {
            string description = settings?.Description;
            bool   required    = settings != null && settings.Required;
            string name        = inType == InType.Query ? ResolveParameterNameFromUri(uriTemplate, parameter) : parameter.Name;

            if (inType == InType.Path)
            {
                required = true;
            }

            if (!required && !parameter.HasDefaultValue)
            {
                required = true;
            }

            Type paramType = settings == null || settings.ParameterType == null
                ? parameter.ParameterType
                : settings.ParameterType;

            if (paramType.IsGenericType && paramType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                required  = false;
                paramType = paramType.GenericTypeArguments[0];
            }

            if (typeFormat.Type == ParameterType.Object)
            {
                return(new ParameterSchema
                {
                    Name = name,
                    Description = description,
                    In = inType,
                    Required = required,
                    SchemaRef = typeFormat.Format
                });
            }

            if (inType == InType.Body)
            {
                if (typeFormat.Type == ParameterType.Array)
                {
                    Type       t             = paramType.GetElementType() ?? GetEnumerableType(paramType);
                    TypeFormat subTypeFormat = Helpers.MapSwaggerType(t);

                    ParameterItems items;

                    if (subTypeFormat.IsPrimitiveType || subTypeFormat.IsEnum)
                    {
                        items = new ParameterItems
                        {
                            TypeFormat = subTypeFormat
                        };
                    }
                    else
                    {
                        items = new ParameterItems
                        {
                            Items = new ParameterSchema
                            {
                                SchemaRef = t.GetModelName()
                            }
                        };
                    }

                    ParameterPrimitive arrayParam = new ParameterPrimitive
                    {
                        Name             = name,
                        Description      = description,
                        In               = inType,
                        Required         = required,
                        TypeFormat       = typeFormat,
                        Items            = items,
                        CollectionFormat = CollectionFormat.Csv
                    };

                    //it's a complex type, so we'll need to map it later
                    if (definitionsTypesList != null && !definitionsTypesList.Contains(t))
                    {
                        definitionsTypesList.Add(t);
                    }

                    return(arrayParam);
                }
                if (typeFormat.IsPrimitiveType || typeFormat.IsEnum)
                {
                    bool isGetRequest = implementation.GetCustomAttributes <WebGetAttribute>().Any() ||
                                        declaration.GetCustomAttributes <WebGetAttribute>().Any();
                    if (!isGetRequest)
                    {
                        WebInvokeAttribute webInvoke = implementation.GetCustomAttribute <WebInvokeAttribute>()
                                                       ?? declaration.GetCustomAttribute <WebInvokeAttribute>();
                        if (webInvoke != null && webInvoke.Method == "GET")
                        {
                            isGetRequest = true;
                        }
                    }
                    if (!wrappedRequest && isGetRequest)
                    {
                        ParameterPrimitive paramPrimitive = new ParameterPrimitive
                        {
                            Name        = name,
                            Description = description,
                            In          = InType.Query,
                            Required    = required,
                            TypeFormat  = typeFormat
                        };
                        return(paramPrimitive);
                    }
                    else
                    {
                        ParameterPrimitive paramPrimitive = new ParameterPrimitive
                        {
                            Name        = name,
                            Description = description,
                            In          = inType,
                            Required    = required,
                            TypeFormat  = typeFormat
                        };
                        return(paramPrimitive);
                    }
                }

                //it's a complex type, so we'll need to map it later
                if (definitionsTypesList != null && !definitionsTypesList.Contains(paramType))
                {
                    definitionsTypesList.Add(paramType);
                }

                typeFormat = new TypeFormat(ParameterType.Object,
                                            HttpUtility.HtmlEncode(paramType.GetModelName()));

                return(new ParameterSchema
                {
                    Name = name,
                    Description = description,
                    In = inType,
                    Required = required,
                    SchemaRef = typeFormat.Format
                });
            }

            ParameterPrimitive param = new ParameterPrimitive
            {
                Name        = name,
                Description = description,
                In          = inType,
                Required    = required,
                TypeFormat  = typeFormat
            };

            return(param);
        }
コード例 #2
0
        internal IEnumerable <Tuple <string, PathAction> > GetActions(MethodInfo[] targetMethods,
                                                                      MethodInfo[] interfaceMethods,
                                                                      IList <Type> definitionsTypesList)
        {
            int methodsCounts = interfaceMethods.Length;

            for (int index = 0; index < methodsCounts; index++)
            {
                MethodInfo implementation = targetMethods[index];
                MethodInfo declaration    = interfaceMethods[index];

                //if a tag from either implementation or declaration is marked as not visible, skip it
                List <SwaggerWcfTagAttribute> methodTags =
                    implementation.GetCustomAttributes <SwaggerWcfTagAttribute>().ToList();
                methodTags =
                    methodTags.Concat(declaration.GetCustomAttributes <SwaggerWcfTagAttribute>()).ToList();

                methodTags = methodTags.Distinct().ToList();

                // If no tags on the method - check declared Type/Interface itself
                if (methodTags.Count < 1)
                {
                    methodTags = implementation.DeclaringType.GetCustomAttributes <SwaggerWcfTagAttribute>()
                                 .Concat(declaration.DeclaringType.GetCustomAttributes <SwaggerWcfTagAttribute>())
                                 .ToList();
                }

                if ((methodTags.Count == 0 && HiddenTags.Contains("default")) ||
                    methodTags.Any(t => HiddenTags.Contains(t.TagName)))
                {
                    continue;
                }

                //if the method is marked Hidden anywhere, skip it (even if methods tags listed as visible).
                if ((implementation.GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null ||
                     declaration.GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null)
                    )
                {
                    continue;
                }

                //find the WebGet/Invoke attributes, or skip if neither is present
                WebGetAttribute    wg = declaration.GetCustomAttribute <WebGetAttribute>();
                WebInvokeAttribute wi = declaration.GetCustomAttribute <WebInvokeAttribute>();
                if (wg == null && wi == null)
                {
                    continue;
                }

                string httpMethod  = (wi == null) ? "GET" : wi.Method ?? "POST";
                string uriTemplate = GetUriTemplate(wi, wg, declaration);

                bool wrappedRequest  = IsRequestWrapped(wg, wi);
                bool wrappedResponse = IsResponseWrapped(wg, wi);

                var wcfPathAttribute = (implementation.GetCustomAttribute(typeof(SwaggerWcfPathAttribute), false) as SwaggerWcfPathAttribute)
                                       ?? (declaration.GetCustomAttribute(typeof(SwaggerWcfPathAttribute), false) as SwaggerWcfPathAttribute);
                int sortOrder = (wcfPathAttribute?.SortOrder).GetValueOrDefault();


                //implementation description overrides interface description
                string description =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "Description") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "Description") ??
                    Helpers.GetCustomAttributeValue <string, DescriptionAttribute>(implementation, "Description") ??
                    Helpers.GetCustomAttributeValue <string, DescriptionAttribute>(declaration, "Description") ??
                    "";

                string summary =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "Summary") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "Summary") ??
                    "";

                string operationId =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "OperationId") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "OperationId") ??
                    "";
                if (operationId == "")
                {
                    if (implementation.DeclaringType != null)
                    {
                        operationId = implementation.DeclaringType.FullName + ".";
                    }
                    operationId += implementation.Name;
                }

                string externalDocsDescription =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation,
                                                                                      "ExternalDocsDescription") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration,
                                                                                      "ExternalDocsDescription") ??
                    "";

                string externalDocsUrl =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "ExternalDocsUrl") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "ExternalDocsUrl") ??
                    "";

                ExternalDocumentation externalDocs = null;
                if (!string.IsNullOrWhiteSpace(externalDocsDescription) || !string.IsNullOrWhiteSpace(externalDocsUrl))
                {
                    externalDocs = new ExternalDocumentation
                    {
                        Description = externalDocsDescription,
                        Url         = HttpUtility.HtmlEncode(externalDocsUrl)
                    };
                }

                bool deprecated =
                    Helpers.GetCustomAttributeValue <SwaggerWcfPathAttribute>(implementation, "Deprecated");
                if (!deprecated)
                {
                    deprecated = Helpers.GetCustomAttributeValue <SwaggerWcfPathAttribute>(declaration, "Deprecated");
                }

                string operationPath =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "OperationPath") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "OperationPath");
                if (!string.IsNullOrWhiteSpace(operationPath))
                {
                    uriTemplate = ConcatPaths(operationPath, uriTemplate);
                }

                PathAction operation = new PathAction
                {
                    Id          = httpMethod.ToLowerInvariant(),
                    SortOrder   = sortOrder,
                    Summary     = summary,
                    Description = description,
                    Tags        =
                        methodTags.Where(t => !t.HideFromSpec).Select(t => HttpUtility.HtmlEncode(t.TagName)).ToList(),
                    Consumes     = new List <string>(GetConsumes(implementation, declaration)),
                    Produces     = new List <string>(GetProduces(implementation, declaration)),
                    Deprecated   = deprecated,
                    OperationId  = HttpUtility.HtmlEncode(operationId),
                    ExternalDocs = externalDocs,
                    Responses    = GetResponseCodes(implementation, declaration, wrappedResponse, definitionsTypesList),
                    Security     = GetMethodSecurity(implementation, declaration)
                                   // Schemes = TODO: how to get available schemes for this WCF service? (schemes: http/https)
                };

                //try to map each implementation parameter to the uriTemplate.
                ParameterInfo[] parameters = declaration.GetParameters();
                if (parameters.Any())
                {
                    operation.Parameters = new List <ParameterBase>();
                }

                List <SwaggerWcfHeaderAttribute> headers =
                    implementation.GetCustomAttributes <SwaggerWcfHeaderAttribute>().ToList();
                headers = headers.Concat(declaration.GetCustomAttributes <SwaggerWcfHeaderAttribute>()).ToList();

                // remove duplicates
                headers = headers.GroupBy(h => h.Name).Select(g => g.First()).ToList();

                // parameters - headers
                foreach (SwaggerWcfHeaderAttribute attr in headers)
                {
                    operation.Parameters.Add(new ParameterPrimitive
                    {
                        Name        = attr.Name,
                        Description = attr.Description,
                        Default     = attr.DefaultValue,
                        In          = InType.Header,
                        Required    = attr.Required,
                        TypeFormat  = new TypeFormat(ParameterType.String, null)
                    });
                }

                bool        isGetRequest       = httpMethod == "GET";
                int         bodyParameterCount = parameters.Where(p => GetInType(uriTemplate, p.Name) == InType.Body).Count();
                TypeBuilder typeBuilder        = null;
                if (!wrappedRequest && !isGetRequest && bodyParameterCount > 1)
                {
                    wrappedRequest = true;
                }
                if (wrappedRequest)
                {
                    typeBuilder = new TypeBuilder(implementation.GetWrappedName(declaration));
                }

                var declarationName = declaration.Name;
                foreach (ParameterInfo parameter in parameters)
                {
                    SwaggerWcfParameterAttribute settings =
                        implementation.GetParameters()
                        .First(p => p.Position.Equals(parameter.Position))
                        .GetCustomAttribute <SwaggerWcfParameterAttribute>() ??
                        parameter.GetCustomAttribute <SwaggerWcfParameterAttribute>();

                    if (implementation.GetParameters()
                        .First(p => p.Position.Equals(parameter.Position))
                        .GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null ||
                        parameter.GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null)
                    {
                        continue;
                    }

                    List <SwaggerWcfTagAttribute> piTags =
                        methodTags.Concat(parameter.GetCustomAttributes <SwaggerWcfTagAttribute>())
                        .ToList();

                    InType inType = GetInType(uriTemplate, parameter.Name);

                    if (inType == InType.Body && wrappedRequest)
                    {
                        bool required = settings != null && settings.Required;

                        if (!required && !parameter.HasDefaultValue)
                        {
                            required = true;
                        }

                        typeBuilder.AddField(parameter.Name, parameter.ParameterType, required);

                        continue;
                    }

                    if (piTags.Any(t => HiddenTags.Contains(t.TagName)))
                    {
                        continue;
                    }

                    Type type = settings == null || settings.ParameterType == null
                        ? parameter.ParameterType
                        : settings.ParameterType;

                    TypeFormat typeFormat = Helpers.MapSwaggerType(type, definitionsTypesList);

                    operation.Parameters.Add(GetParameter(typeFormat, declaration, implementation, parameter, settings, uriTemplate, wrappedRequest,
                                                          definitionsTypesList, inType));
                }

                if (wrappedRequest)
                {
                    TypeFormat typeFormat = Helpers.MapSwaggerType(typeBuilder.Type, definitionsTypesList);

                    operation.Parameters.Add(new ParameterSchema
                    {
                        Name      = implementation.GetWrappedName(declaration) + "Wrapper",
                        In        = InType.Body,
                        Required  = true,
                        SchemaRef = typeFormat.Format
                    });
                }

                if (!string.IsNullOrWhiteSpace(uriTemplate))
                {
                    int indexOfQuestionMark = uriTemplate.IndexOf('?');
                    if (indexOfQuestionMark >= 0)
                    {
                        uriTemplate = uriTemplate.Substring(0, indexOfQuestionMark);
                    }

                    uriTemplate = RemoveParametersDefaultValuesFromUri(uriTemplate);
                }

                yield return(new Tuple <string, PathAction>(uriTemplate, operation));
            }
        }
コード例 #3
0
        private ParameterBase GetParameter(TypeFormat typeFormat, ParameterInfo parameter,
                                           SwaggerWcfParameterAttribute settings, string uriTemplate,
                                           IList <Type> definitionsTypesList)
        {
            string description = settings != null ? settings.Description : null;
            bool   required    = settings != null && settings.Required;
            string name        = parameter.Name;

            //Check for set DataContractAttribute to set Name and - Should this check for, and set DataContractAttribute.Namespace as well? /GustafRG
            //DataContractAttribute was not accessible on parameter, but on parameter.ParameterType. /GustafRG
            DataContractAttribute dataContractAttribute = parameter.ParameterType.GetCustomAttribute <DataContractAttribute>();

            if (dataContractAttribute != null)
            {
                if (!string.IsNullOrEmpty(dataContractAttribute.Name))
                {
                    name = dataContractAttribute.Name;
                }
                else
                {
                    name = parameter.ParameterType.Name;
                }
            }

            //Removed this. DataMemberAttribute is not valid on Object, Only on Object Members. Also, it does not seem to be accessible on "parameter" /GustafRG
            //DataMemberAttribute dataMemberAttribute = parameter.ParameterType.GetCustomAttribute<DataMemberAttribute>();

            //         if (dataMemberAttribute != null && !string.IsNullOrEmpty(dataMemberAttribute.Name))
            //             name = dataMemberAttribute.Name;

            InType inType = GetInType(uriTemplate, parameter.Name);

            if (inType == InType.Path)
            {
                required = true;
            }

            if (!required && !parameter.HasDefaultValue)
            {
                required = true;
            }

            Type paramType = parameter.ParameterType;

            if (paramType.IsGenericType && paramType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                required  = false;
                paramType = paramType.GenericTypeArguments[0];
            }

            if (typeFormat.Type == ParameterType.Object)
            {
                return(new ParameterSchema
                {
                    Name = name,
                    Description = description,
                    In = inType,
                    Required = required,
                    SchemaRef = typeFormat.Format
                });
            }

            if (inType == InType.Body)
            {
                if (typeFormat.Type == ParameterType.Array)
                {
                    Type t = paramType.GetElementType() ?? GetEnumerableType(paramType);
                    ParameterPrimitive arrayParam = new ParameterPrimitive
                    {
                        Name        = name,
                        Description = description,
                        In          = inType,
                        Required    = required,
                        TypeFormat  = typeFormat,
                        Items       = new ParameterItems
                        {
                            Items = new ParameterSchema
                            {
                                SchemaRef = t.FullName
                            }
                        },
                        CollectionFormat = CollectionFormat.Csv
                    };

                    //it's a complex type, so we'll need to map it later
                    if (definitionsTypesList != null && !definitionsTypesList.Contains(t))
                    {
                        definitionsTypesList.Add(t);
                    }

                    return(arrayParam);
                }

                //it's a complex type, so we'll need to map it later
                if (definitionsTypesList != null && !definitionsTypesList.Contains(paramType))
                {
                    definitionsTypesList.Add(paramType);
                }
                typeFormat = new TypeFormat(ParameterType.Object,
                                            HttpUtility.HtmlEncode(paramType.FullName));

                return(new ParameterSchema
                {
                    Name = name,
                    Description = description,
                    In = inType,
                    Required = required,
                    SchemaRef = typeFormat.Format
                });
            }

            ParameterPrimitive param = new ParameterPrimitive
            {
                Name        = name,
                Description = description,
                In          = inType,
                Required    = required,
                TypeFormat  = typeFormat
            };

            return(param);
        }
コード例 #4
0
ファイル: Mapper.cs プロジェクト: mecek/swaggerwcf
        private ParameterBase GetParameter(TypeFormat typeFormat, ParameterInfo parameter,
                                           SwaggerWcfParameterAttribute settings, string uriTemplate,
                                           IList <Type> definitionsTypesList)
        {
            string description = settings != null ? settings.Description : null;
            bool   required    = settings != null && settings.Required;
            string name        = parameter.Name;
            DataMemberAttribute dataMemberAttribute = parameter.GetCustomAttribute <DataMemberAttribute>();

            if (dataMemberAttribute != null && !string.IsNullOrEmpty(dataMemberAttribute.Name))
            {
                name = dataMemberAttribute.Name;
            }

            InType inType = GetInType(uriTemplate, parameter.Name);

            if (inType == InType.Path)
            {
                required = true;
            }

            if (!required && !parameter.HasDefaultValue)
            {
                required = true;
            }

            Type paramType = settings == null || settings.ParameterType == null
                ? parameter.ParameterType
                : settings.ParameterType;

            if (paramType.IsGenericType && paramType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                required  = false;
                paramType = paramType.GenericTypeArguments[0];
            }

            if (typeFormat.Type == ParameterType.Object)
            {
                return(new ParameterSchema
                {
                    Name = name,
                    Description = description,
                    In = inType,
                    Required = required,
                    SchemaRef = typeFormat.Format
                });
            }

            if (inType == InType.Body)
            {
                if (typeFormat.Type == ParameterType.Array)
                {
                    Type t = paramType.GetElementType() ?? GetEnumerableType(paramType);
                    ParameterPrimitive arrayParam = new ParameterPrimitive
                    {
                        Name        = name,
                        Description = description,
                        In          = inType,
                        Required    = required,
                        TypeFormat  = typeFormat,
                        Items       = new ParameterItems
                        {
                            Items = new ParameterSchema
                            {
                                SchemaRef = t.FullName
                            }
                        },
                        CollectionFormat = CollectionFormat.Csv
                    };

                    //it's a complex type, so we'll need to map it later
                    if (definitionsTypesList != null && !definitionsTypesList.Contains(t))
                    {
                        definitionsTypesList.Add(t);
                    }

                    return(arrayParam);
                }
                if (typeFormat.IsPrimitiveType)
                {
                    ParameterPrimitive paramPrimitive = new ParameterPrimitive
                    {
                        Name        = name,
                        Description = description,
                        In          = inType,
                        Required    = required,
                        TypeFormat  = typeFormat
                    };
                    return(paramPrimitive);
                }

                //it's a complex type, so we'll need to map it later
                if (definitionsTypesList != null && !definitionsTypesList.Contains(paramType))
                {
                    definitionsTypesList.Add(paramType);
                }
                typeFormat = new TypeFormat(ParameterType.Object,
                                            HttpUtility.HtmlEncode(paramType.FullName));

                return(new ParameterSchema
                {
                    Name = name,
                    Description = description,
                    In = inType,
                    Required = required,
                    SchemaRef = typeFormat.Format
                });
            }

            ParameterPrimitive param = new ParameterPrimitive
            {
                Name        = name,
                Description = description,
                In          = inType,
                Required    = required,
                TypeFormat  = typeFormat
            };

            return(param);
        }
コード例 #5
0
        internal IEnumerable <Tuple <string, PathAction> > GetActions(MethodInfo[] targetMethods,
                                                                      MethodInfo[] interfaceMethods,
                                                                      IList <Type> definitionsTypesList)
        {
            int methodsCounts = interfaceMethods.Count();

            for (int index = 0; index < methodsCounts; index++)
            {
                MethodInfo implementation = targetMethods[index];
                MethodInfo declaration    = interfaceMethods[index];

                //if the method is marked Hidden anywhere, skip it
                if (implementation.GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null ||
                    declaration.GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null)
                {
                    continue;
                }

                //if a tag from either implementation or declaration is marked as not visible, skip it
                List <SwaggerWcfTagAttribute> methodTags =
                    implementation.GetCustomAttributes <SwaggerWcfTagAttribute>().ToList();
                methodTags =
                    methodTags.Concat(declaration.GetCustomAttributes <SwaggerWcfTagAttribute>()).ToList();
                methodTags = methodTags.Distinct().ToList();

                if (methodTags.Select(t => t.TagName).Any(HiddenTags.Contains))
                {
                    continue;
                }

                //find the WebGet/Invoke attributes, or skip if neither is present
                WebGetAttribute    wg = declaration.GetCustomAttribute <WebGetAttribute>();
                WebInvokeAttribute wi = declaration.GetCustomAttribute <WebInvokeAttribute>();
                if (wg == null && wi == null)
                {
                    continue;
                }

                string httpMethod  = (wi == null) ? "GET" : wi.Method ?? "POST";
                string uriTemplate = (wi == null) ? (wg.UriTemplate ?? "") : (wi.UriTemplate ?? "");

                //implementation description overrides interface description
                string description =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "Description") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "Description") ??
                    Helpers.GetCustomAttributeValue <string, DescriptionAttribute>(implementation, "Description") ??
                    Helpers.GetCustomAttributeValue <string, DescriptionAttribute>(declaration, "Description") ??
                    "";

                string summary =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "Summary") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "Summary") ??
                    "";

                string operationId =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "OperationId") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "OperationId") ??
                    "";
                if (operationId == "")
                {
                    if (implementation.DeclaringType != null)
                    {
                        operationId = implementation.DeclaringType.FullName + ".";
                    }
                    operationId += implementation.Name;
                }

                string externalDocsDescription =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation,
                                                                                      "ExternalDocsDescription") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration,
                                                                                      "ExternalDocsDescription") ??
                    "";

                string externalDocsUrl =
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(implementation, "ExternalDocsUrl") ??
                    Helpers.GetCustomAttributeValue <string, SwaggerWcfPathAttribute>(declaration, "ExternalDocsUrl") ??
                    "";

                ExternalDocumentation externalDocs = null;
                if (!string.IsNullOrWhiteSpace(externalDocsDescription) || !string.IsNullOrWhiteSpace(externalDocsUrl))
                {
                    externalDocs = new ExternalDocumentation
                    {
                        Description = HttpUtility.HtmlEncode(externalDocsDescription),
                        Url         = HttpUtility.HtmlEncode(externalDocsUrl)
                    };
                }

                bool deprecated =
                    Helpers.GetCustomAttributeValue <SwaggerWcfPathAttribute>(implementation, "Deprecated");
                if (!deprecated)
                {
                    deprecated = Helpers.GetCustomAttributeValue <SwaggerWcfPathAttribute>(declaration, "Deprecated");
                }

                PathAction operation = new PathAction
                {
                    Id          = httpMethod.ToLowerInvariant(),
                    Summary     = HttpUtility.HtmlEncode(summary),
                    Description = HttpUtility.HtmlEncode(description),
                    Tags        =
                        methodTags.Where(t => !t.HideFromSpec).Select(t => HttpUtility.HtmlEncode(t.TagName)).ToList(),
                    Consumes     = new List <string>(GetConsumes(implementation, declaration)),
                    Produces     = new List <string>(GetProduces(implementation, declaration)),
                    Deprecated   = deprecated,
                    OperationId  = HttpUtility.HtmlEncode(operationId),
                    ExternalDocs = externalDocs,
                    Responses    = GetResponseCodes(implementation, declaration, definitionsTypesList)
                                   // Schemes = TODO: how to get available schemes for this WCF service? (schemes: http/https)
                };

                //try to map each implementation parameter to the uriTemplate.
                ParameterInfo[] parameters = declaration.GetParameters();
                if (parameters.Any())
                {
                    operation.Parameters = new List <ParameterBase>();
                }
                foreach (ParameterInfo parameter in parameters)
                {
                    TypeFormat typeFormat = Helpers.MapSwaggerType(parameter.ParameterType, definitionsTypesList);

                    SwaggerWcfParameterAttribute settings =
                        implementation.GetParameters()
                        .First(p => p.Position.Equals(parameter.Position))
                        .GetCustomAttribute <SwaggerWcfParameterAttribute>() ??
                        parameter.GetCustomAttribute <SwaggerWcfParameterAttribute>();

                    if (implementation.GetParameters()
                        .First(p => p.Position.Equals(parameter.Position))
                        .GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null ||
                        parameter.GetCustomAttribute <SwaggerWcfHiddenAttribute>() != null)
                    {
                        continue;
                    }

                    List <SwaggerWcfTagAttribute> piTags =
                        methodTags.Concat(parameter.GetCustomAttributes <SwaggerWcfTagAttribute>())
                        .ToList();

                    if (piTags.Select(t => t.TagName).Any(HiddenTags.Contains))
                    {
                        continue;
                    }

                    operation.Parameters.Add(GetParameter(typeFormat, parameter, settings, uriTemplate,
                                                          definitionsTypesList));
                }

                if (!string.IsNullOrWhiteSpace(uriTemplate))
                {
                    int indexOfQuestionMark = uriTemplate.IndexOf('?');
                    if (indexOfQuestionMark >= 0)
                    {
                        uriTemplate = uriTemplate.Substring(0, indexOfQuestionMark);
                    }
                }
                yield return(new Tuple <string, PathAction>(uriTemplate, operation));
            }
        }