Created
October 1, 2014 20:38
-
-
Save DoggettCK/e6da2981096968b43e15 to your computer and use it in GitHub Desktop.
API self-documentation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Net; | |
using System.Net.Http; | |
using System.Web.Hosting; | |
using System.Web.Http; | |
using System.Web.Http.Description; | |
using NLog; | |
namespace Project.Controllers.API { | |
/// | |
/// Controller for providing discoverable API | |
/// | |
[ApiExplorerSettings(IgnoreApi = true)] | |
[Authorize] | |
public class DiscoveryController : ApiController { | |
private readonly Logger _logger; | |
/// | |
/// Default constructor | |
/// | |
public DiscoveryController() { | |
_logger = LogManager.GetCurrentClassLogger(); | |
} | |
/// | |
/// Lists all publicly-available API calls | |
/// | |
/// JSON list of API methods, relative paths, and parameters | |
[AcceptVerbs("GET"), ActionName("get")] | |
public HttpResponseMessage DiscoverAPI() { | |
_logger.Info(string.Format("Request: {0}", Request.RequestUri)); | |
HttpConfiguration config = GlobalConfiguration.Configuration; | |
config.Services.Replace(typeof (IDocumentationProvider), new ApiDocumentationProvider(HostingEnvironment.MapPath("~/App_Data/Documentation.xml"))); | |
IApiExplorer apiExplorer = config.Services.GetApiExplorer(); | |
var apiDescriptions = apiExplorer.ApiDescriptions.Select( | |
delegate(ApiDescription api) { | |
var parts = api.RelativePath.Split(new[] {"?"}, StringSplitOptions.RemoveEmptyEntries); | |
if (parts.Length > 0) { | |
parts[0] = parts[0].ToLowerInvariant(); | |
} | |
var cleanedPath = String.Join("?", parts); | |
return new | |
{ | |
RelativePath = cleanedPath, | |
api.HttpMethod.Method, | |
SupportedResponseFormats = api.SupportedResponseFormatters.SelectMany(formatter => formatter.SupportedMediaTypes.Select(format => format.MediaType)), | |
SupportedEncodings = api.SupportedResponseFormatters.SelectMany(formatter => formatter.SupportedEncodings.Select(encoding => encoding.HeaderName)), | |
api.Documentation, | |
Parameters = api.ParameterDescriptions.Select( | |
param => new | |
{ | |
param.Name, | |
Source = ParameterSourceToString(param.Source), | |
param.Documentation, | |
Descriptor = new | |
{ | |
Default = param.ParameterDescriptor.DefaultValue, | |
Optional = param.ParameterDescriptor.IsOptional, | |
Type = TypeNameToProviderAgnosticName(param.ParameterDescriptor.ParameterType.Name), | |
} | |
}) | |
}; | |
}); | |
return Request.CreateResponse(HttpStatusCode.OK, new {Items = apiDescriptions}); | |
} | |
private String ParameterSourceToString(ApiParameterSource source) { | |
switch (source) { | |
case ApiParameterSource.FromUri: | |
return "From URL"; | |
case ApiParameterSource.FromBody: | |
return "From Body"; | |
default: | |
return "Unknown"; | |
} | |
} | |
private String TypeNameToProviderAgnosticName(string typeName) { | |
if (String.IsNullOrWhiteSpace(typeName)) return null; | |
switch (typeName.ToLowerInvariant()) { | |
case "string": | |
return "String"; | |
case "uint32": | |
return "Unsigned 32-bit integer"; | |
case "int32": | |
return "Signed 32-bit integer"; | |
case "uint64": | |
return "Unsigned 64-bit integer"; | |
case "int64": | |
return "Signed 64-bit integer"; | |
case "boolean": | |
return "Boolean"; | |
default: | |
return typeName; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment