You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core MVC中HttpMethodAttribute路由匹配异常问题求助

Hey there, let's break down and solve this routing issue you're hitting in ASP.NET Core MVC 2.2.0.

The Root Cause

First, let's understand why your original setup behaved unexpectedly:

  • When you used [HttpPut("obj/{pk?}")], the routing system only checks if the URL structure matches the template—it doesn't validate the data type of pk upfront. So when you send a request like /obj/AStringValue, the router still matches the route, but since "AStringValue" can't be converted to a decimal?, it just sets pk to null, triggering your add logic instead of returning 404.
  • When you split into two methods, the problem with pk becoming 0 happens because value types like decimal have a default value of 0. If the router matches the route with a non-decimal pk value, the binding system can't convert it, so it falls back to the default 0 instead of rejecting the request.

Fix #1: Use Route Constraints (Single Method Approach)

The cleanest fix is to add a decimal route constraint to your original method. This tells the router only to match the route if the pk segment is a valid decimal value. Non-decimal values will automatically return a 404 because the route won't be matched at all.

Here's the corrected code:

[HttpPut("obj/{pk:decimal?}")]
public IActionResult SaveObj(decimal? pk, [FromBody] ObjDef obj)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState); // Optional: Catch any other binding issues
    }

    if (pk.HasValue)
    {
        // Execute update logic for the object with pk = pk.Value
        return Ok($"Updated object with PK {pk.Value}");
    }
    else
    {
        // Execute add logic for a new object
        return CreatedAtAction(nameof(GetObj), new { pk = newCreatedPk }, obj);
    }
}

Fix #2: Split Methods with Constraints (If You Prefer Separation)

If you want to keep separate methods for add and update, you still need to add the decimal constraint to the update method to prevent invalid values from triggering it. Here's how:

// Handles PUT /obj (add new object)
[HttpPut("obj")]
public IActionResult CreateObj([FromBody] ObjDef obj)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    // Add logic here
    return CreatedAtAction(nameof(GetObj), new { pk = newCreatedPk }, obj);
}

// Handles PUT /obj/123 (only valid decimal PKs)
[HttpPut("obj/{pk:decimal}")]
public IActionResult UpdateObj(decimal pk, [FromBody] ObjDef obj)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    // Update logic here
    return Ok($"Updated object with PK {pk}");
}

With this setup, requests like /obj/AStringValue won't match either route and will return a 404, just as you expected.

Key Takeaway

Route constraints are your friend here—they let you enforce data type validation at the routing layer, before the request even reaches your controller method. This avoids unexpected binding behavior and ensures only valid requests hit your business logic.

内容的提问来源于stack exchange,提问作者T.Z.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:29:47