c# - 在 action 方法中只接受某些 DateTime 格式
问题描述
我有这个模型:
public class CalendarAvailabilityRequest
{
[Required]
[FromQuery]
public DateTime StartDate { get; set; }
}
和这个控制器/动作方法:
[ApiController]
[Route("api/[controller]")]
public class AppointmentController : ControllerBase
{
[Route("{providerName}/CalendarAvailability")]
[HttpGet]
public Task<CalendarAvailabilityResponse> GetCalendarAvailability(CalendarAvailabilityRequest request)
{
return null;
}
}
如何确保仅"yyyy-MM-dd"
在到达端点时被接受?
例如。这将被接受:
https://example.org/api?StartDate=2019-04-17
但是这些会抛出异常:
https://example.org/api?StartDate=2019-17-04
https://example.org/api?StartDate=17-04-2017
解决方案
我建议使用fluentvalidation,因为它允许分离和重用验证规则。
在您的情况下,假设startdate
是 的一部分CalendarAvailabilityRequest
,您将为请求 dto 添加一个验证器:
public class CalendarAvailabilityRequestValidator :
AbstractValidator<CalendarAvailabilityRequest>
{
public CalendarAvailabilityRequestValidator()
{
RuleFor(request => request.StartDate)
.Must(BeAValidDateFormat).WithMessage("Date must follow the format: yyyy-mm-dd")
.NotNull().WithMessage("A start date must be provided.");
}
// will only match yyyy-mm-dd
private static bool BeAValidDateFormat(string date)
=> Regex.IsMatch(date, "2\d{3}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$", RegexOptions.Compiled);
}
在您的控制器中,您实例化一个验证器并让它验证:
[Route("{providerName}/CalendarAvailability")]
[HttpGet]
public Task<IActionResult> GetCalendarAvailability(CalendarAvailabilityRequest request)
{
var validationResult = new CalendarAvailabilityRequestValidator().Validate(request);
if (!validationResult.IsValid)
{
Log.Warning(validationResult.Errors.ToString());
return BadRequest(validationResult.Errors);
}
var statDate = DateTime.ParseExact(request.StartDate, "yyyy-mm-dd", CultureInfo.InvariantCulture);
//TODO: calendar availability logic
return OK();
}
当然,您也可以使用上面的正则表达式并在您的控制器中验证请求。
另一种选择是尝试使用DateTime.ParseExact
以下方法捕获:
try
{
var statDate = DateTime.ParseExact(request.StartDate, "yyyy-mm-dd", CultureInfo.InvariantCulture);
}
catch(exception ex)
{
Log.Warning("Request for {startdate} was invalid: {message}", request.StartDate, ex.Message);
return BadRequest(ex.message);
}
但我建议您在可以验证输入时避免尝试捕获,除非您真的需要。
推荐阅读
- spring-mvc - Spring Reactive 与 Spring MVC + MySQL 的集成
- micronaut - 如果我们有两个带有@MicronautTest 的测试类,那么嵌入式服务器将被启动多少次?
- rest - 如何获取 REST API 多对多对多信息?
- javascript - 将 PWA(渐进式 Web 应用程序)部署到 Firebase 后,如何解决“加载资源失败:服务器响应状态为 404 ()”错误?
- python - 如何在 python 3.7.3 64 位 windows 10 上安装 dlib 时修复错误
- laravel - 使用 Laravel 查询生成器,我需要来自两个表订单和出价的拒绝出价
- dji-sdk - DJI Windows 示例代码 - USB 连接 - 无法查看 FPV
- react-native - 如何使用 React Navigation 根据 React Native 中的 state 属性更改导航标题按钮样式?
- mysql - 字符串集中的 MySQL 更新字符串
- html - 在文本之上显示文本