简体   繁体   English

从基础 controller 继承 controller 操作时生成 swagger.json 文件的问题

[英]Issue generating swagger.json file when inheriting controller actions from a base controller

I am writing a web api in .net 6. The api has 32 controllers for getting lookup values from a database.我在 .net 6 中写了一个 web api。api 有 32 个控制器用于从数据库中获取查找值。 I have a service layer that talks to the repository and maps the entity to the response object. Meaning the functionality for 90% of the controllers is exactly the same, outside of the entity that is being retrieved.我有一个与存储库对话并将实体映射到响应 object 的服务层。这意味着 90% 的控制器的功能完全相同,只是在正在检索的实体之外。 So, I moved all of the common code to a generically typed controller base and am now using inheritance to implement the correct type.因此,我将所有通用代码移至通用类型 controller 基,现在使用 inheritance 来实现正确的类型。

Basically, I have moved the Get, GetById, Create and Update methods to the base controller and have inherited that class for the individual controllers.基本上,我已将 Get、GetById、Create 和 Update 方法移至基 controller,并为各个控制器继承了 class。

Executing the web api using Postman works as expected.使用 Postman 执行 web api 按预期工作。 If I execute the Get method on the AddressType route, versus the EmailType route, it returns the appropriate list.如果我在 AddressType 路由上执行 Get 方法,而不是在 EmailType 路由上,它会返回适当的列表。

However, trying to get the swagger definition is failing miserably with the following:但是,尝试获取 swagger 定义失败了,原因如下:

An unhandled exception occurred while processing the request.处理请求时发生未处理的异常。 IndexOutOfRangeException: Index was outside the bounds of the array. IndexOutOfRangeException:索引超出数组范围。 Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata.InitializeTypeInformation() Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata.InitializeTypeInformation()

Up to moving to inheritance, I was able to get the swagger definition correctly.直到移动到 inheritance,我才能够正确地获得 swagger 的定义。

I've looked at other similar questions and tried a handful of their solutions.我看过其他类似的问题并尝试了一些他们的解决方案。 But, either they are talking about older versions of WebApi/.net or do not apply.但是,他们要么在谈论旧版本的 WebApi/.net,要么不适用。

code edited for length为长度编辑的代码

public abstract class HubControllerEntityBase<TEntity, TCreate, TUpdate, TResponse, TCategoryName, TService> : HubControllerBase<TCategoryName>, IHubController<TEntity, TCreate, TUpdate>
    where TEntity : class, IHubEntity, new()
    where TCreate : class, ICreateEntityRequest, new()
    where TUpdate : class, IUpdateEntityRequest, new()
    where TResponse : class, IEntityResponse, new()
    where TCategoryName : class
    where TService : IHubEntityService<IGetEntityRequest, TCreate, TUpdate, TResponse>
{
    #region Constructors

    /// <summary>
    ///     The primary constructor.
    /// </summary>
    /// <param name="logger">The logger to use for logging and debugging.</param>
    /// <param name="dependencies">The controller dependencies.</param>
    /// <param name="service">The service used for processing the requests.</param>
    protected HubControllerEntityBase(
        ILogger<TCategoryName> logger,
        HubControllerDependencies dependencies,
        TService service
    ) : base(logger, dependencies)
    {
        Service = service;
    }

    #endregion

    #region Public methods

    /// <summary>
    ///     Gets all of the entities in the data store.
    /// </summary>
    /// <param name="options">
    ///     An <see cref="ODataQueryOptions" /> object that contains the filters, sorts, etc applied from the query string.
    /// </param>
    /// <returns>An <see cref="IEnumerable{T}" /> list of entities.</returns>
    /// <response code="200">The query was processed successfully.</response>
    /// <response code="500">A system exception occurred executing the query.</response>
    [HttpGet]
    [ProducesResponseType(typeof(IEnumerable<>), 200)]
    [ProducesResponseType(500)]
    public virtual async Task<IActionResult> GetAll(ODataQueryOptions<TEntity> options)
    {
        // Initialize the event id structure and log entry
        var ev = new EventId(LogEventId, MethodBase.GetCurrentMethod()?.Name);
        Logger.LogDebug(ev, $"Request: {ev.Name}");

        // Get the list of entities, passing in the OData options
        var response = await Service.GetAsync(options);

        // Return the response
        return GetResponseResult(response);
    }

    #endregion
}

[ApiController]
[ApiVersion("1.0")]
[Route(ApiRoutes.AddressType.ControllerRoute)]
[Route(ApiRoutes.AddressType.ControllerRouteWithVersion)]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class AddressTypeController : HubControllerEntityNameBase<AddressType, AddressTypeRequest, AddressTypeRequest, AddressTypeResponse, AddressTypeController,
    IAddressTypeService<AddressTypeRequest, AddressTypeResponse>>
{
    public AddressTypeController(
        ILogger<AddressTypeController> logger,
        HubControllerDependencies dependencies,
        IAddressTypeService<AddressTypeRequest, AddressTypeResponse> service
    ) : base(logger, dependencies, service)
    {
        LogEventId = 60100;
    }
}

Any help is greatly appreciated.任何帮助是极大的赞赏。

As it turns out, there were three separate issues.事实证明,存在三个不同的问题。

The first was mine.第一个是我的。 Despite it compiling successfully, there was a reference to an empty IEnumerable<> in the schema definition.尽管编译成功,但在架构定义中引用了一个空的IEnumerable<> This was causing the initial swagger/API explorer failure:这导致了最初的 swagger/API 资源管理器失败:

[HttpGet]
[ProducesResponseType(typeof(IEnumerable<>), 200)]
[ProducesResponseType(500)]

There were two other issues that needed to be addressed in the swagger configuration: unique schema names, and odata.在 swagger 配置中还有两个其他问题需要解决:唯一模式名称和 odata。 Fortunately, swagger config can handle both.幸运的是,swagger 配置可以处理这两个问题。 They were resolved by adding the following lines to my swagger options:通过将以下行添加到我的 swagger 选项中解决了这些问题:

services.AddSwaggerGen(x =>
{
    x.CustomSchemaIds(x => x.FullName);
    x.MapType(typeof(ODataQueryOptions<>), () => new());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 .net core/swagger - 生成 swagger.json 文件时如何绕过控制器文件? - .net core/swagger - How can I around a controller file when generating the swagger.json file? 从自定义基本控制器类继承时,无法使用swagger解析JSON / YAML响应 - getting failed to parse JSON/YAML response using swagger when inheriting from custom base controller class Swagger 不生成 swagger.json - Swagger is not generating swagger.json 如何按控制器名称对 NSwag swagger.json 中的路径进行排序/排序 - How to order/sort paths in NSwag swagger.json by controller name Generating C# Rest API Client from swagger.json - Generating C# Rest API Client from swagger.json 当本地主机提供 swagger.json 时,Autorest 无法针对文件解析 swagger.json - Autorest Failed resolving swagger.json against file when swagger.json is served by localhost 使用在 Swashbuckle 的后期构建操作中生成的 swagger.json 文件,而不是在运行时生成的文件 - Use swagger.json file generated in post build actions in Swashbuckle instead of the file generated at runtime 有没有办法在孩子 controller 中隐藏基本通用 controller 的操作? - Is there a way in a child controller to hide actions from a base generic controller? 在不继承控制器的情况下注入基本控制器的正确方法 - Proper way to inject into a base controller without passing from inheriting one ASP.NET Core - Swashbuckle 未创建 swagger.json 文件 - ASP.NET Core - Swashbuckle not creating swagger.json file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM