Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API Help pages - customizing Property documentation

I have my web api and I added the web api help pages to auto-generate my documentation. It's working great for methods where my parameters are listed out, but I have a method like this:

public SessionResult PostLogin(CreateSessionCommand request)

And, on my help page, it is only listing the command parameter in the properties section. However, in the sample request section, it lists out all of the properties of my CreateSessionCommand class.

Parameters

Name | Description | Additional information

request | No documentation available. | Define this parameter in the request body.

I would like it instead to list all of the properties in my CreateSessionCommand class. Is there an easy way to do this?

like image 502
Josh Avatar asked Aug 15 '13 15:08

Josh


1 Answers

So, I managed to devise a workaround for this problem, in case anyone is interested.

In HelpPageConfigurationExtensions.cs I added the following extension method:

public static void AlterApiDescription(this ApiDescription apiDescription, HttpConfiguration config)
{
    var docProvider = config.Services.GetDocumentationProvider();
    var addParams = new List<ApiParameterDescription>();
    var removeParams = new List<ApiParameterDescription>();

    foreach (var param in apiDescription.ParameterDescriptions)
    {
        var type = param.ParameterDescriptor.ParameterType;

        //string is some special case that is not a primitive type
        //also, compare by full name because the type returned does not seem to match the types generated by typeof
        bool isPrimitive = type.IsPrimitive || String.Compare(type.FullName, typeof(string).FullName) == 0;

        if (!isPrimitive)
        {
            var properties = from p in param.ParameterDescriptor.ParameterType.GetProperties() 
                               let s = p.SetMethod 
                               where s.IsPublic 
                               select p;

            foreach (var property in properties)
            {
                var documentation = docProvider.GetDocumentation(new System.Web.Http.Controllers.ReflectedHttpParameterDescriptor()
                {
                    ActionDescriptor = param.ParameterDescriptor.ActionDescriptor,
                    ParameterInfo = new CustomParameterInfo(property)
                });

                addParams.Add(new ApiParameterDescription()
                {
                    Documentation = documentation,
                    Name = property.Name,
                    Source = ApiParameterSource.FromBody,
                    ParameterDescriptor = param.ParameterDescriptor
                });
            }

            //since this is a complex type, select it to be removed from the api description
            removeParams.Add(param);
        }
    }

    //add in our new items
    foreach (var item in addParams)
    {
        apiDescription.ParameterDescriptions.Add(item);
    }

    //remove the complex types
    foreach (var item in removeParams)
    {
        apiDescription.ParameterDescriptions.Remove(item);
    }
}

And here is the Parameter info instanced class I use

internal class CustomParameterInfo : ParameterInfo
{
    public CustomParameterInfo(PropertyInfo prop)
    {
        base.NameImpl = prop.Name;
    }
}

Then, we call the extension in another method inside the extensions class

public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
{
    object model;
    string modelId = ApiModelPrefix + apiDescriptionId;
    if (!config.Properties.TryGetValue(modelId, out model))
    {
        Collection<ApiDescription> apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
        ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
        if (apiDescription != null)
        {
            apiDescription.AlterApiDescription(config);

            HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
            model = GenerateApiModel(apiDescription, sampleGenerator);
            config.Properties.TryAdd(modelId, model);
        }
    }

    return (HelpPageApiModel)model;
}

The comments that are used for this must be added to the controller method and not the properties of the class object. This might be because my object is part of an outside library

like image 58
Josh Avatar answered Oct 11 '22 04:10

Josh