【问题标题】:MVC 5 DropDownListFor & Select List results in error on PostMVC 5 DropDownListFor & Select List 导致发布错误
【发布时间】:2016-09-25 16:20:43
【问题描述】:

所以我认为这会非常简单,但我很难弄清楚。

首先,我将回顾一下到目前为止的内容。

RegisterViewModel:

public class RegisterViewModel
{
    [Display(Name = "First Name:")]
    public string FirstName { get; set; }
    [Display(Name = "Last Name:")]
    public string LastName { get; set; }

    [Required]
    [EmailAddress]
    [Display(Name = "Email:")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password:")]
    public string Password { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Confirm password:")]
    [System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

    [Display(Name = "Please choose the category that best describes your professional relation to the field of Orthotics and Prosthetics:")]
    public List<string> ProfessionalRelations { get; set; }
    [Display(Name = "Please check all of the following that apply to you:")]
    public List<string> UserRelations { get; set; }
    [Required]
    [Display(Name = "Country")]
    public SelectList Countries { get; set; }
    [Required]
    [Display(Name = "EDGE Direct E-mail Newsletter:")]
    public List<string> EdgeNewsletter { get; set; }
}

注意国家选择列表。

现在,在我的控制器中。当有人进入注册页面时,我会按如下方式填充国家选择列表:

var countries = oandpService.GetCountries().OrderBy(x => x.CountryName).ToList();
var usa = countries.FirstOrDefault(x => x.CountryID == "US");
countries.Remove(usa);
countries.Insert(0, new Country() { CountryID = string.Empty, CountryName = string.Empty });
countries.Insert(1, usa);

rvm.Countries = new SelectList(countries, "CountryID", "CountryName");

最后,这是国家 DropDownListFor 视图的一部分:

@Html.DropDownListFor(x => x.Countries, Model.Countries, Model.Countries)

当您转到该页面时,这一切都显示正常。使用 CountryID 作为值和 CountryName 作为显示文本生成国家下拉列表。

然后,为了测试单选按钮、复选框和下拉菜单,我有以下内容:

[HttpPost]
[ValidateAntiForgeryToken]
[ReCaptchaFilter]
public ActionResult Register(RegisterViewModel rvm)
{
    ViewBag.Countries = rvm.Countries.SelectedValue;
    ViewBag.UserRelation = rvm.UserRelations;
    ViewBag.ProfessionalRelation = rvm.ProfessionalRelations;

    return View(rvm);
}

除了我在帖子中收到以下错误:

  1. 没有为此对象定义无参数构造函数。
  2. 没有为此对象定义无参数构造函数。对象类型“System.Web.Mvc.SelectList”。

谁能帮我指出正确的方向?我做了一些研究,但还没有弄清楚。任何意见都会非常感激。

【问题讨论】:

  • 没有为这个对象定义无参数的构造函数。向你的控制器添加一个没有参数的构造函数
  • 当人们第一次访问该页面(不是 HTTP 帖子)时,我已经有一个无参数构造函数。如果我尝试添加另一个 ActionResult Register() 它表示 AccountController 已经定义了一个名为 Register 的成员具有相同的参数类型。
  • 所以我尝试通过在我的模型中创建一个名为 public Country Country {get;set;} 的新属性并将我的 DropDown 更改为:@Html.DropDownListFor(x => x.Country.CountryID,模型.国家);现在我得到了错误:对象引用未设置为对象的实例。

标签: c# asp.net-mvc asp.net-mvc-5 html.dropdownlistfor selectlist


【解决方案1】:

您使用的辅助方法错误!检查页面的视图源!您当前的代码正在生成一个名为“Countries”的 SELECT 元素。提交表单时,将根据表单元素键“Countries”提交所选值。当模型绑定器尝试将此提交的值映射到您的 RegisterViewModel 的实例时,它会看到类型为 SelectList 的“Countries” (根据视图模型类定义)并且它不能从整数值构建SelectList 对象(从表单提交的选定 CountryId)。这就是您看到此错误的原因!造成这一切的原因,是因为你用错了helper方法!

理想情况下,您应该添加另一个属性来保存所选值。

public class RegisterViewModel
{
   [Required]
   [Display(Name = "Country")]
   public int SelectedCountry { set;get;}

   public SelectList Countries { get; set; }

   //Your existing properties goes here
}

在视图中

@Html.DropDownListFor(x => x.SelectedCountry, Model.Countries )

在您的 HttpPost 操作中,您将在 SelectedCountry 属性中获得选定的选项值

public ActionResult Register(RegisterViewModel rvm)
{
    var selectedCountry = rvm.SelectedCountry;
    //to do : Reload Countries property of rvm again here(same as your GET action)

    return View(rvm);
}

另外,要添加空选择选项,您不需要在控制器代码中添加空项,您可以简单地使用 DropDownListFor 辅助方法的重载。

@Html.DropDownListFor(x => x.SelectedCountry, Model.Countries,string.Empty)

【讨论】:

  • 感谢您的回复。但是,当我发布到控制器时,我收到错误:没有类型为 'IEnumerable' 的 ViewData 项具有键'SelectedCountry'。我填充 DropDownList 的方式有问题吗?上面有,但它: rvm.Countries = new SelectList(countries, "CountryID", "CountryName");再次感谢您!
  • 另外,不知道这是否重要,但 SelectedCountry 是一个字符串。
  • @ajtatum,该错误是因为您在POST方法中返回视图但没有像在GET方法中那样重新填充SelectList(参考this answer
  • 在答案中,我有一条待办事项评论,告诉您重新加载与 GET 操作相同的国家属性,因为您将返回相同的视图,并且视图正在使用国家属性来构建选择元素。所以你应该在调用 View 方法之前重新加载它。关于 SelectedCountry 属性的类型,您可以根据您的用例使用适当的属性。通常人们使用 int 作为他们的主键。那就是y我选择了int类型
  • 感谢@Shyju,所以我们取得了一些进展。对于 DropDownListFor,我有以下内容:@Html.DropDownListFor(x => x.SelectedCountry, Model.Countries)。在 ViewModel 中,我就像您推荐的那样拥有它,除了 SelectedCountry 是一个字符串(CountryID 是缩写的 Country,即:US。在注册后的帐户控制器中,我填充了所有字段。当我提交页面时,它返回“请选择一个国家/地区。”但是,在下拉列表中选择了国家/地区。我尝试了一些方法来解决这个问题,但我有点迷茫。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-06
  • 1970-01-01
  • 2016-11-13
相关资源
最近更新 更多