在模型上注释属性的默认值

26

我创建了一个EF4.1的代码优先模型(可能重要,也可能不重要),现在我尝试获取我的创建脚手架模板的默认值。我的模型如下:

class Person {
    [DefaultValue (18)]
    public int Age { get; set; }
}

然后我的Create视图看起来像:

<div class="editor-label">
    @Html.LabelFor(model => model.Age)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Age)
    @Html.ValidationMessageFor(model => model.Age)
</div>

我在运行时期望EditorFor能用“18”预先填充文本框,但它并没有这样做。我是否误解了DefaultValue属性的作用,或者还有其他需要我做的事情?

注意:我不想在EditorFor方法上使用new { Value = "18" }覆盖,因为这似乎违反了DRY原则。

5个回答

34

我不知道这是否能满足您的DRY需求,但我认为这是一个开始。

我会像这样重新设计模型:

public class Person {
    private const int DEFAULT_AGE = 18;
    private int _age = DEFAULT_AGE;
    [DefaultValue(DEFAULT_AGE)]
    public int Age {
        get { return _age; }
        set { _age = value; }
    }
}

保留原视图不变,但在创建操作中执行以下操作:

public ActionResult Create() {
    return View(new Person());
}
那样做,输入文本框将会以默认的年龄值被创建,并且只有一个地方需要指定这个默认值。

我应该补充一下,我已经尝试在构造函数中设置Age属性,但似乎也不起作用。视图是强类型的Person。然而,我错过的是将一个新的Person传递到视图中。这样做可以达到我想要的效果,而你的解决方案足够DRY :)(我完全省略了DefaultValue,只使用构造函数) - Bryan Boettcher
你如何访问 DefaultValue 属性?我找不到它。 - Hanna
@Johannes也许你忘记了using System.ComponentModel- http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx - Kenji Kina
DefaultValue 只适用于视图的模型绑定,但当您再次将其传递给控制器的构造函数时,它不适用。如果未传递年龄,则它将为 null 而不是默认值。您必须拥有一个构造函数才能在两侧工作。 - Bart Calixto
2
请注意,Code First 迁移不会获取这些默认值。您需要手动将它们添加到迁移脚本中,在定义类型的调用中,您可以传递一个 defaultValue 参数。请参阅 https://dev59.com/J2gu5IYBdhLWcg3wJD2b#13953246。 - Bart Verkoeijen

7
class Person {
    public Person() {
        Age = 18;    
    }
    public int Age { get; set; }
}

在这种情况下,每次创建新的Person对象时,年龄都将被初始化为18岁,即使该新对象是由模型绑定器创建的。


1

模型

class Person {
    public Person() {
        Age = 18;    
    }
    public int Age { get; set; }
}

控制器
public ActionResult Create() {
    return View(new Person());
}

它运行良好。


1
假设你的视图有一个定义,如下所示:-
@model Person

你的控制器 HTML GET 返回一个空视图

return View();

然后只需添加一个可呈现的包含默认值的类。
return View(new Person{ Age = 18 });

另一个选择是向您的Person类添加一个单例静态助手,该助手返回一个默认填充的类。

  static public Person GetDefaultNew()
        {
            return new Person{ Age = 18 };
        }

然后你需要。

return View(new Person.GetDefaultNew());

你不需要从GetDefaultNew()中新建返回值,但我知道你的意思。在原始问题中,我只是忘记传递任何模型实例了。 - Bryan Boettcher
为了扩展我的回答,我想说值得创建自己的“ViewModel”类,该类具有视图所需的所有实例数据。这使控制器变得轻巧,您的模型带有其注释,而您的视图模型类具有业务规则和其他选项(例如设置默认业务值 - 其中一些将无法在没有引用视图模型中的其他列表的情况下知道)适用于相关视图。它还使您的视图模型高度可测试,并使视图尽可能简单。 - user1489673

0

设置 JSON.net 的 DefaultValueHandling 参数使 DefaultValue 生效:

class Person {
    [JsonProperty("Age", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
    [DefaultValue(18)]
    public int Age { get; set; }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接