【问题标题】:Swashbuckle/Swagger not picking up routes from configSwashbuckle/Swagger 没有从配置中获取路线
【发布时间】:2016-10-24 06:34:15
【问题描述】:

我正在使用 Swashbuckle(一个 .NET 包装器)。

当我生成我的 swagger 文档时,它会根据控制器名称/参数生成文档中的 URI,而不是在应用程序启动时在配置中定义的已定义路由。

所以我有一个控制器:

namespace Pat.PostingService.Api.Version1
{
    public class DeliveryStatusController : ApiController
    {
         [ResponseType(typeof(DeliveryStatusDto))]
         public dynamic Get(string deliveryType, Guid? orderId = null)
         {
             ...
         }
    }
{

在 RouteConfig.cs 文件中,我重新定义了路由:

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();

    ...

    config.Routes.MapHttpRoute(
         name: "DeliveryStatusService",
         routeTemplate: "SpecialDeliveryServiceStatus/{deliveryType}/{orderId}",
         defaults: new {
             controller = "DeliveryStatus",
             orderId = RouteParameter.Optional
         }
    );

    config.Routes.MapHttpRoute(
         name: "Default",
         routeTemplate: "{controller}/{id}",
         defaults: new { id = RouteParameter.Optional }
    );
}

调用 API 时,我现在无法使用 /DeliveryStatus 端点,我必须使用 /SpecialDeliveryServiceStatus 端点。

但是,Swagger 文档指出端点是 /DeliveryStatus

与我的同事一起,我们相信 _apiExplorer.ApiDescriptions(来自 SwaggerGenerator.cs 在 Swashbuckle.Core 中使用的 System.Web.Http.Description.IApiExplorer)正在向我们返回不正确的路由,尽管我们可能是错误的。

我们错过了什么?我们可以使用什么来确保 Swagger 使用配置中使用的路由而不是默认路由?


编辑:

我们还使用 SDamann 进行版本控制(想象在 version2 文件夹中的第二个 RouteConfig.cs 文件),它不支持 [AttributeRouting],因此我们需要从启动路由配置中获取路由。


编辑 2:

action = "Get" 设置为路由的默认值也不能解决问题。

【问题讨论】:

  • 这很奇怪,我刚刚测试了你的代码,我得到了一个完美的结果......它向我显示了端点为 /SpecialDeliveryServiceStatus/{deliveryType}/{orderId}。尝试创建一个 ISchemaFilter 并检查 ApiDescription - 如果您愿意,您可以在此处更改路径,尽管这将需要大量静态代码和大量 operationId(如果这是您唯一的端点,则不会有问题)

标签: c# asp.net swagger swagger-ui swashbuckle


【解决方案1】:

当第一场比赛获胜时,您注册/映射路线的顺序在路线表中起着重要作用。您的示例显示了您如何注册有问题的路线,但没有显示它相对于您的其他路线的注册位置。

例如,如果您在相关路由之前注册默认路由

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();

    ...

    config.Routes.MapHttpRoute(
         name: "Default",
         routeTemplate: "{controller}/{id}",
         defaults: new { id = RouteParameter.Optional }
    );

    config.Routes.MapHttpRoute(
         name: "DeliveryStatusService",
         routeTemplate: "SpecialDeliveryServiceStatus/{deliveryType}/{orderId}",
         defaults: new {
             controller = "DeliveryStatus",
             orderId = RouteParameter.Optional
         }
    );
}

...然后GET /DeliveryStatus 将按照惯例匹配到

public dynamic Get(string deliveryType, Guid? orderId = null) { ... }

特别是如果 id 占位符是可选的。

因此,请检查以确保您的路线映射顺序正确。默认路由通常最后映射为备用路由。

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();

    ...

    config.Routes.MapHttpRoute(
         name: "DeliveryStatusService",
         routeTemplate: "SpecialDeliveryServiceStatus/{deliveryType}/{orderId}",
         defaults: new {
             controller = "DeliveryStatus",
             orderId = RouteParameter.Optional
         }
    );

    config.Routes.MapHttpRoute(
         name: "Default",
         routeTemplate: "{controller}/{id}",
         defaults: new { id = RouteParameter.Optional }
    );
}

如果您不反对使用attribute routing in web api 2,您可以改为...

namespace Pat.PostingService.Api.Version1
{
    [RoutePrefix("SpecialDeliveryServiceStatus")]
    public class DeliveryStatusController : ApiController
    {
         //GET SpecialDeliveryServiceStatus/{deliveryType}/{orderId}
         [HttpGet]
         [Route("{deliveryType}/{orderId?}")]
         [ResponseType(typeof(DeliveryStatusDto))]
         public dynamic Get(string deliveryType, Guid? orderId = null) { ... }
    }
}

并在RouteConfig.cs文件中,配置属性路由:

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();

    config.MapHttpAttributeRoutes();
    ...

}

再次映射的顺序很重要,这就是为什么通常在其他映射之前配置它的原因。

更新:

尝试以下方法:

config.Routes.MapHttpRoute(
     name: "DeliveryStatusService",
     routeTemplate: "SpecialDeliveryServiceStatus/{deliveryType}/{orderId}",
     defaults: new {
         controller = "DeliveryStatus",
         action = "Get"
         orderId = RouteParameter.Optional
     }
);

在控制器中:

[HttpGet]
[ResponseType(typeof(DeliveryStatusDto))]
public dynamic Get(string deliveryType, Guid? orderId = null) { ... }

确保路由表不会猜测操作映射到哪个路由。

【讨论】:

  • 感谢 Nkosi 的回答 - 我可能应该把它放在那里,但我们确实在底部有最通用的路线(我尝试重新排列只是为了检查)。
  • 同样,我们也尝试过基于属性的路由,但是我们使用 Sdammann 进行版本控制,它不支持基于属性的路由,因此我们需要 Swashbuckle 来支持启动路由配置。
  • 您应该使用这些详细信息更新问题,以便其他人可以更好地了解完整情况。
  • 您是否尝试在路由映射的默认值中手动设置action="Get"。即defaults: new { controller = "DeliveryStatus", action = "Get", orderId = RouteParameter.Optional }。以及HttpGet 属性,以确保不会猜测动作属于哪条路线?
  • 恐怕这并没有解决问题:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
  • 2019-08-02
  • 1970-01-01
  • 2020-03-01
相关资源
最近更新 更多