using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Net.Http.Headers;
using System.Web.Http;
using System.Web.Http.Description;
using WebAPiUtils_test.Areas.HelpPage.Models;
namespace WebAPiUtils_test.Areas.HelpPage
{
public static class HelpPageConfigurationExtensions
{
private const string ApiModelPrefix = "MS_HelpPageApiModel_";
///
/// Sets the documentation provider for help page.
///
/// The .
/// The documentation provider.
public static void SetDocumentationProvider(this HttpConfiguration config, IDocumentationProvider documentationProvider)
{
config.Services.Replace(typeof(IDocumentationProvider), documentationProvider);
}
///
/// Sets the objects that will be used by the formatters to produce sample requests/responses.
///
/// The .
/// The sample objects.
public static void SetSampleObjects(this HttpConfiguration config, IDictionary sampleObjects)
{
config.GetHelpPageSampleGenerator().SampleObjects = sampleObjects;
}
///
/// Sets the sample request directly for the specified media type and action.
///
/// The .
/// The sample request.
/// The media type.
/// Name of the controller.
/// Name of the action.
public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, new[] { "*" }), sample);
}
///
/// Sets the sample request directly for the specified media type and action with parameters.
///
/// The .
/// The sample request.
/// The media type.
/// Name of the controller.
/// Name of the action.
/// The parameter names.
public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, parameterNames), sample);
}
///
/// Sets the sample request directly for the specified media type of the action.
///
/// The .
/// The sample response.
/// The media type.
/// Name of the controller.
/// Name of the action.
public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, new[] { "*" }), sample);
}
///
/// Sets the sample response directly for the specified media type of the action with specific parameters.
///
/// The .
/// The sample response.
/// The media type.
/// Name of the controller.
/// Name of the action.
/// The parameter names.
public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, parameterNames), sample);
}
///
/// Sets the sample directly for all actions with the specified type and media type.
///
/// The .
/// The sample.
/// The media type.
/// The parameter type or return type of an action.
public static void SetSampleForType(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, Type type)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, type), sample);
}
///
/// Specifies the actual type of passed to the in an action.
/// The help page will use this information to produce more accurate request samples.
///
/// The .
/// The type.
/// Name of the controller.
/// Name of the action.
public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, new[] { "*" }), type);
}
///
/// Specifies the actual type of passed to the in an action.
/// The help page will use this information to produce more accurate request samples.
///
/// The .
/// The type.
/// Name of the controller.
/// Name of the action.
/// The parameter names.
public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, parameterNames), type);
}
///
/// Specifies the actual type of returned as part of the in an action.
/// The help page will use this information to produce more accurate response samples.
///
/// The .
/// The type.
/// Name of the controller.
/// Name of the action.
public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, new[] { "*" }), type);
}
///
/// Specifies the actual type of returned as part of the in an action.
/// The help page will use this information to produce more accurate response samples.
///
/// The .
/// The type.
/// Name of the controller.
/// Name of the action.
/// The parameter names.
public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, parameterNames), type);
}
///
/// Gets the help page sample generator.
///
/// The .
/// The help page sample generator.
public static HelpPageSampleGenerator GetHelpPageSampleGenerator(this HttpConfiguration config)
{
return (HelpPageSampleGenerator)config.Properties.GetOrAdd(
typeof(HelpPageSampleGenerator),
k => new HelpPageSampleGenerator());
}
///
/// Sets the help page sample generator.
///
/// The .
/// The help page sample generator.
public static void SetHelpPageSampleGenerator(this HttpConfiguration config, HelpPageSampleGenerator sampleGenerator)
{
config.Properties.AddOrUpdate(
typeof(HelpPageSampleGenerator),
k => sampleGenerator,
(k, o) => sampleGenerator);
}
///
/// Gets the model that represents an API displayed on the help page. The model is initialized on the first call and cached for subsequent calls.
///
/// The .
/// The ID.
///
/// An
///
public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
{
object model;
string modelId = ApiModelPrefix + apiDescriptionId;
if (!config.Properties.TryGetValue(modelId, out model))
{
Collection apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
if (apiDescription != null)
{
HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
model = GenerateApiModel(apiDescription, sampleGenerator);
config.Properties.TryAdd(modelId, model);
}
}
return (HelpPageApiModel)model;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded as ErrorMessages.")]
private static HelpPageApiModel GenerateApiModel(ApiDescription apiDescription, HelpPageSampleGenerator sampleGenerator)
{
HelpPageApiModel apiModel = new HelpPageApiModel();
apiModel.ApiDescription = apiDescription;
try
{
foreach (var item in sampleGenerator.GetSampleRequests(apiDescription))
{
apiModel.SampleRequests.Add(item.Key, item.Value);
LogInvalidSampleAsError(apiModel, item.Value);
}
foreach (var item in sampleGenerator.GetSampleResponses(apiDescription))
{
apiModel.SampleResponses.Add(item.Key, item.Value);
LogInvalidSampleAsError(apiModel, item.Value);
}
}
catch (Exception e)
{
apiModel.ErrorMessages.Add(String.Format(CultureInfo.CurrentCulture, "An exception has occurred while generating the sample. Exception Message: {0}", e.Message));
}
return apiModel;
}
private static void LogInvalidSampleAsError(HelpPageApiModel apiModel, object sample)
{
InvalidSample invalidSample = sample as InvalidSample;
if (invalidSample != null)
{
apiModel.ErrorMessages.Add(invalidSample.ErrorMessage);
}
}
}
}