ASP.NET MVC 5 - 如何在ViewModel中添加[必需]数据注释

时间:2017-05-04 13:05:12

标签: c# asp.net-mvc entity-framework data-annotations

我在名为UnitAdminViewModel的视图模型中调用了三个模型(Unit,Site,Work_Type)。我需要根据单位模型的要求设置一个字段。由于我使用的是Database First方法,因此无法直接修改单元模型,因为这会自动生成。如何成功添加:

[Required(ErrorMessage = "Group is required")] public string GroupName { get; set; }

到我的视图模型UnitAdminViewModel?

public class UnitAdminViewModel
{
    public Unit Unit { get; set; }
    public List<Site> Site { get; set; }
    public IEnumerable<Work_Type> Work_Type { get; set; }
}

在单元模型中,我想将字段GroupName设置为[Required]

public partial class Unit
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Unit()
    {
        this.Staffs = new HashSet<Staff>();
    }

    public int UnitID { get; set; }
    public string UnitCode { get; set; }
    public string UnitName { get; set; }
    public string GroupName { get; set; }
    public byte IncentiveUnit { get; set; }
    public bool CallCenter { get; set; }
    public bool CDWUnit { get; set; }
    public string CDWSite { get; set; }
    public Nullable<int> SiteID { get; set; }
    public Nullable<int> DivisionID { get; set; }
    public bool WFCUnit { get; set; }
    public bool QAMonitored { get; set; }
    public bool NICEMonitored { get; set; }
    public string ListPrefix { get; set; }
    public string TSHSource { get; set; }
    public string StatsSource { get; set; }
    public string DialerSource { get; set; }
    public Nullable<int> CostCenterID { get; set; }
    public int WaterfallView { get; set; }
    public bool Locked { get; set; }
    public string Platform { get; set; }
    public Nullable<int> Supplier { get; set; }
    public string Work_Type { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Staff> Staffs { get; set; }
}

更新

我尝试了离开@Izzy的例子。我觉得我离我更近了,但是当我提交一个没有填充该字段的表单时,[Required]似乎仍然没有触发验证错误。 @Izzy,有什么我可能会失踪的吗?

查看模型

public class UnitAdminViewModel
{
    public Unit Unit { get; set; }
    public List<Site> Site { get; set; }
    public IEnumerable<Work_Type> Work_Type { get; set; }

}

UnitMetaData类

[MetadataType(typeof(UnitMetaData))]
    public partial class Unit
    {

    }

    public class UnitMetaData {
        [Required(ErrorMessage = "Group is required")]
        public string GroupName { get; set; }

        [Required(ErrorMessage = "UnitName is required")]
        public string UnitName { get; set; }

        public string CDWSite { get; set; }

        public string Platform { get; set; }

        public Nullable<int> Supplier { get; set; }

        public string Work_Type { get; set; }
}

查看

    @model WebReportingToolDAL.Models.ViewModels.UnitAdminViewModel

@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Create</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Unit</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        @Html.LabelFor(model => model.Unit.UnitName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Unit.UnitName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Unit.UnitName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Unit.GroupName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Unit.GroupName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Unit.GroupName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Unit.CDWSite, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.Unit.CDWSite, new SelectList(Model.Site, "SiteName", "SiteName"), new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Unit.Platform, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.Unit.Platform, new List<SelectListItem> { new SelectListItem { Text = "PSCC", Value = "PSCC" }, new SelectListItem { Text = "RC", Value = "RC" } }, new { @class = "form-control" }) 
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Unit.Supplier, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.Unit.Supplier, new List<SelectListItem> { new SelectListItem { Text = "0", Value = "0" }, new SelectListItem { Text = "1", Value = "1" } }, new { @class = "form-control" }) 
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Unit.Work_Type, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.Unit.Work_Type,new SelectList(Model.Work_Type, "Name", "Name"),new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

控制器

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "UnitID,UnitCode,UnitName,GroupName,IncentiveUnit,CallCenter,CDWUnit,CDWSite,SiteID,DivisionID,WFCUnit,QAMonitored,NICEMonitored,ListPrefix,TSHSource,StatsSource,DialerSource,CostCenterID,WaterfallView,Locked,Platform,Supplier,Work_Type")] Unit unit)
    {
        if (ModelState.IsValid)
        {
            unit.UnitCode = "XX";
            unit.IncentiveUnit = 1;
            unit.CallCenter = true;
            unit.CDWUnit = true;
            unit.DivisionID = 2;
            unit.WFCUnit = false;
            unit.QAMonitored = false;
            unit.NICEMonitored = true;
            unit.ListPrefix = null;
            unit.TSHSource = null;
            unit.StatsSource = null;
            unit.DialerSource = null;
            unit.CostCenterID = 3;
            unit.WaterfallView = 1;
            unit.Locked = false;

            var siteId = (from s in db.Sites
                         where s.SiteName.ToLower().Equals(unit.CDWSite.ToLower())
                         select s.SiteID).First();

            unit.SiteID = siteId;

            db.Units.Add(unit);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(unit);
    }

2 个答案:

答案 0 :(得分:4)

使用数据库第一种方法时,您会发现该类已标记为partial所以您可以使用MetadataType属性来实现您之后的目标。

所以继续创建一个文件并命名它,例如UnitMetaData。您的代码应该类似于:

public class UnitMetaData
{
    [Required(ErrorMessage = "Group is required")]
    public string GroupName { get; set; }
    //more properties
}

您的Unit类是部分的,因此您可以创建另一个文件并使用MetadataType作为:

[MetadataType(typeof(UnitMetaData))]
public partial class Unit
{
}

有关MetadataType here

的更多信息

partial定义:

  

可以在两个或多个源文件上拆分类或结构,接口或方法的定义。每个源文件都包含类型或方法定义的一部分,并且在编译应用程序时将所有部分组合在一起。

<强> source

请注意:确保namespace与生成的Unit类相同,否则无法使用

答案 1 :(得分:1)

您可以使用真实视图模型。简单地将一堆实体包装在一个类中是缺少视图模型的用途。您的视图模型应该只包含应该显示/编辑的属性,它应该包含视图的业务逻辑,例如需要GroupName的事实(当它显然不在数据库级别时) )。

这意味着创建类似的东西:

public class UnitViewModel
{
    // other properties you want to edit

    [Required]
    public string GroupName { get; set; }
}

然后,您在视图中使用而不是Unit,并将已发布的属性从UnitViewModel映射到您的Unit实例。