WebApi - 控制器继承 - 方法的新版本

时间:2014-08-01 07:00:16

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

我使用Web API 2.我在版本1中提供客户端方法:

http://localhost/version1/api/base 
http://localhost/version1/api/values

这是我的控制器:

[RoutePrefix("version1")]
public class ValuesController : ApiController
{
    [Route("api/base")]
    public string GetBaseMethod()
    {
        return "bbb";
    }

    [Route("api/values")]
    public string GetVersion1()
    {
        return "aaa";
    }   
}

现在我想以版本2方法提供客户端:

  • / version2 / api / base(方法与版本1中的相同)
  • / version2 / api / values(方法已更改,现在返回int,而不是字符串,但地址必须与version1中的相同:/ api / values)

所以我有第二个带继承的控制器:

[RoutePrefix("version2")]
public class Values2Controller : ValuesController
{
    [Route("api/values")]
    public int GetVersion2()
    {
        return 5;
    }
}

我在WebApiConfig.cs中启用了属性路由继承:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());

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

public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
    {
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
    }
}

结果:

http://localhost/version1/api/base

  • 它有效。

http://localhost/version2/api/base

  • 它有效。

http://localhost/version1/api/values

  • 它有效。

http://localhost/version2/api/values

  • 它没有工作。我有错误
  

{       &#34;消息&#34;:&#34;发生了错误。&#34;,       &#34; ExceptionMessage&#34;:&#34;找到与请求匹配的多个操作:\ r \ n \ nGetVersion2 on type   类型上的WebApplication1.Controllers.Values2Controller \ r \ n \ nGetVersion1   WebApplication1.Controllers.Values2Controller&#34 ;,       &#34; ExceptionType&#34;:&#34; System.InvalidOperationException&#34;,       &#34; StackTrace&#34;:&#34; w System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext   controllerContext)\ r \ n w   System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext   controllerContext)\ r \ n w   System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext   controllerContext,CancellationToken cancellationToken)\ r \ n w   System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()&#34;   }

我该怎么办?

2 个答案:

答案 0 :(得分:2)

我能够重现你的问题。使用不同的变体我只能在原始的 GetVersion1 虚拟,将返回类型更改为更通用的对象然后在继承的类中重写它时才能使它工作。

像这样:

[RoutePrefix("version1")]
public class ValuesController : ApiController {
    [Route("api/base")]
    public string GetBaseMethod() {
        return "bbb";
    }

    [Route("api/values")]
    public virtual object GetVersion1() {
        return "aaa";
    }
}

[RoutePrefix("version2")]
public class Values2Controller : ValuesController {

    public override object GetVersion1() {
        return 5;
    }
}

一旦启用了冲突的Route属性和路由继承,它就会失败,就像你指示的那样。

这让我思考。如果您要使用继承,那么为什么不仅仅使用路由来处理它。所以我最终根据你的例子确定了以下内容:

[RoutePrefix("version1")]
public class ValuesController : ApiController {
    [Route("api/base")]
    public virtual HttpResponseMessage GetBaseMethod() {
        return Request.CreateResponse("bbb");
    }

    [Route("api/values")]
    public virtual HttpResponseMessage GetVersion1() {
        return Request.CreateResponse("aaa");
    }
}

[RoutePrefix("version2")]
public class Values2Controller : ValuesController {

    public override HttpResponseMessage GetVersion1() {
        return Request.CreateResponse(5);
    }
}

这将允许我在没有路由冲突的情况下更改未来版本中的基础返回值。

结果:

http://localhost/version1/api/base

  • 它有效。 =&GT; “BBB”

http://localhost/version2/api/base

  • 它有效。 =&GT; “BBB”

http://localhost/version1/api/values

  • 它有效。 =&GT; “AAA”

http://localhost/version2/api/values

  • 它有效。 =&GT; 5

答案 1 :(得分:0)

Multiple actions were found that match the request: webapi

我相信这是同样的问题。您需要&#34; api / {controller} / {action} / {id}&#34;