Cyr
Cyr

Reputation: 501

asp.net WebApi ApiVersionUnspecified return error

I have used WebApi for some years but now it seems doesn't work. In a recent asp.net .NET Framework project I have added WebApi to existing MVC solution. I am using the nuget package Microsoft.AspNet.WebApi.Versioning 3.0.1

The app configuration is below:
Global.asax

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

WebApiConfig.cs

public static void Register(HttpConfiguration config)
{
    var constraintResolver = new DefaultInlineConstraintResolver()
        {
            ConstraintMap =
            {
                ["apiVersion"] = typeof( ApiVersionRouteConstraint )
            }
        };
    config.MapHttpAttributeRoutes(constraintResolver);
    config.AddApiVersioning();


   //config.MapHttpAttributeRoutes(); //commented due to route versioning

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{version}/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

the API controller is in folder /Controller/v1/MyControllerAPI.cs

MyControllerAPI.cs

namespace MyProject.Controllers
{

    [AllowAnonymous]
    [ApiVersion("1")]
    [RoutePrefix("api/v{version:apiVersion}/MyControllerAPI")]
    public class MyControllerAPI : ApiController
    {

        private ApplicationDbContext db = new ApplicationDbContext();


        [HttpGet]
        [Route("GetMonthly")]
        public IQueryable<Monthly> GetMonthly()
        {
            return db.Monthly;
        }
    }
}

using Postman calling a GET api: https://localhost:44377/api/v1/MyControllerAPI/GetMonthly

it returns this error:

{
    "Error": {
        "Code": "ApiVersionUnspecified",
        "Message": "An API version is required, but was not specified."
    }
}

What's wrong in my configuration? I am quietly sure to have used a similar configuration in the past and it worked.

Upvotes: 2

Views: 2803

Answers (2)

ukie
ukie

Reputation: 318

Maybe this will help somebody else. I was also getting the same error, but in Postman:

{
"error": {
    "code": "ApiVersionUnspecified",
    "message": "An API version is required, but was not specified.",
    "innerError": null
}

}

I was able to get it to work by unchecking the default Accept header, and adding my own in the following format application/json;v=1.0

Get Postman to not throw "ApiVersionUnspecified" error

Upvotes: 0

MFARKAN
MFARKAN

Reputation: 226

I have double HomeController like that ;

 [Authorize]
[ApiVersion("1.0")]
public class HomeController : BaseApiController
{
    private ILogger _logger;
    public HomeController(ILogger logger) : base(logger)
    {
        this._logger = logger;
    }
    // GET api/<controller>
    public IEnumerable<string> Get()
    {

        return new string[] { "value1", "value2" };
    }

    // GET api/<controller>/5
    public string Get(int id)
    {
        return "value";
    }

    // POST api/<controller>
    public void Post([FromBody]string value)
    {
    }

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

    // DELETE api/<controller>/5
    public void Delete(int id)
    {
    }
}

And Version 2.0 just like that ;

[Authorize]
[ApiVersion("2.0")]
public class HomeController : BaseApiController
{
    private ILogger _logger;
    public HomeController(ILogger logger) : base(logger)
    {
        this._logger = logger;
    }
    public IEnumerable<string> Get()
    {

        return new string[] { "value2.0", "value3.0" };
    }

    // GET api/<controller>/5
    public string Get(int id)
    {
        return "value";
    }

    // POST api/<controller>
    public void Post([FromBody]string value)
    {
    }

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

    // DELETE api/<controller>/5
    public void Delete(int id)
    {
    }
}

Im using Swashbuckle and adding some IOperationFilter to change parameters or versioning parameter's set default value to apiVersion ;

public class SwaggerAuthTokenHeaderParameter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        operation.deprecated |= apiDescription.IsDeprecated();

        if (operation.parameters == null)
        {
            return;
        }

        if (operation.parameters != null)
        {

            foreach (var parameter in operation.parameters)
            {
                var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.name);
                if (parameter.description == null)
                {
                    parameter.description = description.Documentation;
                }
                if (parameter.@default == null)
                {
                    parameter.@default = description.ParameterDescriptor?.DefaultValue;
                }
            }

            operation.parameters.Add(new Parameter
            {
                name = "Authorization",
                @in = "header",
                @default = "Bearer ",
                description = "Access token for the API",
                required = false,
                type = "string"
            });
        }
    }
}

Or you look my github repo for ApiVersioning and more features with it :) API Repo

Upvotes: 0

Related Questions