【问题标题】:How to show other model column in Razor view?如何在 Razor 视图中显示其他模型列?
【发布时间】:2016-03-10 20:56:02
【问题描述】:

目前我能够从 userRole 模型中显示 razer 视图中的所有列。 只是好奇我是否想在 UserRole Razor 视图中显示 SiteName 列,而不是显示 SiteID,这可能吗?我知道它可以通过自定义视图模型来完成,但这是必须的吗?如果我错了,请纠正我!

用户角色模型:

    public int UserID { get; set; }
    public string UserName { get; set; }
    public int SiteID { get; set; }
    *No SiteName column here....so i only can show SiteID in razor..

网站模型:

public int SiteID { get; set; }
public string SiteName { get; set; } <<-- the column i want..

控制器:

public ActionResult Index()

    {
         //need join table here perhaps?

         return View(db.User_Role.ToList());
    }

剃刀视图:

@model IEnumerable<FAB_Portal_POC.Models.UserRole>

<table class="table table-striped table-hover">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.UserName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Role)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.SiteID)
        </th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.UserName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Role)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.SiteID) <<-- i want site name.
        </td>      
    </tr>
}
</table>

【问题讨论】:

  • 为什么所有的 MVC 教程都这么难?跟我重复一遍:不要使用实体模型作为视图模型。时期。无论如何,你的User_Role实体模型应该有一个Site导航属性,你可以Include()加入站点表,然后你可以选择站点名称。
  • @CodeCaster,就我个人而言,我认为这总是是正确的。 ViewModel 可以是任何满足视图需求的东西。通常,实体不会(或会造成太多麻烦),但这并不总是正确的。
  • @CodeCaster 好的,我知道这可以通过使用自定义视图模型来完成。只是好奇!
  • @haim 不,不是总是,但在实际应用程序中使用实体模型作为视图模型几乎不够。当然,您的 My First TODO 网站可以正常工作,直到您想要引入相关表格并在下拉列表中显示这些表格。然后 ViewBag 黑客入侵,您将面临一场噩梦。从一开始就使用视图模型。编辑:QED.
  • @CodeCaster,我在这里挑剔,但尽管实体通常更重且面向业务(或至少应该如此),但一些(实体框架)“实体”仅仅是价值对象,而且导致人们只是为了“不使用实体作为视图模型”而复制整个 Country 类型(例如)。

标签: c# asp.net-mvc asp.net-mvc-4 razor


【解决方案1】:

第一个问题是您的UserRole 实体模型似乎没有导航属性。

您并不需要,但是查询变得很尴尬:

var rolesWithSite = from r in db.User_Role
                    join s in db.Sites on s.ID equals r.Site_ID
                    select new
                    {
                        Role = r,
                        Site = s
                    }
                    .ToList();

当您添加导航属性时(甚至可能代替外键属性):

public class User_Role
{
    public int UserID { get; set; }
    public string Role { get; set; }
    public string UserName { get; set; }
    public virtual Site Site { get; set; }
}

查询将变得容易得多:

var rolesWithSite = db.User_Role.Include(r => r.Site).ToList();

然后你可以引入一个视图模型:

public class UserRoleViewModel
{
    public int UserID { get; set; }
    public string UserName { get; set; }
    public string Role { get; set; }
    public string Site { get; set; }
}

并将查询结果映射到:

var viewModels = rolesWithSite.Select(r => new UserRoleViewModel
{
    UserID = r.UserID,
    UserName = r.UserName,
    Role = r.Role,
    Site = r.Site.SiteName,

}).ToList();

return View(viewModels);

【讨论】:

    【解决方案2】:

    实体和模型非常不同。

    你必须为你的页面创建一个特定的模型。

    类似这样的:

    页面模型

    public string UserName { get; set; }
    public string SiteName { get; set; }
    

    在您的控制器中,您必须准备好要发送到页面的所有数据。在这里,您可以将实体“关联”到您的页面模型

    public ActionResult Index()
    
    {
         var roles = db.User_Role.ToList();
         var sites = db.Sites.ToList(); // i don t know how you get this information in your exemple.
    
         //define here every property of the PageModel you want to use there
         var model = new PageModel();
         model.UserName = roles.UserName;
         model.SiteName = sites.Select(...).SiteName;
    
         return View(model);
    }
    

    然后在剃刀视图中

    @model IEnumerable<FAB_Portal_POC.Models.PageModel>
    

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      您有多种方法可以做到这一点,最简单的一种是您必须创建新的类名称 UserRoleViewData 并提及这些字段并将类对象传递给查看。就这样。

      新类UserRoleViewData看起来像这样

      public int UserID { get; set; }
      public string UserName { get; set; }
      public int SiteID { get; set; }
      public string SiteName { get; set; }
      

      和您的控制者

      public ActionResult Index()
      
      {
            List<className> dto = (from a in _db.User_Role
                       join b in db.Site on a.SiteID equals b.SiteID 
                        select (new classname { UserID =a.UserID , UserName =a.UserName , SiteID =a.SiteID , SiteName =b.SiteName })).ToList();
           return View(dto);
      }
      

      在视图中你必须改变@model IEnumerable&lt;FAB_Portal_POC.folderName.ClassName&gt; 并像其他人一样在视图上映射其他属性。我希望你能理解,这会对你有所帮助。

      【讨论】:

      • 是否需要在列表中创建一个DTO?因为它显示“无法在 LINQ to Entities 查询中构造实体或复杂类型”。无论如何感谢您的信息:)
      • 你有多种方法可以做到这一点,但我分享一个简单的。
      【解决方案4】:

      您可以将站点列表存储在 ViewBag 中,并通过从 ViewBag 中提取站点名称来显示站点名称:

      public ActionResult Index()
      {
           ViewBag.Sites = db.Sites.ToList();
           return View(db.User_Role.ToList());
      }
      

      还有观点:

      <td>
          @Html.DisplayFor(modelItem => ViewBag.Sites.Single(s => s.SiteID == item.SiteID).SiteName)
      </td>
      

      另一个对我来说更好的方法是为您的视图创建一个ViewModel,其中包含您需要的所有数据。并将该视图模型返回到您的视图。

      public class UserSiteViewModel
      {
          public int UserID { get; set; }
          public string UserName { get; set; }
          public string Role { get; set; }
          public int SiteID { get; set; }
          public string SiteName { get; set; }
      }
      

      【讨论】:

      • 不要建议这样的不良做法。你不知道db.Sites 有多大,你也不想在你看来做那样的业务逻辑。只需引入一个视图模型。
      • 同意@CodeCaster,永远不要考虑业务逻辑,实际上使用模型。
      • @CodeCaster 这就是我在帖子末尾所说的。
      • 如果您的答案包含看似有效的可复制粘贴代码,谁会阅读?
      【解决方案5】:

      无需使用 ViewBag ,在 2 个表之间连接并将结果存储在另一个 viewModel 中,这是一个很糟糕的主意。请查看参考链接,它真的会帮助您朝着非常好的方向编写代码。 Click Here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-22
        • 2020-09-06
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 2014-10-15
        • 1970-01-01
        • 2021-10-18
        相关资源
        最近更新 更多