0

我是 MVC/C# 初学者,所以请轻松一点。

我有一个现有的数据库,其中客户有零个或多个项目。我已经从 ADODB 实体数据模型和 dbContext 代码生成器构建了一个 ASP.Net 项目。

我有一个客户:Joe Bloggs (ID=7)。我在我的表单中单击 Joe Bloggs 的“项目”链接以查看他的项目。他没有。我想为他创建一个项目,所以我在项目控制器上调用 Create 操作。

出于三个原因,我需要将 Joe Bloggs ID 传递给 Create 操作(这可能没有必要 - 如果需要,请赐教)

  1. 因为这是 Joe Bloggs 的项目,所以我需要将 ID=7 传递给控制器​​,以便在为创建视图生成模型数据时为他设置默认客户 ID

  2. 当我点击 Create 视图上的 Cancel 按钮时,我想回到基于 Joe Blogs 的最初过滤的项目视图

  3. 当我点击保存时,我想回到最初基于 Joe Bloggs 过滤的项目视图。

无论如何,如果我确实有一个或多个 Joe Bloggs 项目,那么我可以使用下面的这个怪物从视图中的模型数据中访问他的 id:

<input type="button" title = "New Project" value="New Project" onclick="location.href='@Url.Action("Create", new { id = Model.First().Customer_ID })'" />

这是问题所在:如果他没有任何项目, Model.First() 不会返回任何内容,因此我找不到“父” Customer_ID 记录。

我使用 dbContext 生成模型类(这是数据优先开发)。有些东西告诉我,我可以扩展这些类或创建一个新类以允许上述情况。

我目前的解决方法是使用 ViewBag 从查看器 > 控制器中传递各种 id 和字符串,就像烫手山芋一样,但这意味着如果获得三个深度(客户 > 项目 > 任务),并且我想在任务上显示客户名称,我已经通过了两次。它闻起来臭臭的。

我注意到项目索引视图中的下拉列表中有客户。这是我的代码:

@Html.DropDownList("Customer_ID", null, "Select a Customer to Filter", new { @onchange = "this.form.submit();" })

我也许可以从那里破解它,但我真的希望能够从一个可能有两到三个深度并且与此下拉菜单相距甚远的类向上遍历

这是从 dbContext 生成的删节的 Customer 和 CustomerProject 类

public partial class Customer
{
    public Customer()
    {
        this.Tasks = new HashSet<Task>();
        this.CustomerProjects = new HashSet<CustomerProject>();
    }

    public int Customer_ID { get; set; }
    public string Customer_Name { get; set; }

    public virtual ICollection<CustomerProject> CustomerProjects { get; set; }
}

public partial class CustomerProject
{
    public CustomerProject()
    {
        this.Tasks = new HashSet<Task>();
        this.CustomerProjectTasks = new HashSet<CustomerProjectTask>();
    }

    public int CustomerProject_ID { get; set; }
    public int Customer_ID { get; set; }
    public string Project_Name { get; set; }

    public virtual ICollection<Task> Tasks { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual ICollection<CustomerProjectTask> CustomerProjectTasks { get; set; }
}

我确信有一个明显的解决方案,但我的优势在于数据库和 VB6,而不是 C#

在 Mystere Man 的建议下,我构建了一个 ViewModel 类,但我遇到了一些麻烦:

这是我的模型类文件中的内容(据我了解,这只是现有项目实体的包装):

namespace zzz.Models
{
    using System;
    using System.Collections.Generic;

    public class ProjectsViewModel
    {
        public int Customer_ID { get; set; }
        public ICollection<CustomerProject> CustomerProjects;
    }
}

这是我的控制器的 Index 操作中的内容(我刚刚将现有的 Project 集合添加到新的 ViewModel 类中):

    public ViewResult Index(int pCustomer_ID = 0, string pProjectName_Filter = "")
    {

        // Set up drop down
        ViewBag.Customer_ID = new SelectList(db.Customers.OrderBy(x => x.Customer_Name), "Customer_ID", "Customer_Name");
        //ViewBag.Selected_Customer_ID = Customer_ID;

        // If no parameters entered, show nothing
        // Otherwise optionally filter each parameter
        var projects = from p in db.CustomerProjects
            orderby p.Active, p.Project_Order
            where
            (p.Project_Name.Contains(pProjectName_Filter) || pProjectName_Filter.Equals("")) &&
            (p.Customer_ID == pCustomer_ID || pCustomer_ID.Equals(0)) &&
            !(pCustomer_ID.Equals(0) && pProjectName_Filter.Equals(""))
            select p;


        var customerprojects = new ProjectsViewModel
        {
            Customer_ID = pCustomer_ID,
            CustomerProjects = projects.ToList()
        };


        return View(customerprojects);
    }

这是我的视图的摘录(我试图遍历 ViewModel 类中的 Project 集合):

@model IEnumerable<BistechPortal.Models.ProjectsViewModel>

<table>
@foreach (var item in Model.CustomerProjects)
{
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.Project_Name)
    </td>
</tr>
}
</table>

当我运行 Index 操作时,在 foreach 行上我得到:

'System.Collections.Generic.IEnumerable<zzzzPortal.Models.ProjectsViewModel>' does not contain a definition for 'CustomerProjects' "

请翻译 - 为什么它在我的 ViewModel 中找不到我的“CustomerProjects”集合?

4

1 回答 1

0

这就是为什么您不应该将实体对象直接传递给视图的原因。在大多数情况下,视图需要比定义的实体提供的信息更多的信息(或不同的信息)。

这就是视图模型存在的原因。您将创建一个包含 Customer_ID 和项目(以及您需要的任何其他数据)的视图模型。然后,即使用户没有项目,您也可以访问 Customer_ID。

public class ProjectsViewModel {
     public int Customer_ID {get;set;}
     public List<CustomerProject> CustomerProjects;
}

然后你将这个新对象传递给你的视图。

(由OP添加:)

要将这个对象传递给您的视图,您需要告诉视图它不再接受 CustomerProjects 类型的数据,并且(这花了我三个小时来解决)它不再获得“可枚举”数据。

所以在你看来改变

@model IEnumerable<Portal.Models.CustomerProjects>

@model Portal.Models.ProjectsViewModel

同样在您的视图中,您现在想要迭代 Model.CustomerProject,所以更改

@foreach (var item in Model)

@foreach (var item in Model.CustomerProjects)
于 2012-09-30T18:55:55.057 回答