【问题标题】:MVC 4 Custom template for bool (razor)MVC 4 bool(剃刀)的自定义模板
【发布时间】:2013-01-03 18:16:17
【问题描述】:

我正在使用 twitter 引导框架,所以为了让 EditorFor 和 DisplayFor 方法输出我需要的内容,我为字符串、文本、密码等每种类型创建了自定义模板。对于我的登录页面,我想要一个 RememberMe bool,所以和以前一样,我创建了以下模板并放入Boolean.cshtml中:

@model bool

<div class="control-group">
    <div class="controls">
        <label class="checkbox">
            @Html.CheckBoxFor(m => m, new {@class = "checkbox"})
            @Html.LabelFor(m => m)
        </label>
    </div>
</div>

很简单,但是当我使用时:

@Html.EditorFor(m => m.RememberMe)

我得到一个异常,说基于的值不能为空:

The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type 'System.Boolean'.

我错过了什么?似乎它应该是直截了当的。模型对象上的字段如下所示:

[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }

谢谢。

更新:所以看起来最终是创建一个空的视图模型对象并将其传递给视图,而不是让 MVC 自己创建一个。

【问题讨论】:

  • 您可以尝试使用数据注释[DefaultValue(false)] 设置RememberMe 默认值

标签: c# .net asp.net-mvc razor


【解决方案1】:

我不会那样做。如果该值可以为空,我会确保您的编辑器模板具有可空的布尔值作为模型类型。因此,您的编辑器模板(在 Views\Shared\EditorTemplates\Boolean.cshtml 中)将是:

@model Boolean?

@Html.CheckBox("", Model.HasValue && Model.Value)

然后在您的主视图中,您可以:

<div class="control-group">
    <div class="controls">
        <label class="checkbox">
            @Html.EditorFor(m => m, new {@class = "checkbox"})
            @Html.LabelFor(m => m)
        </label>
    </div>
</div>

【讨论】:

  • 我喜欢这种方法。布尔值通常不能为空(无论如何不在我使用的模型对象中),但我认为这种方法将允许它使用标准 MVC 方式调用视图,而不是创建一个新的空模型对象.注意:我实际上认为这是对我最初问题的实际答案,我的答案是一种解决方法。
【解决方案2】:

阅读到目前为止的回复,我开始想知道模型对象是如何被初始化的。所以这很奇怪,但我找到了答案。希望有人可以解释其中的怪异之处。如果您不指定模型对象,可能是 MVC 初始化模型对象的方式。

默认的 MVC Internet 模板具有以下登录操作:

[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
    ViewBag.ReturnUrl = returnUrl;

    return View();
}

这给出了错误。但是,将其更改为以下内容可以解决问题:

[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
    var loginModel = new LoginModel();

    ViewBag.ReturnUrl = returnUrl;

    return View(loginModel);
}

所以这回答了如何解决问题的问题,但仍然没有解决原因。可能是因为 MVC 以不同的方式创建对象的实例,比如使用反射或其他方式?

【讨论】:

  • 看起来在第一个示例中您没有设置视图模型 - 但您的视图期待一个......因此属性(和模型)都是空的。仔细检查错误,因为我希望 null 出现在模型上,而不是属性本身。第二个例子,你显式地实例化了视图模型,所以世界是个好地方。
  • 是的,这似乎是正在发生的事情。第一位是默认的 MVC 模板代码,它可以正常工作。我假设 MVC 在某个地方创建了视图模型,但对于自定义模板来说还不够快。
  • 不同的是MVC3 EditorFor是public static class EditorExtensions中的扩展方法返回MvcHtmlString。这意味着它可以处理空值并返回空复选框。我的建议:a) 保留你所拥有的......如果你愿意,你甚至可以将 returnUrl 添加到模型中。 b) 在视图中,添加一个@code 块并为复选框设置一个本地布尔值。 c) 添加一个 editorfor 作为您自己的返回 mvchtmlstring 的扩展方法。最后:您使用自己的编辑器模板覆盖 EditorFor 的原因是什么?可以用css代替吗?
【解决方案3】:

您可以更改模型,使其接受空值作为“是”/“否”

public bool? RememberMe { get; set; }

【讨论】:

    【解决方案4】:

    你必须在构造函数中初始化你的RememberMebool value,如下所示。

    请记住,不允许在 C# 中使用未初始化的变量。

    using System.ComponentModel; 
    
    public class ClassName
     {    
       public ClassName ()
            {
                RememberMe = false;
            }
    
       [DefaultValue(false)]
       [Display(Name = "Remember me?")]
       public bool RememberMe { get; set; }
     }
    

    更多信息请查看Default Values Table

    希望对你有帮助。

    【讨论】:

    • 只有引用类型有null 作为默认值。 Bool 是一个值类型,是bool is false. 的默认值。 OP 有一个简单的 bool 属性,一个不可为空的布尔值(例如 bool?)。
    • 我的印象是 bool 的默认值为 false。无论如何,我尝试在构造函数和 DefaultValue 属性中设置为 false,结果与以前相同。我想知道我是否只是模板有其他问题。当我使用@Html.ComboBoxFor 直接在代码中使用它时,效果很好,因此设置了布尔值。
    • @TyrelVanNiekerk 你能把整个类与“@model bool”模型相关吗?
    • public class LoginModel { [Required] [Display(Name = "User name")] public string Username { get;放; } [必需] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get;放; } [Display(Name = "还记得我吗?")] public bool RememberMe { get;放; } }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多