Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to generate json for controllers that inherit base controllers #511

Closed
lavinianastase opened this issue Oct 10, 2017 · 2 comments
Closed

Comments

@lavinianastase
Copy link

I have two controllers that inherit other controllers - for one of them, the swagger doc is generated, for the other it is not.
My controllers are:

[Route("Actor")]
public class ActorController : BaseDefControllerLog<Actor> 
 {
        public ActorController(BaseDefController<Actor> baseController, ILogger<ActorController> logger, IAppConfig appSettings) : base(baseController, logger, appSettings)
 { }
  }
[Route("ActorCatalog")]
public class ActorCatalogController: LoggerController, ICatalogController<Actor> 
{
        private readonly BaseDefControllerLog<Actor> _baseController;

        public ActorCatalogController(BaseDefControllerLog<Actor> baseController, ILogger<ActorCatalogController> logger) : base(logger)
        {
            _baseController = baseController;
        }

        [Route("GetAll")]
        [HttpGet]
        public ICollection<Actor> GetAll(int? pageNumber = null, int? pageSize = null)
        {
            //GetAll logic
        }
}

Below, BaseDefController, BaseDefControllerLog and LoggerController:

public class BaseDefController<T> : Controller, ICatalogController<T> where T : class, IConfigDef
    {
        private readonly IReadManager<T> _manager;

        public BaseDefController(IReadManager<T> manager)
        {
            _manager = manager;
        }
        [HttpGet]
        public virtual ICollection<T> GetAll(int? pageNumber = null, int? pageSize = null)
        {
            return _manager.GetAll(pageNumber, pageSize);
        }
    }
public class BaseDefControllerLog<T>: LoggerController where T : class, IConfigDef
    {
        private readonly BaseDefController<T> _baseController;
        private readonly ILogger<BaseDefControllerLog<T>> _logger;
        public BaseDefControllerLog(BaseDefController<T> baseController, ILogger<BaseDefControllerLog<T>> logger, IAppConfig appSettings) : base(logger)
        {
            _baseController = baseController;
            _logger = logger;
        }

       [HttpGet]
        public virtual ICollection<T> GetAll(string remoteIpAddress = null, int? pageNumber = null, int? pageSize = null)
        {
            //GetAll logic
        }
}
public class LoggerController : Controller
{
        protected ILogger Logger;

        public LoggerController(ILogger logger)
        {
            Logger = logger;
        }
        public override void OnActionExecuting(ActionExecutingContext context)
        { //...  }
        public override void OnActionExecuted(ActionExecutedContext context)
        { //... }
 }

VERSION:

Swashbuckle.AspNetCore 1.0.0

STEPS TO REPRODUCE:

I have decorated both ActorController and ActorCatalogController with the Route attribute. At this point, swagger throws an exception when generating the json. If I remove the route on ActorController and therefore generate documentation only for ActorCatalogController, everything works fine. If I decorate the inherited controllers' actions with route attributes, I also get a 500 response on json. I also tried to remove the virtual keyword, with no luck.

EXPECTED RESULT:

Documentation for both controllers (ActorCatalogController and ActorController).

ACTUAL RESULT:

500 : http://localhost:4100/swagger/v1/swagger.json
The JSON cannot be generated. I catch this exception: "Exception thrown: 'System.NotSupportedException' in Swashbuckle.AspNetCore.SwaggerGen.dll".

ADDITIONAL DETAILS

The target framework for my project is .NET framework 4.6.2. I use Microsoft.AspNetCore 1.1.2 and Microsoft.AspNetCore.Hosting.WindowsServices 1.1.2.
My swagger configuration in Startup.cs is the following:

public void ConfigureServices(IServiceCollection services)
        {
            services
                .AddMvc(config =>
                {
                    config.RespectBrowserAcceptHeader = true;
                })
                .AddJsonOptions(options =>
                {
                    options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
                })
                .AddXmlSerializerFormatters();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info { Title = "InternalServer", Version = "v1" });
            });

            InitializeContainer(services);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseMvc();

            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("v1/swagger.json", "SwaggerDemo V1");
            });

            LogRegistration(loggerFactory);
        }
@lavinianastase
Copy link
Author

Since I still didn't find a solution, I attached a project sample that reproduces the bug.
Thanks in advance for your help!

SwaggerTests.InternalServer.zip

@lavinianastase
Copy link
Author

I solved the problem. There were more issues that I only found after appending my solution to Swashbuckle.AspNetCore.

  1. I omitted the routes for some controllers that inherited BaseDefControllerLog. The exception was:
    HTTP method "GET" & path "GetCount" overloaded by actions - InternalServer.Controllers.ActorController.GetCount
    (InternalServer),InternalServer.Controllers.CarrierController.GetCount (InternalServer),InternalServer.Controllers.InstallationController.GetCount (InternalServer),InternalServer.Controllers.LocationController.GetCount (InternalServer),InternalServer.Controllers.ProductController.GetCount .
    Actions require unique method/path combination for Swagger"
    Therefore, ALL the controllers should have a route (even if you want to skip them from the documentation, for example).

  2. I had some entities with the same name, but in different namespaces. For example:
    Common.Domain.ClientConfiguration.Actor
    CustomerConfiguration.PublicContracts.Actor

I solved this with the following setting in Startup.cs:

services.ConfigureSwaggerGen(options =>
{
options.CustomSchemaIds(x => x.FullName);
});
I found the solution here: domaindrivendev/Swashbuckle.WebApi#442

With this workaround, I also resolved this exception;

"HTTP method "GET" & path "Actor" overloaded by actions -
InternalServer.Controllers.ActorController.GetCount (InternalServer),InternalServer.Controllers.ActorController.GetAll (InternalServer),InternalServer.Controllers.ActorController.GetMaxDate (InternalServer),InternalServer.Controllers.ActorController.GetUpdates (InternalServer). Actions require unique method/path combination for Swagger".

I will close the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant