asp.net-coreaspnet-api-versioningaspnetzero

AspNetZero .NetCore + Angular project - api versioning


I have a AspNetZero .NetCore + Angular project and I need to implement api versioning to the project for backwards compatibility. I followed a few examples online, but they either don't specify all the steps, or are specific to mvc, and this project uses the AppService pattern. If any one has successfully managed to implement api versioning in a AspNetZero project, I would really appreciate your help.

I'm currently at the swagger page showing two version, but for v1, I get an AmbiguousMatchException and for v2 swagger can't find the v2 file, so I assume it's not getting generated.

In my Application project, I changed the current AppService's namespace to .v1, and created a new AppService with namespace v2, that inherits the old one, and overrides 1 method which will be the v2.

The aim is to be able to call both methods once it's done with i.e: (http://localhost:9901/api/services/app/Equities/Get_Snapshot or http://localhost:9901/api/services/v1/Equities/Get_Snapshot) and http://localhost:9901/api/services/v2/Equities/Get_Snapshot


Solution

    1. Open Startup.cs in YOURCOMPANY.Web.Host project.

    2. In the ConfigureServices method, scroll down and find services.AddSwaggerGen ...

    3. Implement the following code:

          services.AddSwaggerGen(options =>
          {
              options.SwaggerDoc("v1", new OpenApiInfo()
              {
                  Title = "MY API",
                  Version = "v1",
                  Description = "Any description for your V1 APIs."
              });
      
              options.SwaggerDoc("public", new OpenApiInfo()
              {
                  Title = "CMS API",
                  Version = "v2",
                  Description = "Any description for your V2 APIs."
              });
      
              options.DocInclusionPredicate((docName, apiDesc) =>
              {
                  switch (docName)
                  {
                      case "v1":
                          return true;
                      case "v2":
                          return apiDesc.GroupName == null || apiDesc.GroupName == "v2";
                      default:
                          return false;
                  }
              });
      
              options.ParameterFilter<SwaggerEnumParameterFilter>();
              options.SchemaFilter<SwaggerEnumSchemaFilter>();
              options.OperationFilter<SwaggerOperationIdFilter>();
              options.OperationFilter<SwaggerOperationFilter>();
              options.CustomDefaultSchemaIdSelector();
          }).AddSwaggerGenNewtonsoftSupport();
      
    4. Next, in the Configure method, scroll down and find app.UseSwaggerUI ...

    5. Open appsettings.json in YOURCOMPANY.Web.Host and add a new endpoint configuration variable in the "App" field:


    "SwaggerEndPoint": "/swagger/v1/swagger.json",
    "SwaggerV2EndPoint": "/swagger/v2/swagger.json"
    
    1. Implement the following code:

      app.UseSwaggerUI(options =>
                  {
                      options.SwaggerEndpoint(_appConfiguration["App:SwaggerEndPoint"], "MY API V1");
                      options.SwaggerEndpoint(_appConfiguration["App:SwaggerPublicEndPoint"], "MY API V2");
      
                      options.IndexStream = () => Assembly.GetExecutingAssembly()
                          .GetManifestResourceStream("YOURCOMPANY.Web.wwwroot.swagger.ui.index.html");
                      options.InjectBaseUrl(_appConfiguration["App:ServerRootAddress"]);
                  }); 
      
    2. Now you can implement APIs in V2 group by adding ApiExplorerSettings attribute in your YOURCOMPANY.Application project; let's assume you have a service named (TestAppService),

    Then implement your methods (APIs) in the below namespace, and simply open your Swagger UI and test it.

    namespace CMS.TestNameSpace
    {
        [ApiExplorerSettings(GroupName = "v2")]
        [Route("api/[controller]/[action]")]
        public class TestAppService : (YOUR)AppServiceBase, ITestAppService
        {
            [HttpGet]
            public async Task<TestDto> GetTest(TestDtoInput input)
            {
    
            }
        }
    }