简体   繁体   English

使用 DTO 查看 - ASP.NET MVC

[英]View using DTO - ASP.NET MVC

I'm fairly new to MVC and I've been trying to create a view using a DTO as the Model Class, but it seems to be using the Data Context class I use for my Models, even though I am clearing the selection when I am creating the view.我对 MVC 还很陌生,我一直在尝试使用 DTO 作为模型类来创建视图,但它似乎正在使用我用于模型的数据上下文类,即使我在清除选择时正在创建视图。

This issue seems to be causing a NullReferenceException which is caused by the following exception being thrown and the view not having any returned to it.此问题似乎导致 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.

My DTO:我的 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; }
    }
}

Controller method:控制器方法:

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

These are the settings when I'm creating the view:这些是我创建视图时的设置:

I realise I can get rid of the NullReferenceException by checking for null values, but I don't have any idea how to fix the issue with my DTO.我意识到我可以通过检查空值来摆脱 NullReferenceException,但我不知道如何解决我的 DTO 问题。

I am going to try to explain using a ViewModel/DTO to create a Form and POST back.我将尝试解释如何使用 ViewModel/DTO 创建一个表单并回传。

ViewModels are outside of the Database Context, So if you are using a ViewModel you have to Map your data from ViewModel to Model and Model to ViewModel. ViewModel 位于数据库上下文之外,因此如果您使用的是 ViewModel,则必须将数据从 ViewModel 映射到 Model,并将 Model 映射到 ViewModel。

So if you are reading from Database所以如果你从数据库中读取

  1. Create DBContext创建数据库上下文
  2. read data you want to read读取你想读取的数据
  3. Map to a ViewModel映射到 ViewModel
  4. Pass ViewModel to the View or API将 ViewModel 传递给 View 或 API

If you are writing to the database如果您正在写入数据库

  1. POST ViewMdoel from View to Controller (You can use Ajax) POST ViewMdoel 从视图到控制器(你可以使用 Ajax)
  2. Create DBContext创建数据库上下文
  3. Map from ViewModel to Model从 ViewModel 到 Model 的映射
  4. Save Model to Database将模型保存到数据库

let's say you have a DTO,假设你有一个 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; }
    }

Create a controller ie CountryController and you have a Views Folder Country , Right Click Country Folder Add --> View , Name it CreateCountry and Select Model to be CountryDTO创建一个控制器,即CountryController并且您有一个 Views Folder Country ,右键单击 Country Folder Add --> View ,将其命名为CreateCountry并选择模型为CountryDTO

You can't select DataContext here , because DTO is not part of the Context您不能在此处选择 DataContext ,因为 DTO 不是 Context 的一部分

在此处输入图片说明

This will create your view with Fields from the DTO.这将使用来自 DTO 的字段创建您的视图。

Now in your Controller you need 2 Actions现在在您的控制器中,您需要 2 个操作

  1. GET method to return the View GET方法返回视图
  2. POST method to POST back the form POST返回表单的POST方法

    public ActionResult CreateCountry() { return PartialView(new CountryDTO()); }

Now in the POST method you will Pass the DTO, Let's assume you have a Country table in your Database, you will have to create a New Country type Object and add to the Context现在在 POST 方法中,您将传递 DTO,假设您的数据库中有一个Country表,您必须创建一个新的 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);
    }

在此处输入图片说明

IF you want to display this Country:如果要显示此国家/地区:

    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);
    }
try
{
    // <...>
    return View(viewModel);
}
catch
{
    return View(); //this is where the NullReferenceException is thrown
}

You get NullReferenceException because your view expects the model and doesn't perform null checks in Razor.您得到NullReferenceException是因为您的视图需要模型并且不在 Razor 中执行空检查。

To verify this, you can create a dummy model and pass it into your return View(/* model */);为了验证这一点,您可以创建一个虚拟模型并将其传递到您的return View(/* model */); call.称呼。

As I understood the exception trouble is not with DbContext but with lame model: "No key defined".据我了解,异常问题不是 DbContext 而是蹩脚模型:“未定义键”。 I think checking data-annotations might help.我认为检查数据注释可能会有所帮助。

I created a new View Model which contains everything I need from the two models.我创建了一个新的视图模型,其中包含我需要的两个模型的所有内容。

I then set the values for the View Model within the controller.然后我在控制器中设置视图模型的值。

Which gave me the result I wanted.这给了我想要的结果。 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM