为啥我的属性路由不起作用?

Posted

技术标签:

【中文标题】为啥我的属性路由不起作用?【英文标题】:Why is my attribute routing not working?为什么我的属性路由不起作用? 【发布时间】:2017-10-29 06:55:04 【问题描述】:

这是我的控制器的样子:

[Route("api/[controller]")]
[Produces("application/json")]
public class ClientsController : Controller

    private readonly IDataService _clients;

    public ClientsController(IDataService dataService)
    
        _clients = dataService;
    

    [HttpPost]
    public int Post([Bind("GivenName,FamilyName,GenderId,DateOfBirth,Id")] Client model)
    
        // NB Implement.
        return 0;
    

    [HttpGet("api/Client/Get")]
    [Produces(typeof(IEnumerable<Client>))]
    public async Task<IActionResult> Get()
    
        var clients = await _clients.ReadAsync();
        return Ok(clients);
    

    [HttpGet("api/Client/Get/id:int")]
    [Produces(typeof(Client))]
    public async Task<IActionResult> Get(int id)
    
        var client = await _clients.ReadAsync(id);
        if (client == null)
        
            return NotFound();
        

        return Ok(client);
    

    [HttpGet("api/Client/Put")]
    public void Put(int id, [FromBody]string value)
    
    

    [HttpGet("api/Client/Delete/id:int")]
    public void Delete(int id)
    
    

然而当我请求网址/api/Clients/Get时,如下:

json = await Client.GetStringAsync("api/Clients/Get");

我得到以下异常:

AmbiguousActionException:匹配多个动作。下列 动作匹配路由数据并满足所有约束:

Assessment.Web.Controllers.ClientsController.Index (Assessment.Web) Assessment.Web.Controllers.ClientsController.Details (Assessment.Web) Assessment.Web.Controllers.ClientsController.Create (Assessment.Web)

Client 是一个HttpClient。请注意,没有 GET 操作匹配路由数据,尽管名称相同,id

这里有什么问题?

【问题讨论】:

mvc-5? - 看起来像 asp.net-core-mvc @StephenMuecke 这是核心,我的错。我经常混淆 MVC 5 和 6。 这是ClientsController的整个界面吗?异常消息中的 3 个操作方法不在代码示例中。如果所有内容都已发布,我们将需要查看您的其余路由配置,以确定哪个路由与api/Clients/Get 的请求匹配。 @NightOwl888 这是唯一控制器的完整代码。在 API 中。原来这些错误消息来自客户端项目中的控制器。 【参考方案1】:

你使用了错误的属性。

控制器上有路由

[Route("api/[controller]")]

这将映射到api/Clients,并将其作为控制器中任何操作路由的前缀。

这意味着

[HttpGet("api/Client/Get")] // Matches GET api/Clients/api/Client/Get
[Produces(typeof(IEnumerable<Client>))]
public async Task<IActionResult> Get()

    var clients = await _clients.ReadAsync();
    return Ok(clients);

由于控制器上的路由前缀,将 GET 匹配到 api/Clients/api/Client/Get

引用Routing to Controller Actions

您需要相应地更新动作上的属性路由

[Route("api/[controller]")]
[Produces("application/json")]
public class ClientsController : Controller 
    private readonly IDataService _clients;

    public ClientsController(IDataService dataService)
    
        _clients = dataService;
    

    [HttpPost] //Matches POST api/Clients
    public int Post([Bind("GivenName,FamilyName,GenderId,DateOfBirth,Id")] Client model) 
        // NB Implement.
        return 0;
    

    [HttpGet("Get")] //Matches GET api/Clients/Get
    [Produces(typeof(IEnumerable<Client>))]
    public async Task<IActionResult> Get() 
        //...code removed for brevity
    

    [HttpGet("Get/id:int")] //Matches GET api/Clients/Get/5
    [Produces(typeof(Client))]
    public async Task<IActionResult> Get(int id) 
        //...code removed for brevity
    

    [HttpGet("Put")] //Matches PUT api/Clients/Put
    public void Put(int id, [FromBody]string value) 
        //...code removed for brevity
    

    [HttpGet("Delete/id:int")] //Matches GET api/Clients/Delete/5
    public void Delete(int id) 
    

删除操作实际上应该被重构为 HTTP DELETE 并且应该返回一个IActionResult

[HttpDelete("Delete/id:int")] //Matches DELETE api/Clients/Delete/5
public IActionResult Delete(int id) 
    //...code removed for brevity

【讨论】:

【参考方案2】:

我认为路径中有错字,应该是 Clients,末尾带有 (s) 而不是 Client。

[HttpGet("api/Clients/Get")]

而不是

[HttpGet("api/Client/Get")]

或者把对端点的调用改为:

 json = await Client.GetStringAsync("api/Client/Get");

【讨论】:

以上是关于为啥我的属性路由不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 React 路由在组件中不起作用?

为啥 Laravel 发布方法在路由器页面上不起作用?

为啥宽度属性在我的桌子上不起作用?

为啥路由器链接不起作用,尽管我使用与 href 相同的组件链接并且它可以工作?

为啥 FileSearch 元素的 MinVersion 属性在我的 WiX 安装程序中不起作用?

为啥 flex 属性在反应样式的组件中不起作用?