private ResourceListing getDocs(HttpActionContext actionContext) { var assemblyType = (actionContext.ActionDescriptor as ReflectedHttpActionDescriptor).MethodInfo.DeclaringType; var docProvider = new XmlCommentDocumentationProvider(); //(XmlCommentDocumentationProvider)GlobalConfiguration.Configuration.Services.GetDocumentationProvider(); ResourceListing r = SwaggerGen.CreateResourceListing(actionContext); foreach (var api in GlobalConfiguration.Configuration.Services.GetApiExplorer().ApiDescriptions) { if (api.ActionDescriptor.ActionName.EndsWith("API"))//Ignore each Default API action { continue; } string apiControllerName = api.ActionDescriptor.ControllerDescriptor.ControllerName; if (api.Route.Defaults.ContainsKey(SwaggerGen.SWAGGER) || apiControllerName.ToUpper().Equals(SwaggerGen.SWAGGER.ToUpper())) { continue; } // Make sure we only report the current controller docs if (!apiControllerName.Equals(actionContext.ControllerContext.ControllerDescriptor.ControllerName)) { continue; } ResourceApi rApi = SwaggerGen.CreateResourceApi(api); r.apis.Add(rApi); ResourceApiOperation rApiOperation = SwaggerGen.CreateResourceApiOperation(r, api, docProvider); rApi.operations.Add(rApiOperation); foreach (var param in api.ParameterDescriptions) { ResourceApiOperationParameter parameter = SwaggerGen.CreateResourceApiOperationParameter(r, api, param, docProvider); rApiOperation.parameters.Add(parameter); } if (System.Configuration.ConfigurationManager.AppSettings["swagger:APITOKEN"] != null && System.Configuration.ConfigurationManager.AppSettings["swagger:APITOKEN"].Equals("true") && !api.ActionDescriptor.ActionName.EndsWith("API")) { //添加Token ResourceApiOperationParameter p = new ResourceApiOperationParameter(); p.name = "ApiToken"; p.description = "Api Token"; p.paramType = "path"; p.required = true; p.dataType = "String"; rApiOperation.parameters.Insert(0, p); } SwaggerGen.CreateModel(r, api, docProvider); //r.models = new ResourceApiModel(); } return(r); }
private static bool IsRequired(PropertyInfo propertyInfo, XmlCommentDocumentationProvider docProvider) { if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(false); } return(docProvider.IsRequired(propertyInfo)); }
/// <summary> /// Creates an api operation /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An api operation</returns> public static ResourceApiOperation CreateResourceApiOperation(ApiDescription api, XmlCommentDocumentationProvider docProvider) { ResourceApiOperation rApiOperation = new ResourceApiOperation() { httpMethod = api.HttpMethod.ToString(), nickname = docProvider.GetNickname(api.ActionDescriptor), responseClass = docProvider.GetResponseClass(api.ActionDescriptor), summary = api.Documentation, notes = docProvider.GetNotes(api.ActionDescriptor), parameters = new List<ResourceApiOperationParameter>() }; return rApiOperation; }
public static Dictionary<string,Model> CreateModels(IEnumerable<ApiDescription> apiDescriptions, XmlCommentDocumentationProvider docProvider) { var parameters = apiDescriptions.SelectMany(a => a.ParameterDescriptions) .Where(p => !p.ParameterDescriptor.ParameterType.IsPrimitive()); var models = new Dictionary<string,Model>(); foreach (var param in parameters) { if (!models.ContainsKey(param.ParameterDescriptor.ParameterType.Name)) { var model = new Model() { Id = param.ParameterDescriptor.ParameterType.Name, Properties = CreateProperties(param.ParameterDescriptor.ParameterType) }; models.Add(param.ParameterDescriptor.ParameterType.Name, model); } } return models; }
/// <summary> /// Creates an operation parameter /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="param">Description of a parameter on an operation via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An operation parameter</returns> public static ResourceApiOperationParameter CreateResourceApiOperationParameter(ResourceListing r, ApiDescription api, ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { string paramType = (param.Source.ToString().Equals(FROMURI)) ? QUERY : BODY; var dataType = param.ParameterDescriptor.ParameterType.Name; switch (dataType) { case "List`1": var dataObjType = param.ParameterDescriptor.ParameterType.GetGenericArguments()[0]; dataType = string.Format("Array[{0}]", dataObjType.Name); break; case "Nullable`1": var dd = param.ParameterDescriptor.ParameterType.GetGenericArguments()[0]; dataType = dd.Name; break; case "Dictionary`2": dataType = string.Format("Array[{0},{1}]", param.ParameterDescriptor.ParameterType.GetGenericArguments()[0].Name, param.ParameterDescriptor.ParameterType.GetGenericArguments()[1].Name); break; default: if (param.ParameterDescriptor.ParameterType.IsPrimitive) { if (!IsExceptType(param.ParameterDescriptor.ParameterType)) { AddModelDataObject(r, param.ParameterDescriptor.ParameterType); } } else { foreach (var item in param.ParameterDescriptor.ParameterType.GetProperties()) { ResourceApiOperationParameter parametera = new ResourceApiOperationParameter() { paramType = (paramType == "query" && api.RelativePath.IndexOf("{" + item.Name + "}") > -1) ? PATH : paramType, name = item.Name, description = GetDocumentation(param.ParameterDescriptor.ParameterType), // string.IsNullOrWhiteSpace(param.Documentation) ? NODESCRIPTION : param.Documentation, dataType = dataType, required = docProvider.GetRequired(param.ParameterDescriptor) }; if (string.IsNullOrWhiteSpace(parametera.description) || NODESCRIPTION.Equals(parametera.description, StringComparison.OrdinalIgnoreCase)) { parametera.description = GetParameterDocumentation((param.ParameterDescriptor as ReflectedHttpParameterDescriptor).ParameterInfo, api.ActionDescriptor.ControllerDescriptor.ControllerType); } } } break; } ResourceApiOperationParameter parameter = new ResourceApiOperationParameter() { paramType = (paramType == "query" && api.RelativePath.IndexOf("{" + param.Name + "}") > -1) ? PATH : paramType, name = param.Name, description = param.Name.Equals("sessionKey") ? "Login session" : (string.IsNullOrWhiteSpace(param.Documentation) ? NODESCRIPTION : param.Documentation), dataType = dataType, required = docProvider.GetRequired(param.ParameterDescriptor) }; if (string.IsNullOrWhiteSpace(parameter.description) || NODESCRIPTION.Equals(parameter.description, StringComparison.OrdinalIgnoreCase)) { parameter.description = GetParameterDocumentation((param.ParameterDescriptor as ReflectedHttpParameterDescriptor).ParameterInfo, api.ActionDescriptor.ControllerDescriptor.ControllerType); } return(parameter); }
/// <summary> /// Creates an api operation /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An api operation</returns> public static ResourceApiOperation CreateResourceApiOperation(ApiDescription api, XmlCommentDocumentationProvider docProvider, DataTypeRegistry dataTypeRegistry) { ResourceApiOperation rApiOperation = new ResourceApiOperation() { httpMethod = api.HttpMethod.ToString(), nickname = docProvider.GetNickname(api.ActionDescriptor), responseClass = docProvider.GetResponseClass(api.ActionDescriptor), summary = api.Documentation, notes = docProvider.GetNotes(api.ActionDescriptor), type = docProvider.GetResponseClass(api.ActionDescriptor), parameters = new List <ResourceApiOperationParameter>(), responseMessages = new List <ResourceApiOperationResponseMessage>(), }; var responseType = api.ActualResponseType(); if (responseType == null) { rApiOperation.type = "void"; } else { var dataType = dataTypeRegistry.GetOrRegister(responseType); if (dataType.Type == "object") { rApiOperation.type = dataType.Id; } else { rApiOperation.type = dataType.Type; rApiOperation.format = dataType.Format; rApiOperation.items = dataType.Items; rApiOperation.Enum = dataType.Enum; } } return(rApiOperation); }
public static void TryToAddModels(ConcurrentDictionary<string, TypeInfo> models, Type type, XmlCommentDocumentationProvider docProvider, ConcurrentDictionary<string, string> typesToReturn = null, int level = 0) { var _type = type; if (type.IsArray) _type = type.GetElementType(); else if (type.IsGenericType) _type = type.GetGenericArguments().First(); string typeName = GetTypeName(_type); if (models.Any(m => m.Key == typeName)) return; if (IsOutputable(_type)) { var typeInfo = new TypeInfo { id = typeName }; if (!IgnoreTypes.Contains(_type.Name.ToLower())) { typeInfo.description = docProvider.GetSummary(_type); } //Ignore properties for .net types if (!_type.Assembly.FullName.Contains("System") && !_type.Assembly.FullName.Contains("mscorlib")) { var modelInfoDic = new Dictionary<string, PropInfo>(); foreach (var propertyInfo in _type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (propertyInfo.GetCustomAttributes(typeof(JsonIgnoreAttribute), false).FirstOrDefault() != null) continue; var propInfo = new PropInfo(); string propName = GetPropertyName(propertyInfo); Type propType = docProvider.GetType(propertyInfo); SwaggerType swaggerType = GetSwaggerType(propType); propInfo.type = swaggerType.Name; propInfo.items = swaggerType.Items; propInfo.required = IsRequired(propertyInfo, docProvider); if (!modelInfoDic.Keys.Contains(propName)) modelInfoDic.Add(propName, propInfo); if (!IgnoreTypes.Contains(propInfo.type)) { propInfo.description = docProvider.GetSummary(propertyInfo); if (propertyInfo.PropertyType.IsEnum) { modelInfoDic[propName].@enum = propertyInfo.PropertyType.GetEnumNames(); } //Don't go too deep if (level < 10) { TryToAddModels(models, swaggerType.type, docProvider, typesToReturn, ++level); } } } typeInfo.properties = modelInfoDic; } if (_type.IsEnum) { typeInfo.values = _type.GetEnumNames(); } models.TryAdd(typeName, typeInfo); } }
/// <summary> /// Creates an operation parameter /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="param">Description of a parameter on an operation via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An operation parameter</returns> public static ResourceApiOperationParameter CreateResourceApiOperationParameter(ApiDescription api, ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { string paramType = (param.Source.ToString().Equals(FROMURI)) ? QUERY : BODY; var parameter = new ResourceApiOperationParameter() { paramType = (paramType == "query" && api.RelativePath.IndexOf("{" + param.Name + "}") > -1) ? PATH : paramType, name = param.Name, description = param.Documentation, dataType = TypeParser.Parse(param.ParameterDescriptor.ParameterType), required = docProvider.GetRequired(param.ParameterDescriptor) }; parameter.allowMultiple = parameter.dataType.StartsWith("List["); parameter.allowableValues = CreateAllowableValues(param.ParameterDescriptor.ParameterType); CustomAttributeHelper.PrepareByOptionAttribute(parameter, param.ParameterDescriptor); return(parameter); }
private static IList <ResourceModelNode> CreateResourceModel(ApiParameterDescription param, Type modelType, XmlCommentDocumentationProvider docProvider) { lock (s_lock) { var result = new List <ResourceModelNode>(); ResourceModelNode rModel = null; if ((!modelType.IsEnum && !modelType.Equals(typeof(string)))) { if (modelType.IsGenericType) { modelType = modelType.GetGenericArguments().First(); return(CreateResourceModel(param, modelType, docProvider)); } if (s_cache.ContainsKey(modelType)) { result.AddRange(s_cache[modelType]); return(result); } rModel = new ResourceModelNode() { Id = TypeParser.Parse(modelType.Name) }; s_cache.Add(modelType, result); foreach (var typeProperty in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { var property = new ResourceModelPropertyNode(); property.Id = TypeParser.Parse(typeProperty.Name); property.Type = TypeParser.Parse(typeProperty.PropertyType); if (typeProperty.PropertyType.IsValueType || Nullable.GetUnderlyingType(typeProperty.PropertyType) == null) { rModel.Required.Add(property.Id); } if (property.Type.StartsWith("List[")) { property.Type = "array"; var itemType = typeProperty.PropertyType.GetGenericArguments().FirstOrDefault(); if (itemType == null) { itemType = typeProperty.PropertyType; } property.DefineContainerType(itemType); } result.AddRange(CreateResourceModel(typeProperty.PropertyType, docProvider)); if (docProvider != null) { property.Description = docProvider.GetDocumentation(typeProperty); if (typeProperty.PropertyType.IsEnum) { property.AllowableValues = CreateAllowableValues(typeProperty.PropertyType); } else if ((typeProperty.PropertyType.IsClass || typeProperty.PropertyType.IsValueType) && typeof(string) != typeProperty.PropertyType) { result.AddRange(CreateResourceModel(typeProperty.PropertyType, docProvider)); } } rModel.Properties.Add(property); } if (rModel.Properties.Count > 0) { result.Add(rModel); } } return(result); } }
public static IList <ResourceModelNode> CreateResourceModel(ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { return(CreateResourceModel(param, param.ParameterDescriptor.ParameterType, docProvider)); }
/// <summary> /// Creates an operation parameter /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="param">Description of a parameter on an operation via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An operation parameter</returns> public static ResourceApiOperationParameter CreateResourceApiOperationParameter(ApiDescription api, ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { string paramType = (param.Source.ToString().Equals(FROMURI)) ? QUERY : BODY; ResourceApiOperationParameter parameter = new ResourceApiOperationParameter() { paramType = (paramType == "query" && api.RelativePath.IndexOf("{" + param.Name + "}") > -1) ? PATH : paramType, name = param.Name, description = param.Documentation, dataType = param.ParameterDescriptor.ParameterType.Name, required = docProvider.GetRequired(param.ParameterDescriptor) }; return parameter; }
public static IList<ResourceModelNode> CreateResourceModel(Type modelType, XmlCommentDocumentationProvider docProvider) { return CreateResourceModel(null, modelType, docProvider); }
public static IList<ResourceModelNode> CreateResourceModel(ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { return CreateResourceModel(param, param.ParameterDescriptor.ParameterType, docProvider); }
/// <summary> /// Creates an api operation /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An api operation</returns> public static ResourceApiOperation CreateResourceApiOperation(ApiDescription api, XmlCommentDocumentationProvider docProvider) { ResponseMeta responseMeta = docProvider.GetResponseType(api.ActionDescriptor); SwaggerType swaggerType = Helper.GetSwaggerType(responseMeta.Type); ResourceApiOperation rApiOperation = new ResourceApiOperation { httpMethod = api.HttpMethod.ToString(), nickname = docProvider.GetNickname(api.ActionDescriptor), items = swaggerType.Items, type = swaggerType.Name, summary = api.Documentation, notes = docProvider.GetNotes(api.ActionDescriptor), parameters = new List <ResourceApiOperationParameter>(), responseMessages = docProvider.GetResponseCodes(api.ActionDescriptor) }; var typesToReturn = new ConcurrentDictionary <string, string>(); Helper.TryToAddModels(models, responseMeta.Type, docProvider, typesToReturn); return(rApiOperation); }
public static Dictionary <string, Model> CreateModels(IEnumerable <ApiDescription> apiDescriptions, XmlCommentDocumentationProvider docProvider) { var parameters = apiDescriptions.SelectMany(a => a.ParameterDescriptions) .Where(p => !p.ParameterDescriptor.ParameterType.IsPrimitive()); var models = new Dictionary <string, Model>(); foreach (var param in parameters) { if (!models.ContainsKey(param.ParameterDescriptor.ParameterType.Name)) { var model = new Model() { Id = param.ParameterDescriptor.ParameterType.Name, Properties = CreateProperties(param.ParameterDescriptor.ParameterType) }; models.Add(param.ParameterDescriptor.ParameterType.Name, model); } } return(models); }
public SwaggerGen() { _docProvider = (XmlCommentDocumentationProvider)GlobalConfiguration.Configuration.Services.GetDocumentationProvider(); }
/// <summary> /// Creates an api operation /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An api operation</returns> public static ResourceApiOperation CreateResourceApiOperation(ApiDescription api, XmlCommentDocumentationProvider docProvider, HttpControllerDescriptor controllerDescriptor) { var parts = docProvider.GetNotes(api.ActionDescriptor).Split(new string[] { "schema=" }, StringSplitOptions.None); ReflectedHttpActionDescriptor actionDescriptor = (api.ActionDescriptor as ReflectedHttpActionDescriptor); string _attributes = ""; _attributes += GetCustomAttributesAsString(actionDescriptor.MethodInfo.GetCustomAttributes(true)); _attributes += GetCustomAttributesAsString(controllerDescriptor.ControllerType.GetCustomAttributes(true)); ResourceApiOperation rApiOperation = new ResourceApiOperation() { httpMethod = api.HttpMethod.ToString(), nickname = docProvider.GetNickname(api.ActionDescriptor), responseClass = docProvider.GetResponseClass(api.ActionDescriptor), summary = api.Documentation+" "+_attributes, notes = parts[0], schema = parts.Length > 1 ? parts[1] : "", parameters = new List<ResourceApiOperationParameter>(), }; return rApiOperation; }
private static IList<ResourceModelNode> CreateResourceModel(ApiParameterDescription param, Type modelType, XmlCommentDocumentationProvider docProvider) { lock (s_lock) { var result = new List<ResourceModelNode>(); ResourceModelNode rModel = null; if ((!modelType.IsEnum && !modelType.Equals(typeof(string)))) { if (modelType.IsGenericType) { modelType = modelType.GetGenericArguments().First(); return CreateResourceModel(param, modelType, docProvider); } if (s_cache.ContainsKey(modelType)) { result.AddRange(s_cache[modelType]); return result; } rModel = new ResourceModelNode() { Id = TypeParser.Parse(modelType.Name) }; s_cache.Add(modelType, result); foreach (var typeProperty in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { var property = new ResourceModelPropertyNode(); property.Id = TypeParser.Parse(typeProperty.Name); property.Type = TypeParser.Parse(typeProperty.PropertyType); if (typeProperty.PropertyType.IsValueType || Nullable.GetUnderlyingType(typeProperty.PropertyType) == null) { rModel.Required.Add(property.Id); } if (property.Type.StartsWith("List[")) { property.Type = "array"; var itemType = typeProperty.PropertyType.GetGenericArguments().FirstOrDefault(); if (itemType == null) { itemType = typeProperty.PropertyType; } property.DefineContainerType(itemType); } result.AddRange(CreateResourceModel(typeProperty.PropertyType, docProvider)); if (docProvider != null) { property.Description = docProvider.GetDocumentation(typeProperty); if (typeProperty.PropertyType.IsEnum) { property.AllowableValues = CreateAllowableValues(typeProperty.PropertyType); } else if ((typeProperty.PropertyType.IsClass || typeProperty.PropertyType.IsValueType) && typeof(string) != typeProperty.PropertyType) { result.AddRange(CreateResourceModel(typeProperty.PropertyType, docProvider)); } } rModel.Properties.Add(property); } if (rModel.Properties.Count > 0) { result.Add(rModel); } } return result; } }
/// <summary> /// Creates an operation parameter /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="param">Description of a parameter on an operation via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An operation parameter</returns> public static ResourceApiOperationParameter CreateResourceApiOperationParameter(ApiDescription api, ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { string paramType = (param.Source.ToString().Equals(FROMURI)) ? QUERY : BODY; var parameter = new ResourceApiOperationParameter() { paramType = (paramType == "query" && api.RelativePath.IndexOf("{" + param.Name + "}") > -1) ? PATH : paramType, name = param.Name, description = param.Documentation, dataType = TypeParser.Parse(param.ParameterDescriptor.ParameterType), required = docProvider.GetRequired(param.ParameterDescriptor) }; parameter.allowMultiple = parameter.dataType.StartsWith("List["); parameter.allowableValues = CreateAllowableValues(param.ParameterDescriptor.ParameterType); CustomAttributeHelper.PrepareByOptionAttribute(parameter, param.ParameterDescriptor); return parameter; }
/// <summary> /// Creates an operation parameter /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="param">Description of a parameter on an operation via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An operation parameter</returns> public static ResourceApiOperationParameter CreateResourceApiOperationParameter(ApiDescription api, ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { string paramType = (param.Source.ToString().Equals(FROMURI)) ? QUERY : BODY; ResourceApiOperationParameter parameter = new ResourceApiOperationParameter() { paramType = (paramType == "query" && api.RelativePath.IndexOf("{" + param.Name + "}") > -1) ? PATH : paramType, name = param.Name, description = param.Documentation, dataType = param.ParameterDescriptor.ParameterType.Name, required = docProvider.GetRequired(param.ParameterDescriptor) //allowableValues = new OperationParameterAllowableValues() }; return(parameter); }
/// <summary> /// Creates an api operation /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An api operation</returns> public static ResourceApiOperation CreateResourceApiOperation(ApiDescription api, XmlCommentDocumentationProvider docProvider) { ResponseMeta responseMeta = docProvider.GetResponseType(api.ActionDescriptor); SwaggerType swaggerType = Helper.GetSwaggerType(responseMeta.Type); ResourceApiOperation rApiOperation = new ResourceApiOperation { httpMethod = api.HttpMethod.ToString(), nickname = docProvider.GetNickname(api.ActionDescriptor), items = swaggerType.Items, type = swaggerType.Name, summary = api.Documentation, notes = docProvider.GetNotes(api.ActionDescriptor), parameters = new List<ResourceApiOperationParameter>(), responseMessages = docProvider.GetResponseCodes(api.ActionDescriptor) }; var typesToReturn = new ConcurrentDictionary<string, string>(); Helper.TryToAddModels(models, responseMeta.Type, docProvider, typesToReturn); return rApiOperation; }
public static IList <ResourceModelNode> CreateResourceModel(Type modelType, XmlCommentDocumentationProvider docProvider) { return(CreateResourceModel(null, modelType, docProvider)); }
public static void CreateModel(ResourceListing r, ApiDescription api, XmlCommentDocumentationProvider docProvider) { if (r.models == null) { r.models = new ConcurrentDictionary <string, object>(); } ReflectedHttpActionDescriptor reflectedActionDescriptor = api.ActionDescriptor as ReflectedHttpActionDescriptor; if (reflectedActionDescriptor != null) { //this function will be called generating swagger API json //limitations //-only generating swagger models (API return type documentation) for return type is ApiResponse //--most calls fall into these 3 categories: //--ApiResponse<PageData<T>> //--ApiResponse<T> //--ApiResponse<T> where T is simple type such as object, string, int, etc. //-only generate detail when T is DataObject //implementation notes //-get the actual T //--when T is DataObject, add into a queue (i.e. a FIFO Stack) for next step processing //-loop until queue is empty //--process (add model details) for the first item in queue, remove it after processed //--during the processing, if found any property is type of DataObject, add the nested type into queue //-the reason to use a while loop with a queue is to avoid using recursive implementation which will throw a stack-overflow exception when it's too many nested types var returnType = reflectedActionDescriptor.MethodInfo.ReturnType; List <Type> queue = new List <Type>();//process queue AddTypeToProcessQueue(r, returnType, queue); //parameter handling var parameters = reflectedActionDescriptor.MethodInfo.GetParameters(); if (parameters != null && parameters.Length > 0) { foreach (var p in parameters) { if (p.ParameterType.IsGenericType) { var dataObjType = p.ParameterType.GetGenericArguments()[0]; AddTypeToProcessQueue(r, dataObjType, queue); } else { AddTypeToProcessQueue(r, p.ParameterType, queue); } } } if (returnType.IsGenericType) { Type[] types = returnType.GetGenericArguments(); if (types[0].Name.Equals("PageData`1")) { var dataObjType = types[0].GetGenericArguments()[0]; AddTypeToProcessQueue(r, dataObjType, queue); //ApiResponse_PageData_xxxxx var model = AddModelApiResponse(r, "ApiResponse_PageData_" + dataObjType.Name); if (model != null) { var p = new ResourceApiModelProperty(); p.type = "Array"; p.description = "Page data set"; var items = new Dictionary <string, string>(); items.Add("$ref", "PageData_" + dataObjType.Name); p.items = items; model.properties.Add("Results", p); } if (!r.models.ContainsKey("PageData_" + dataObjType.Name)) { model = new ResourceApiModel(); model.id = "PageData_" + dataObjType.Name; model.properties = new Dictionary <string, ResourceApiModelProperty>(); var p = new ResourceApiModelProperty(); p.type = "int"; p.description = "total no of qualified data"; model.properties.Add("TotalRecords", p); p = new ResourceApiModelProperty(); p.type = "bool"; p.description = "whether has next page"; model.properties.Add("HasNextPage", p); p = new ResourceApiModelProperty(); p.type = "int"; p.description = "curent page index, start from 0"; model.properties.Add("PageIndex", p); p = new ResourceApiModelProperty(); p.type = "int"; p.description = "how many records in one page"; model.properties.Add("PageSize", p); p = new ResourceApiModelProperty(); p.type = "Array"; p.description = "A page of data"; var items = new Dictionary <string, string>(); items.Add("$ref", dataObjType.Name); p.items = items; model.properties.Add("Results", p); r.models.TryAdd("PageData_" + dataObjType.Name, model); } } else if (returnType.Name.Equals("Page`1")) { var dataObjType = types[0]; AddTypeToProcessQueue(r, dataObjType, queue); var paging = returnType.GetProperty("Paging"); if (paging != null) {//add paging type manually AddTypeToProcessQueue(r, paging.PropertyType, queue); } //Page_xxxxx if (!r.models.ContainsKey("Page_" + dataObjType.Name)) { var model = new ResourceApiModel(); model.id = "Page_" + dataObjType.Name; model.properties = new Dictionary <string, ResourceApiModelProperty>(); var p = new ResourceApiModelProperty(); p.type = "Paging"; p.description = "Paging info"; model.properties.Add("Paging", p); p = new ResourceApiModelProperty(); p.type = "Array"; p.description = "A page of data"; var items = new Dictionary <string, string>(); items.Add("$ref", dataObjType.Name); p.items = items; model.properties.Add("Records", p); r.models.TryAdd("Page_" + dataObjType.Name, model); } } else { var dataObjType = types[0]; AddTypeToProcessQueue(r, dataObjType, queue); } } //process queue while (queue.Count > 0) { var type = queue[0]; AddModelDataObject(r, queue[0], queue); queue.Remove(type); } } }
/// <summary> /// Creates an api operation /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An api operation</returns> public static ResourceApiOperation CreateResourceApiOperation(ApiDescription api, XmlCommentDocumentationProvider docProvider) { ResourceApiOperation rApiOperation = new ResourceApiOperation() { httpMethod = api.HttpMethod.ToString(), nickname = docProvider.GetNickname(api.ActionDescriptor), responseClass = TypeParser.Parse(docProvider.GetResponseClass(api.ActionDescriptor)), summary = api.Documentation, notes = docProvider.GetNotes(api.ActionDescriptor), parameters = new List <ResourceApiOperationParameter>(), errorResponses = docProvider.GetErrorResponses(api) }; return(rApiOperation); }
public static void TryToAddModels(ConcurrentDictionary <string, TypeInfo> models, Type type, XmlCommentDocumentationProvider docProvider, ConcurrentDictionary <string, string> typesToReturn = null, int level = 0) { var _type = type; if (type.IsArray) { _type = type.GetElementType(); } else if (type.IsGenericType) { _type = type.GetGenericArguments().First(); } string typeName = GetTypeName(_type); if (models.Any(m => m.Key == typeName)) { return; } if (IsOutputable(_type)) { var typeInfo = new TypeInfo { id = typeName }; if (!IgnoreTypes.Contains(_type.Name.ToLower())) { typeInfo.description = docProvider.GetSummary(_type); } //Ignore properties for .net types if (!_type.Assembly.FullName.Contains("System") && !_type.Assembly.FullName.Contains("mscorlib")) { var modelInfoDic = new Dictionary <string, PropInfo>(); foreach (var propertyInfo in _type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (propertyInfo.GetCustomAttributes(typeof(JsonIgnoreAttribute), false).FirstOrDefault() != null) { continue; } var propInfo = new PropInfo(); string propName = GetPropertyName(propertyInfo); Type propType = docProvider.GetType(propertyInfo); SwaggerType swaggerType = GetSwaggerType(propType); propInfo.type = swaggerType.Name; propInfo.items = swaggerType.Items; propInfo.required = IsRequired(propertyInfo, docProvider); if (!modelInfoDic.Keys.Contains(propName)) { modelInfoDic.Add(propName, propInfo); } if (!IgnoreTypes.Contains(propInfo.type)) { propInfo.description = docProvider.GetSummary(propertyInfo); if (propertyInfo.PropertyType.IsEnum) { modelInfoDic[propName].@enum = propertyInfo.PropertyType.GetEnumNames(); } //Don't go too deep if (level < 10) { TryToAddModels(models, swaggerType.type, docProvider, typesToReturn, ++level); } } } typeInfo.properties = modelInfoDic; } if (_type.IsEnum) { typeInfo.values = _type.GetEnumNames(); } models.TryAdd(typeName, typeInfo); } }
/// <summary> /// Creates an api operation /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An api operation</returns> public static ResourceApiOperation CreateResourceApiOperation(ResourceListing r, ApiDescription api, XmlCommentDocumentationProvider docProvider) { ResourceApiOperation rApiOperation = new ResourceApiOperation() { httpMethod = api.HttpMethod.ToString(), nickname = docProvider.GetNickname(api.ActionDescriptor), responseClass = docProvider.GetResponseClass(api.ActionDescriptor), summary = docProvider.GetDocumentation(api.ActionDescriptor), notes = docProvider.GetNotes(api.ActionDescriptor), parameters = new List <ResourceApiOperationParameter>(), }; if (string.IsNullOrEmpty(rApiOperation.notes) || rApiOperation.notes.Equals("No Documentation Found.")) { rApiOperation.notes = rApiOperation.summary; } return(rApiOperation); }
private static bool IsRequired(PropertyInfo propertyInfo, XmlCommentDocumentationProvider docProvider) { if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) return false; return docProvider.IsRequired(propertyInfo); }
/// <summary> /// Creates an operation parameter /// </summary> /// <param name="api">Description of the api via the ApiExplorer</param> /// <param name="param">Description of a parameter on an operation via the ApiExplorer</param> /// <param name="docProvider">Access to the XML docs written in code</param> /// <returns>An operation parameter</returns> public static ResourceApiOperationParameter CreateResourceApiOperationParameter(ResourceListing r, ApiDescription api, ApiParameterDescription param, XmlCommentDocumentationProvider docProvider) { string paramType = (param.Source.ToString().Equals(FROMURI)) ? QUERY : BODY; var dataType = param.ParameterDescriptor.ParameterType.Name; switch (dataType) { case "List`1": var dataObjType = param.ParameterDescriptor.ParameterType.GetGenericArguments()[0]; dataType = string.Format("Array[{0}]", dataObjType.Name); break; case "Nullable`1": var dd = param.ParameterDescriptor.ParameterType.GetGenericArguments()[0]; dataType = dd.Name; break; case "Dictionary`2": dataType = string.Format("Array[{0},{1}]", param.ParameterDescriptor.ParameterType.GetGenericArguments()[0].Name, param.ParameterDescriptor.ParameterType.GetGenericArguments()[1].Name); break; default: if (!IsExceptType(param.ParameterDescriptor.ParameterType)) { AddModelDataObject(r, param.ParameterDescriptor.ParameterType); } break; } ResourceApiOperationParameter parameter = new ResourceApiOperationParameter() { paramType = (paramType == "query" && api.RelativePath.IndexOf("{" + param.Name + "}") > -1) ? PATH : paramType, name = param.Name, description = param.Name.Equals("sessionKey") ? "Login session" : (string.IsNullOrWhiteSpace(param.Documentation) ? NODESCRIPTION : param.Documentation), dataType = dataType, required = docProvider.GetRequired(param.ParameterDescriptor) }; return(parameter); }
public static List <ResourceApiOperationResponseMessage> GetResourceApiResponseMessage(ApiDescription api, XmlCommentDocumentationProvider docProvider) { List <ResourceApiOperationResponseMessage> ret = new List <ResourceApiOperationResponseMessage>(); var elements = docProvider.GetResponseMessages(api.ActionDescriptor); if (elements != null) { while (elements.MoveNext()) { ret.Add(new ResourceApiOperationResponseMessage() { code = elements.Current.GetAttribute("code", ""), message = elements.Current.Value }); } } return(ret); }