【问题标题】:ASP.NET MVC Viewmodel returns nothingASP.NET MVC Viewmodel 不返回任何内容
【发布时间】:2017-11-19 13:47:21
【问题描述】:

尝试制作一个简单的应用程序,但在尝试使用视图模型时我的视图没有返回任何内容。我假设在域模型上应用时有效的“db.[TableName].ToList();”是不够的,并且在使用视图模型时选择应该以不同的方式发生,但我不知道该怎么做它。请帮忙。谢谢。

Town.cs

using System.Collections.Generic;

namespace City.Models
{
    public class Town
    {
        public Town()
        {
            Streets = new List<Street>();
        }
        public int TownId { get; set; }
        public string TownName { get; set; }
        public virtual ICollection<Street> Streets { get; set; }
    }
}

Street.cs

using System.Collections.Generic;

namespace City.Models
{
    public class Street
    {
        public Street()
        {
            Houses = new List<House>();
        }
        public int StreetId { get; set; }
        public string StreetName { get; set; }
        public virtual ICollection<House> Houses { get; set; }
    }
}

House.cs

namespace City.Models
{
    public class House
    {
        public int HouseId { get; set; }
        public string HoueseName { get; set; }
        public int StreetId { get; set; }
        public virtual Street Street { get; set; }
    }
}

Floor.cs

namespace City.Models
{
    public class Floor
    {
        public int FloorId { get; set; }
        public int FloorNumber { get; set; }
        public int FireExtinguisherId { get; set; }
    }
}

FireExtinguisher.cs

namespace City.Models
{
    public class FireExtinguisher
    {
        public int FireExtinguisherId { get; set; }
        public string FireExtinguisherName { get; set; }
        public int FloorId { get; set; }
    }
}

MyViewModel.cs

namespace City.Models
{
    public class MyViewModel
    {
        public MyViewModel()
        {
            Town = new Town();
            Street = new Street();
            House = new House();
            Floor = new Floor();
            FireExtinguisher = new FireExtinguisher();
        }

        public int MyViewModelId { get; set; }
        public Town Town { get; set; }
        public Street Street { get; set; }
        public House House { get; set; }
        public Floor Floor { get; set; }
        public FireExtinguisher FireExtinguisher { get; set; }
    }
}

ApplicationDbContext.cs

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public DbSet<Town> Towns { get; set; }
        public DbSet<Street> Streets { get; set; }
        public DbSet<House> Houses { get; set; }
        public DbSet<Floor> Floors { get; set; }
        public DbSet<FireExtinguisher> FireExtinguishers { get; set; }
        public DbSet<MyViewModel> MyViewModels { get; set; }
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }

HomeController.cs(我认为问题出在这里)

using System.Linq;
using System.Web.Mvc;
using City.Models;

