27

I have a basic WebApi implementation setup with the default Values controller.

After reading a blog about RESTful WebApi Versioning I decided to integrate the package into a new WebApi project.

I've added the NuGet package Microsoft.AspNet.WebApi.Versioning to assist with the versioning of my API. Here is the URL to the packages configuration instructions that I am following:

https://github.com/Microsoft/aspnet-api-versioning/wiki/Configuring-Your-Application

My values controller is very straightforward. I've added the decoration to my Get method. Here is the code:

[Authorize]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/values")]
public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
    
    public string Get(int id)
    {
        return "value";
    }

    // POST api/values
    public void Post([FromBody]string value)
    {
    }

    // PUT api/values/5
    public void Put(int id, [FromBody]string value)
    {
    }

    // DELETE api/values/5
    public void Delete(int id)
    {
    }
}

Unfortunately, as soon as I add the following line of code to the controller the whole thing blows up:

[Route("api/v{version:apiVersion}/values")]

Here is a peek at the error message that is being returned:

The inline constraint resolver of type 'DefaultInlineConstraintResolver' was unable to resolve the following inline constraint: 'apiVersion'. 

Line 82:             GlobalConfiguration.Configure(WebApiConfig.Register);

Here is the code I have inside of my Startup.cs

public void Configuration(IAppBuilder app)
{
    // HTTP Configuration
    HttpConfiguration config = new HttpConfiguration();
    //config.MapHttpAttributeRoutes();

    // Configure API Versioning
    config.AddApiVersioning();
    var constraintResolver = new DefaultInlineConstraintResolver()
    {
        ConstraintMap =
        {
            ["apiVersion"] = typeof( ApiVersionRouteConstraint ) // or mvc routing?
        }
    };
    config.MapHttpAttributeRoutes(constraintResolver);   

    // Configure the API to accept token authentication
    ConfigureOAuthTokenConsumption(app);

    // CORS
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

    // Configure the Authorization server
    ConfigureOAuth(app);

    // Use WebAPI
    app.UseWebApi(config);

    // Moved from global.asax
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

I thought that calling AddApiVersioning and supplying the constraintResolver as outlined in the documentation would fix the issue, but it did not. Now I am struggling with what to do next.

config.AddApiVersioning();
var constraintResolver = new DefaultInlineConstraintResolver()
{
    ConstraintMap =
    {
        ["apiVersion"] = typeof( ApiVersionRouteConstraint ) // or mvc routing?
    }
};
config.MapHttpAttributeRoutes(constraintResolver);

Any suggestions?

Ciarán Bruen
  • 5,221
  • 13
  • 59
  • 69
Zoop
  • 872
  • 3
  • 11
  • 24

2 Answers2

32

You should resolve the version in WebApiConfig.cs file

     var constraintResolver = new DefaultInlineConstraintResolver()
        {
            ConstraintMap =
            {
                ["apiVersion"] = typeof( ApiVersionRouteConstraint ) 
            }
        };
        config.MapHttpAttributeRoutes(constraintResolver); 

before mapping the routes. I mean before config.Routes.MapHttpRoute()

Champ
  • 690
  • 1
  • 7
  • 13
  • There is no WebApiConfig.cs, I am using the OWIN startup.cs class, and the constraint resolver is being set before mapping any routes. – Zoop Sep 08 '17 at 13:07
  • 1
    You must be having ConfigureAuth(app); in [assembly: OwinStartup(typeof(Owin.Startup))] class, You can go to that class and inject above code by adding Microsoft.AspNet.WebApi.Versioning nuget. – Champ Sep 18 '17 at 09:15
  • You are correct, now I just need to try to figure out how to get Swagger to recognize the routes as well. Thanks for the answer! – Zoop Oct 09 '17 at 15:12
0

I got this error when Type as declared as string. When I changed that to int it started working. If you pass the data in string format in route the don't use string datatype just write name of variable in {}.

Demo available in this video https://youtu.be/Bc-z9l4HP7Y

  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 05 '22 at 06:19