模型和视图中的MVC“一次写入”字段

时间:2012-06-08 02:54:37

标签: asp.net-mvc razor data-annotations

我希望尽可能多地使用DRY /重用编辑器代码(视图和模型)。我的一些字段只能在创建时设置,而不能编辑。我应该看一下预先存在的MVC / DataAnnotation功能吗?

例如,如果值为非null,则可能存在导致EditorFor像DisplayFor一样运行的数据属性。

Model.cs

[Unchangeable]
string UserReferenceId { get; set; }

string Description { get; set; }

编辑:为了澄清我的目标,我已经为我目前正在计划的方法添加了示例代码的答案。如果有更好的方式/预先存在的功能,请告诉我。

2 个答案:

答案 0 :(得分:1)

System.ComponentModel.ReadOnlyAttributeSystem.ComponentModel.DataAnnotations.EditableAttribute都有(我认为EditableAttribute是.NET 4)。为标记有其中任何一个的属性创建模型元数据时,您可以看到ModelMetadata.IsReadOnly将被正确设置。

然而,令人沮丧的是,即使ModelMetadata.IsReadOnlytrue,内置编辑器模板仍会显示可编辑字段。

但是,您可以为希望遵循此元数据属性的每种数据类型创建自己的共享编辑器模板,并专门处理它。

<强>〜/查看/共享/ EditorTemplates / String.cshtml

@model String
@if (ViewData.ModelMetadata.IsReadOnly)
{
  @Html.Hidden(string.Empty, Model)
}
@(ViewData.ModelMetadata.IsReadOnly ? Html.DisplayText(string.Empty) : Html.TextBox(string.Empty))

查看模型

[Editable(false)]
public string UserReferenceId { get; set; }

您将注意到,如果模型的元数据指示IsReadOnly,我会绘制一个隐藏字段。这样就可以在帖子中保留该属性的值。

如果您根本不想显示该字段,但在帖子中保留,则可以使用System.Web.Mvc.HiddenInputAttribute。在这种情况下,只绘制隐藏。

[HiddenInput(DisplayValue=false)]
public string UserReferenceId { get; set; }

答案 1 :(得分:0)

如果没有类似的预先存在,我正在考虑实施这些:

<强> EditableWhenNewModel.cs

public class EditableWhenNewModel : IIsNew
{
    public bool IsNew { get { return recordId == 0; } }
    string UserReferenceId { get; set; }
    string Description { get; set; }
    public void Save(RepositoryItem record) {
        if (IsNew) { record.UserReferenceId = UserReferenceId; }
        record.Description = Description;
... etc.

<强> View.cshtml

@model EditableWhenNewModel
@Html.EditorWhenNewFor(m => m.UserReferenceId)
@Html.EditorFor(m => m.Description)

<强> EditorWhenNewFor.cs

public static MvcHtmlString EditorWhenNewFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression
) where TModel : IIsNew {
    return htmlHelper.ViewData.Model.IsNew ?
        htmlHelper.EditorFor(expression) :
        htmlHelper.DisplayFor(expression);
}