3

I have an ASP.NET Web API 2 application which uses convention-based routing:

[app-url]/v1/[controller]

Now, I want to add another version to the API, and found that attribute routing is the easiest way to achieve what I want. Therefore, I registered the Web API routes in the Application_Start() method as shown below.

GlobalConfiguration.Configure(WebApiConfig.Register);

Additionally, I made sure that the Register() method in the WebApiConfig class only contains the following line:

config.MapHttpAttributeRoutes();

There are two controllers to test the versioning:

/v1/StatusController.cs

[RoutePrefix("v1/status")]
public class StatusController : ApiController
{
    [Route("")]
    public string Get()
    {
        return "V1 - OK";
    }
}

/v2/StatusController.cs

[RoutePrefix("v2/status")]
public class StatusController : ApiController
{
    [Route("")]
    public string Get()
    {
        return "V2 - OK";
    }
}

However, when I navigate to either of the routes shown below, I receive an error.

  1. [app-url]/v1/status
  2. [app-url]/v2/status

SERVER ERROR

404 - File or directory not found.

The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.

6
  • 1
    How do you have two classes with the same name in your project? Commented Feb 13, 2019 at 10:51
  • 1
    They are under different namespaces. (Controllers.V1 and Controllers.V2) Commented Feb 13, 2019 at 10:52
  • 1
    Which URL do you access? Commented Feb 13, 2019 at 10:53
  • 2
    Rather than rely on manual routing, I would suggest you look at the Microsoft API versioning Nuget package. It is built to allow you to specify versions and is quite simple to use. Commented Feb 13, 2019 at 10:55
  • 1
    I tried that package, and I managed to get the versioning to work without too much work, and for this, I thank you. But, this is only a solution for the problem, not the solution for the attribute routing not working. Commented Feb 13, 2019 at 11:25

2 Answers 2

2

Your approach will not work because ASP.NET Web API uses a so-called Controller Selector to find the respective controller for a given route. This selector however, does not take into account the namespace of a controller, but rather uses its name.

By default, Web API ships with the DefaultHttpControllerSelector and you can find information on its implementation here.

A possible solution to your problem is to implement a custom IHttpControllerSelector and tell Web API to use it instead. For this you can find several examples on the internet.

Instead you can also change your controller names to be unique, e.g.:

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

2 Comments

Changing the controller names would cause truble with applications already using the API, because (to my understanding) the URL to each endpoint would be different. In this case the best approach indeed would be implementing my own controller selector.
For some reason I tought that the controller's name must be the same as the one's controller referenced in the URL. I'm relatively new to ASP.NET so some areas still cause some confusion. Thank you for clarifying this.
2

Instead of using different namespaces, use different controller names (if this works for you). If so, here is about how the code should look like:

/v1/StatusController.cs:

[System.Web.Http.RoutePrefix("v1/status")]
public class StatusController : ApiController
{
    [System.Web.Http.Route("")]
    public string Get()
    {
        return "V1 - OK";
    }
 }

/v2/StatusController.cs:

[System.Web.Http.RoutePrefix("v2/status")]
public class Status2Controller : ApiController
{
    [System.Web.Http.Route("")]
    public string Get()
    {
        return "V2 - OK";
    }
 }

Now you would be able to invoke these 2 different versions by calling the Http Get Method like:

Https://YourUrl.com/v1/status

and:

Https://YourUrl.com/v2/status

Hope this suggested alternative helps. Good luck.

3 Comments

The only problem with this solution is that it would change the URL to the endpoint, and that would break applications already using the API. (please correct me if I'm wrong)
The endpoints would be reached entirely by the defined route, so you would be ok in that case as well. For example: [System.Web.Http.Route("{id:int}")] would be reached by using using the Http Get Method with Https://YourUrl.com/v2/status/2. Looks like my example request Urls above didn't make it, so I'll see if I can edit my original answer to include that info as well. Does this answer your question?
So just to add to my prior comment to provide clarification, is your request Url was Https://YourUrl.com/v1/status/2, that would go to the "StatusController", whereas in the prior comment, that request Url of Https://YourUrl.com/v2/status/2 would go to the "Status2Controller". Hope this comment clarifies any potential confusion. Let me know.

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.