Swashbuckle / Swagger没有从配置中获取路由

时间:2016-06-22 10:56:07

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

我正在使用Swashbuckle(swagger的.NET包装器)。

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

所以我有一个控制器:

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(来自Swashbuckle.Core中SwaggerGenerator.cs使用的System.Web.Http.Description.IApiExplorer)正在向我们返回错误的路由,尽管我们可能错了。

我们错过了什么?有什么东西可以用来确保Swagger使用config中使用的路由而不是默认路由吗?

编辑:

我们也使用SDammann进行版本控制(想象一下版本2文件夹中的第二个RouteConfig.cs文件),它不支持[AttributeRouting],因此我们需要从启动路由配置中选择路由。

编辑2:

action = "Get"置于路线的默认值中也不能解决问题。

1 个答案:

答案 0 :(得分:2)

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

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

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();
    ...

}

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

UPDATE:

尝试以下方法:

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) { ... }

确保路由表没有关于动作映射到哪条路径的猜测。