c# - 必需属性不适用于外键下拉列表

标签 c# asp.net-mvc

我已经使用数据库优先方法创建了一个项目,其中我的表

城市 - 具有以下列

City_Id
City_Name
State_Id

State_Id 是状态表的外键。

现在所有验证和一切都正常工作,直到我将 [Required] 注释放在我的 City.cs 模型文件中的 State_Id 上

    //------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Manual changes to this file may cause unexpected behavior in your application.
//     Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SS.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    public partial class City
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public City()
        {
            this.Areas = new HashSet<Area>();
        }

        public int City_Id { get; set; }

        [Required]
        [DisplayName("City Name")]
        [StringLength(50,ErrorMessage = "City Name exceeds limit of 50 characters")]
        [RegularExpression(@"[A-Z][a-z]+",ErrorMessage ="Input Format Incorrect")]
        [Remote("CheckDuplicateInState","Cities",AdditionalFields ="State_Id",ErrorMessage ="There cannot be duplicate city names in same state")]
        public string City_Name { get; set; }


        [DisplayName("State Name")]
        public int State_Id { get; set; }

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

        public virtual State State { get; set; }
    }
}

当我将 [Required] 放在 State_Id 上并按按钮在创建 View 的表单中提交时,没有任何反应,即使我从下拉列表中选择正确的状态,也不会发生回发或者我只是选择默认显示值“选择状态”则也不会显示错误。

我的观点如下

@model SS.Models.City

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


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

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

        <div class="form-group">
            @Html.LabelFor(model => model.State_Id,htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("State_Id", null,"Select State", htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.State_Id, "", new { @class = "text-danger" })
            </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>
}

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

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

而我的 Controller (相关代码)如下

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using SS.Models;

namespace SS.Controllers.Admin
{
    public class CitiesController : Controller
    {
        private SS db = new SSDatabaseEntities();

        // GET: Cities/Create
        public ActionResult Create()
        {
            ViewBag.State_Id = new SelectList(db.States, "State_Id", "State_Name");
            return View();
        }

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

            return View(city);
        }



        public JsonResult CheckDuplicateInState(string City_Name,int state_id)
        {
            State st = db.States.Find(state_id);

            if (st.Cities.Any(x => x.City_Name == City_Name))
                return Json(false, JsonRequestBehavior.AllowGet);
            else
                return Json(true, JsonRequestBehavior.AllowGet);
        }
    }
}

将 [Required] 放在 City.cs 中的 State_Id 上时,查看页面源代码的下拉 html 中不会生成必需的属性 data-val-required。

    <div class="form-group">
            <label class="control-label col-md-2" for="State_Id">State Name</label>
            <div class="col-md-10">
                <select class="form-control" id="State_Id" name="State_Id"><option value="">Select State</option>
<option value="1">Madhya Pradesh</option>
<option value="2">Gujarat</option>
<option value="4">Punjab</option>
<option value="9">Tamil Nadu</option>
<option value="10">Haryana</option>
</select>
                <span class="field-validation-valid text-danger" data-valmsg-for="State_Id" data-valmsg-replace="true"></span>
            </div>
        </div>

最佳答案

您对 @Html.DropDownList("State_Id", null, ...) 的使用情况绑定(bind)到State_Id这是 SelectList您已添加到 ViewBag 的属性(并且没有任何验证属性。

而是给你绑定(bind)的属性和 SelectList不同的名称,以便您可以强绑定(bind)到模型属性。在 GET 方法中

ViewBag.StateList = new SelectList(db.States, "State_Id", "State_Name");

并在 View 中

@Html.DropDownListFor(m => m.State_Id, (SelectList)ViewBag.StateList, "Select State", new { @class = "form-control" })

正确的data-val-requireddata-val-number现在将添加属性以进行客户端验证。

然后在POST方法中,需要重新填充ViewBag返回 View 之前的属性

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(City city)
{
    if (ModelState.IsValid)
    {
        ....
    }
    ViewBag.StateList = new SelectList(db.States, "State_Id", "State_Name"); // add this
    return View(city);
}

旁注:不需要 [Bind]属性,因为您包括默认的所有属性(并且您包括 City_Id 这是没有意义的,因为您没有 - 也不应该 - 对其进行控制。

更好的方法是使用包含 IEnumerable<SelectListItem> StateList 的 View 模型这样您就可以简单地使用 @Html.DropDownListFor(m => m.State_Id, Model.StateList, ....)

关于c# - 必需属性不适用于外键下拉列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35392318/

相关文章:

asp.net-mvc - mvc中如何将多个对象传递给 View ?

asp.net - RotativaPDF css不在服务器上工作

c# - 使用循环在 HTML(MVC) 中显示列表字符串

c# - 以编程方式将程序注册到添加/删除程序中并将文件存储在可执行文件中

java - 为什么以下案件的执行流程不同?

C# 索引器和 Linq

c# - ASP.NET MVC View 编译失败

javascript - MVC 4 : Create HTML textboxes dynamically with JQUERY and PartialViewResult. 如果动态添加代码如何填充模型?

c# - 事件未显示在属性网格中

c# - 如何为事件总线使用 Reactive Extensions