@@ -84,7 +84,7 @@ public VersionedApiExplorer( HttpConfiguration configuration )
8484 /// <value>The <see cref="IDocumentationProvider">documentation provider</see> used to document APIs.</value>
8585 public IDocumentationProvider DocumentationProvider
8686 {
87- get => documentationProvider ?? Configuration . Services . GetDocumentationProvider ( ) ;
87+ get => documentationProvider ?? ( documentationProvider = Configuration . Services . GetDocumentationProvider ( ) ) ;
8888 set => documentationProvider = value ;
8989 }
9090
@@ -258,7 +258,7 @@ protected virtual ApiDescriptionGroupCollection InitializeApiDescriptions()
258258 var directRouteController = GetDirectRouteController ( directRouteCandidates , apiVersion ) ;
259259 var apiDescriptionGroup = newApiDescriptions . GetOrAdd ( apiVersion , GetGroupName ) ;
260260 var descriptionsFromRoute = ( directRouteController != null && directRouteCandidates != null ) ?
261- ExploreDirectRoute ( directRouteController , directRouteCandidates , route , apiVersion ) :
261+ ExploreDirectRouteControllers ( directRouteController , directRouteCandidates . Select ( c => c . ActionDescriptor ) . ToArray ( ) , route , apiVersion ) :
262262 ExploreRouteControllers ( controllerMappings , route , apiVersion ) ;
263263
264264 // Remove ApiDescription that will lead to ambiguous action matching.
@@ -532,12 +532,24 @@ static HttpControllerDescriptor GetDirectRouteController( CandidateAction[] dire
532532 return controllerDescriptor ;
533533 }
534534
535- Collection < VersionedApiDescription > ExploreDirectRoute ( HttpControllerDescriptor controllerDescriptor , CandidateAction [ ] candidates , IHttpRoute route , ApiVersion apiVersion )
535+ /// <summary>
536+ /// Explores a controller that uses direct routes (aka "attribute" routing).
537+ /// </summary>
538+ /// <param name="controllerDescriptor">The <see cref="HttpControllerDescriptor">controller</see> to explore.</param>
539+ /// <param name="candidateActionDescriptors">The <see cref="IReadOnlyList{T}">read-only list</see> of candidate <see cref="HttpActionDescriptor">actions</see> to explore.</param>
540+ /// <param name="route">The <see cref="IHttpRoute">route</see> to explore.</param>
541+ /// <param name="apiVersion">The <see cref="ApiVersion">API version</see> to explore.</param>
542+ /// <returns>The <see cref="Collection{T}">collection</see> of discovered <see cref="VersionedApiDescription">API descriptions</see>.</returns>
543+ protected virtual Collection < VersionedApiDescription > ExploreDirectRouteControllers (
544+ HttpControllerDescriptor controllerDescriptor ,
545+ IReadOnlyList < HttpActionDescriptor > candidateActionDescriptors ,
546+ IHttpRoute route ,
547+ ApiVersion apiVersion )
536548 {
537- Contract . Requires ( controllerDescriptor != null ) ;
538- Contract . Requires ( candidates != null ) ;
539- Contract . Requires ( route != null ) ;
540- Contract . Requires ( apiVersion != null ) ;
549+ Arg . NotNull ( controllerDescriptor , nameof ( controllerDescriptor ) ) ;
550+ Arg . NotNull ( candidateActionDescriptors , nameof ( candidateActionDescriptors ) ) ;
551+ Arg . NotNull ( route , nameof ( route ) ) ;
552+ Arg . NotNull ( apiVersion , nameof ( apiVersion ) ) ;
541553 Contract . Ensures ( Contract . Result < Collection < VersionedApiDescription > > ( ) != null ) ;
542554
543555 var descriptions = new Collection < VersionedApiDescription > ( ) ;
@@ -547,9 +559,8 @@ Collection<VersionedApiDescription> ExploreDirectRoute( HttpControllerDescriptor
547559 return descriptions ;
548560 }
549561
550- foreach ( var action in candidates )
562+ foreach ( var actionDescriptor in candidateActionDescriptors )
551563 {
552- var actionDescriptor = action . ActionDescriptor ;
553564 var actionName = actionDescriptor . ActionName ;
554565
555566 if ( ! ShouldExploreAction ( actionName , actionDescriptor , route , apiVersion ) )
@@ -571,11 +582,18 @@ Collection<VersionedApiDescription> ExploreDirectRoute( HttpControllerDescriptor
571582 return descriptions ;
572583 }
573584
574- Collection < VersionedApiDescription > ExploreRouteControllers ( IDictionary < string , HttpControllerDescriptor > controllerMappings , IHttpRoute route , ApiVersion apiVersion )
585+ /// <summary>
586+ /// Explores controllers that do not use direct routes (aka "attribute" routing)
587+ /// </summary>
588+ /// <param name="controllerMappings">The <see cref="IDictionary{TKey, TValue}">collection</see> of controller mappings.</param>
589+ /// <param name="route">The <see cref="IHttpRoute">route</see> to explore.</param>
590+ /// <param name="apiVersion">The <see cref="ApiVersion">API version</see> to explore.</param>
591+ /// <returns>The <see cref="Collection{T}">collection</see> of discovered <see cref="VersionedApiDescription">API descriptions</see>.</returns>
592+ protected virtual Collection < VersionedApiDescription > ExploreRouteControllers ( IDictionary < string , HttpControllerDescriptor > controllerMappings , IHttpRoute route , ApiVersion apiVersion )
575593 {
576- Contract . Requires ( controllerMappings != null ) ;
577- Contract . Requires ( route != null ) ;
578- Contract . Requires ( apiVersion != null ) ;
594+ Arg . NotNull ( controllerMappings , nameof ( controllerMappings ) ) ;
595+ Arg . NotNull ( route , nameof ( route ) ) ;
596+ Arg . NotNull ( apiVersion , nameof ( apiVersion ) ) ;
579597 Contract . Ensures ( Contract . Result < Collection < VersionedApiDescription > > ( ) != null ) ;
580598
581599 var apiDescriptions = new Collection < VersionedApiDescription > ( ) ;
@@ -706,7 +724,6 @@ void PopulateActionDescriptions(
706724 Contract . Requires ( apiDescriptions != null ) ;
707725 Contract . Requires ( apiVersion != null ) ;
708726
709- var apiDocumentation = DocumentationProvider ? . GetResponseDocumentation ( actionDescriptor ) ;
710727 var parsedRoute = RouteParser . Parse ( localPath ) ;
711728 var parameterDescriptions = CreateParameterDescriptions ( actionDescriptor , parsedRoute , route . Defaults ) ;
712729
@@ -715,14 +732,17 @@ void PopulateActionDescriptions(
715732 return ;
716733 }
717734
735+ var documentation = DocumentationProvider ? . GetDocumentation ( actionDescriptor ) ;
718736 var bodyParameter = parameterDescriptions . FirstOrDefault ( description => description . Source == FromBody ) ;
719- var supportedRequestBodyFormatters = bodyParameter != null ?
737+ var supportedRequestBodyFormatters =
738+ bodyParameter != null ?
720739 Configuration . Formatters . Where ( f => f . CanReadType ( bodyParameter . ParameterDescriptor . ParameterType ) ) :
721740 Enumerable . Empty < MediaTypeFormatter > ( ) ;
722741
723742 var responseDescription = CreateResponseDescription ( actionDescriptor ) ;
724743 var returnType = responseDescription . ResponseType ?? responseDescription . DeclaredType ;
725- var supportedResponseFormatters = ( returnType != null && returnType != typeof ( void ) ) ?
744+ var supportedResponseFormatters =
745+ ( returnType != null && returnType != typeof ( void ) ) ?
726746 Configuration . Formatters . Where ( f => f . CanWriteType ( returnType ) ) :
727747 Enumerable . Empty < MediaTypeFormatter > ( ) ;
728748
@@ -736,7 +756,7 @@ void PopulateActionDescriptions(
736756 {
737757 var apiDescription = new VersionedApiDescription ( )
738758 {
739- Documentation = apiDocumentation ,
759+ Documentation = documentation ,
740760 HttpMethod = method ,
741761 RelativePath = finalPath ,
742762 ActionDescriptor = actionDescriptor ,
@@ -753,9 +773,14 @@ void PopulateActionDescriptions(
753773 }
754774 }
755775
756- ResponseDescription CreateResponseDescription ( HttpActionDescriptor actionDescriptor )
776+ /// <summary>
777+ /// Creates a description for the response of the action.
778+ /// </summary>
779+ /// <param name="actionDescriptor">The <see cref="HttpActionDescriptor">action</see> to create a response description for.</param>
780+ /// <returns>A new <see cref="ResponseDescription">response description</see>.</returns>
781+ protected virtual ResponseDescription CreateResponseDescription ( HttpActionDescriptor actionDescriptor )
757782 {
758- Contract . Requires ( actionDescriptor != null ) ;
783+ Arg . NotNull ( actionDescriptor , nameof ( actionDescriptor ) ) ;
759784 Contract . Ensures ( Contract . Result < ResponseDescription > ( ) != null ) ;
760785
761786 var responseType = actionDescriptor . GetCustomAttributes < ResponseTypeAttribute > ( ) . FirstOrDefault ( ) ? . ResponseType ;
@@ -857,7 +882,7 @@ IList<ApiParameterDescription> CreateParameterDescriptions( HttpActionDescriptor
857882 {
858883 foreach ( var parameter in parameters )
859884 {
860- parameterDescriptions . Add ( CreateParameterDescriptionFromDescriptor ( parameter ) ) ;
885+ parameterDescriptions . Add ( CreateParameterDescription ( parameter ) ) ;
861886 }
862887 }
863888 }
@@ -894,16 +919,21 @@ static void AddUndeclaredRouteParameters( IParsedRoute parsedRoute, IDictionary<
894919 }
895920 }
896921
897- ApiParameterDescription CreateParameterDescriptionFromDescriptor ( HttpParameterDescriptor parameter )
922+ /// <summary>
923+ /// Creates a parameter description from the speicfied descriptor.
924+ /// </summary>
925+ /// <param name="parameterDescriptor">The <see cref="HttpParameterDescriptor">parameter descriptor</see> to create a description from.</param>
926+ /// <returns>A new <see cref="ApiParameterDescription">parameter description</see>.</returns>
927+ protected virtual ApiParameterDescription CreateParameterDescription ( HttpParameterDescriptor parameterDescriptor )
898928 {
899- Contract . Requires ( parameter != null ) ;
929+ Arg . NotNull ( parameterDescriptor , nameof ( parameterDescriptor ) ) ;
900930 Contract . Ensures ( Contract . Result < ApiParameterDescription > ( ) != null ) ;
901931
902932 return new ApiParameterDescription ( )
903933 {
904- ParameterDescriptor = parameter ,
905- Name = parameter . Prefix ?? parameter . ParameterName ,
906- Documentation = DocumentationProvider ? . GetDocumentation ( parameter ) ,
934+ ParameterDescriptor = parameterDescriptor ,
935+ Name = parameterDescriptor . Prefix ?? parameterDescriptor . ParameterName ,
936+ Documentation = DocumentationProvider ? . GetDocumentation ( parameterDescriptor ) ,
907937 Source = Unknown ,
908938 } ;
909939 }
@@ -913,7 +943,7 @@ ApiParameterDescription CreateParameterDescriptionFromBinding( HttpParameterBind
913943 Contract . Requires ( parameterBinding != null ) ;
914944 Contract . Ensures ( Contract . Result < ApiParameterDescription > ( ) != null ) ;
915945
916- var parameterDescription = CreateParameterDescriptionFromDescriptor ( parameterBinding . Descriptor ) ;
946+ var parameterDescription = CreateParameterDescription ( parameterBinding . Descriptor ) ;
917947
918948 if ( parameterBinding . WillReadBody )
919949 {
@@ -927,10 +957,6 @@ ApiParameterDescription CreateParameterDescriptionFromBinding( HttpParameterBind
927957 return parameterDescription ;
928958 }
929959
930- string GetApiDocumentation ( HttpActionDescriptor actionDescriptor ) => DocumentationProvider ? . GetDocumentation ( actionDescriptor ) ;
931-
932- string GetApiResponseDocumentation ( HttpActionDescriptor actionDescriptor ) => DocumentationProvider ? . GetResponseDocumentation ( actionDescriptor ) ;
933-
934960 static Collection < VersionedApiDescription > RemoveInvalidApiDescriptions ( Collection < VersionedApiDescription > apiDescriptions )
935961 {
936962 Contract . Requires ( apiDescriptions != null ) ;
0 commit comments