ASP.NET Web Api Routing Customization

穿精又带淫゛_ 提交于 2019-12-21 07:18:25

问题


I have WebApi controllers that end with the "Api" suffix in their names (For ex: StudentsApiController, InstructorsApiController). I do this to easily differentiate my MVC controllers from WebApi controllers. I want my WebApi routes to look similar to

http://localhost:50009/api/students/5 and not http://localhost:50009/api/studentsapi/5.

Currently to achieve this, I am setting up routes like

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 });

This is turning out to be very cumbersome as I have to add a route for each method in my controllers. I am hoping there should be an easy way to setup route templates that automatically adds the "api" suffix the controller name while processing routes.


回答1:


I think the extensibility point you're looking for is the controller selector. You can create a class that derives from DefaultHttpControllerSelector and overrides the GetControllerName to strip out the "api" part. You can then register this controller selector on your service's configuration Services.




回答2:


Following @Youssef Moussaoui's direction I ended up writing the following code that solved the problem.

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;
    }
}

And register it in Global.asax as

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



回答3:


Now that ASP.NET Web API 2 is out, there is a much less cumbersome way to do more complex routing like that you suggested, by using attribute routing.

At the top of your controller just add the following attribute:

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

And then before each API method:

[Route("{id}"]
public HttpResponseMessage Get(int id)
{
    ...
}

There is a bit of setup required, but the positives of doing routing this way are many. For one, you can put the routing with the controllers and methods that do the actual work, so you're never searching around wondering if you have the right route. Secondly and more importantly, it's much easier to do more complex routing, like having the controller name different from the route name (like you want) or having very complex patterns to match against.




回答4:


Following Youssef's comment on muruug's answer would look something like this

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

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


来源:https://stackoverflow.com/questions/14484635/asp-net-web-api-routing-customization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!