M. Ozn
M. Ozn

Reputation: 1220

Create a custom ControllerAttribute with a standardized RoutingAttribute nested in

On the top of every of my controllers, I have these attributes :

[Route("api/[controller]")]
[ApiController]
[Produces("application/json")]

I'm trying to merge them, and to add a notion of "version" to the controller.

For example, if my api evolves, I don't want all my applications to crash because of a breaking change. So I want the route to be /api/v1/[controller] and if I update it, I'll create a new controller with a /api/v2/[controller] route. Both routes will be available at the same time, and I would be able to progressively update my applications to connect to the v2 of the api without any crash.

So here is the code I'm working on :

[Route($"api/v{ApiVersion}/[controller]")]
[Produces("application/json")]
public class ExtendedApiControllerAttribute : ApiControllerAttribute
{
    public string ApiVersion { get; set; }

    public ExtendedApiControllerAttribute(string apiVersion): base()
    {
        ApiVersion = apiVersion;
    }
}

But I'm facing a bunch of problems.

First, I can't reference the ApiVersion field as easily as I wanted to. I get this error :

An object reference is required for the non-static field, method, or property 'ExtendedApiControllerAttribute.ApiVersion'

But even if I just ignore the "versioning" system, and switch to the simple Routing system [Route("api/[controller]")] on the ExtendedAttribute, the controller isn't accessible. I get a 404 error when I try to go on the corresponding endpoint (even if it still being available through Swagger).

How can I merge these functionalities in one unique Attribute like this one : [ExtendedApiController("1")] ?

Upvotes: 0

Views: 79

Answers (1)

Zhi Lv
Zhi Lv

Reputation: 21383

Generally, to version ASP.NET Core Web API, we could use the Microsoft.AspNetCore.Mvc.Versioning package. You can refer to the following steps:

  1. Install the Microsoft.AspNetCore.Mvc.Versioning package via NuGet.

  2. Register the ReportApiVersions service in the ConfigureServices method (in asp.net 5, if you are using Asp.net 6, you can add it in the Program.cs file).

     public void ConfigureServices(IServiceCollection services)
     {
    
         services.AddControllers();
         services.AddApiVersioning(x =>
         {
             x.DefaultApiVersion = new ApiVersion(1, 0);
             x.AssumeDefaultVersionWhenUnspecified = true;
             x.ReportApiVersions = true;
         });
         services.AddSwaggerGen(c =>
         {
             c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebAPIService", Version = "v1" });
         });
     }
    
  3. Then, we can do versioning of Web API using the following methods: Query string, ​URL and HTTP header.

    From your description, you want to set the version via URL, if that is the case, you can add the route attribute as below:

     [ApiVersion("1.0")]
     [Route("api/{v:apiVersion}/todoV1")]
     [ApiController]
     public class TodoV1Controller : ControllerBase
     {
         //...
     }
    

Then, the request url as below:

enter image description here

More detail information, refer to this article:API Versioning in ASP.NET Core

Upvotes: 1

Related Questions