为什么 BindNever 属性不起作用

Why BindNever attribute doesn't work

我不想在我的 CustomerViewModel 上绑定 Id 属性,所以我添加了一个 [BindNever] 属性,但它不起作用。可能的解决方案是什么?

我有以下内容:

CustomerController.cs

// PUT api/customers/5
[HttpPut("{id}")]
public async Task<IActionResult> Put([FromUri] int id, [FromBody]CustomerViewModel customer)
{
  //Implementation
}

CustomerViewModel

public class CustomerViewModel
{
    [BindNever]
    public int Id { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Email { get; set; }
}

如果我输入以下 json 。 id 属性 仍然绑定

{
  "id": 100,
  "lastName": "Bruce",
  "firstName": "Wayne",
  "email": "bruce@gothamcity.com"
}

这篇 Blog post 是一篇有趣的读物,它得出的结论是 [FromBody] 注释“覆盖”了 BindBehaviourAttributeBindNever 是一个简单的专业化)。该模型由正文中可用的所有数据填充(在本例中为您的 JSON 数据)。

我不认为这是直观的,issue 对此有一个很好的陈述:

[BindRequired] customizes the MVC model binding system . That's its purpose and it's working as designed.

[FromBody] switches the affected property or parameter into the different world of input formatting. Each input formatter (e.g. Json.NET and a small MVC-specific wrapper) can be considered a separate system with its own customization. The model binding system has no knowledge the details of JSON (or any other) deserialization.

经验教训:BindNever 在这种情况下不起作用。

有哪些替代方案?

解决方案 1:编写一些自定义模型绑定代码。我自己没有做过,但 What is the correct way to create custom model binders in MVC6? 可能会有所帮助。

解决方案 2:比较实用的解决方案

也许这个简单(但不是很好)的解决方法可以帮助您:

[HttpPut("{id}")]
public async Task<IActionResult> Put([FromUri] int id, [FromBody]CustomerViewModel customer)
{
    customer.Id = 0;
    //Implementation
}

尝试 NotMapped 属性。

正文必须至少包含 30 个字符;你输入了 24.

我加个备注。

现在微软官方给解释了

https://docs.microsoft.com/ja-jp/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#attributes-for-complex-type-targets

https://docs.microsoft.com/ja-jp/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#input-formatters

https://docs.microsoft.com/ja-jp/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#frombody-attribute

综上所述,

如果我们使用“FromBody 属性(包括默认值,例如 HttpPost 属性)”,这取决于输入格式化程序,BindNever 属性等将不起作用。

相反,我们可以通过指定与输入格式化程序对应的属性来实现。 例如,对于默认 json 可以使用 "System.Text.Json.Serialization.JsonIgnoreAttribute".

忽略

你也可以这样做

public class CustomerViewModel
{
    public int Id { get; private set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Email { get; set; }
}