. net Core webapi模式的错误请求



我正在使用。net Core 5 Web API,我正在尝试确定是否有比我当前处理400个错误请求的逻辑更好的模式。

类似于这个问题-在ASP中返回错误的最佳实践。. NET Web API

下面是我的代码
[HttpPost("register-customer")]
[Produces("application/json")]
[MapToApiVersion("1")]
public async Task<ActionResult<IRegistrationStatus>> RegisterCustomer([FromBody] Customer customer)
{
try
{
if (customer == null)
return StatusCode(400, "Request body is required");
if (string.IsNullOrEmpty(customer.FirstName))
return StatusCode(400, "First name is required");
if (string.IsNullOrEmpty(customer.LastName))
return StatusCode(400, "Last name is required");
if (string.IsNullOrEmpty(customer.EmailAddress))
return StatusCode(400, "Email address is required");
if (customer.Roles == null || customer.Roles.Count == 0)
return StatusCode(400, "At least one role is required");
//call service to register
return Ok(registrationStatus);
}
catch (Exception ex)
{
return StatusCode(500, ex.ToString());
}
}

所有的代码工作得很好,但我想知道是否有一个更好的模式,我可以使用多个if语句的每个道具,我想检查。RegisterEmployee例如我还有其他api和employee类不同的模型,但它有一些相同的字段,正在检查400 - I, e FirstName、LastName——我不真的想要改变模型坐在说无论我想我可以一个人接口做然后员工和客户都将继承它,如果我做它可能打破改变消费者的api

您可以使用:

  • ApiController属性。它将强制自动HTTP 400响应。
  • 在模型dto类的成员上使用数据注释。强制FirstName不为空:
public class Customer
{
[Required]
public string FirstName { get; set; }
public string LastName { get; set; }
}

应用这两种技术可以省略if检查。

您应该使用DataAnnotations而不是逐个检查每个字段。您可以返回ModelState 400。

另一个解决方案是使用Fluent Validation。这个包可以在Nuget管理器中找到。

Api控制器:

[HttpPost]
public async Task<ApiResponse> Create([FromBody] BPRPEmailDto bprpEmail)
{
BPRPEmail _bPRPEmailDto = _mapper.Map<BPRPEmail>(bprpEmail);
ValidationResult result = _bprpEmailValidator.Validate(_bPRPEmailDto);
if (!result.IsValid)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(error.ErrorCode, error.ErrorMessage);
}
throw new ApiProblemDetailsException(ModelState);
}
await _db.BPRPEmails.AddAsync(_bPRPEmailDto);
await _db.SaveChangesAsync();
return new ApiResponse("New record has been created in the database.", _mapper.Map<BPRPEmailDto>(_bPRPEmailDto), 201);
}

这段代码是做什么的?控制器得到一个BPRPEmailDto,然后将它映射到我们的模型BPRPEmail。之后,它将此对象发送给Fluent Validation。

public class BPRPEmailValidator : AbstractValidator<BPRPEmail>
{
private readonly AppDbContext _db;
public BPRPEmailValidator(AppDbContext db)
{
_db = db;
RuleFor(x => x.Id);
RuleFor(x => x.Email).NotEmpty().Must((model, Email) => BeUniqueEmail(model, Email)).WithMessage("An email should be unique in the database");
RuleFor(x => x.Email).EmailAddress().WithMessage("Please enter a valid email adress");
RuleFor(x => x.BPResponsiblePersonId).NotEmpty().WithMessage("An Email's ResponsiblePersonID is required in the database");
RuleFor(x => x.BPResponsiblePersonId)
.Must(BeRegisteredResponsiblePerson).WithMessage("An Email's ResponsiblePersonID should be a reqistered ResponsiblePerson in the database");
}

private bool BeUniqueEmail(BPRPEmail sCRPEmail, string email)
{
var dbEmail = _db.BPRPEmails.Where(x => x.Email == email).FirstOrDefault();
if (dbEmail == null)
return true;
return sCRPEmail.Id == dbEmail.Id;
}
private bool BeRegisteredResponsiblePerson(int id)
{
if (id == 0)
return true;
if (_db.BPResponsiblePeople.Any(x => x.Id == id))
return true;
return false;
}
}

如果存在验证错误,我们将这些错误添加到ModelState并抛出ApiProblemDetailsException。在前端,我们捕获这个响应

try
{
BPRPEmailDto.ResponsiblePersonId = ResponsiblePersonId;
var response = await BPResponsiblePeopleScreenUseCases.CreateEmailToBPRP(BPRPEmailDto);
ShowNotification(new NotificationMessage { Severity = NotificationSeverity.Success, Summary = "Insert", Detail = $"Email with id {response.Id} inserted successfully.", Duration = 4000 });
isCreate = false;
await _bprpEmailGrid.Reload();
}
catch (Exception e)
{
JsonElement JsonErrors = JsonSerializer.Deserialize<dynamic>(e.Message);
if (JsonErrors.GetProperty("validationErrors").EnumerateArray().Count() != 0)
{
foreach (var error in JsonErrors.GetProperty("validationErrors").EnumerateArray())
{
ShowNotification(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = error.GetProperty("name").ToString(), Detail = error.GetProperty("reason").ToString(), Duration = 4000 });
}
}
else
{
ShowNotification(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "Error", Detail = JsonErrors.GetProperty("title").ToString(), Duration = 4000 });
}
await InsertRow(BPRPEmailDto);
}

在我们反序列化请求之后,在foreach循环中,我们可以向用户显示所有的验证错误。

在我的例子中,我使用了AutoMapper、AutoWrapper和Fluent Validation。我建议你学习如何使用AutoMapper和AutoWrapper,但是为了验证,你也可以使用DataAnnotations。

最新更新