将DTO属性保证为某些值,同时向控制器和价值设置进行传入请求
我有一个DTO,其中只想接受某些价值,说“准备就绪”或“开始”,而别无其他。 我试图通过在设定方法中放置一些“验证”来阻碍任何其他被分配给该物业的价值,例如
public class Dto
{
private string? _status;
public string? Status
{
get => _status;
set
{
_status = !string.IsNullOrWhiteSpace(value) &&
(value == "Ready" ||
value == "Started")
? value
: throw new ArgumentException("Status value was not allowed. Value: " + value);
}
}
}
(一个人可以使用“准备就绪”和“开始”的枚举)
为什么我要这个?
- > DTO的目的是充当控制器和数据库表之间的数据载体。根据我的经验,前端和后端逻辑频繁地依赖于属于一组值的数据库中的字符串值,尤其是在字符串的情况下。
因此,这里的目标是严格执行弦 - 托管以仅接受某些特定值。通过具有此限制,我实现了至少可以看到的2件事:
- 对控制器的输入将来将是不正确的
- 当忘记了所接受的价值的规则时,将来 ,它阻碍了我本人和其他程序员但是
DTO并在那里进行相同的验证,这会在响应中产生更简洁的错误消息。 上面的类重写:
public class Dto : IValidatableObject
{
private string? _status;
public string? Status
{
get => _status;
set
{
_status = IsValidStatus(value)
? value
: throw new ArgumentException("Status value was not allowed. Value: " + value);
}
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (IsValidStatus(Status))
yield return new ValidationResult("Ticket status invalid");
}
private bool IsValidStatus(string input)
=> string.IsNullOrWhiteSpace(input) &&
(input== "Ready" ||
input== "Started");
}
如果这是按预期工作的,那么不正确的状态会产生像
{
"type": "...",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "...",
"errors": {
"Status": [
"Value wasn't an accepted status."
]
}
}
我遇到的问题一样的响应,即在执行验证之前实例化了DTO,因此产生了例外和500响应,
所以我会蒙受损失关于如何
- 在控制器中验证,并
- 限制DTO不正确设置值。
谢谢
I have a dto with a property where I only want to accept certain values, say ”Ready” or ”Started” and nothing else.
I try to hinder any other values of being assigned to the property by placing some ”validation” inside the set-method, such as
public class Dto
{
private string? _status;
public string? Status
{
get => _status;
set
{
_status = !string.IsNullOrWhiteSpace(value) &&
(value == "Ready" ||
value == "Started")
? value
: throw new ArgumentException("Status value was not allowed. Value: " + value);
}
}
}
(One could use enums for ”Ready” and ”Started” of course)
Why would I want this?
-> the purpose of the dto is to act as a carrier of data between a controller and database table. In my experience, frontend- and backend-logic more often than not dependent on string-values in the database belonging to a set of values, especially in the case of strings.
Therefore, the goal here is to strictly enforce a string-property to only accept some particular values. By having this limitation, I achieve what I can see at least 2 things:
- Input to Apimethod in controllers won’t be able to be incorrect
- In the future when the rule of what values are accepted is forgotten, it hinders myself and other programmers from using the dto in an unsought manner (unless of course the ”validation” is altered)
However, If we agree on that it is bad practice to return exceptions instead of controlled http-responses in a controller, I imagined I could add IValidatableObject to the dto and make the same validation there, this produces a more concise error message in the response.
The above class rewritten:
public class Dto : IValidatableObject
{
private string? _status;
public string? Status
{
get => _status;
set
{
_status = IsValidStatus(value)
? value
: throw new ArgumentException("Status value was not allowed. Value: " + value);
}
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (IsValidStatus(Status))
yield return new ValidationResult("Ticket status invalid");
}
private bool IsValidStatus(string input)
=> string.IsNullOrWhiteSpace(input) &&
(input== "Ready" ||
input== "Started");
}
If this was working as intendend, an incorrect status produces a response like
{
"type": "...",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "...",
"errors": {
"Status": [
"Value wasn't an accepted status."
]
}
}
The problem I have is that the Dto is instantiated before the validation is performed, thus producing a exception and 500-response instead
So I am at a loss at how to
- having Validation in my controller, and
- limit the Dto from accepting incorrectly set values.
Thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以使用正则验证:
另一个(可能更清洁的)解决方案是实现自定义验证属性: https://learn.microsoft.com/en-us/aspnet/aspnet/core/core/core/mvc/mmodels/models/Validation?view = wiew = =自定义属性
您必须在设定器方法中删除代码。但这应该没问题,因为ASP将确保在请求到达控制器之前进行验证。
You could use a RegEx validation like so:
Another (probably cleaner) solution would be to implement a custom validation attribute: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-6.0#custom-attributes
You would have to remove the code in your setter method. But that should be no problem since ASP will ensure that the validation will be run before the request reaches your controller.