Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带继承的Web API版本控制_C#_Asp.net Web Api_Asp.net Web Api2_Asp.net Web Api Routing - Fatal编程技术网

C# 带继承的Web API版本控制

C# 带继承的Web API版本控制,c#,asp.net-web-api,asp.net-web-api2,asp.net-web-api-routing,C#,Asp.net Web Api,Asp.net Web Api2,Asp.net Web Api Routing,我试图让Web API版本控制与继承的类一起工作。我正在使用股票值的两个非常简单的变体控制器 [ApiVersion("1.0")] [RoutePrefix("api/v{version:apiVersion}/Values")] [ControllerName("Values")] public class ValuesController : ApiController { // GET api/values [Route("")] public IEnumerab

我试图让Web API版本控制与继承的类一起工作。我正在使用股票
值的两个非常简单的变体
控制器

[ApiVersion("1.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class ValuesController : ApiController
{
    // GET api/values
    [Route("")]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    [Route("{id:int}")]
    public virtual string Get(int id)
    {
        return "value from 1";
    }
}

[ApiVersion("2.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class Values2Controller : ValuesController
{
    //Want to use the method in the base class
    //public IEnumerable<string> Get()
    //{
    //    return new string[] { "value2-1", "value2-2" };
    // }

    [Route("{id:int}")]
    // GET api/values/5
    public new string Get(int id)
    {
        return "value from 2";
    }
} 
非重写路由的工作方式与我预期的完全相同
http://localhost:32623/api/v1.0/Values/12
->“1的值”
http://localhost:32623/api/v2.0/Values/12
->“来自2的值”

调用默认
Get
Route的v1 ->价值1,价值2

但是,在子控制器上尝试相同的路由会导致错误

http://localhost:32623/api/v2.0/Values

<Message>
The HTTP resource that matches the request URI 'http://localhost:32623/api/v2.0/Values' does not support the API version '2.0'.
</Message>
<InnerError>
<Message>
No route providing a controller name with API version '2.0' was found to match request URI 'http://localhost:32623/api/v2.0/Values'.
</Message>
</InnerError>

与请求URI的名称匹配的HTTP资源http://localhost:32623/api/v2.0/Values“”不支持API版本“2.0”。
找不到提供API版本为“2.0”的控制器名称的路由与请求URI匹配http://localhost:32623/api/v2.0/Values'.
错误消息表明被重写的成员需要一个“1.0”路由,我可以在子类中使用类似这样的方法来解决这个问题

[Route("")]
public override IEnumerable<string> Get()
{
    return base.Get();
}
[路线(“”)]
公共覆盖IEnumerable Get()
{
返回base.Get();
}

但在更大的应用程序中,这似乎不太理想。如果没有这些“空”覆盖,是否有办法使其按我所希望的方式工作?

您需要做的是覆盖
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);
    }
}
因此,现在继承值控制器将在派生控制器中具有可用的基本路由

为了说明的目的

[ApiVersion("1.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class ValuesController : ApiController {

    [HttpGet]
    [Route("")] // GET api/v1.0/values
    public virtual IHttpActionResult Get() {
        return Ok(new string[] { "value1", "value2" });
    }

    [HttpGet]
    [Route("{id:int}")] // GET api/v1.0/values/5
    public virtual IHttpActionResult Get(int id) {
        return Ok("value from 1");
    }
}

[ApiVersion("2.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class Values2Controller : ValuesController {

    //Will have inherited GET "api/v2.0/Values" route

    // GET api/v2.0/values/5 (Route also inherited from base controller)
    public override IHttpActionResult Get(int id) {
        return Ok("value from 2");
    }
} 
您将注意到,子级中的路由不会用于重写操作,因为它也将从基本控制器继承

[ApiVersion("1.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class ValuesController : ApiController
{
    // GET api/values
    [Route("")]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    [Route("{id:int}")]
    public virtual string Get(int id)
    {
        return "value from 1";
    }
}

[ApiVersion("2.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class Values2Controller : ValuesController
{
    //Want to use the method in the base class
    //public IEnumerable<string> Get()
    //{
    //    return new string[] { "value2-1", "value2-2" };
    // }

    [Route("{id:int}")]
    // GET api/values/5
    public new string Get(int id)
    {
        return "value from 2";
    }
} 
[ApiVersion("1.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class ValuesController : ApiController {

    [HttpGet]
    [Route("")] // GET api/v1.0/values
    public virtual IHttpActionResult Get() {
        return Ok(new string[] { "value1", "value2" });
    }

    [HttpGet]
    [Route("{id:int}")] // GET api/v1.0/values/5
    public virtual IHttpActionResult Get(int id) {
        return Ok("value from 1");
    }
}

[ApiVersion("2.0")]
[RoutePrefix("api/v{version:apiVersion}/Values")]
[ControllerName("Values")]
public class Values2Controller : ValuesController {

    //Will have inherited GET "api/v2.0/Values" route

    // GET api/v2.0/values/5 (Route also inherited from base controller)
    public override IHttpActionResult Get(int id) {
        return Ok("value from 2");
    }
}