模型绑定复杂类型不能是抽象类型或值类型

模型绑定复杂类型不能是抽象类型或值类型

本文介绍了模型绑定复杂类型不能是抽象类型或值类型,并且必须具有无参数构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下问题,我创建了一个应用程序来将游戏类别和游戏本身添加到数据库中.我创建了一个关系,但不幸的是,当我添加到数据库时出现错误.

I have the following problem, I created an application to add game categories and the games themselves to the database. I created a relationship and unfortunately when I add to the database I get an error.

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

游戏类别模型

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

我不知道出了什么问题.

I don't have any idea what is wrong.

我的错误画面

推荐答案

让我们试着打破这个错误.

Let's try and break this error down.

无法创建relationship.ViewModels.AddGameViewModel 的实例.

不言自明:模型绑定组件正在尝试创建您的类型的实例,但失败了.

Pretty self-explanatory: the model-binding components are trying to create an instance of your type, but failed.

模型绑定复杂类型

模型绑定"是指它们被 ASP.NET 管道绑定.复杂类型"基本上是任何不是基本"的类型,如 stringint.您的模型类是复杂类型.

"Model bound" refers to that they're being bound by the ASP.NET pipeline. "complex types" are basically any types which aren't "basic" like string or int. Your model classes are complex types.

不能抽象

模型绑定系统希望能够创建类的实例,因此它不能是抽象的;它必须是具体的.您展示的所有类型都是具体的,所以这不是问题.

The model-binding system is going to want to be able to create instances of the class, so it cannot be abstract; it must be concrete. All of the types you've show are concrete so this isn't the problem.

或值类型

您不能将 struct 类型与模型绑定一起使用;这只是它的局限性之一.幸运的是你的类型都是类,所以你可以忽略这一点.

You can't use struct types with model-binding; it's just one of its limitations. Fortunately your types are all classes, so you can ignore this.

并且必须有一个无参数的构造函数.

ASP.NET 不知道如何向模型构造函数提供参数.它只能做等效于 new T() 的事情,所以你所有的模型类型都必须定义一个具有零参数的构造函数.这就是您看到错误的原因;你的 AddGameViewModel 类只定义了这个构造函数:

ASP.NET doesn't know how to supply parameters to model constructors. It can only do the equivalent of new T(), so all your model types must define a constructor which has zero parameters. This is the reason you're seeing the error; your AddGameViewModel class only defines this constructor:

public AddGameViewModel(IEnumerable<GameCategory> categories)

C# 语言的一项功能是,当您不手动指定构造函数时,它会为您添加一个默认构造函数.当您在代码中定义构造函数时,不会添加此默认构造函数.

One of the C# language features is that when you don't specify a constructor manually, it adds a default one for you. When you define a constructor in your code, this default constructor is not added.

在所有其他模型中,您没有定义任何构造函数,因此编译器会为您添加默认构造函数.在 AddGameViewModel 的情况下,您添加了一个构造函数,因此要解决此问题,您还必须添加默认构造函数:

In all of your other models, you aren't defining any constructors so the compiler is adding the default one for you. In the case of AddGameViewModel you have added a constructor, so to fix the problem you must also add the default constructor:

public AddGameViewModel()
{
}

这篇关于模型绑定复杂类型不能是抽象类型或值类型,并且必须具有无参数构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 20:32