-
Notifications
You must be signed in to change notification settings - Fork 712
Web API Help Page - method paths and controllers grouping #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
You're on the right path. Unfortunately, the model in Web API makes things more complicated than they ought to be for creating API documentation. The design of Web API doesn't support multiple controller types per route and, hence, doesn't directly support enumerating the associated HttpControllerDescriptor and HttpControllerActionDescriptor instances. All is not lost. In order to make things work in Web API, the descriptors themselves are aggregated together in a custom HttpControllerDescriptorGroup. Working with an aggregated HttpControllerDescriptor is a little awkward, but it's the only thing I could come up with that didn't break the model of the Web API design. I provided a pretty detailed explanation of how this information can be used in Issue #46. In that explanation, I would probably go with option 2. Once you have all the aggregated descriptors, you can aggregate the API version models together. There are built-in extension methods to achieve that. Since the version information is normally only aggregated during route evaluation, this is something you'll have to do yourself for documentation. This is also demonstrated in Issue #46. Using the aggregated API version model, you'll want to enumerate the SupportedApiVersions and DeprecatedApiVersions, if you want things separated; otherwise, you can just use the ImplementedApiVersions. The DeclaredApiVersions aren't useful for controller documentation because it's used for matching the controller types internally for dispatch; that's irrelevant for documentation. You might want to use the DeclaredApiVersions on actions if you have interleaving API versions. That will enable you to select which documentation applies to which version of an action. The ApiVersion class supports formatting. If you only want the major and minor version number displayed, you can simply use Finally, while you can substitute the replacement tokens in the URL template yourself, it might be easier and more reliable to use the UrlHelper class to generate the link for you. You just need to provide the version template parameter, which will enable the UrlHelper to create the link for you. It's really no different than if you were filling in the controller or id tokens. Hopefully that gets you where you want to go. Expanding the existing documentation support or at least providing end-to-end examples of how to compose the documentation yourself is definitely on the radar. Let me know if you need additional pointers. |
I'm not sure if i understand your explanation. Let's say that my controllers structure is grouped by namespace:
I did the changes in the WebApiConfig.cs as you explained in #46. Because i want to group my controllers by namespace the WebApiConfig.cs looks as bellow:
How can i then achieve the groups aggregated by namespace in the Index.cshtml and why still my model is returning only one route except of two for Hi2Controller? |
I guess I missed the tidbits about namespaces. Since the second version was named Hi2Controller, I assumed the controllers were in the same namespaces. If the controllers are in different namespaces, then I would keep the controller type names the same (e.g. HiController). This will make your documentation efforts easier. It seems I steered you slightly the wrong way. If you keep the names the same, then Option 1 from my suggestion will probably work better. The default controller name convention is XXXController, which is why you see two listed items for Hi and Hi2. I won't pretend that there's no work to be done here. There is no out-of-the-box support for the IApiExplorer (and help page) or Swagger - yet. I can point in you in the right direction and even take feedback, but for now, expect for there to be work on your side. Hopefully, some time in the not too distant future I'll have time or additional community support to provide included support or a complementary library. Since you're using the Help Page approach, you may want to have a look at the built-in, default implementation of ApiExplorer.cs if you haven't already. You may be able to extend it to suit your needs, but if not, at least it should provide a good foundation of where to start. The Help Page support does not account for different controller versions. As such, the first page should not list any routes or actions because they could be different between API versions. For example, you might add new routes, remove odd routes, or change some other part of an existing route - like a route parameter. I would suggest the first page only list the controller (e.g. service) names. The first click-through will take you to a details page that breaks things down by API version. Using a drop-down box seems like it would work well there. Based on the API version selected, you can then display the relevant API version-specific details. Here's how you might start: using static System.Diagnostics.Debug;
var controllerMapping = Configuration.Services.GetHttpControllerSelector().GetControllerMapping();
var actionSelector = Configuration.Services.GetActionSelector();
foreach ( var entry in controllerMapping )
{
// flatten controller mapping
var serviceName = entry.Key;
var controllerDescriptors = ( entry.Value as IEnumerable<HttpControllerDescriptor> )?.ToArray() ?? new[] { entry.Value };
var serviceVersionModel = controllerDescriptors.Select( cd => cd.GetApiVersionModel() ).Aggregate();
WriteLine( serviceName );
// document controller by api version
foreach ( var apiVersion in serviceVersionModel.ImplementedApiVersions )
{
var controllerDescriptor = controllerDescriptors.First( cd => cd.GetApiVersionModel().DeclaredApiVersions.Contains( apiVersion ) );
var actionMapping = actionSelector.GetActionMapping( controllerDescriptor );
var deprecated = controllerDescriptor.GetApiVersionModel().DeprecatedApiVersions.Contains( apiVersion );
WriteLine( " Version {0}{1}", apiVersion, deprecated ? " (Deprecated)" : "" );
WriteLine( " Actions" );
// filter actions supported by the current controller
foreach ( var actionDescriptor in from mapping in actionSelector.GetActionMapping( controllerDescriptor )
from descriptor in mapping
let declaredVersions = descriptor.GetApiVersionModel().DeclaredApiVersions
let implicitlyVersioned = !declaredVersions.Any()
where implicitlyVersioned || declaredVersions.Contains( apiVersion )
select descriptor )
{
WriteLine( $" {actionDescriptor.ActionName}" );
// TODO: document action parameters
}
}
} Figure 1: Enumerate controllers and actions by API version This example is based on the By Namespace Web API sample. The output will be:
Figure 2: Output from Figure 1 example Naturally, this is not a complete solution, but hopefully that helps you get closer to your goal. |
As you mentioned ApiExplorer.cs turned out to be helpful in this case. I added new class VersionedApiExplorer.cs which inherits from IApiExplorer interface and then replaced default ApiExplorer with my new VersionedApiExplorer in WebApiConfig.cs in the Register method. In several cases it generates more ApiDescriptions than actually exist. In the ApiGroup.cshtml I passed it by distinction apiGroup by GetFriendlyId() method. VersionedApiExplorer.cs
WebApiConfig.cs
ApiGroup.cshtml
|
Hi, let's assume that i have two versions of HiController. I'm versioning my services by using URL path. In the ApiGroup.cshtml file i'm replacing
{version}
with the value of ApiVersionAttribute in order to get paths like these:GET api/framework/{version}/hello
->GET api/framework/1/hello
. In the bellow configuration i'm expecting to get three paths but instead i'm getting only two. Is this a bug or misconfiguration? What's more, do you know how to group HiController and Hi2Controller in the one group "Hi"?Controllers:
WebApiConfig
ApiGroup.cshtml
The text was updated successfully, but these errors were encountered: