Web API Routing - api/{controller}/{action}/{id} “dysfunctions” api/{controller}/{id}

前端 未结 5 751
一向
一向 2020-12-02 06:16

I have the default Route in Global.asax:

 RouteTable.Routes.MapHttpRoute(
         name: \"DefaultApi\",
         routeTemplate: \"api/{controller}/{id}\",
          


        
相关标签:
5条回答
  • 2020-12-02 06:40

    Try this.

    public class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
    
            var json = config.Formatters.JsonFormatter;
            json.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
            config.Formatters.Remove(config.Formatters.XmlFormatter);
    
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional , Action =RouteParameter.Optional }
    
            );
        }
    }
    
    0 讨论(0)
  • 2020-12-02 06:42

    The route engine uses the same sequence as you add rules into it. Once it gets the first matched rule, it will stop checking other rules and take this to search for controller and action.

    So, you should:

    1. Put your specific rules ahead of your general rules(like default), which means use RouteTable.Routes.MapHttpRoute to map "WithActionApi" first, then "DefaultApi".

    2. Remove the defaults: new { id = System.Web.Http.RouteParameter.Optional } parameter of your "WithActionApi" rule because once id is optional, url like "/api/{part1}/{part2}" will never goes into "DefaultApi".

    3. Add an named action to your "DefaultApi" to tell the route engine which action to enter. Otherwise once you have more than one actions in your controller, the engine won't know which one to use and throws "Multiple actions were found that match the request: ...". Then to make it matches your Get method, use an ActionNameAttribute.

    So your route should like this:

    // Map this rule first
    RouteTable.Routes.MapRoute(
         "WithActionApi",
         "api/{controller}/{action}/{id}"
     );
    
    RouteTable.Routes.MapRoute(
        "DefaultApi",
        "api/{controller}/{id}",
        new { action="DefaultAction", id = System.Web.Http.RouteParameter.Optional }
    );
    

    And your controller:

    [ActionName("DefaultAction")] //Map Action and you can name your method with any text
    public string Get(int id)
    {
        return "object of id id";
    }        
    
    [HttpGet]
    public IEnumerable<string> ByCategoryId(int id)
    {
        return new string[] { "byCategory1", "byCategory2" };
    }
    
    0 讨论(0)
  • 2020-12-02 06:49

    To differentiate the routes, try adding a constraint that id must be numeric:

    RouteTable.Routes.MapHttpRoute(
             name: "DefaultApi",
             routeTemplate: "api/{controller}/{id}",
             constraints: new { id = @"\d+" }, // Only matches if "id" is one or more digits.
             defaults: new { id = System.Web.Http.RouteParameter.Optional }
             );  
    
    0 讨论(0)
  • 2020-12-02 07:04

    You can solve your problem with help of Attribute routing

    Controller

    [Route("api/category/{categoryId}")]
    public IEnumerable<Order> GetCategoryId(int categoryId) { ... }
    

    URI in jquery

    api/category/1
    

    Route Configuration

    using System.Web.Http;
    
    namespace WebApplication
    {
        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // Web API routes
                config.MapHttpAttributeRoutes();
    
                // Other Web API configuration not shown.
            }
        }
    }
    

    and your default routing is working as default convention-based routing

    Controller

    public string Get(int id)
        {
            return "object of id id";
        }   
    

    URI in Jquery

    /api/records/1 
    

    Route Configuration

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Attribute routing.
            config.MapHttpAttributeRoutes();
    
            // Convention-based routing.
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
    

    Review article for more information Attribute routing and onvention-based routing here & this

    0 讨论(0)
  • 2020-12-02 07:04

    The possible reason can also be that you have not inherited Controller from ApiController. Happened with me took a while to understand the same.

    0 讨论(0)
提交回复
热议问题