MVC ViewModel 错误 - 没有为此对象定义无参数构造函数 [英] MVC ViewModel Error - No parameterless constructor defined for this object

查看:29
本文介绍了MVC ViewModel 错误 - 没有为此对象定义无参数构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何在 Create Action 上使用我的 ViewModel?我尝试了在论坛上找到的几个例子,但没有一个能解决我的问题.我已经绞尽脑汁好几天了,但还是想不出哪里出了问题.

每当我单击创建"按钮时,都会出现以下错误:没有为此对象定义无参数构造函数.

@model MvcMusicStore.ViewModels.AlbumViewModel@{ViewBag.Title = "创建";}<h2>创建</h2><script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script><script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>@using (Html.BeginForm()) {@Html.ValidationSummary(true)<字段集><legend>专辑</legend><div class="editor-label">@Html.LabelFor(model => model.AlbumItem.GenreId, "流派")

<div class="editor-field">@Html.DropDownList("流派", String.Empty)@Html.ValidationMessageFor(model => model.AlbumItem.GenreId)

<div class="editor-label">@Html.LabelFor(model => model.AlbumItem.ArtistId, "艺术家")

<div class="editor-field">@Html.DropDownList("艺术家", String.Empty)@Html.ValidationMessageFor(model => model.AlbumItem.ArtistId)

<div class="editor-label">@Html.LabelFor(model => model.AlbumItem.Title)

<div class="editor-field">@Html.EditorFor(model => model.AlbumItem.Title)@Html.ValidationMessageFor(model => model.AlbumItem.Title)

<div class="editor-label">@Html.LabelFor(model => model.AlbumItem.Price)

<div class="editor-field">@Html.EditorFor(model => model.AlbumItem.Price)@Html.ValidationMessageFor(model => model.AlbumItem.Price)

<div class="editor-label">@Html.LabelFor(model => model.AlbumItem.AlbumArtUrl)

<div class="editor-field">@Html.EditorFor(model => model.AlbumItem.AlbumArtUrl)@Html.ValidationMessageFor(model => model.AlbumItem.AlbumArtUrl)

<p><输入类型=提交"值=创建"/></p></fieldset>}<div>@Html.ActionLink("返回列表", "索引")

创建.cshtml

 公共类 StoreManagerController : 控制器{私有 MusicStoreDB db = new MusicStoreDB();////获取:/StoreManager/创建公共 ActionResult 创建(){var viewModel = new AlbumViewModel(){Genres = new SelectList(db.Genres, "GenreId", "Name"),Artists = new SelectList(db.Artists, "ArtistId", "Name")};返回视图(视图模型);}////POST:/StoreManager/Create[HttpPost]公共 ActionResult 创建(AlbumViewModel vm){如果(模型状态.IsValid){db.Albums.Add(vm.AlbumItem);db.SaveChanges();return RedirectToAction("索引");}vm.Genres = new SelectList(db.Genres, "GenreId", "Name", vm.AlbumItem.GenreId);vm.Artists = new SelectList(db.Artists, "ArtistId", "Name", vm.AlbumItem.ArtistId);返回视图(vm);}}

StoreManager.cs - 片段

公共类AlbumViewModel{公共相册视图模型(){// 没有什么}公共相册 AlbumItem { 获取;放;}公共选择列表流派 { 获取;放;}公共选择列表艺术家{得到;放;}}公开课专辑{公开专辑(){// 没有什么}公共虚拟 int AlbumId { 获取;放;}公共虚拟 int GenreId { 获取;放;}公共虚拟 int ArtistId { 获取;放;}公共虚拟字符串 Title { get;放;}公共虚拟十进制价格{得到;放;}公共虚拟字符串 AlbumArtUrl { get;放;}公共虚拟流派流派{得到;放;}公共虚拟艺术家艺术家{得到;放;}}公开课艺术家{公共艺术家(){//没有什么}公共虚拟 int ArtistId { 获取;放;}公共虚拟字符串名称 { 获取;放;}}公开课类型{公共流派(){//没有什么}公共虚拟 int GenreId { 获取;放;}公共虚拟字符串名称 { 获取;放;}公共虚拟字符串 描述 { get;放;}公共虚拟列表<专辑>专辑{得到;放;}}

解决方案

如果我每次看到这个问题都能得到五分的话.它通常与模型属性的命名以及如何在 DropDownList 中使用它们有关.99.999% 的时间是因为人们使用 Html.DropDownList() 并将其命名为与他们的 SelectList 相同.这是您应该使用强类型 DropDownListFor 的原因之一.

在这种情况下,您的问题是您有名为 GenresArtistsSelectLists,那么在您看来,您有:>

@Html.DropDownList("流派", String.Empty)@Html.DropDownList("艺术家", String.Empty)

看,同名.

您应该做的是更改您的模型,使 SelectList 被命名为 GenreListArtistList.然后,将您的视图更改为使用强类型模型.

@Html.DropDownListFor(m => m.AlbumItem.GenreID, Model.GenreList)@Html.DropDownListFor(m => m.AlbumItem.ArtistID, Model.ArtistList)

发生这种情况的原因是您向控制器发布了一个名为 Genres 的值.默认模型绑定器尽职尽责地查看模型以找到称为 Genres 的内容并将其实例化.但是,它找到了一个名为 Genres 的 SelectList,而不是一个 ID 或字符串,当它尝试实例化它时,它发现没有默认构造函数.

因此你的错误.SO 充满了关于同一件事的问题.

I would like to know how can I use my ViewModel on the Create Action? I tried several examples I found here in the forum, but none solved my problem. I've been racking my brain for a few days, but can't figure out what is wrong.

Whenever I click the Create button I get the following error: No parameterless constructor defined for this object.

@model MvcMusicStore.ViewModels.AlbumViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Album</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.AlbumItem.GenreId, "Genre")
        </div>
        <div class="editor-field">
            @Html.DropDownList("Genres", String.Empty)
            @Html.ValidationMessageFor(model => model.AlbumItem.GenreId)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.AlbumItem.ArtistId, "Artist")
        </div>
        <div class="editor-field">
            @Html.DropDownList("Artists", String.Empty)
            @Html.ValidationMessageFor(model => model.AlbumItem.ArtistId)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.AlbumItem.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.AlbumItem.Title)
            @Html.ValidationMessageFor(model => model.AlbumItem.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.AlbumItem.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.AlbumItem.Price)
            @Html.ValidationMessageFor(model => model.AlbumItem.Price)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.AlbumItem.AlbumArtUrl)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.AlbumItem.AlbumArtUrl)
            @Html.ValidationMessageFor(model => model.AlbumItem.AlbumArtUrl)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

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

