[英]C# WebApi ModelBinding Validation in custom property type of DTO
我在控制器中有一條路線,並轉移了一些模型。 此模型 (DTO) 包含自定義類型屬性(例如,密碼、郵政編碼……)。 我想添加一個像這里描述的模型綁定器( https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-6.0 )到屬性類型(密碼)。 !不是整個DTO!
生成的模型 (DTO) 定義應如下所示:
namespace UserService.Models.DTO
{
public class UserRegisterDto
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
public Password Password { get; set; }
}
}
現在傳輸 JSON(例如,見下文)時,應自動驗證 Password 屬性。
{
"firstname": "John",
"lastname": "Doe",
"email": "johndoe@mail.com",
"password": "Test12345!"
}
路由實現應如下所示:
namespace UserService.Controllers
{
[ApiController]
[Route("/api/user/")]
public class AuthController : ControllerBase
{
[HttpPost("register")]
public async Task<ActionResult> Register(UserRegisterDto request)
{
User? user = await this._userService.Register(request);
if (user == null)
{
return BadRequest();
}
return Ok(user);
}
}
}
起初我以為我可以實現以下內容,但驗證根本不起作用......
namespace UserService.Models
{
[ModelBinder(typeof(PasswordEntityBinder))]
public class Password
{
private const string PasswordRegex = "(?=^.{8,}$)(?=.*\\d)(?=.*[!@#$%&?*\\\"§$\\/()=~]+)(?![.\\n])(?=.*[A-Z])(?=.*[a-z]).*$";
#region Properties
public string Value { get; set; }
public override string ToString() => Value;
public static implicit operator string(Password e) => e.Value;
public static bool TryParse(ReadOnlySpan<char> s, out Password? result)
{
result = null;
if (string.IsNullOrWhiteSpace(s.ToString()))
return false;
if (!Regex.IsMatch(s.ToString(), PasswordRegex))
return false;
result = new Password()
{
Value = s.ToString(),
};
return true;
}
}
}
有誰知道是否有可能實現對用作模型(DTO)中的屬性的類型的模型綁定?
由於我對使用某些 3rd 方庫不滿意,因此我正在進一步尋找我的問題。 我找到了一個合適的解決方案,它允許我使用自定義復雜類型,例如 int 同時進行驗證和轉換。 此解決方案適用於 asp.net net6.0。 我用:
json 密碼首先使用 JSON 轉換器進行轉換,然后進行驗證。
下面顯示了示例,它可以應用於任何類型:
// Password.cs
namespace UserService.Models
{
[JsonConverter(typeof(PasswordJsonConverter))]
public class Password : IValidatableObject
{
private const string PasswordRegex = "(?=^.{8,}$)(?=.*\\d)(?=.*[!@#$%&?*\\\"§$\\/()=~]+)(?![.\\n])(?=.*[A-Z])(?=.*[a-z]).*$";
public string Value { get; set; } = "";
public override string ToString() => Value;
public static implicit operator string(Password e) => e.Value;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(this.Value))
{
yield return new ValidationResult("Password may not be empty");
yield break;
}
if (!Regex.IsMatch(this.Value, PasswordRegex))
yield return new ValidationResult("Password invalid formatted");
}
}
}
// PasswordJsonConverter.cs
namespace UserService.Converter
{
public class PasswordJsonConverter : JsonConverter<Password>
{
public override bool CanConvert(Type typeToConvert)
{
return (typeToConvert == typeof(Password));
}
public override Password? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Password pw = new Password();
string? pw_string;
try
{
pw_string = reader.GetString();
}catch(InvalidOperationException)
{
return null;
}
if (pw_string == null)
return null;
pw.Value = pw_string;
return pw;
}
public override void Write(Utf8JsonWriter writer, Password value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
}
這使我可以像使用任何基本類型一樣在 DTO 中使用 Password 對象。 例如:
// RegisterDto.cs
namespace UserService.Models.DTO
{
public class UserRegisterDto
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
public Password Password { get; set; }
}
}
輸入 json 看起來像:
{
"firstname": "John",
"lastname": "Doe",
"email": "johndoe@mail.com",
"password": "Test12345!"
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.