Example #1
0
        private void ParseModel(IDictionary<string, SwaggerModel> models, Type modelType, string route, string verb)
        {
            if (IsSwaggerScalarType(modelType)) return;

            var modelId = GetModelTypeName(modelType, route, verb);
            if (models.ContainsKey(modelId)) return;

            var modelTypeName = GetModelTypeName(modelType);
            var model = new SwaggerModel
            {
                Id = modelId,
                Description = modelTypeName,
                Properties = new OrderedDictionary<string, ModelProperty>()
            };
            models[model.Id] = model;
            models[modelTypeName] = new SwaggerModel
            {
                Id = modelTypeName,
                Description = modelTypeName,
                Properties = model.Properties,
            };

            var properties = modelType.GetProperties();

            // Order model properties by DataMember.Order if [DataContract] and [DataMember](s) defined
            // Ordering defined by: http://msdn.microsoft.com/en-us/library/ms729813.aspx
            var dataContractAttr = modelType.GetCustomAttributes(typeof(DataContractAttribute), true).OfType<DataContractAttribute>().FirstOrDefault();
            if (dataContractAttr != null && properties.Any(prop => prop.IsDefined(typeof(DataMemberAttribute), true)))
            {
                var typeOrder = new List<Type> { modelType };
                var baseType = modelType.BaseType;
                while (baseType != null)
                {
                    typeOrder.Add(baseType);
                    baseType = baseType.BaseType;
                }              
                
                var propsWithDataMember = properties.Where(prop => prop.IsDefined(typeof(DataMemberAttribute), true));
                var propDataMemberAttrs = properties.ToDictionary(prop => prop, prop => prop.FirstAttribute<DataMemberAttribute>());

                properties = propsWithDataMember
                    .OrderBy(prop => propDataMemberAttrs[prop].Order)                // Order by DataMember.Order
                    .ThenByDescending(prop => typeOrder.IndexOf(prop.DeclaringType)) // Then by BaseTypes First
                    .ThenBy(prop =>                                                  // Then by [DataMember].Name / prop.Name
                    {
                        var name = propDataMemberAttrs[prop].Name;
                        return name.IsNullOrEmpty() ? prop.Name : name;
                    }).ToArray();
            }

            foreach (var prop in properties)
            {
                var allApiDocAttributes = prop
                    .AllAttributes<ApiMemberAttribute>()
                    .Where(attr => prop.Name.Equals(attr.Name, StringComparison.InvariantCultureIgnoreCase))
                    .OrderByDescending(attr => attr.Route)
                    .ToList();
                var apiDoc = allApiDocAttributes
                    .Where(attr => string.IsNullOrEmpty(verb) || string.IsNullOrEmpty(attr.Verb) || (verb ?? "").Equals(attr.Verb))
                    .Where(attr => string.IsNullOrEmpty(route) || string.IsNullOrEmpty(attr.Route) || (route ?? "").StartsWith(attr.Route))
                    .FirstOrDefault(attr => attr.ParameterType == "body" || attr.ParameterType == "model");

                if (allApiDocAttributes.Any(x => !string.IsNullOrEmpty(x.Verb) 
                    || !string.IsNullOrEmpty(x.Route)) 
                    && apiDoc == null) 
                    continue;

                var propertyType = prop.PropertyType;
                var modelProp = new ModelProperty { Type = GetSwaggerTypeName(propertyType, route, verb), Required = !IsNullable(propertyType) };

                if (IsListType(propertyType))
                {
                    modelProp.Type = SwaggerType.Array;
                    var listItemType = GetListElementType(propertyType);
                    modelProp.Items = new Dictionary<string, string> {
                        { IsSwaggerScalarType(listItemType) ? "type" : "$ref", GetSwaggerTypeName(listItemType, route, verb) }
                    };
                    ParseModel(models, listItemType, route, verb);
                }
                else if ((Nullable.GetUnderlyingType(propertyType) ?? propertyType).IsEnum)
                {
                    var enumType = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
                    if (enumType.IsNumericType())
                    {
                        var underlyingType = Enum.GetUnderlyingType(enumType);
                        modelProp.Type = GetSwaggerTypeName(underlyingType, route, verb);
                        modelProp.AllowableValues = new ParameterAllowableValues
                        {
                            Values = GetNumericValues(enumType, underlyingType).ToArray(),
                            ValueType = "LIST"
                        };
                    }
                    else
                    {
                        modelProp.Type = SwaggerType.String;
                        modelProp.AllowableValues = new ParameterAllowableValues
                        {
                            Values = Enum.GetNames(enumType),
                            ValueType = "LIST"
                        };
                    } 
                }
                else
                {
                    ParseModel(models, propertyType, route, verb);
                }

                modelProp.Description = prop.GetDescription();

                if (apiDoc != null && modelProp.Description == null)
                    modelProp.Description = apiDoc.Description;

                var allowableValues = prop.FirstAttribute<ApiAllowableValuesAttribute>();
                if (allowableValues != null)
                    modelProp.AllowableValues = GetAllowableValue(allowableValues);

                if (ModelPropertyFilter != null)
                {
                    ModelPropertyFilter(modelProp);
                }

                model.Properties[GetModelPropertyName(prop)] = modelProp;
            }

            if (ModelFilter != null)
            {
                ModelFilter(model);
            }
        }
        private static void ParseModel(IDictionary <string, SwaggerModel> models, Type modelType)
        {
            if (IsSwaggerScalarType(modelType))
            {
                return;
            }

            var modelId = modelType.Name;

            if (models.ContainsKey(modelId))
            {
                return;
            }

            var model = new SwaggerModel
            {
                Id         = modelId,
                Properties = new Dictionary <string, ModelProperty>()
            };

            models[model.Id] = model;

            foreach (var prop in modelType.GetProperties())
            {
                var allApiDocAttributes = prop
                                          .GetCustomAttributes(typeof(ApiMemberAttribute), true)
                                          .OfType <ApiMemberAttribute>()
                                          .Where(attr => prop.Name.Equals(attr.Name, StringComparison.InvariantCultureIgnoreCase))
                                          .ToList();
                var apiDoc = allApiDocAttributes.FirstOrDefault(attr => attr.ParameterType == "body");

                if (allApiDocAttributes.Any() && apiDoc == null)
                {
                    continue;
                }

                var propertyType = prop.PropertyType;
                var modelProp    = new ModelProperty {
                    Type = GetSwaggerTypeName(propertyType), Required = !IsNullable(propertyType)
                };

                if (IsListType(propertyType))
                {
                    modelProp.Type = SwaggerType.Array;
                    var listItemType = GetListElementType(propertyType);
                    modelProp.Items = new Dictionary <string, string> {
                        { IsSwaggerScalarType(listItemType) ? "type" : "$ref", GetSwaggerTypeName(listItemType) }
                    };
                    ParseModel(models, listItemType);
                }
                else if (propertyType.IsEnum)
                {
                    modelProp.Type            = SwaggerType.String;
                    modelProp.AllowableValues = new ParameterAllowableValues
                    {
                        Values    = Enum.GetNames(propertyType),
                        ValueType = "LIST"
                    };
                }
                else
                {
                    ParseModel(models, propertyType);
                }

                var descriptionAttr = prop.GetCustomAttributes(typeof(DescriptionAttribute), true).OfType <DescriptionAttribute>().FirstOrDefault();
                if (descriptionAttr != null)
                {
                    modelProp.Description = descriptionAttr.Description;
                }

                if (apiDoc != null)
                {
                    modelProp.Description = apiDoc.Description;
                }

                var allowableValues = prop.GetCustomAttributes(typeof(ApiAllowableValuesAttribute), true).OfType <ApiAllowableValuesAttribute>().FirstOrDefault();
                if (allowableValues != null)
                {
                    modelProp.AllowableValues = GetAllowableValue(allowableValues);
                }

                model.Properties[GetModelPropertyName(prop)] = modelProp;
            }
        }
Example #3
0
        private static void ParseModel(IDictionary<string, SwaggerModel> models, Type modelType)
        {
            if (IsSwaggerScalarType(modelType)) return;

            var modelId = modelType.Name;
            if (models.ContainsKey(modelId)) return;

            var model = new SwaggerModel
            {
                Id = modelId,
                Properties = new Dictionary<string, ModelProperty>()
            };
            models[model.Id] = model;

            foreach (var prop in modelType.GetProperties())
            {
                var allApiDocAttributes = prop
                    .GetCustomAttributes(typeof(ApiMemberAttribute), true)
                    .OfType<ApiMemberAttribute>()
                    .Where(attr => prop.Name.Equals(attr.Name, StringComparison.InvariantCultureIgnoreCase))
                    .ToList();
                var apiDoc = allApiDocAttributes.FirstOrDefault(attr => attr.ParameterType == "body");

                if (allApiDocAttributes.Any() && apiDoc == null) continue;

                var propertyType = prop.PropertyType;
                var modelProp = new ModelProperty { Type = GetSwaggerTypeName(propertyType), Required = !IsNullable(propertyType) };

                if (IsListType(propertyType))
                {
                    modelProp.Type = SwaggerType.Array;
                    var listItemType = GetListElementType(propertyType);
                    modelProp.Items = new Dictionary<string, string> {
                        { IsSwaggerScalarType(listItemType) ? "type" : "$ref", GetSwaggerTypeName(listItemType) }
                    };
                    ParseModel(models, listItemType);
                }
                else if (propertyType.IsEnum)
                {
                    modelProp.Type = SwaggerType.String;
                    modelProp.AllowableValues = new ParameterAllowableValues
                    {
                        Values = Enum.GetNames(propertyType),
                        ValueType = "LIST"
                    };
                }
                else
                {
                    ParseModel(models, propertyType);
                }

                var descriptionAttr = prop.GetCustomAttributes(typeof(DescriptionAttribute), true).OfType<DescriptionAttribute>().FirstOrDefault();
                if (descriptionAttr != null)
                    modelProp.Description = descriptionAttr.Description;

                if (apiDoc != null)
                    modelProp.Description = apiDoc.Description;

                var allowableValues = prop.GetCustomAttributes(typeof(ApiAllowableValuesAttribute), true).OfType<ApiAllowableValuesAttribute>().FirstOrDefault();
                if (allowableValues != null)
                    modelProp.AllowableValues = GetAllowableValue(allowableValues);

                model.Properties[GetModelPropertyName(prop)] = modelProp;
            }
        }
        private void ParseModel(IDictionary <string, SwaggerModel> models, Type modelType, string route, string verb)
        {
            if (IsSwaggerScalarType(modelType))
            {
                return;
            }

            var modelId = GetModelTypeName(modelType, route, verb);

            if (models.ContainsKey(modelId))
            {
                return;
            }

            var modelTypeName = GetModelTypeName(modelType);
            var model         = new SwaggerModel
            {
                Id          = modelId,
                Description = modelTypeName,
                Properties  = new OrderedDictionary <string, ModelProperty>()
            };

            models[model.Id]      = model;
            models[modelTypeName] = new SwaggerModel
            {
                Id          = modelTypeName,
                Description = modelTypeName,
                Properties  = model.Properties,
            };

            var properties = modelType.GetProperties();

            // Order model properties by DataMember.Order if [DataContract] and [DataMember](s) defined
            // Ordering defined by: http://msdn.microsoft.com/en-us/library/ms729813.aspx
            var dataContractAttr = modelType.GetCustomAttributes(typeof(DataContractAttribute), true).OfType <DataContractAttribute>().FirstOrDefault();

            if (dataContractAttr != null && properties.Any(prop => prop.IsDefined(typeof(DataMemberAttribute), true)))
            {
                var typeOrder = new List <Type> {
                    modelType
                };
                var baseType = modelType.BaseType;
                while (baseType != null)
                {
                    typeOrder.Add(baseType);
                    baseType = baseType.BaseType;
                }

                var propsWithDataMember = properties.Where(prop => prop.IsDefined(typeof(DataMemberAttribute), true));
                var propDataMemberAttrs = properties.ToDictionary(prop => prop, prop => prop.FirstAttribute <DataMemberAttribute>());

                properties = propsWithDataMember
                             .OrderBy(prop => propDataMemberAttrs[prop].Order)                // Order by DataMember.Order
                             .ThenByDescending(prop => typeOrder.IndexOf(prop.DeclaringType)) // Then by BaseTypes First
                             .ThenBy(prop =>                                                  // Then by [DataMember].Name / prop.Name
                {
                    var name = propDataMemberAttrs[prop].Name;
                    return(name.IsNullOrEmpty() ? prop.Name : name);
                }).ToArray();
            }

            foreach (var prop in properties)
            {
                var allApiDocAttributes = prop
                                          .AllAttributes <ApiMemberAttribute>()
                                          .Where(attr => prop.Name.Equals(attr.Name, StringComparison.InvariantCultureIgnoreCase))
                                          .OrderByDescending(attr => attr.Route)
                                          .ToList();
                var apiDoc = allApiDocAttributes
                             .Where(attr => string.IsNullOrEmpty(verb) || string.IsNullOrEmpty(attr.Verb) || (verb ?? "").Equals(attr.Verb))
                             .Where(attr => string.IsNullOrEmpty(route) || string.IsNullOrEmpty(attr.Route) || (route ?? "").StartsWith(attr.Route))
                             .FirstOrDefault(attr => attr.ParameterType == "body" || attr.ParameterType == "model");

                if (allApiDocAttributes.Any(x => !string.IsNullOrEmpty(x.Verb) ||
                                            !string.IsNullOrEmpty(x.Route)) &&
                    apiDoc == null)
                {
                    continue;
                }

                var propertyType = prop.PropertyType;
                var modelProp    = new ModelProperty {
                    Type = GetSwaggerTypeName(propertyType, route, verb), Required = !IsNullable(propertyType)
                };

                if (IsListType(propertyType))
                {
                    modelProp.Type = SwaggerType.Array;
                    var listItemType = GetListElementType(propertyType);
                    modelProp.Items = new Dictionary <string, string> {
                        { IsSwaggerScalarType(listItemType) ? "type" : "$ref", GetSwaggerTypeName(listItemType, route, verb) }
                    };
                    ParseModel(models, listItemType, route, verb);
                }
                else if ((Nullable.GetUnderlyingType(propertyType) ?? propertyType).IsEnum)
                {
                    var enumType = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
                    if (enumType.IsNumericType())
                    {
                        var underlyingType = Enum.GetUnderlyingType(enumType);
                        modelProp.Type            = GetSwaggerTypeName(underlyingType, route, verb);
                        modelProp.AllowableValues = new ParameterAllowableValues
                        {
                            Values    = GetNumericValues(enumType, underlyingType).ToArray(),
                            ValueType = "LIST"
                        };
                    }
                    else
                    {
                        modelProp.Type            = SwaggerType.String;
                        modelProp.AllowableValues = new ParameterAllowableValues
                        {
                            Values    = Enum.GetNames(enumType),
                            ValueType = "LIST"
                        };
                    }
                }
                else
                {
                    ParseModel(models, propertyType, route, verb);
                }

                modelProp.Description = prop.GetDescription();

                if (apiDoc != null && modelProp.Description == null)
                {
                    modelProp.Description = apiDoc.Description;
                }

                var allowableValues = prop.FirstAttribute <ApiAllowableValuesAttribute>();
                if (allowableValues != null)
                {
                    modelProp.AllowableValues = GetAllowableValue(allowableValues);
                }

                if (ModelPropertyFilter != null)
                {
                    ModelPropertyFilter(modelProp);
                }

                model.Properties[GetModelPropertyName(prop)] = modelProp;
            }

            if (ModelFilter != null)
            {
                ModelFilter(model);
            }
        }