【问题标题】:ASP.NET Web Api Routing CustomizationASP.NET Web Api 路由自定义
【发布时间】: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”后缀控制器名称。

【问题讨论】:

    标签: rest asp.net-web-api wcf-web-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";
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-10
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-23
      • 1970-01-01
      • 1970-01-01
      • 2014-11-12
      相关资源
      最近更新 更多