usingSystem;usingSystem.Collections.Generic;usingSystem.Collections.ObjectModel;usingSystem.ComponentModel;usingSystem.Diagnostics;usingSystem.Diagnostics.CodeAnalysis;usingSystem.Globalization;usingSystem.Linq;usingSystem.Net.Http;usingSystem.Net.Http.Headers;usingSystem.Web.Http;usingSystem.Web.Http.Controllers;usingSystem.Web.Http.Description;usingHHECS.API.Areas.HelpPage.ModelDescriptions;usingHHECS.API.Areas.HelpPage.Models;namespaceHHECS.API.Areas.HelpPage{publicstaticclassHelpPageConfigurationExtensions{privateconststringApiModelPrefix="MS_HelpPageApiModel_";///<summary>///Setsthedocumentationproviderforhelppage.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="documentationProvider">Thedocumentationprovider.</param>publicstaticvoidSetDocumentationProvider(thisHttpConfigurationconfig,IDocumentationProviderdocumentationProvider){config.Services.Replace(typeof(IDocumentationProvider),documentationProvider);}///<summary>///Setstheobjectsthatwillbeusedbytheformatterstoproducesamplerequests/responses.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sampleObjects">Thesampleobjects.</param>publicstaticvoidSetSampleObjects(thisHttpConfigurationconfig,IDictionary<Type,object>sampleObjects){config.GetHelpPageSampleGenerator().SampleObjects=sampleObjects;}///<summary>///Setsthesamplerequestdirectlyforthespecifiedmediatypeandaction.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sample">Thesamplerequest.</param>///<paramname="mediaType">Themediatype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>publicstaticvoidSetSampleRequest(thisHttpConfigurationconfig,objectsample,MediaTypeHeaderValuemediaType,stringcontrollerName,stringactionName){config.GetHelpPageSampleGenerator().ActionSamples.Add(newHelpPageSampleKey(mediaType,SampleDirection.Request,controllerName,actionName,new[]{"*"}),sample);}///<summary>///Setsthesamplerequestdirectlyforthespecifiedmediatypeandactionwithparameters.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sample">Thesamplerequest.</param>///<paramname="mediaType">Themediatype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>///<paramname="parameterNames">Theparameternames.</param>publicstaticvoidSetSampleRequest(thisHttpConfigurationconfig,objectsample,MediaTypeHeaderValuemediaType,stringcontrollerName,stringactionName,paramsstring[]parameterNames){config.GetHelpPageSampleGenerator().ActionSamples.Add(newHelpPageSampleKey(mediaType,SampleDirection.Request,controllerName,actionName,parameterNames),sample);}///<summary>///Setsthesamplerequestdirectlyforthespecifiedmediatypeoftheaction.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sample">Thesampleresponse.</param>///<paramname="mediaType">Themediatype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>publicstaticvoidSetSampleResponse(thisHttpConfigurationconfig,objectsample,MediaTypeHeaderValuemediaType,stringcontrollerName,stringactionName){config.GetHelpPageSampleGenerator().ActionSamples.Add(newHelpPageSampleKey(mediaType,SampleDirection.Response,controllerName,actionName,new[]{"*"}),sample);}///<summary>///Setsthesampleresponsedirectlyforthespecifiedmediatypeoftheactionwithspecificparameters.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sample">Thesampleresponse.</param>///<paramname="mediaType">Themediatype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>///<paramname="parameterNames">Theparameternames.</param>publicstaticvoidSetSampleResponse(thisHttpConfigurationconfig,objectsample,MediaTypeHeaderValuemediaType,stringcontrollerName,stringactionName,paramsstring[]parameterNames){config.GetHelpPageSampleGenerator().ActionSamples.Add(newHelpPageSampleKey(mediaType,SampleDirection.Response,controllerName,actionName,parameterNames),sample);}///<summary>///Setsthesampledirectlyforallactionswiththespecifiedmediatype.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sample">Thesample.</param>///<paramname="mediaType">Themediatype.</param>publicstaticvoidSetSampleForMediaType(thisHttpConfigurationconfig,objectsample,MediaTypeHeaderValuemediaType){config.GetHelpPageSampleGenerator().ActionSamples.Add(newHelpPageSampleKey(mediaType),sample);}///<summary>///Setsthesampledirectlyforallactionswiththespecifiedtypeandmediatype.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sample">Thesample.</param>///<paramname="mediaType">Themediatype.</param>///<paramname="type">Theparametertypeorreturntypeofanaction.</param>publicstaticvoidSetSampleForType(thisHttpConfigurationconfig,objectsample,MediaTypeHeaderValuemediaType,Typetype){config.GetHelpPageSampleGenerator().ActionSamples.Add(newHelpPageSampleKey(mediaType,type),sample);}///<summary>///Specifiestheactualtypeof<seecref="System.Net.Http.ObjectContent{T}"/>passedtothe<seecref="System.Net.Http.HttpRequestMessage"/>inanaction.///Thehelppagewillusethisinformationtoproducemoreaccuraterequestsamples.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="type">Thetype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>publicstaticvoidSetActualRequestType(thisHttpConfigurationconfig,Typetype,stringcontrollerName,stringactionName){config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(newHelpPageSampleKey(SampleDirection.Request,controllerName,actionName,new[]{"*"}),type);}///<summary>///Specifiestheactualtypeof<seecref="System.Net.Http.ObjectContent{T}"/>passedtothe<seecref="System.Net.Http.HttpRequestMessage"/>inanaction.///Thehelppagewillusethisinformationtoproducemoreaccuraterequestsamples.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="type">Thetype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>///<paramname="parameterNames">Theparameternames.</param>publicstaticvoidSetActualRequestType(thisHttpConfigurationconfig,Typetype,stringcontrollerName,stringactionName,paramsstring[]parameterNames){config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(newHelpPageSampleKey(SampleDirection.Request,controllerName,actionName,parameterNames),type);}///<summary>///Specifiestheactualtypeof<seecref="System.Net.Http.ObjectContent{T}"/>returnedaspartofthe<seecref="System.Net.Http.HttpRequestMessage"/>inanaction.///Thehelppagewillusethisinformationtoproducemoreaccurateresponsesamples.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="type">Thetype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>publicstaticvoidSetActualResponseType(thisHttpConfigurationconfig,Typetype,stringcontrollerName,stringactionName){config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(newHelpPageSampleKey(SampleDirection.Response,controllerName,actionName,new[]{"*"}),type);}///<summary>///Specifiestheactualtypeof<seecref="System.Net.Http.ObjectContent{T}"/>returnedaspartofthe<seecref="System.Net.Http.HttpRequestMessage"/>inanaction.///Thehelppagewillusethisinformationtoproducemoreaccurateresponsesamples.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="type">Thetype.</param>///<paramname="controllerName">Nameofthecontroller.</param>///<paramname="actionName">Nameoftheaction.</param>///<paramname="parameterNames">Theparameternames.</param>publicstaticvoidSetActualResponseType(thisHttpConfigurationconfig,Typetype,stringcontrollerName,stringactionName,paramsstring[]parameterNames){config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(newHelpPageSampleKey(SampleDirection.Response,controllerName,actionName,parameterNames),type);}///<summary>///Getsthehelppagesamplegenerator.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<returns>Thehelppagesamplegenerator.</returns>publicstaticHelpPageSampleGeneratorGetHelpPageSampleGenerator(thisHttpConfigurationconfig){return(HelpPageSampleGenerator)config.Properties.GetOrAdd(typeof(HelpPageSampleGenerator),k=>newHelpPageSampleGenerator());}///<summary>///Setsthehelppagesamplegenerator.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="sampleGenerator">Thehelppagesamplegenerator.</param>publicstaticvoidSetHelpPageSampleGenerator(thisHttpConfigurationconfig,HelpPageSampleGeneratorsampleGenerator){config.Properties.AddOrUpdate(typeof(HelpPageSampleGenerator),k=>sampleGenerator,(k,o)=>sampleGenerator);}///<summary>///Getsthemodeldescriptiongenerator.///</summary>///<paramname="config">Theconfiguration.</param>///<returns>The<seecref="ModelDescriptionGenerator"/></returns>publicstaticModelDescriptionGeneratorGetModelDescriptionGenerator(thisHttpConfigurationconfig){return(ModelDescriptionGenerator)config.Properties.GetOrAdd(typeof(ModelDescriptionGenerator),k=>InitializeModelDescriptionGenerator(config));}///<summary>///GetsthemodelthatrepresentsanAPIdisplayedonthehelppage.Themodelisinitializedonthefirstcallandcachedforsubsequentcalls.///</summary>///<paramname="config">The<seecref="HttpConfiguration"/>.</param>///<paramname="apiDescriptionId">The<seecref="ApiDescription"/>ID.</param>///<returns>///An<seecref="HelpPageApiModel"/>///</returns>publicstaticHelpPageApiModelGetHelpPageApiModel(thisHttpConfigurationconfig,stringapiDescriptionId){objectmodel;stringmodelId=ApiModelPrefix+apiDescriptionId;if(!config.Properties.TryGetValue(modelId,outmodel)){Collection<ApiDescription>apiDescriptions=config.Services.GetApiExplorer().ApiDescriptions;ApiDescriptionapiDescription=apiDescriptions.FirstOrDefault(api=>String.Equals(api.GetFriendlyId(),apiDescriptionId,StringComparison.OrdinalIgnoreCase));if(apiDescription!=null){model=GenerateApiModel(apiDescription,config);config.Properties.TryAdd(modelId,model);}}return(HelpPageApiModel)model;}privatestaticHelpPageApiModelGenerateApiModel(ApiDescriptionapiDescription,HttpConfigurationconfig){HelpPageApiModelapiModel=newHelpPageApiModel(){ApiDescription=apiDescription,};ModelDescriptionGeneratormodelGenerator=config.GetModelDescriptionGenerator();HelpPageSampleGeneratorsampleGenerator=config.GetHelpPageSampleGenerator();GenerateUriParameters(apiModel,modelGenerator);GenerateRequestModelDescription(apiModel,modelGenerator,sampleGenerator);GenerateResourceDescription(apiModel,modelGenerator);GenerateSamples(apiModel,sampleGenerator);returnapiModel;}privatestaticvoidGenerateUriParameters(HelpPageApiModelapiModel,ModelDescriptionGeneratormodelGenerator){ApiDescriptionapiDescription=apiModel.ApiDescription;foreach(ApiParameterDescriptionapiParameterinapiDescription.ParameterDescriptions){if(apiParameter.Source==ApiParameterSource.FromUri){HttpParameterDescriptorparameterDescriptor=apiParameter.ParameterDescriptor;TypeparameterType=null;ModelDescriptiontypeDescription=null;ComplexTypeModelDescriptioncomplexTypeDescription=null;if(parameterDescriptor!=null){parameterType=parameterDescriptor.ParameterType;typeDescription=modelGenerator.GetOrCreateModelDescription(parameterType);complexTypeDescription=typeDescriptionasComplexTypeModelDescription;}//Example://[TypeConverter(typeof(PointConverter))]//publicclassPoint//{//publicPoint(intx,inty)//{//X=x;//Y=y;//}//publicintX{get;set;}//publicintY{get;set;}//}//ClassPointisbindablewithaTypeConverter,soPointwillbeaddedtoUriParameterscollection.////publicclassPoint//{//publicintX{get;set;}//publicintY{get;set;}//}//RegularcomplexclassPointwillhavepropertiesXandYaddedtoUriParameterscollection.if(complexTypeDescription!=null&&!IsBindableWithTypeConverter(parameterType)){foreach(ParameterDescriptionuriParameterincomplexTypeDescription.Properties){apiModel.UriParameters.Add(uriParameter);}}elseif(parameterDescriptor!=null){ParameterDescriptionuriParameter=AddParameterDescription(apiModel,apiParameter,typeDescription);if(!parameterDescriptor.IsOptional){uriParameter.Annotations.Add(newParameterAnnotation(){Documentation="Required"});}objectdefaultValue=parameterDescriptor.DefaultValue;if(defaultValue!=null){uriParameter.Annotations.Add(newParameterAnnotation(){Documentation="Default value is "+Convert.ToString(defaultValue,CultureInfo.InvariantCulture)});}}else{Debug.Assert(parameterDescriptor==null);//IfparameterDescriptorisnull,thisisanundeclaredrouteparameterwhichonlyoccurs//whensourceisFromUri.Ignoredinrequestmodelandamongresourceparametersbutlisted//asasimplestringhere.ModelDescriptionmodelDescription=modelGenerator.GetOrCreateModelDescription(typeof(string));AddParameterDescription(apiModel,apiParameter,modelDescription);}}}}privatestaticboolIsBindableWithTypeConverter(TypeparameterType){if(parameterType==null){returnfalse;}returnTypeDescriptor.GetConverter(parameterType).CanConvertFrom(typeof(string));}privatestaticParameterDescriptionAddParameterDescription(HelpPageApiModelapiModel,ApiParameterDescriptionapiParameter,ModelDescriptiontypeDescription){ParameterDescriptionparameterDescription=newParameterDescription{Name=apiParameter.Name,Documentation=apiParameter.Documentation,TypeDescription=typeDescription,};apiModel.UriParameters.Add(parameterDescription);returnparameterDescription;}privatestaticvoidGenerateRequestModelDescription(HelpPageApiModelapiModel,ModelDescriptionGeneratormodelGenerator,HelpPageSampleGeneratorsampleGenerator){ApiDescriptionapiDescription=apiModel.ApiDescription;foreach(ApiParameterDescriptionapiParameterinapiDescription.ParameterDescriptions){if(apiParameter.Source==ApiParameterSource.FromBody){TypeparameterType=apiParameter.ParameterDescriptor.ParameterType;apiModel.RequestModelDescription=modelGenerator.GetOrCreateModelDescription(parameterType);apiModel.RequestDocumentation=apiParameter.Documentation;}elseif(apiParameter.ParameterDescriptor!=null&&apiParameter.ParameterDescriptor.ParameterType==typeof(HttpRequestMessage)){TypeparameterType=sampleGenerator.ResolveHttpRequestMessageType(apiDescription);if(parameterType!=null){apiModel.RequestModelDescription=modelGenerator.GetOrCreateModelDescription(parameterType);}}}}privatestaticvoidGenerateResourceDescription(HelpPageApiModelapiModel,ModelDescriptionGeneratormodelGenerator){ResponseDescriptionresponse=apiModel.ApiDescription.ResponseDescription;TyperesponseType=response.ResponseType??response.DeclaredType;if(responseType!=null&&responseType!=typeof(void)){apiModel.ResourceDescription=modelGenerator.GetOrCreateModelDescription(responseType);}}[SuppressMessage("Microsoft.Design","CA1031:DoNotCatchGeneralExceptionTypes",Justification="The exception is recorded as ErrorMessages.")]privatestaticvoidGenerateSamples(HelpPageApiModelapiModel,HelpPageSampleGeneratorsampleGenerator){try{foreach(variteminsampleGenerator.GetSampleRequests(apiModel.ApiDescription)){apiModel.SampleRequests.Add(item.Key,item.Value);LogInvalidSampleAsError(apiModel,item.Value);}foreach(variteminsampleGenerator.GetSampleResponses(apiModel.ApiDescription)){apiModel.SampleResponses.Add(item.Key,item.Value);LogInvalidSampleAsError(apiModel,item.Value);}}catch(Exceptione){apiModel.ErrorMessages.Add(String.Format(CultureInfo.CurrentCulture,"An exception has occurred while generating the sample. Exception message: {0}",HelpPageSampleGenerator.UnwrapException(e).Message));}}privatestaticboolTryGetResourceParameter(ApiDescriptionapiDescription,HttpConfigurationconfig,outApiParameterDescriptionparameterDescription,outTyperesourceType){parameterDescription=apiDescription.ParameterDescriptions.FirstOrDefault(p=>p.Source==ApiParameterSource.FromBody||(p.ParameterDescriptor!=null&&p.ParameterDescriptor.ParameterType==typeof(HttpRequestMessage)));if(parameterDescription==null){resourceType=null;returnfalse;}resourceType=parameterDescription.ParameterDescriptor.ParameterType;if(resourceType==typeof(HttpRequestMessage)){HelpPageSampleGeneratorsampleGenerator=config.GetHelpPageSampleGenerator();resourceType=sampleGenerator.ResolveHttpRequestMessageType(apiDescription);}if(resourceType==null){parameterDescription=null;returnfalse;}returntrue;}privatestaticModelDescriptionGeneratorInitializeModelDescriptionGenerator(HttpConfigurationconfig){ModelDescriptionGeneratormodelGenerator=newModelDescriptionGenerator(config);Collection<ApiDescription>apis=config.Services.GetApiExplorer().ApiDescriptions;foreach(ApiDescriptionapiinapis){ApiParameterDescriptionparameterDescription;TypeparameterType;if(TryGetResourceParameter(api,config,outparameterDescription,outparameterType)){modelGenerator.GetOrCreateModelDescription(parameterType);}}returnmodelGenerator;}privatestaticvoidLogInvalidSampleAsError(HelpPageApiModelapiModel,objectsample){InvalidSampleinvalidSample=sampleasInvalidSample;if(invalidSample!=null){apiModel.ErrorMessages.Add(invalidSample.ErrorMessage);}}}}