namespace City.Controllers
{
    public class HomeController : Controller
    {
        private ApplicationDbContext db;
        public HomeController()
        {
            db = new ApplicationDbContext();
        }
        public ActionResult Index()
        {
            return View(db.MyViewModels.ToList());
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

Index.cshtml

@model IEnumerable<City.Models.MyViewModel>

<h2>Map information</h2>

<div class="container">
    <table class="table">
        <thead>
            <tr>
                <th>Town</th>
                <th>Street</th>
                <th>House</th>
                <th>Floor</th>
                <th>FireExtinguisher</th>
            </tr>
        </thead>
        @foreach (var item in Model)
        {
            <tbody>
                <tr>
                    <td>@(item.Town.TownName)</td>
                    <td>@(item.Street.StreetName)</td>
                    <td>@(item.House.HoueseName)</td>
                    <td>@(item.Floor.FloorNumber)</td>
                    <td>@(item.FireExtinguisher.FireExtinguisherName)</td>
                </tr>
            </tbody>
        }
    </table>
</div>

尽管我在数据库中有测试数据,但我在运行它时看到的都是这样的:

Image is here

请告诉我应该修复什么,如何检索数据。谢谢

编辑@CrowdCoder

new picture here

【问题讨论】:

  • 我认为您没有为实体框架使用正确的约定。您正在更新 MyViewModel 的构造函数中的所有内容,我认为您的结构没有创建正确的导航属性。但是,我已经有一段时间没有使用 EF 了。在您的控制器中,将此行分隔为一个变量,以便您可以中断它并查看它的值db.MyViewModels.ToList()(另外,您不需要 ToList() this)
  • 我试过了,但是没有 ToList() 就坏了。编辑了我的帖子,请查看更改
  • 您可以通过在控制器中返回硬编码视图模型而不是调用数据库来帮助诊断您的问题是否与 EF 相关。只是为了测试,手动创建一些MyViewModels,看看你的视图是否显示它们。
  • hc-ing 一些值有效,所以问题肯定在于查询数据库 - 但这并不奇怪,因为我从一开始就很确定数据选择有问题。我的问题更像是在使用视图模型时从 db 检索数据的正确 LINQ 语法是什么。
  • 我就是这么想的。您更改或提出一个关注 EF 的新问题并消除所有 MVC 内容。我很确定您的课程不符合 EF 约定,但更专业的人可以更好地帮助您。

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


【解决方案1】:

我认为你对视图模型的理解是错误的。

视图模型是一个在视图和操作方法之间传输数据的类。 视图模型特定于视图。因此,如果您的视图只需要显示 2 个属性(NameAge),那么您的视图模型将只有这 2 个属性。无需将实体模型中的所有属性带到视图模型类中。

我看到您在数据库上下文中添加了一个新集合,

public DbSet<MyViewModel> MyViewModels { get; set; }

这没有任何意义。正如我之前提到的,视图模型是 UI 问题。它不应该出现在您的数据访问代码中。也不要在视图模型中混合 ORM 层创建的实体。

视图模型也是简单的 POCO。它应该是具有属性的精益扁平类。加载属性值是您的责任。您可以在您的操作方法或从您的操作方法调用的其他方法中执行此操作。

假设您要显示带有街道名称的房屋列表,您将创建一个这样的视图模型

public class HouseViewModel
{
   public int HouseId { set; get;}
   public string HoueseName { set;get;}
   public string StreetName { set;get; }
}

现在在您看来,您只需访问这些属性

@model IEnumerable<HouseViewModel>
<table>
@foreach(var item in Model)
{
    <tr>
         <td>@item.HouseId </td>
         <td>@item.HoueseName </td>
         <td>@item.StreetName </td>
    </tr>
}
</table>

当然,要使这段代码正常工作,您需要确保您将创建一个 HouseViewModel 列表并将其从您的操作方法发送到视图。

public ActionResult Index()
{
   var list= new List<HouseViewModel>{
               new HouseViewModel { HouseId =1,HoueseName ="Abc", StreetName ="Detroit"},
               new HouseViewModel { HouseId =2,HoueseName ="Xyz", StreetName ="Novi"}
   };
   return View(list);
}

现在您可以看到我们如何使用视图模型将数据从操作方法传输到视图。在这里,我们只是硬编码了我们要发送的列表中项目的属性值。我们可以根据需要更新它以从您的 EF 数据库上下文中读取。

让我们阅读所有房屋,使用 LINQ 投影为该集合中的每个项目创建一个 HouseViewModel 对象并分配属性值。

public ActionResult Index()
{
   var houses = db.Houses
                  .Select(a=>new HouseViewModel 
                                  { HouseId =a.HouseId,
                                    HoueseName =a.HouseName,
                                    StreetName = a.Street.StreetName
                                  })
                  .ToList();
   return View(houses);
}

【讨论】:

  • 虽然它可能是糟糕的设计,但没有法律禁止在您的上下文中使用与视图模型中相同的类,因此不会导致报告的问题。另外,请注意模型的属性是其他类型,而不是字符串,因此需要连接导航属性。
  • "我们可以根据需要更新它以从您的 EF 数据库上下文中读取。" - 是的,这实际上是我问题的重点。正如我在上面已经指出的那样,hc-ing 值是一个可行的解决方案,但显然这不是我想要的,而是从 db 中获取它们。至于您对VM更改的建议,谢谢,我会按照建议做的。那么,如果 VM 不是数据库实体,如何将 VM 属性与域模型属性相关联呢?如何从数据库中取回数据?
  • 我刚刚更新了代码,向您展示了如何从您的数据库上下文中读取数据并将其映射到视图模型对象。看看更新后的答案。
  • @Crowcoder 当然没有法律。恕我直言,视图模型不应与您的数据访问层混合。如果明天您出于性能原因决定更改 EF 并改用另一种技术怎么办?我更喜欢这样做。但是,嘿,是我。欢迎你以不同的方式。
  • 我不是说你错了,你只是没有解决问题,所以我不认为这是一个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-27
  • 2019-04-06
  • 2012-02-15
  • 2020-09-07
相关资源
最近更新 更多