question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ApiVersioning + Swagger + ApplicationService not working

See original GitHub issue

Hi I try to use ApiVersioning for dynamic web api But this doesn’t work reference:https://github.com/microsoft/aspnet-api-versioning/blob/master/samples/aspnetcore/SwaggerSample/Startup.cs

ApplicationService

 [ApiVersion("1.0")]
 public class TestAppService: ApplicationService, ITestAppService
    {
        public Task<string> Get()
        {
           return  Task.FromResult("Test");
        }
    }

Startup.cs

           services.AddApiVersioning(options =>
            {
                options.ReportApiVersions = true;
                options.ApiVersionReader = new HeaderApiVersionReader("Api-Version");
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.DefaultApiVersion = new ApiVersion(1, 0);
            });
            services.AddVersionedApiExplorer(options =>
            {
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.DefaultApiVersion = new ApiVersion(1, 0);
                options.GroupNameFormat = "'v'VVV";
            });

apiVersioning and swagger cannot find TestAppService on abp 5.5.0.0

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:16 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
jalilzadecommented, Aug 2, 2021

Hi @vcluopeng thanks for answering.

Hi @ismcagdas,

I managed to add API versioning to asp.net Zero. If you think there is more easier or better way to achieve this, I would happy to here. If you think it is ok, can we have this as part of documentation of asp.net zero (.netcore + angular)

File ProjectName.Web.Host\startup\startup.cs method ConfigureServices changed related code to this:

if (WebConsts.SwaggerUiEnabled)
  {
      //Swagger - Enable this line and the related lines in Configure method to enable swagger UI
      services.AddSwaggerGen(options =>
      {
          options.SwaggerDoc("v1.0", new OpenApiInfo() { Title = "ProjectName API", Version = "v1.0" });
          // if needed add swagger version like following
          options.SwaggerDoc("v2.0", new OpenApiInfo() { Title = "ProjectName API", Version = "v2.0" });
          options.SwaggerDoc("v3.0", new OpenApiInfo() { Title = "ProjectName API", Version = "v3.0" });

          options.DocInclusionPredicate((docName, apiDesc) =>
          {
              if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;

              IEnumerable<ApiVersion> versions = new List<ApiVersion>();

              versions = methodInfo.GetCustomAttributes(true)
                  .OfType<ApiVersionAttribute>()
                  .SelectMany(attr => attr.Versions).ToList();

              if (!versions.Any())
                  versions = methodInfo.DeclaringType
                                  .GetCustomAttributes(true)
                                  .OfType<ApiVersionAttribute>()
                                  .SelectMany(attr => attr.Versions).ToList();

              return versions.Count() == 0 || versions.Any(v => $"v{v}" == docName && apiDesc.RelativePath.Contains($"v{v}"));
          });

          options.ParameterFilter<SwaggerEnumParameterFilter>();
          options.SchemaFilter<SwaggerEnumSchemaFilter>();
          options.OperationFilter<SwaggerOperationIdFilter>();
          options.OperationFilter<SwaggerOperationFilter>();
          options.CustomDefaultSchemaIdSelector();
          options.EnableAnnotations();

          var basePath = AppContext.BaseDirectory;
          foreach (var name in Directory.GetFiles(basePath, "*.XML", SearchOption.AllDirectories))
              options.IncludeXmlComments(name);

      }).AddSwaggerGenNewtonsoftSupport();
  }

File ProjectName.Web.Host\startup\startup.cs in Configure method changed code to this:

if (WebConsts.SwaggerUiEnabled)
     {
         // Enable middleware to serve generated Swagger as a JSON endpoint
         app.UseSwagger();
         // Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)

         app.UseSwaggerUI(options =>
         {
             options.SwaggerEndpoint(_appConfiguration["App:SwaggerEndPoint"], "ProjectName API V1");
             // if needed add swagger version like following
            //addreses can be add to appsetting.json
             options.SwaggerEndpoint("/swagger/v2.0/swagger.json", "ProjectName API V2");
             options.SwaggerEndpoint("/swagger/v3.0/swagger.json", "ProjectName API V3");

             options.IndexStream = () => Assembly.GetExecutingAssembly()
                 .GetManifestResourceStream("XX.Web.wwwroot.swagger.ui.index.html");
             options.InjectBaseUrl(_appConfiguration["App:ServerRootAddress"]);
         }); //URL: /swagger
     }

