【问题标题】:ASP.NET Web API Attribute Routing To Wrong ActionASP.NET Web API 属性路由到错误的操作
【发布时间】:2017-12-23 06:25:45
【问题描述】:

我在我的控制器上应用了属性路由,但它正在路由到错误的操作。我不知道我哪里弄错了。

这是我的控制器:

using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.Description;
using System.Linq;
using System;

namespace Iboo.API.Controllers
{
    public class ClientsController : ApiController
    {
        private readonly IClientRepository _repository;

        public ClientsController(IClientRepository repository)
        {
            _repository = repository;
        }

        // GET: api/Clients
        [Route("api/v1/clients")]
        public IEnumerable<Client> Get()
        {

           //code
        }


        // GET: api/Clients/5
        [HttpGet]
        [ResponseType(typeof(Client))]
        [Route("api/v1/clients/get/{id}")]
        public IHttpActionResult GetClientById(int id)
        {
            //code
        }

        // GET: api/Clients/5
        [HttpGet]
        [ResponseType(typeof(string))]
        [Route("api/v1/clients/{id}/emailid")]
        public IHttpActionResult GetClientEmailId(int id)
        {
            //code
        }        
    }
}

我对 GetClientEmailId 方法特别感兴趣。下面是我的 WebApiConfig

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
    var container = new UnityContainer();
    container.RegisterType<IClientRepository, ClientRepository>(new 
    HierarchicalLifetimeManager());


    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/v1/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

我的 Global.asax.cs 如下

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

在浏览器中如果我输入http://localhost:54919/api/v1/clients/?id=1/getemailid,它会将我带到http://localhost:54919/api/v1/clients,这不是我想要的。

如果我尝试http://localhost:54919/api/v1/clients/1/getemailid,我会收到 404 错误。

我不确定自己做错了什么。

【问题讨论】:

  • 当你说“它不工作”时......你是什么意思?你有错误吗?如果是这样,它说什么?它会到达一个意想不到的地方吗?如果有,在哪里?
  • @Munhu 我们可以看到调用 GetClientEmailId 方法的代码吗?
  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及重现它所需的最短代码在问题本身。没有明确的问题陈述的问题对其他读者没有用处。请参阅:如何创建minimal reproducible example
  • 我正在使用浏览器进行测试。我想访问localhost:54919/api/v1/clients/?id=1/getemailid,但它路由到了错误的操作。
  • @Munhu 您根据操作的路由调用了错误的 URL。您得到 404,因为您调用的 URL 与您在操作中拥有的任何路由模板都不匹配

标签: c# asp.net-web-api asp.net-web-api-routing attributerouting


【解决方案1】:

你说:

在浏览器中如果我输入http://localhost:54919/api/v1/clients/?id=1/getemailid,它会将我带到http://localhost:54919/api/v1/clients,这不是我想要的。

从您的路线设置方式来看,您似乎需要前往http://localhost:54919/api/v1/client/1/emailid 才能到达您想要的路线

为了解释差异,当您调用 http://localhost:54919/api/v1/clients/?id=1/getemailid 时,匹配的路由类似于:

[Route("api/v1/clients")]
public IHttpActionResult GetClientEmailId(string id)
{
    //code
}

因为您已将 id 参数添加为查询字符串参数。在这种情况下,id 参数的值为 1/getemailid,这没有多大意义。

通过使用路由参数(通过将?id=1/getemailid 替换为1/emailid),您实际上将匹配您想要的路由

【讨论】:

    【解决方案2】:

    您根据操作的路由调用了错误的 URL。您得到 404,因为您调用的 URL 与您在操作中拥有的任何路由模板都不匹配

    [RoutePrefix("api/v1/clients")]
    public class ClientsController : ApiController {
        //...other code removed for brevity
    
        [HttpGet]
        [Route("")] //Matches GET api/v1/Clients
        public IHttpActionResult Get() {
           //code
        }
    
        [HttpGet]
        [ResponseType(typeof(Client))]
        [Route("{id:int}")] //Matches GET api/v1/Clients/5
        public IHttpActionResult GetClientById(int id) {
            //code
        }
    
        [HttpGet]
        [ResponseType(typeof(string))]
        [Route("{id:int}/emailid")] //Matches GET api/v1/Clients/5/emailid
        public IHttpActionResult GetClientEmailId(int id) {
            //code
        }        
    }
    

    记下 cmets 中的预期 URL

    您还应该阅读Attribute Routing in ASP.NET Web API 2 以更好地了解如何进行属性路由。

    【讨论】:

      【解决方案3】:

      您可以尝试在控制器上使用路由前缀。

      [RoutePrefix("api/v1/clients")]
      public class ClientsController : ApiController
      {
          // GET: api/Clients/5
          [ResponseType(typeof(string))]
          [Route("{id:int}/emailid"),HttpGet]
          public IHttpActionResult GetClientEmailId(int id)
          {
              //code
          }     
      }
      

      【讨论】:

        猜你喜欢
        • 2014-07-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-17
        • 2017-08-16
        • 1970-01-01
        • 2015-03-19
        • 2013-06-15
        • 2018-01-01
        相关资源
        最近更新 更多