asp.net 模型绑定复杂类型不能是抽象类型或值类型,并且必须具有无参数构造函数

cgyqldqp  于 2022-12-15  发布在  .NET
关注(0)|答案(6)|浏览(178)

我有以下问题,我创建了一个应用程序添加游戏类别和游戏本身到数据库。我创建了一个关系,不幸的是,当我添加到数据库时,我得到了一个错误。
一个月一个月一个月一个月一个月
游戏类别型号:

using System.Collections.Generic;

namespace relationship.Models
{
    public class GameCategory
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public ICollection<Game> Game { get; set; }
    }
}

游戏模型:

namespace relationship.Models
{
    public class Game
    {
        public int GameId { get; set; }
        public string Name { get; set; }

        public GameCategory Category { get; set; }
        public int CategoryId { get; set; }
    }
}

视图模型:

using relationship.Models;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace relationship.ViewModels
{
    public class AddGameViewModel
    {     
        [Required]
        public string GameName { get; set; }
        public int CategoryID { get; set; }

        public List<SelectListItem> Categories { get; set; }

        public AddGameViewModel(IEnumerable<GameCategory> categories)
        {
            Categories = new List<SelectListItem>();
            foreach (var catData in categories)
            {
                Categories.Add(new SelectListItem { Text = catData.Name.ToString(), Value = catData.Id.ToString() });
            }
            return;
        }
    }
}

游戏存储库:

using System.Collections.Generic;
using System.Linq;

namespace relationship.Models
{
    public class GameRepository : IGameRepository
    {
        private readonly AppDbContext appDbContext;
        public GameRepository(AppDbContext dbContext)
        {
            appDbContext = dbContext;
        }

        public void AddGame(Game game)
        {
            appDbContext.Games.Add(game);
            appDbContext.SaveChanges();
        }

        public IEnumerable<Game> Games()
        {
            return appDbContext.Games.ToList();
        }
    }
}

最后是游戏控制器:

using Microsoft.AspNetCore.Mvc;
using relationship.Models;
using relationship.ViewModels;

namespace relationship.Controllers
{
    public class GameController : Controller
    {
        private readonly IGameRepository gameRepository;
        private readonly ICategoryRepository categoryRepository;

        public GameController(IGameRepository gameRepo, ICategoryRepository catRepo)
        {
            gameRepository = gameRepo;
            categoryRepository = catRepo;
        }

        public IActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public IActionResult Add()
        {
            var addGameViewModel = new AddGameViewModel(categoryRepository.GameCategory());
            return View(addGameViewModel);
        }

        [HttpPost]
        public IActionResult Add(AddGameViewModel addGameViewModel)
        {
            if (ModelState.IsValid)
            {
                GameCategory gameCategory = categoryRepository.GetDetails(addGameViewModel.CategoryID);

                if(gameCategory == null)
                {
                    return NotFound();
                }

                Game game = new Game
                {
                    Name = addGameViewModel.GameName,
                    Category = gameCategory
                };

                gameRepository.AddGame(game);
                return RedirectToAction("Index");
            }
            return View(addGameViewModel);
        }
    }
}

我不知道出了什么问题。
我的错误屏幕:

fnx2tebb

fnx2tebb1#

未能创建relationship. ViewModels. AddGameViewModel的示例。模型绑定复杂类型不能是抽象类型或值类型,并且必须具有无参数构造函数。
让我们试着把这个错误分解开来。
无法创建关系.视图模型.添加游戏视图模型的示例。
很明显:模型绑定组件正在尝试创建类型的示例,但失败了。
模型绑定复杂类型
“模型绑定”指的是它们被ASP.NET管道绑定。“复杂类型”基本上是任何不像stringint这样的“基本”类型。你的模型类是复杂类型。
不能抽象
模型绑定系统将希望能够创建类的示例,因此它不能是抽象的;它必须是具体的,你展示的所有类型都是具体的,所以这不是问题所在。
或值类型
不能将struct类型用于模型绑定;这只是它的局限性之一,幸运的是你的类型都是类,所以你可以忽略这一点。
并且必须具有无参数构造函数。
ASP.NET不知道如何给模型构造函数提供参数。它只能做new T()的等价物,所以你所有的模型类型必须定义一个没有参数的构造函数。这就是你看到错误的原因;你的AddGameViewModel类只定义了这个构造函数:

public AddGameViewModel(IEnumerable<GameCategory> categories)

C#语言的一个特性是,当您不手动指定构造函数时,它会为您添加一个默认构造函数。当您在代码中定义构造函数时,不会添加此默认构造函数。
在所有其他模型中,你没有定义任何构造函数,所以编译器会为你添加默认的构造函数,在AddGameViewModel的例子中,你已经添加了一个构造函数,所以要解决这个问题,你也必须添加默认的构造函数:

public AddGameViewModel()
{
}
knsnq2tg

knsnq2tg2#

您需要将[FromBody]添加到参数中,以便asp.net核心知道如何绑定模型。

[HttpPost]
public IActionResult Add([FromBody] AddGameViewModel addGameViewModel)
fkvaft9z

fkvaft9z3#

在撰写本文时,我在Asp.NET Core 2.2控制器中遇到了这个问题,其中类型被注入到了一个方法中。将类型移动到控制器的构造函数中可以解决这个问题。由于这实际上是不可接受的,因此我们最终将有问题的类从控制器中重构出来,并将其重构到已经广泛使用单例的处理层中。此时再添加一个就解决了这个问题。
请注意,这是Asp.NET Core内置的OOB IoC容器。其他IoC提供程序可能能够更好地处理方法上的注入属性。
X1 E0 F1 X可以是一种替代方案。
使用模型绑定器可能也会起作用,因为绑定器可能会更干净地使用单例和/或支持构造函数注入。

u5i3ibmn

u5i3ibmn4#

在我的例子中,我天真地绑定了一个复杂对象(没有无参数构造函数的复杂对象):
Edit.cshtml.cs:

namespace MyNamespace.Pages.CSDA
{
    public class EditModel : PageModel
    {
        ...
        [BindProperty]
        public MyComplexClass WorkflowItem { get; set; }
        ...

当我点击“保存”时,我得到了这个运行时错误:
系统操作无效异常:未能创建类型“MyNamespace.MyComplexClass”的示例。
模型绑定复杂类型不能是抽象类型或值类型,并且必须具有无参数构造函数。
或者,也可以在“MyNamespace.EditModel”构造函数中将“WorkflowItem”属性设置为非Null值。在Microsoft中为AspNetCore.Mvc.模型绑定.绑定器.复杂类型模型绑定器.创建模型(模型绑定上下文绑定上下文)在Microsoft中为AspNetCore.Mvc.模型绑定.绑定器.复杂类型模型绑定器.绑定模型核心异步(模型绑定上下文绑定上下文,Int32属性数据)
我需要这个对象(它有我想向用户显示的信息),但我 * 不 * 需要 “更新” 它(至少不在这个编辑菜单中)。
溶液:
只需删除[BindProperty]就可以消 debugging 误。

wsewodh2

wsewodh25#

我遇到了同样的错误。构造函数是 internal,我把它作为 public 返回,模型正常传递。

c86crjj0

c86crjj06#

在Controller类的顶部添加[ApiController]为我修复了这个问题:

[Route("api/[controller]")]
[ApiController]
public class ProductController : Controller
{
    ...
}

相关问题