3

I created one web API application with versioning. I am going to use Microsoft.AspNet.WebApi.Versioning package to do that.

Webapi configuration:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.AddApiVersioning(o => {
            o.AssumeDefaultVersionWhenUnspecified = true;
        });
        // Web API routes
        config.MapHttpAttributeRoutes();

    }
}

Here my assumption is if I didn't pass the version, by default it will select version 1.

Controller code:

[ApiVersion("1.0")]
[RoutePrefix("api/users")]
public class UserV1Controller : BaseController
{
    public UserV1Controller()
    {
    }

    [Route("all", Name = "UsersCollection")]
    public async Task<IHttpActionResult> GetAll()
    {
        var items = await UnitOfWork.Users.GetPaged(x => x.OrderBy(y => y.Id), 1, 20);
        //Add mapping to DTO 
        return Ok(items);
    }

}

If I test with http://localhost:10280/api/users/all?api-version=1.0 URL, it working fine. I am going to implement this feature in the existing project.

For backward compatibility, I tried http://localhost:10280/api/users/all URL. It gives me the following error with 500 as the status code.

{ "Message": "An error has occurred.",
"ExceptionMessage": "The index cannot be less than 0 or equal to or larger than the number of items in the collection.\r\n
Parameter name: index\r\nActual value was 0.",
"ExceptionType": "System.ArgumentOutOfRangeException",
"StackTrace": " at
System.Web.Http.WebHost.Routing.HostedHttpRouteCollection.get_Item(Int32 index)\r\n at Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.GetControllerName(HttpRequestMessage request)\r\n at Microsoft.Web.Http.Dispatcher.ControllerSelectionContext.<>c__DisplayClass6_0.<.ctor>b__0()\r\n at System.Lazy1.CreateValue()\r\n at System.Lazy1.LazyInitValue()\r\n at System.Lazy`1.get_Value()\r\n
at Microsoft.Web.Http.Dispatcher.ConventionRouteControllerSelector.SelectController(ControllerSelectionContext context)\r\n at Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.SelectController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext()" }


Update 1:

After discussions and a bit of help, I can confirm that this default version works with conventional routing.

The issue reproduced while using attribute routing. Please check my updated code.

  1. I don't have any default API routing in the WebAPIConfig file.
  2. I update Route Prefix and Route in the controller

Now the issue reproduced.

You can also reproduce the issue with combining conventional and attribute.

Update 2:

Now I noticed that the issue lies in the configuration. If I add the routing configurations in the Owin startup class directly it working fine. 

    public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        var configuration = new System.Web.Http.HttpConfiguration();
        var httpServer = new System.Web.Http.HttpServer(configuration);

        // reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
        configuration.AddApiVersioning(options =>
        {
            options.ReportApiVersions = true;
            options.AssumeDefaultVersionWhenUnspecified = true;
        });
        configuration.MapHttpAttributeRoutes();
        app.UseWebApi(httpServer);

    }
}

It creates new HttpConfiugration other than using our existing WebAPIConfig class. So I don't know it may impact any other functionalities

So if i configure Owin to use webaPI instead of GlobalConfiguration.Configure(WebApiConfig.Register) in the Global.asax, it iw working fine.

8
  • This is the route config for mvc. We need the route config for your webapi. this is most likely located in the WebApiConfig.cs if not changed Commented Jan 2, 2019 at 9:11
  • ok. So only I confused. Actually, I removed that default route lines as I configured only for attribute routing. I updated now. Sorry if I confused you. Commented Jan 2, 2019 at 9:14
  • Na. It's ok. Your route config seems ok. I can now safely reproduce your error. Now let's just find a solution for it Commented Jan 2, 2019 at 9:27
  • ok, thanks. I tried all the ways specified. If not got anything seems like go ahead by extending ControllerSelector Commented Jan 2, 2019 at 9:32
  • Is there a controller using version 2, that has the same routeprefix? e.g. [RoutePrefix("api/users")]? because this is causing your error in my local project. If I delete the second controller or its routeprefix, the error goes away. This is only natural, since there cannot be 2 identical routes for 2 different controllers. Commented Jan 2, 2019 at 9:47

3 Answers 3

3

If you do not specify a version it is considered unversioned. In this case you have to set the AssumeDefaultVersionWhenUnspecified property, which if not told otherwise, assumes a default version of "1.0", if none is specified:

config.AddApiVersioning(o => {
    o.AssumeDefaultVersionWhenUnspecified = true;
});

This functionality is documented here: https://github.com/Microsoft/aspnet-api-versioning/wiki/Existing-Services-Quick-Start

Sign up to request clarification or add additional context in comments.

5 Comments

no. I can access if i provide the api version explicitly. I also tried the same sample specified in the documentation but same error. Any other configuration?
my fault, please edit your question with your route config. I can recreate your error by adding the [Route] decorator on an action method.
Your route config is still missing from your question
I added the route.config file code. As this is API only I think we don't care about route.config. correct? I just care only in webApiConfig file
Now I updated with my latest findings. But I don't know why it happened like that
2

This is a confirmed bug that only occurs when hosting on a vanilla IIS implementation (e.g. non-OWIN). Despite the HttpRouteCollection having an indexer, the HostedHttpRouteCollection defined by System.Web does not support it. Instead of throwing NotSupportedException, a generic ArgumentOutOfRangeException is thrown.

For more details see: https://github.com/Microsoft/aspnet-api-versioning/issues/428.

The fix is in and is now available in package version 3.0.1.

1 Comment

Thanks. Working as expected in version 3.0.1
0

You can try setting up the default version number and configure middleware to use it when version number is not specified.

Reference: Scott's blog on routing

services.AddApiVersioning(
    o =>
    {
        o.AssumeDefaultVersionWhenUnspecified = true );
        o.DefaultApiVersion = new ApiVersion("1.0");
    } );

2 Comments

That won't work, since his routes do not use DateTimes as version attributes. A suitable overload would have been new ApiVersion(1,0)
thanks. but that is not the issue. I think this is related to routing. This issue reproduced when I use RoutePrefix and Route attributes only. I mean Attribute routing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.