我正在尝试将 FromRoute 用于模型的一个属性,并将 FromBody 用于其余项目,因为 API 接受 JSON。我的代码如下:
[HttpPost("{state_id}/StateContact")]
[Authorize]
[OktaAllowedRoles(["arms-dmcp-user", "arms-oact-user", "arms-approver"])]
[EnableRateLimiting("api")]
public async Task<IActionResult> AddStateContact(AddStateContactDTO addStateContactDTO)
{
try
{
return Ok(addStateContactDTO);
}
catch(Exception ex)
{
return Ok(ex);
}
}
我的模型如下:
public class AddStateContactDTO
{
[FromRoute(Name = "state_id")]
public int StateId {get; set;}
[FromBody]
[ModelBinder(Name = "first_name")]
public string? FirstName {get; set;}
[FromBody]
[ModelBinder(Name = "last_name")]
public string? LastName {get; set;}
[FromBody]
[ModelBinder(Name = "email_address")]
[Required]
[EmailAddress(ErrorMessage = "The Email address submitted is not a valid e-mail address.")]
public required string EmailAddress {get; set;}
}
我的要求如下:
const submitAddNewStateContact = () => {
if(addStateContactValid.value) {
const json = {
first_name : newStateContactFirstNameModel.value,
last_name : newStateContactLastNameModel.value,
email_address : newStateContactEmailAddressModel.value
}
let form = new FormData();
form.append('first_name' , JSON.stringify(newStateContactFirstNameModel.value))
form.append('last_name' , JSON.stringify(newStateContactLastNameModel.value))
form.append('email_address' , JSON.stringify(newStateContactEmailAddressModel.value))
api.post('/states/'+stateModel.value!.state_id+'/StateContact', json, config).then(response => {})
}
}
使用 json 数据进行 POST 会导致以下错误:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"$": [
"The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1.",
"The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.",
"The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0."
],
"email_address": [
"The EmailAddress field is required."
]
},
"traceId": "00-bcbe8b4460713f9266f5d6bbc15b940a-1746bfdbf5ba5213-00"
}
但是,如果我要把我的模型变成这样:
[HttpPost("{state_id}/StateContact")]
[Authorize]
[OktaAllowedRoles(["arms-dmcp-user", "arms-oact-user", "arms-approver"])]
[EnableRateLimiting("api")]
public async Task<IActionResult> AddStateContact([FromForm] AddStateContactDTO addStateContactDTO)
{
try
{
return Ok(addStateContactDTO);
}
catch(Exception ex)
{
return Ok(ex);
}
}
public class AddStateContactDTO
{
[FromRoute(Name = "state_id")]
public int StateId {get; set;}
[ModelBinder(Name = "first_name")]
public string? FirstName {get; set;}
[ModelBinder(Name = "last_name")]
public string? LastName {get; set;}
[ModelBinder(Name = "email_address")]
[Required]
[EmailAddress(ErrorMessage = "The Email address submitted is not a valid e-mail address.")]
public required string EmailAddress {get; set;}
}
所以基本上切换到使用 FromForm 和 POSTing 表单数据,然后一切都按其应有的方式绑定。但是,我希望选择以 json 形式发送数据而不发送表单数据,并且还使用 FromRoute 作为模型的某些参数,但这似乎不可能。这是一个错误还是无法一起使用 FromRoute 和 FromBody?
[FromBody]
属性:
[FromBody]
应用于复杂类型参数时,应用于其属性的任何绑定源属性都将被忽略。[FromBody]
应用于每个操作方法的多个参数。一旦输入格式化程序读取请求流,就无法再读取它来绑定其他 [FromBody]
参数。因此,您必须将操作方法签名更改为:
public async Task<IActionResult> AddStateContact([FromRoute(Name = "state_id")] int stateId, [FromBody] AddStateContactDTO addStateContactDTO)
{
addStateContactDTO.StateId = stateId;
...
}
public class AddStateContactDTO
{
public int StateId {get; set;}
[ModelBinder(Name = "first_name")]
public string? FirstName {get; set;}
[ModelBinder(Name = "last_name")]
public string? LastName {get; set;}
[ModelBinder(Name = "email_address")]
[Required]
[EmailAddress(ErrorMessage = "The Email address submitted is not a valid e-mail address.")]
public required string EmailAddress {get; set;}
}