在ASP.NET Core 3.0 Web API
中,我对Post
和Put
方法使用了相同的 DTO 。创建新的Item
时,我要防止已有的名称。像这样:
public ItemValidator(IItemRepository itemRepository)
{
RuleFor(input => input.Name).NotEmpty();
RuleFor(input => input.Name).Must(name => !itemRepository.ItemExists(name))
.WithMessage(input => $"Item '{input.Name}' already exists");
}
所有这些都非常适合更新和插入。您无法将名称更新为已经存在的名称。但!当您尝试将“ ItemA”更改为“ ItemA”(新名称与旧名称相同)时,您会收到该错误,并且可能会有点误导(尽管从技术上来说是正确的)。
在 dto 本身中,我没有唯一的id
项。因为我在路径中传递了id
。
如果我可以访问已调用的Controller方法及其参数(包括id
),则可以判断是否有人试图将项目名称更改为相同名称。
答案 0 :(得分:3)
FluentValidation可以识别调用了哪个HTTP方法。为此,您将需要在StartUp文件的ConfigureServices方法中添加HttpContextAccessor。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddHttpContextAccessor();
services.AddMvc(setup => { }).AddFluentValidation();
services.AddTransient<IValidator<MyModel>, MyModelValidator>();
}
现在,您可以在验证器类中使用IHttpContextAccessor。 这是我的验证器类
public class MyModelValidator : AbstractValidator<MyModel>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public MyModelValidator(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
RuleFor(myModel => myModel.Id)
.NotEmpty();
RuleFor(myModel => myModel.Value)
.Must(value => MyRule(value, _httpContextAccessor.HttpContext.Request.Method));
}
private bool MyRule(string value, string method)
{
if (method.ToUpper() == "POST")
{
return true;
}
else if (method.ToUpper() == "PUT")
{
// validatation logic for value
return !string.IsNullOrWhiteSpace(value);
}
return false;
}
}
您可以按照以下方式从_httpContextAccessor获取请求路径
var path = _httpContextAccessor.HttpContext.Request.Path.Value;
编辑:
如果这可以解决您的问题,请考虑将此答案标记为接受。