我的教宗观点没有特定的排列:
String
。
DateOnly?
(又名 Nullable<DateOnly>
)。应该使用
Nullable<T>
,因为它允许空 日期输入,而
<input type="date" value="" />
允许,而在使用 ASP.NET 的模型绑定时,不可为空的
DateOnly
视图模型属性更难使用,因为任何表单字段可以为空或无效,或者只是普通的未定义。您可能认为
[Required]
属性解决了这个问题,但事实并非如此:
[Required]
属性不会阻止属性为空,它只是在属性为空时阻止
ModelStateDictionary.IsValid
返回
true
,这意味着您始终需要正确(如果不是优雅地)处理空/未定义的表单字段,并将其与值类型的
default(T)
区分开来(例如 default(DateOnly)
是 .
class MyPageViewModel
,它可以公开DateOnly?
参数。
<input type="date" />
要求
value=""
参数格式为 yyyy-MM-dd
。HTML-Helpers 如今实际上已经过时,请考虑使用 Tag-Helpers。
<input asp-for="YMDEFF" type="date" />
Html.TextBoxFor
。
asp-for=""
special
ModelExpression
属性,就像 TextBoxFor
的 Expression<>
参数一样,它用于在运行时生成 id=""
和 name=""
属性。
public String SomeProperty { get; } = null!
它在很多层面上都是错误的。 如果一个
String
can曾经是
null
那么它的类型 must是
String?
- 而不是 String
- 并且对 null
的初始化只是多余的。如果 String
null
,则将其初始化为 = String.Empty
或 = ""
,而不是 null!
,yikes。
YMDEFF
YMDEND
- 在 C#/.NET 中,我们使用 PascalCase
和
camelCase
,这样所有 3 个字母或更长的单词和首字母缩略词始终为
TitleCase
,而所有 2 字母缩写始终为大写(如 IO
),而 2 字母缩写(如“Database”的 Db
)则不是。
现在 YMDEFF
YMD
指的是日期格式,而“Eff”是“Effective”的缩写,所以只需将其命名为 EffectiveDate
。并且YMDEND
EndDate
。
public class MyPageViewModel
{
// [Required] // <-- Uncomment or delete this line, based on your actual requirements.
[DisplayFormat( DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true )] // <-- This attribute is necessary to ensure the `<input value=""/>` attribute has the correct format that HTML requires.
public DateOnly? EffectiveDate { get; set; }
// [Required]
[DisplayFormat( DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true )]
public DateOnly? EndDate { get; set; }
}
您的 Razor 标记可能如下所示:
@model MyPageViewModel
// etc
<form asp-controller="Foobar" asp-action="Post">
<div class="field">
<label asp-for="EffectiveDate"></label>
<input asp-for="EffectiveDate" type="date" />
<span asp-validation-for="EffectiveDate"></span>
</div>
<div class="field">
<label asp-for="EndDate"></label>
<input asp-for="EndDate" type="date" />
<span asp-validation-for="EndDate"></span>
</div>
<button type="submit">Submit</button>
</form>
您的控制器操作将保存数据库(令人讨厌的)基于
String
的日期和
DateOnly
日期之间的编组逻辑:[HttpGet( "/my-form" )]
public async Task<IActionResult> GetForm()
{
SomeEntityClass e = await this.db.GetThingAsync();
MyPageViewModel vm = new MyPageViewModel()
{
EffectiveDate = DateOnly.TryParseExact( format; "yyyyMMdd", value: e.YMDEFF, out DateOnly parsed ) ? parsed : (DateOnly?)null,
EndDate = DateOnly.TryParseExact( format; "yyyyMMdd", value: e.YMDEND, out DateOnly parsed ) ? parsed : (DateOnly?)null
};
return this.View( model: vm );
}
[HttpPost( "/my-form" )]
public async Task<IActionResult> PostForm( [FromForm] MyPageViewModel model )
{
SomeEntityClass e = await this.db.GetThingAsync();
if( !this.ModelState.IsValid ) return this.View( model: model );
Debug.Assert( model.EffectiveDate.HasValue ); // <-- This is to workaround how the C# compiler isn't aware that `ModelState.IsValid` indicates (for example) non-nullability of those View-Model properties.
Debug.Assert( model.EndDate.HasValue );
//
e.YMDEFF = model.EffectiveDate.Value.Tostring( format: "yyyyMMdd" );
e.YMDEND = model.EndDate .Value.Tostring( format: "yyyyMMdd" );
await this.db.SaveChangesAsync();
return this.RedirectToAction( nameof(GetForm) );
}