【问题标题】:WebAPI controller inheritance and attribute routingWebAPI 控制器继承和属性路由
【发布时间】:2014-06-14 03:09:41
【问题描述】:

我几乎没有从同一个基类继承的控制器。在它们彼此不共享的不同动作中,它们确实有一些完全相同。我希望将这些放在我的基类中,因为它们的工作方式完全相同,只是它们是通过不同的路线访问的。

我应该如何用几个不同的路由来定义这些动作?

我的继承类也设置了RoutePrefixAttribute,因此它们每个都指向不同的路线。

示例

我有一个名为Vehicle 的基本抽象类,然后继承了CarBikeBus 等。它们都有共同的操作Move()

/bus/move
/car/move
/bike/move

如何在我的基类 Vehicle 上定义操作 Move() 以便在每个子类路由上执行?

【问题讨论】:

  • 您是否尝试过创建一个继承自 APIController 的基类,然后您的控制器继承自基类。在这种情况下,我认为不同的路线不会有什么不同。
  • 还有什么? vehicle/move 所有人?
  • 您是否打算覆盖子类中的Move()
  • @Nkosi:不,它们将在基类上定义,并且只在基类上定义,但应该在子类的不同路径下执行......可能在某些特殊情况下我会覆盖那些,但很少这样做。无论如何,覆盖都会定义新路线,所以这应该不是问题。
  • 那么在这种情况下检查我在下面发布的答案

标签: c# asp.net inheritance asp.net-web-api2 asp.net-web-api-routing


【解决方案1】:

检查我在这里给出的答案WebApi2 attribute routing inherited controllers,它引用了这篇文章.NET WebAPI Attribute Routing and inheritance的答案。

你需要做的是覆盖DefaultDirectRouteProvider:

public class WebApiCustomDirectRouteProvider : DefaultDirectRouteProvider {
    protected override IReadOnlyList<IDirectRouteFactory>
        GetActionRouteFactories(HttpActionDescriptor actionDescriptor) {
        // inherit route attributes decorated on base class controller's actions
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
    }
}

完成后,您需要在 Web API 配置中对其进行配置:

public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {
        .....
        // Attribute routing (with inheritance).
        config.MapHttpAttributeRoutes(new WebApiCustomDirectRouteProvider());
        ....
    }
}

然后您将能够像这样执行您所描述的操作:

public abstract class VehicleControllerBase : ApiController {
    [Route("move")] // All inheriting classes will now have a `{controller}/move` route 
    public virtual HttpResponseMessage Move() {
        ...
    }
}

[RoutePrefix("car")] // will have a `car/move` route
public class CarController : VehicleControllerBase { 
    public virtual HttpResponseMessage CarSpecificAction() {
        ...
    }
}

[RoutePrefix("bike")] // will have a `bike/move` route
public class BikeController : VehicleControllerBase { 
    public virtual HttpResponseMessage BikeSpecificAction() {
        ...
    }
}

[RoutePrefix("bus")] // will have a `bus/move` route
public class BusController : VehicleControllerBase { 
    public virtual HttpResponseMessage BusSpecificAction() {
        ...
    }
}

【讨论】:

  • 我认为其中一些方法签名在 MVC 5.2.3 中发生了变化,这个答案似乎不再适合我。
  • 我仍在同一版本的生产代码中使用它。提出一个新问题,说明什么不适合您,让我们看看我们是否可以解决问题
  • 如果我只在基本控制器中定义Move 方法而没有WebApiCustomDirectRouteProvider 是否也有效?我在我的代码中尝试了这种方法,它奏效了。
【解决方案2】:

这就是我所做的,并且按照您在问题中提到的方式起作用。

我创建了基础 ApiController 类并从它继承了我所有的 API 控制器。我在我的基类中定义了删除操作(返回string“不支持”)并且没有在我的任何子控制器上定义删除。现在,当我在我的任何控制器上执行删除操作时,我会收到“不支持”消息,即调用了基类的删除操作。 (我正在对 Child 执行删除请求,而不是基于 /Bike/move)

但是,如果我在任何控制器上定义删除,它会给我隐藏基本实现的警告,但是在对 api 执行删除请求时,我得到 - "An error has occurred."

我没试过做RoutePrefix的方式。

【讨论】:

  • 我想你已经以经典的方式集中定义了你的路由(我们曾经在 MVC 中做的controller/action/id),而不是使用属性的声明性路由?因为我对通用控制器功能没有那么大的问题,因为我的通用功能的声明性路由存在问题,应该可以通过子路由定义访问......
猜你喜欢
  • 2014-09-17
  • 2013-11-28
  • 1970-01-01
  • 2014-11-27
  • 2019-02-19
  • 1970-01-01
  • 2015-09-27
  • 2015-02-12
  • 2016-12-17
相关资源
最近更新 更多