使用 Web API 属性路由和 RoutePrefix

using Web API attribute routing and RoutePrefix

使用 web api 时,如果使用 [RoutePrefix()]

如何调用正确的路由方法

假设您有类似 "MyReallyLongNamedClassController" 的内容。默认路由为 http:...com/api/MyReallyLongNamedClass。然后应用程序通过名为 Get、Post、Put 等的方法运行(当然除非使用动词装饰器)。

如果我在我的控制器上放置了 [RoutePrefix("api/LongClass")] 的路由前缀装饰器,我怎么能让 web api 仍然使用这些方法的默认值?

意思是,我希望名为 "GetAll()" 的方法仍然映射到 "api/LongClass"(当使用 get header 时)并且 "PostThis(int id)" 仍然映射到 "api/LongClass/{id}"(当使用 post header 时)

您不必担心 RoutePrefix 属性在内部的工作方式。您可以使用 RoutePrefix 装饰您的控制器或操作,并可以根据您的设置调用操作。您必须在操作中使用 Route 属性才能使 [RoutePrefix] 正常工作。

例如,在下面的控制器中,对 url api/longclass/get 的所有 GET 请求将调用 GetAll 方法,对 POST 的所有请求将调用 api/longclass/post将调用PostThis

[RoutePrefix("api/longclass")]
public class MyReallyLongNamedClass: ApiController
{
    [Route("get")]
    public string GetAll(int id)
    { 
        return "result";
    }

    [Route("post")] 
    public string PostThis([FromBody] MyModel model)
    {
       var res=  _repository.Save(model);
       return res;
    }
}

以下是我在无需使用注释修饰所有方法的情况下解决问题的方法。我把 RoutePrefix 放在了 class 级别,默认的 Route

[RoutePrefix("api/longclass")]
[Route("{id?}")]
public class MyReallyLongNamedClass: ApiController
{

    public string GetAll(int id)
    { 
        return "result";
    }


    public string PostThis([FromBody] MyModel model)
    {
       var res=  _repository.Save(model);
       return res;
    }
}

另一种选择:如果您只想更改路由中的控制器名称,您可以创建自定义控制器选择器:

public class CustomControllerSelector : DefaultHttpControllerSelector
{
    public CustomControllerSelector(HttpConfiguration configuration)
        : base(configuration)
    { }

    public override string GetControllerName(HttpRequestMessage request)
    {
        var name = base.GetControllerName(request);

        // Interpret "LongClass" as "MyReallyLongNamedClass"
        if (name == "LongClass")
            name = "MyReallyLongNamedClass";

        return name;
    }
}

然后您可以在 WebApiConfig.Register:

中注册控制器选择器
config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config));

这样做的好处是您可以使用已经映射的路由(使用 HttpRouteCollection.MapHttpRoute() 定义)而不是使用属性路由。但是,如果您出于其他原因需要使用属性路由,那么您的解决方案可能会更好。