API de roteamento 404 se o parâmetro opcional não atendidas
-
21-12-2019 - |
Pergunta
Eu tenho esse roteamento configurado no meu WebApiConfig
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
}
e estes métodos de dentro /Api/ProductController.cs
public object GetProduct(int id)
{
var productRepo = new ProductRepository(db);
var product = productRepo.GetItem(id);
return product.ToAnonymousType();
}
public object GetTest()
{
var productRepo = new ProductRepository(this.db);
var product = productRepo.GetItem(10000);
return product.ToAnonymousType();
}
Posso solicitar /api/produto/getproduct/10000 e obter JSON de volta.
Se eu pedir /api/produto/gettest eu recebo um erro 404
Se eu mudar para gettest
public object GetTest(int id)
e pedido /api/produto/gettest/10000 eu chegar em JSON.
Eu não tenho nenhuma idéia de por que 404 está acontecendo.Eu tenho outros controladores (para não-solicitações de api) que estão lidando com solicitações como normal.Eu sou novo para o MVC depois de alguns anos de webforms, e isso tem me perplexo.Para referência, aqui está o meu RouteConfig
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
e o meu Application_Start
protected void Application_Start()
{
BundleConfig.RegisterBundles(BundleTable.Bundles);
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Solução
Isto é devido à ordenação de seus percursos.
RouteConfig.RegisterRoutes(RouteTable.Routes);
é chamado antes de
GlobalConfiguration.Configure(WebApiConfig.Register);
e o seu método RegisterRoutes contém um padrão (e muito genérico) rota
url: "{controller}/{action}/{id}"
este genérico (padrão) regra irá corresponder ao seu modelo de url de
api/product/gettest
antes de sua WebAPI rota terá uma chance para igualar.
Você pode livrar-se de que super genérico rota se não é necessário (e usar mais rotas específicas), ou simplesmente mover a chamada para
GlobalConfiguration.Configure(WebApiConfig.Register);
para vir antes da chamada para
RouteConfig.RegisterRoutes(RouteTable.Routes);
no seu Global.asax.
Fiz um exemplo com todas as informações que você deu, e movendo-se que a chamada funcionou muito bem.Espero que isso ajude.