【问题标题】:How to Allow Null input for C# Razor page SelectList如何允许 C# Razor 页面 SelectList 的空输入
【发布时间】:2021-03-14 22:10:48
【问题描述】:

考虑以下数据模型:

public partial class RootEntity
{
    [Key]
    public long Id { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string Name { get; set; }
    public string ThingsAboutIt { get; set; }

    public long? RelatedEntity_Id { get; set; }
    [ForeignKey("RelatedEntity_Id")]
    public RelatedEntity RelatedEntity { get; set; }

}

public partial class RelatedEntity
{
    [Key]
    public long Id { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string Name { get; set; }

    public ICollection<RootEntity> RootEntities { get; set; }
}

public partial class MyContext : IdentityDbContext
{
    public MyContext(DbContextOptions<MyContext> options) : base(options) { }

    public virtual DbSet<RootEntity> RootEntities { get; set; }
    public virtual DbSet<RelatedEntity> RelatedEntities { get; set; }
}

在 Razor 页面应用程序中使用 EF (Core) 脚手架插入页面时,用于选择单链接实体记录的默认模式是:

<div class="form-group">
    <label asp-for="RootEntity.RelatedEntity_Id" class="control-label"></label>
    <select asp-for="RootEntity.RelatedEntity_Id" class ="form-control" asp-items="ViewBag.RelatedEntity_Id"></select>
</div>

它的初始化看起来像这样:

ViewData["RelatedEntity_Id"] = new SelectList(_context.RelatedEntities, "Id", "Name");

如果存在这样的属性,我可以通过将第三个参数更改为“名称”之类的东西来稍微配置一下。

我需要更多的可配置性 - 我至少需要选择空值。

为了允许空值,我使用了这种模式:

List<SelectListItem> selectList = _context.RelatedEntities
    .AsNoTracking()
    .Select(x => new SelectListItem()
    {
        Value = x.Id.ToString(),
        Text = x.Name
    })
    .ToList();

selectList.Insert(0, new SelectListItem()
{
    Value = null, // <=========== Here lies the problem...
    Text = "--- Select Related Entity ---"
});

ViewData["RelatedEntity_Id"] = selectList;

呈现的 HTML 看起来像这样:

<select class="form-control" id="RootEntity_RelatedEntity_Id" name="RootEntity.RelatedEntity_Id">
    <option selected="selected">--- select Related Entity ---</option>
    <option value="3">FOO</option>
    <option value="2">MMMBAR</option>
</select>

我遇到的问题是值“--- 选择相关实体 ---” 绑定到该模型属性。这使其验证失败。 (ModelState.IsValid == false)

我已尝试将 SelectListItem 值更改为空白字符串“-1”,但均未修复模型验证错误。

我还尝试为实体类构建自定义绑定器,但这会将根模型本身绑定到它 - 这显然与此选择列表场景无关。

解决这个问题的最简单、最优雅的方法是什么?

【问题讨论】:

  • 你能告诉我们你的模型吗?
  • @mj1313 根据您的要求更新

标签: c# asp.net entity-framework asp.net-core razor


【解决方案1】:

我已尝试将 SelectListItem 值更改为空白字符串“-1”,但均未修复模型验证错误。

如果设置为空字符串,则可以通过验证。

selectList.Insert(0, new SelectListItem()
{
    Value = "",
    Text = "--- Select Related Entity ---"
});

可以看到渲染出来的html代码,默认选项带有value属性但没有值:

当提交表单时,RootEntity.RelatedEntity_Id 将为空。

这是结果。

【讨论】:

    【解决方案2】:

    我能想到的最好的事情是以下代码行:

    ModelState.Remove("RootEntity.RelatedEntity_Id");
    

    在检查ModelState.IsValid 之前。 这似乎工作正常,而且相当优雅,我猜。

    如果我缺少一些主要的语言功能或更好的做法,我仍然愿意接受建议和批评。

    【讨论】:

      【解决方案3】:

      听起来模型验证的行为应该如此。通过像使用空值一样添加“选择”选项,模型验证将触发无效。这是因为您的模型值不可为空。如果您希望该值可以为空,您可能应该调整您的模型以接受空值。虽然它看起来确实是一个表键,但不清楚你为什么想要这种行为。

      public long? Id { get; set; }
      

      更好的是,将它与您的选择列表模型一起添加到 ViewModel 中,以便您也拥有一个强类型列表。

      【讨论】:

      • 我在写这篇文章的时候犯了一个错误,刚刚修复它。我将属性设置为public long? RelatedEntity_Id { get; set; }。但是,模型仍然无效,因为ModelState["RootEntity.RelatedEntity_Id"].AttemptedValue == "--- Select Related Entity ---",而不是ModelState["RootEntity.RelatedEntity_Id"].AttemptedValue == null
      • 发生这种情况的唯一方法是,如果您发送的选项字段“值”属性实际上是您向用户显示的文本。
      • 我就是这么想的。但是没有value 属性,它正在发送内部文本——就好像它试图“纠正我的错误”一样,这和往常一样会导致更多问题。也许还有相关信息,我正在使用 Brave 作为我的浏览器。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 2019-02-10
      相关资源
      最近更新 更多