4

I would like to create a separate help page for each version of my API. For example, the user could go to /help?v=1 to see version 1.0 routes and /help?v=2 to see version 2.0 routes.

Using SDammann.WebApi.Versioning, I added a Version property to VersionedApiExplorer that will return only the routes for the defined version and added the version as an argument to the constructor. Then I tried this:

config.Services.Add(typeof(IApiExplorer), new VersionedApiExplorer(config, "1"));
config.Services.Add(typeof(IApiExplorer), new VersionedApiExplorer(config, "2"));

But this gives me the following error:

The service type IApiExplorer is not supported.
Parameter name: serviceType

I added just one instance of the service - config.Services.Replace(typeof(IApiExplorer), new VersionedApiExplorer(GlobalConfiguration.Configuration, "1")); - to get the configuration to work, so I could test my help controller. Then tried this:

foreach (var service in Configuration.Services.GetServices(typeof(IApiExplorer))) {
    if (service.GetType() != typeof(VersionedApiExplorer)) continue;

    var explorer = service as VersionedApiExplorer;
    if (explorer.Version == v) {
        apiExplorer = explorer;
    }
}

This gives the same error I received above. I know I would normally use this.Configuration.Services.GetApiExplorer() but I don't know how I could use that to get the appropriate instance of VersionedApiExplorer. I know I could instantiate the appropriate ApiExplorer directly in the controller, but I would prefer to keep that in my configuration file if possible.

So I have two questions:

  1. How could I add two services of type VersionedApiExplorer to my config object?
  2. How would I retrieve the appropriate service in my help controller?

Or is there a completely different approach I could take to accomplish the same goal?

Thank you!

Irving
  • 1,257
  • 2
  • 16
  • 28
  • Hi, I don't suppose you ever worked this out? I'm looking to do similar. – SteveA Jul 21 '15 at 15:08
  • I have a working solution, but I'm not very happy with it. I basically did what I described in this question. I modified `VersionedApiExplorer` to accept a version number, and set the appropriate version number in my `HelpController`. I can go into more details if you would find that helpful. – Irving Jul 22 '15 at 13:51
  • That would be great. It would be worthwhile answering your own question for future visitors too. – SteveA Jul 23 '15 at 11:54
  • Posted it. Hope that helps. – Irving Jul 25 '15 at 01:55

1 Answers1

0

I ultimately ended up going with the solution I hinted at in my question. I feel like there's a better solution to this problem, but this gets the job done.

First, I added a Version property to VersionedApiExplorer:

public string Version { get; private set; } 

Then I modified InitializeApiDescriptions to look like this:

private Collection<ApiDescription> InitializeApiDescriptions()
{
    Collection<ApiDescription> apiDescriptions = new Collection<ApiDescription>();
    var controllerSelector = configuration.Services.GetHttpControllerSelector();
    IDictionary<string, HttpControllerDescriptor> allControllerMappings = controllerSelector.GetControllerMapping();
    IDictionary<string, HttpControllerDescriptor> controllerMappings = new Dictionary<string, HttpControllerDescriptor>();
    // get only mappings for defined version
    if (allControllerMappings != null && Version != null) {
        foreach (var key in allControllerMappings.Keys) {
            if (key.Substring(0, key.IndexOf('.')) == VersionedControllerSelector.VersionPrefix + Version) {
                controllerMappings.Add(key, allControllerMappings[key]);
            }
        }
    }
    else if (Version == null) {
        controllerMappings = allControllerMappings;
    }

    if (controllerMappings != null)
    {
        foreach (var route in configuration.Routes)
            ExploreRouteControllers(controllerMappings, route, apiDescriptions);
    }
    return apiDescriptions;
}

I also added a method I could use to set the Version:

public void SetVersion(string version) {
    this.Version = version;
    this.apiDescription = new Lazy<Collection<ApiDescription>>(InitializeApiDescriptions);
}

Finally, I modified my HelpController to looks like this:

public ActionResult Index(string v) {
    return this.View(GetApiExplorer(v).ApiDescriptions);
}

private IApiExplorer GetApiExplorer(string version) {
    if (version == null) {
        version = "1";
    }

    var apiExplorer = this.Configuration.Services.GetApiExplorer() as VersionedApiExplorer;
    if (apiExplorer != null) {
        apiExplorer.SetVersion(version);
    }

    return apiExplorer;
}
Irving
  • 1,257
  • 2
  • 16
  • 28