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; } }
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); } }