创建时不允许Nullable下拉字段

时间:2018-03-23 15:07:31

标签: c# asp.net-mvc validation

我正在使用Entity Framework来创建我的模型,我有一些字段是外键但也可以为空。例如,可能不知道设备的状态,因此如果是这种情况,我将其设置为NULL。如果设备确实具有状态,则值为Dev_Status_ID,它引用Device_Status表,以便Dev_Status_Name可以显示在网站上。

我一直在测试以确保正确处理创建和编辑期间的空字段,但事实并非如此。当我将设备状态下拉列表保留在默认的String.Empty值时,网站会在单击“提交”按钮时突出显示“设备状态”下拉列表。

设备创建视图:

@model ITInventory.Models.Device
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
<div class="form-horizontal">

    <h4>Device</h4>

    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            @* Asset Tag *@
            <div class="form-group">
                @Html.LabelFor(model => model.dev_asset_tag, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.dev_asset_tag, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.dev_asset_tag, "", new { @class = "text-danger" })
                </div>
            </div>

            @*......Leaving out a bunch of other fields for readability*@

            @*Status*@
            <div class="form-group">
                @Html.LabelFor(model => model.Device_Status.dev_status_name, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.DropDownListFor(m => m.Device_Status.dev_status_id, (SelectList)ViewBag.dev_status_id, String.Empty, new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.dev_status_id, "", new { @class = "text-danger" })
                </div>
            </div>

            @*.......Leaving out a bunch of other fields for readability*@

            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />&nbsp;&nbsp;&nbsp;&nbsp;
                    <input type="reset" value="Cancel" class="btn btn-default" />
                </div>

            </div>
        </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

设备型号:

namespace ITInventory.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;

    public partial class Device
    {

        [DisplayName("Device ID")]
        public int dev_id { get; set; }

        [DisplayName("Asset Tag")]
        public string dev_asset_tag { get; set; }

        @*.......Leaving out a bunch of other fields for readability*@

        [DisplayName("Status ID")]
        public Nullable<int> dev_status_id { get; set; }

        @*.......Leaving out a bunch of other fields for readability*@

        public virtual Device_Status Device_Status { get; set; }
        @*.......Leaving out the other public virtual bits for readability*@*@
    }
}

状态模型:

namespace ITInventory.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;

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

        [DisplayName("Status ID")]
        public int dev_status_id { get; set; }

        [DisplayName("Status")]
        public string dev_status_name { get; set; }

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

设备控制器:

// GET: Devices/Create
        public ActionResult Create()
        {
            @*.......Leaving out a bunch of other fields for readability*@

            ViewBag.dev_status_id = new SelectList(db.Device_Status.OrderBy(x => x.dev_status_name), 
            "dev_status_id", "dev_status_name");

            @*.......Leaving out a bunch of other fields for readability*@
            return View();
        }

        // POST: Devices/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Device device)
        {
            if (ModelState.IsValid)
            {
                db.Devices.Add(device);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            @*.......Leaving out a bunch of other fields for readability*@

            ViewBag.dev_status_id = new SelectList(db.Device_Status, "dev_status_id", "dev_status_name", null);

            @*.......Leaving out a bunch of other fields for readability*@

            return View(device);
            }

我是MVC的新手,所以我觉得我必须遗漏一些明显的东西,但我所有的搜索都没有帮助。我的字段设置为Nullable,我没有必填字段,当我尝试手动对数据库执行插入时,它不会抱怨NULL dev_status_id。我试图做一些不允许的事情吗?

2 个答案:

答案 0 :(得分:0)

可能是在选择了您的默认值时,在服务器端它可能是空字符串请在发布操作中检查它。如果其空字符串将DBNull.Value分配给dev_status_id

答案 1 :(得分:0)

在这种情况下,您应该有2个模型。

一种是服务模型,您可以使用Nullable,也可以存储一些数据供以后决策。将它与你的所有逻辑一起使用。

另一个是ViewModel(例如DeviceViewModel),您只放置将要显示的有效数据。该模型应该是轻量级的,并且对显示规则100%有效。

因此,当您完成控制器中的所有逻辑操作后,您可以从服务模型中构建ViewModel并显示它。