Create.cshtml

    public class StoreManagerController : Controller
        {
            private MusicStoreDB db = new MusicStoreDB();

            //
            // GET: /StoreManager/Create

            public ActionResult Create()
            {
                var viewModel = new AlbumViewModel()
                {
                    Genres = new SelectList(db.Genres, "GenreId", "Name"),
                    Artists = new SelectList(db.Artists, "ArtistId", "Name")
                };
                return View(viewModel);
            } 

            //
            // POST: /StoreManager/Create

            [HttpPost]
            public ActionResult Create(AlbumViewModel vm)
            {
                if (ModelState.IsValid)
                {
                    db.Albums.Add(vm.AlbumItem);
                    db.SaveChanges();
                    return RedirectToAction("Index");  
                }

                vm.Genres = new SelectList(db.Genres, "GenreId", "Name", vm.AlbumItem.GenreId);
                vm.Artists = new SelectList(db.Artists, "ArtistId", "Name", vm.AlbumItem.ArtistId);
                return View(vm);
            }
}

StoreManager.cs - Snippet

public class AlbumViewModel
    {
        public AlbumViewModel()
        {
            //  nothing
        }

        public Album AlbumItem { get; set; }
        public SelectList Genres { get; set; }
        public SelectList Artists { get; set; }
    }

public class Album
    {
        public Album()
        {
            //  nothing
        }

        public virtual int AlbumId { get; set; }
        public virtual int GenreId { get; set; }
        public virtual int ArtistId { get; set; }
        public virtual string Title { get; set; }
        public virtual decimal Price { get; set; }
        public virtual string AlbumArtUrl { get; set; }
        public virtual Genre Genre { get; set; }
        public virtual Artist Artist { get; set; }
    }

public class Artist
    {
        public Artist()
        {
            // nothing
        }

        public virtual int ArtistId { get; set; }
        public virtual string Name { get; set; }
    }

public class Genre
    {
        public Genre()
        {
            // nothing
        }

        public virtual int GenreId { get; set; }
        public virtual string Name { get; set; }
        public virtual string Description { get; set; }
        public virtual List<Album> Albums { get; set; }
    }

解决方案

If I had a nickel for every time I've seen this problem. It's typically related to the naming of your model properties and how you use them in a DropDownList. 99.999% of the time it's because people are using Html.DropDownList() and naming it the same as their SelectList. This is one reason you should use the strongly typed DropDownListFor.

In this case, your problem is that you have SelectLists named Genres and Artists, then in your view you have:

@Html.DropDownList("Genres", String.Empty)
@Html.DropDownList("Artists", String.Empty)

See, same name.

What you should do is change your Model to make the SelectLists be named GenreList and ArtistList. Then, change your view to use strongly typed model.

@Html.DropDownListFor(m => m.AlbumItem.GenreID, Model.GenreList)
@Html.DropDownListFor(m => m.AlbumItem.ArtistID, Model.ArtistList)

The reason this happens is that you are posting a value called Genres to the controller. The default model binder dutifully looks in the model to find something called Genres and instantiate it. But, rather than an ID or string, it finds a SelectList named Genres, and when it tries to instantiate it, it finds there is no default constructor.

Thus your error. SO is filled with questions asking about this same thing.

这篇关于MVC ViewModel 错误 - 没有为此对象定义无参数构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
C#/.NET最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