使用DTO查看 - ASP.NET MVC

时间:2015-09-14 12:07:42

标签: c# asp.net asp.net-mvc entity-framework asp.net-mvc-4

我对MVC很新,我一直在尝试使用DTO作为模型类创建视图,但它似乎使用我用于模型的数据上下文类,即使我正在清除我在创建视图时的选择。

这个问题似乎导致了NullReferenceException,它是由抛出以下异常引起的,并且视图没有返回它。

ITSSkillsDatabase.Models.PersonSkillSetsDTO: : EntityType 'PersonSkillSetsDTO' has no key defined. Define the key for this EntityType.

PersonSkillSets: EntityType: EntitySet 'PersonSkillSets' is based on type 'PersonSkillSetsDTO' that has no keys defined.

我的DTO:

namespace ITSSkillsDatabase.Models
{
    public class PersonSkillSetsDTO
    {
        public int IDSkillset { get; set; }
        public int IDCategory { get; set; }
        public string Product { get; set; }
        public string P_Version { get; set; }
        public string Notes { get; set; }
        public int PersonSkillsID { get; set; }
        public int IDPerson { get; set; }
        public int Score { get; set; }
        public DateTime ScoreDate { get; set; }
        public int TargetScore { get; set; }
        public DateTime TargetDate { get; set; }
        public DateTime RefresherDate { get; set; }
    }
}

控制器方法:

public ActionResult SkillSets(int? id)
{
    try
    {
        if (id == null)
        {
            return HttpNotFound();
        }
        var viewModel = (from a in db.SkillSets
                         join c in db.PersonSkills on a.IDSkillset equals c.IDSkillSet
                         where c.IDPerson == id
                         select new Models.PersonSkillSetsDTO
                         {
                             IDSkillset = a.IDSkillset,
                             IDCategory = a.IDCategory,
                             Product = a.Product,
                             P_Version = a.P_Version,
                             Notes = a.Notes,
                             PersonSkillsID = c.PersonSkillsID,
                             IDPerson = c.IDPerson,
                             Score = c.Score,
                             ScoreDate = c.ScoreDate,
                             TargetScore = c.TargetScore,
                             TargetDate = c.TargetDate,
                             RefresherDate = c.RefresherDate
                         }).ToList();
        return View(viewModel);
    }
    catch
    {
        return View(); //this is where the NullReferenceException is thrown
    }
}

这些是我创建视图时的设置:

我意识到我可以通过检查空值来摆脱NullReferenceException,但我不知道如何解决我的DTO问题。

4 个答案:

答案 0 :(得分:2)

我将尝试使用ViewModel / DTO来解释创建表单和POST。

ViewModel不在数据库上下文中,因此,如果您使用的是ViewModel,则必须将数据从ViewModel映射到Model和Model到ViewModel。

因此,如果您正在阅读数据库

  1. 创建DBContext
  2. 读取您想要阅读的数据
  3. 映射到ViewModel
  4. 将ViewModel传递给View或API
  5. 如果您要写入数据库

    1. POST ViewMdoel从View到Controller(您可以使用Ajax)
    2. 创建DBContext
    3. 从ViewModel映射到模型
    4. 将模型保存到数据库
    5. 假设你有一个DTO,

         public class CountryDTO
          {
      
              public int CountryId { get; set; }
      
              [Display(Name = "Country Name")]
              [Required(ErrorMessage = "This field is required")]
              public string CountryName { get; set; }
      
              [Display(Name = "Latitude")]
              [Required(ErrorMessage = "This field is required")]
              public double CentralLat { get; set; }
      
              [Display(Name = "Longitude")]
              [Required(ErrorMessage = "This field is required")]
              public double CentralLang { get; set; }
      
              [Display(Name = "GMT Offset")]
              [Required(ErrorMessage = "This field is required")]
              public double GMTOffSet { get; set; }
      
              [Display(Name = "Currency")]
              [Required(ErrorMessage = "This field is required")]
              public string Currency { get; set; }
          }
      

      创建一个控制器,即CountryController,您有一个观看文件夹Country,右键单击国家/地区文件夹Add - > View,将其命名为CreateCountry,将模型选为CountryDTO

      您无法在此处选择DataContext,因为DTO不是Context

      的一部分

      enter image description here

      这将使用DTO中的字段创建您的视图。

      现在在你的控制器中你需要2个动作

      1. GET方法返回视图
      2. POST方法回复表单

        public ActionResult CreateCountry()
        {
            return PartialView(new CountryDTO());
        }
        
      3. 现在在POST方法中你将通过DTO,让我们假设你的数据库中有一个Country表,你必须创建一个新的国家类型对象并添加到上下文

            [HttpPost]
            public ActionResult CreateCountry(CountryDTO model)
            {
                if (ModelState.IsValid)
                {
                    // Model State is Valid
                    // here you will create Context
        
                    using (var dbContext = new DATBASE_CONTEXT())
                    {
                        var newCountry = new Country() // Country is a Model from Database
                        {
                            CountryName = model.CountryName,
                            CentralLat = model.CentralLat,
                            // Map All Properties from View Model to Model
                        };
        
                        // Add the New Country to the Countries 
                        dbContext.Countries.Add(newCountry);
        
                        // Save Database Changes
                        dbContext.SaveChanges();
                    }
                }
                return PartialView(model);
            }
        

        enter image description here

        如果您想显示此国家/地区:

            public ActionResult CountryDetails(int id)
            {
                var model = new CountryDTO();
        
                using (var dbContext = new DATABASE_CONTEXT())
                {
                    var country = dbContext.Country.First(s => s.CountryId == id);
                    model.CountryName = country.CountryName;
                    // Same for other Properties
                    // You can use AutoMapper Library to Map from Model to DTO/ViewModel
        
                }
                return View(model);
            }
        

答案 1 :(得分:0)

try
{
    // <...>
    return View(viewModel);
}
catch
{
    return View(); //this is where the NullReferenceException is thrown
}

您得到NullReferenceException,因为您的视图需要该模型,并且不会在Razor中执行空检查。

要验证这一点,您可以创建虚拟模型并将其传递到return View(/* model */);来电。

答案 2 :(得分:0)

据我所知,异常问题不在于DbContext,而在于lame模型:“没有键定义”。我认为检查数据注释可能会有所帮助。

答案 3 :(得分:-2)

我创建了一个新的视图模型,其中包含了我需要的两个模型。

然后我在控制器中设置View Model的值。

这给了我想要的结果。 enter image description here