ASP.NET Web Api 路由自定义

Posted

技术标签:

【中文标题】ASP.NET Web Api 路由自定义【英文标题】:ASP.NET Web Api Routing Customization 【发布时间】:2013-01-23 16:34:50 【问题描述】:

我的 WebApi 控制器的名称以“Api”后缀结尾(例如:StudentApiController、InstructorsApiController)。我这样做是为了轻松区分我的 MVC 控制器和 WebApi 控制器。我希望我的 WebApi 路由看起来类似于

http://localhost:50009/api/students/5 而不是http://localhost:50009/api/studentsapi/5

目前为了实现这一点,我正在设置类似的路线

routes.MapHttpRoute(
name: "GetStudents",
routeTemplate: "api/students/id",
defaults: new  controller = "StudentsApi", id = RouteParameter.Optional );

routes.MapHttpRoute(
name: "GetInstructors",
routeTemplate: "api/instructors/id",
defaults: new  controller = "InstructorsApi", id = RouteParameter.Optional );

这变得非常麻烦,因为我必须在我的控制器中为每个方法添加一个路由。我希望应该有一种简单的方法来设置路由模板,在处理路由时自动添加“api”后缀控制器名称。

【问题讨论】:

【参考方案1】:

按照@Youssef Moussaoui 的指导,我最终编写了解决问题的以下代码。

public class ApiControllerSelector : DefaultHttpControllerSelector

    public ApiControllerSelector(HttpConfiguration configuration)
        : base(configuration)
    
    

    public override string GetControllerName(HttpRequestMessage request)
    
        if (request == null)
            throw new ArgumentNullException("request");

        IHttpRouteData routeData = request.GetRouteData();

        if (routeData == null)
            return null;

        // Look up controller in route data
        object controllerName;
        routeData.Values.TryGetValue("controller", out controllerName);

        if (controllerName != null)
            controllerName += "api";

        return (string)controllerName;
    

并在 Global.asax 中注册为

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
            new ApiControllerSelector(GlobalConfiguration.Configuration));

【讨论】:

muruge,如果您只调用 base.GetControllerName 然后向其添加“api”,这会容易得多。但这是正确的想法。很高兴看到这个结果:) 我同意,那样会干净得多。没打到我。 :) 我一定遗漏了一些东西,这对我不起作用。我看到我的控制器选择器被调用,它最后返回 api 但我的控制器从未被调用。【参考方案2】:

既然 ASP.NET Web API 2 已经发布,那么使用 attribute routing 就可以像您建议的那样执行更复杂的路由。

只需在控制器顶部添加以下属性:

[RoutePrefix("api/students")]
public class StudentsApiController : ApiController

    ...

然后在每个 API 方法之前:

[Route("id"]
public HttpResponseMessage Get(int id)

    ...

需要进行一些设置,但以这种方式进行路由的好处很多。一方面,您可以将路由与执行实际工作的控制器和方法放在一起,因此您永远不会四处寻找是否有正确的路由。其次,更重要的是,执行更复杂的路由要容易得多,例如控制器名称与路由名称不同(如您所愿)或匹配非常复杂的模式。

【讨论】:

它仍然需要带有属性路由的“控制器”后缀。【参考方案3】:

我认为您正在寻找的可扩展点是控制器选择器。您可以创建一个派生自 DefaultHttpControllerSelector 并覆盖 GetControllerName 以去除“api”部分的类。然后,您可以在服务的配置服务中注册此控制器选择器。

【讨论】:

听起来是个值得研究的好地方。我会试一试,然后告诉你情况如何。【参考方案4】:

在 Youssef 对 muruug 的回答发表评论之后,看起来像这样

public class ApiControllerSelector : DefaultHttpControllerSelector

    public ApiControllerSelector (HttpConfiguration configuration) : base(configuration)  

    public override string GetControllerName(HttpRequestMessage request)
    
        return base.GetControllerName(request) + "api";
    

【讨论】:

以上是关于ASP.NET Web Api 路由自定义的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net MVC 自定义路由

如何自定义 ASP .NET Web API JWT 令牌响应?

ASP.NET web api - 设置自定义 IIdentity 或 IPrincipal

asp.net web api添加自定义认证

自定义 ASP.NET MVC 404 错误页面的路由

如何在 ASP.NET Web API 中为 Json.NET 设置自定义 JsonSerializerSettings?