所需的属性不外键下拉列表上工作 [英] Required Attribute does not work on foreign key dropdown list

查看:121
本文介绍了所需的属性不外键下拉列表上工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用数据库第一种方法创建了一个项目中,我的表

城 - 具有以下的列

  City_Id
城市名
STATE_ID

STATE_ID是一个外键状态表。

现在所有的验证和一切工作,直到我把[必填]注释过STATE_ID在我City.cs模型文件这是本

  // ------------------------------------ ------------------------------------------
//<自动生成>
//这个code是从模板生成。
//
//这个文件的手动更改可能会导致应用程序意外行为。
//如果code再生此文件的手动更改将被覆盖。
//< /自动生成>
// ------------------------------------------------ ------------------------------
命名空间SS.Models
{
    使用系统;
    使用System.Collections.Generic;
    使用System.ComponentModel;
    使用System.ComponentModel.DataAnnotations;
    使用System.Web.Mvc;
    公共部分类城市
    {
        [System.Diagnostics程序codeAnalysis.Sup pressMessage。(Microsoft.Usage,CA2214:DoNotCallOverridableMethodsInConstructors)]
        公众城()
        {
            this.Areas =新的HashSet<面积和GT;();
        }        公众诠释City_Id {搞定;组; }        [需要]
        [DisplayName的(城市名称)]
        [StringLength(50的ErrorMessage =城市名称超过50个字符限制)
        [RegularEx pression(@[A-Z] [A-Z] +的ErrorMessage =输入格式不正确)]
        [远程(CheckDuplicateInState,城市,AdditionalFields =STATE_ID的ErrorMessage =目前不能在同一状态的重复的城市名称)]
        公共字符串CITY_NAME {搞定;组; }
        [显示名称(国家名称)]
        公众诠释STATE_ID {搞定;组; }        [System.Diagnostics程序codeAnalysis.Sup pressMessage(Microsoft.Usage,CA2227:CollectionPropertiesShouldBeReadOnly)。]
        公共虚拟的ICollection<面积和GT;地区{搞定;组; }        公共虚拟州州立{搞定;组; }
    }
}

当我把[必填]在STATE_ID和preSS按钮的形式提交在创建视图没有任何反应,即使我从下拉无回后选择一个正确的状态发生或我只是选择然后也没有显示任何错误的选择国家默认显示值。

我的看法如下:

  @model SS.Models.City@ {
    ViewBag.Title =创建;
}< H2>创建< / H>
@using(Html.BeginForm())
{
    @ Html.AntiForgeryToken()    < D​​IV CLASS =形横>
        < H4>城市< / H4>
        <小时/>
        @ Html.ValidationSummary(真,新{@class =TEXT-危险})
        < D​​IV CLASS =表单组>
            @ Html.LabelFor(型号=> model.City_Name,htmlAttributes:新{@class =控制标签COL-MD-2})
            < D​​IV CLASS =COL-MD-10>
                @ Html.EditorFor(型号=> model.City_Name,新{htmlAttributes = {新@class =表格控}})
                @ Html.ValidationMessageFor(型号=> model.City_Name,新{@class =TEXT-危险})
            < / DIV>
        < / DIV>        < D​​IV CLASS =表单组>
            @ Html.LabelFor(型号=> model.State_Id,htmlAttributes:新{@class =控制标签COL-MD-2})
            < D​​IV CLASS =COL-MD-10>
                @ Html.DropDownList(STATE_ID,NULL,选择国家,htmlAttributes:新{@class =表格控})
                @ Html.ValidationMessageFor(型号=> model.State_Id,新{@class =TEXT-危险})
            < / DIV>
        < / DIV>        < D​​IV CLASS =表单组>
            < D​​IV CLASS =COL-MD-偏移2 COL-MD-10>
                <输入类型=提交值=创建类=BTN BTN-默认的/>
            < / DIV>
        < / DIV>
    < / DIV>
}< D​​IV>
    @ Html.ActionLink(返回目录,索引)
< / DIV>@section脚本{
    @ Scripts.Render(〜/包/ jqueryval)
}

和我的控制器(相关code)如下:

 使用系统;
使用System.Collections.Generic;
使用System.Data这;
使用System.Data.Entity的;
使用System.Linq的;
使用System.Net;
使用的System.Web;
使用System.Web.Mvc;
使用SS.Models;命名空间SS.Controllers.Admin
{
    公共类CitiesController:控制器
    {
        私人SS DB =新SSDatabaseEntities();        // GET:城市/创建
        公众的ActionResult的Create()
        {
            ViewBag.State_Id =新的SelectList(db.States,STATE_ID,STATE_NAME);
            返回查看();
        }        // POST:城市/创建
        //从overposting攻击保护,请启用要绑定到特定的属性,
        //更多详情请参阅http://go.microsoft.com/fwlink/?LinkId=317598。
        [HttpPost]
        [ValidateAntiForgeryToken]
        公众的ActionResult创建([绑定(包括=City_Id,CITY_NAME,STATE_ID)]城市)
        {
            如果(ModelState.IsValid)
            {
                db.Cities.Add(市);
                db.SaveChanges();
                返回RedirectToAction(「指数」);
            }            返回查看(市);
        }        公共JsonResult CheckDuplicateInState(字符串CITY_NAME,诠释STATE_ID)
        {
            国家ST = db.States.Find(STATE_ID);            如果(st.Cities.Any(X => x.City_Name == CITY_NAME))
                返回JSON(假,JsonRequestBehavior.AllowGet);
            其他
                返回JSON(真,JsonRequestBehavior.AllowGet);
        }
    }
}

在把[必填]上STATE_ID在City.cs数据-VAL-所需的必需属性在下拉HTML上观看网页的源代码,不产生。

 < D​​IV CLASS =表单组>
            <标签类=控制标签COL-MD-2=STATE_ID>国家名称和LT; /标签>
            < D​​IV CLASS =COL-MD-10>
                <选择类=表格控ID =STATE_IDNAME =STATE_ID><期权价值=>选择国家< /选项>
<期权价值=1>中央邦< /选项>
<期权价值=2>古吉拉特邦< /选项>
<期权价值=4>&旁遮普LT; /选项>
<期权价值=9>泰米尔纳德邦< /选项>
<期权价值=10>哈里亚纳邦< /选项>
< /选择>
                <跨度类=现场验证,有效文本危险数据valmsg换=STATE_ID数据valmsg替换=真正的>< / SPAN>
            < / DIV>
        < / DIV>


解决方案

@ Html.DropDownList的使用(STATE_ID,NULL,...)是绑定在 STATE_ID 这是你已经添加到 ViewBag 的SelectList 属性C>(并且没有任何验证的属性。

而不是给你的财产结合和的SelectList 不同的名称,这样就可以强烈绑定到你的模型属性。在GET方法

  ViewBag.StateList =新的SelectList(db.States,STATE_ID,STATE_NAME);

和视图

  @ Html.DropDownListFor(M = GT; m.State_Id,(的SelectList)ViewBag.StateList,选择国家,新{@class =表格控})

正确数据-VAL-要求数据-VAL-号属性现在将增加了对客户端验证。

然后在POST方法,您需要返回视图之前重新填充 ViewBag 属性

  [HttpPost]
[ValidateAntiForgeryToken]
公众的ActionResult创建(城市)
{
    如果(ModelState.IsValid)
    {
        ....
    }
    ViewBag.StateList =新的SelectList(db.States,STATE_ID,STATE_NAME); //添加此
    返回查看(市);
}

边注:没有必要为 [绑定] 属性,因为您的包括所有属性这是默认的(和你包括 City_Id ,因为你不知道它没有任何意义 - 并且不应该 - 有一个控制它

有一个更好的办法是使用含有的IEnumerable℃的视图模型; SelectListItem> StateList ,这样就可以简单地使用 @ Html.DropDownListFor(M = GT; m.State_Id,Model.StateList,....)

I have created a project using database first approach in which My table

City - has the following columns

City_Id
City_Name
State_Id

State_Id is a foreign key to state table.

Now all validations and everything is working until I put the [Required] annotation over State_Id in my City.cs model file which is this

    //------------------------------------------------------------------------------
// <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; }
    }
}

When I put [Required] over State_Id and press the button to Submit in the form in Create view nothing happens, even if I select a correct state from the drop down no post-back happens or I just select the default display value of "Select State" then also no error is shown.

My view is as follows

@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")
}

And my controller (relevant code) is as follows

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);
        }
    }
}

On putting [Required] on State_Id in City.cs the required attribute data-val-required is not generated in the drop down html on viewing page source.

    <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>

解决方案

Your usage of @Html.DropDownList("State_Id", null, ...) is binding to the State_Id which is the SelectList property you have added to ViewBag (and does not have any validation attributes.

Instead give the property your binding to and the SelectList different names so that you can strongly bind to you model property. In the GET method

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

and in the view

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

The correct data-val-required and data-val-number attributes will now be added for client side validation.

then in the POST method, you need to repopulate the ViewBag property before you return the 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);
}

Side note: There is no need for the [Bind] attribute since your including all properties which is the default (and your including City_Id which does not make sense since you don't - and should not - have a control for it.

A better approach would be to use a view model containing IEnumerable<SelectListItem> StateList so that you can simply use @Html.DropDownListFor(m => m.State_Id, Model.StateList, ....)

这篇关于所需的属性不外键下拉列表上工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