File ProjectName.Web.Core.ProjectNameCoreModule.cs In PreInitialize method changed code to this:

Comment or remove following lines

            //Configuration.Modules.AbpAspNetCore()
            //    .CreateControllersForAppServices(
            //        typeof(ProjectNameApplicationModule).GetAssembly()
            //    );

And add these line to be able adding apppservice as controller with version in url:

var moduleName = "app";
  Configuration.Modules.AbpAspNetCore()
  .CreateControllersForAppServices(typeof(ProjectNameApplicationModule).GetAssembly(), moduleName)
  .ConfigureControllerModel(model =>
  {
      foreach (var action in model.Actions)
      {
          List<ApiVersion> controllerVersions = new List<ApiVersion>();
          if (action.Attributes.Any(x => x is ApiVersionAttribute))
          {
              controllerVersions = action.Attributes.OfType<ApiVersionAttribute>().SelectMany(x => x.Versions).ToList();
          }
          else if (action.Controller.Attributes.Any(x => x is ApiVersionAttribute))
          {
              controllerVersions = action.Controller.ControllerType.GetCustomAttributes(true)
                  .OfType<ApiVersionAttribute>().SelectMany(x => x.Versions).ToList();

          }

          if (controllerVersions.Any())
          {
              foreach (var version in controllerVersions.Select(x => x.ToString()).ToList())
              {
                  var selectorModel = new SelectorModel
                  {
                      AttributeRouteModel = new AttributeRouteModel(
                          new RouteAttribute(
                              $"api/v{version}/services/{moduleName}/{action.Controller.ControllerName}/{action.ActionName}"
                          )
                      )
                  };

                  selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new List<string>
                              {ProxyScriptingHelper.GetConventionalVerbForMethodName(action.ActionName)}));

                  action.Selectors.Add(selectorModel);
              }
          }

      }
  });

Change appsettingjson.json

`"SwaggerEndPoint": "/swagger/v1/swagger.json", ->`  `"SwaggerEndPoint": "/swagger/v1.0/swagger.json",`

Add version Info to AppService or methods:

    [ApiVersion("1.0")]
    [ApiVersion("2.0")]

    [AbpAuthorize(AppPermissions.Pages_AddressToContacts)]
    public class AddressSystemAppService : ProjectNameAppServiceBase, IAddressSystemAppService
    {
      // ....

        [ApiVersion("3.0")]
        public async Task<ListResultDto<GetCountryForViewDto>> GetAllCountries()
        {
            var countries = await _countryRepository.GetAllIncluding(p => p.Translations).ToListAsync();
            return new ListResultDto<GetCountryForViewDto>(ObjectMapper.Map<List<GetCountryForViewDto>>(countries));
        }

   // ....
    }

Note: To get latest APı methods in nswag In file ProjectName.Web.Host\nswag\service.config.nswag change following: "url": "https://localhost:44301/swagger/v1/swagger.json", --> "url": "https://localhost:44301/swagger/v1.0/swagger.json", Or change to desired version "url": "https://localhost:44301/swagger/v3.0/swagger.json",

Now versioning works as expected.

V1 image

V2 image

V3 image

0reactions
jalilzadecommented, Jun 19, 2023

@sajasbana Unfortunately I couldn’t create sample project because of time. But I have added all steps in this comment. May this can help you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Swagger versioning is not working. It displays all endpoints ...
I need to create an endpoint for the new version of API and with the same route as a previous version. My controller...
Read more >
Troubleshooting issues when using Swagger as a REST API ...
This error can occur in the following circumstances: Syntax errors in the index.html file, located in /swagger/dist/ folder. The variable URL ...
Read more >
How to Swagger API Versioning in ASP.NET Core
In this article, let's see how we can dynamically integrate Swagger UI documentation, for all the API versions available in our ASP.
Read more >
2. Making Swagger work with API versioning - YouTube
Small problem - Swagger not working with version APIs : 00:18 3. ... Configuring Swagger services using IOptions pattern: 05:04 5.
Read more >
Set up Swagger and API versioning in .NET 5 web API
API versioning and Swagger goes hand in hand when developing APIs. Learn how to easily set it up.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found