如何在mvc5中绑定单个视图与多个动作?

时间:2016-10-13 08:49:42

标签: c# asp.net-mvc-5

您好我正在为我的应用程序创建Dashboard。它包含控制器中的多个动作。我想将Single View与多个动作绑定,因为我想在视图中显示不同类型的结果。但模型在单一模型中。每个动作都使用相同的模型。

我的模型(客户类型ViewModel)

public class CustomerTypeViewModel
{
    public System.Guid CustomerID { get; set; }
    public string CustomerName { get; set; }
    public DateTime CreatedDate { get; set; }
    public string SalesCount { get; set; }
    public string CustomerType { get; set; }

    public List<View_VisitorsForm> Visits { get; set; }
}
}

我的控制器(这里有两个动作)

这里我创建了两个动作,这两个动作做了不同的计算,这两个动作的模型是相同的(即CustomerTypeViewModel),这两个动作也重定向到同一视图。

   public ActionResult Dashboard()
    {
        List<Customer> n = (from c in db.Customers where c.IsDeleted == false select c).ToList();
        var customertype = string.Empty;
        List<CustomerTypeViewModel> obj = new List<CustomerTypeViewModel>();
        for (var i = 0; i < n.Count; i++)
        {
            var objCustomerName = n[i].DisplayName;
            var objCustomerID = n[i].CustomerID;
            var objCusCreatedDate = n[i].CreatedDate;
            var objNextDate = objCusCreatedDate.GetValueOrDefault().AddDays(120);
            var ObjTodayDate = DateTime.Now.Date;
            var salescount = (from sc in db.SalesOrders where sc.CustomerID == objCustomerID && sc.CreatedDate >= objCusCreatedDate && sc.CreatedDate <= objNextDate select sc.SalesOrderID).Count();
            var ordercount = (from oc in db.SalesOrders where oc.CustomerID == objCustomerID && oc.CreatedDate >= objCusCreatedDate && oc.CreatedDate <= ObjTodayDate select oc.SalesOrderID).Count();
            if (ordercount >= 3)
            {
                customertype = "Existing Customer";
            }
            else if (ordercount == 0 && ordercount <= 0)
            {
                customertype = "New Customer";
            }
            else if (ordercount <= 2 && ordercount >= 1)
            {
                customertype = "Potential Customer";
            }
            obj.Add(new CustomerTypeViewModel()
            {
                CustomerName = objCustomerName,
                CustomerType = customertype,
                SalesCount = ordercount.ToString()
            });
        }
        return View("Dashboard",obj);
    }
    public ActionResult NextFollowup()
    {
        var userID = System.Web.HttpContext.Current.Session["UserID"].ToString();
        var objEmpDepUTID = db.UserRightsSettings.Where(u => u.UserID.ToString() == userID).Select(e => new
        {
            objemployeeID = e.EmployeeID,
            objdepartmentID = e.DepartmentID,
            objusertypeID = e.UserTypeID
        }).FirstOrDefault();

        var EmployeeID = objEmpDepUTID.objemployeeID;
        var DepartmentID = objEmpDepUTID.objdepartmentID;
        var UserTypeID = objEmpDepUTID.objusertypeID;
        var TodayDate = DateTime.Now.Date;

        List<View_VisitorsForm> objVisitorsList = new List<View_VisitorsForm>();
        if (DepartmentID == new Guid("47D2C992-1CB6-44AA-91CA-6AA3C338447E") &&
           (UserTypeID == new Guid("106D02CC-7DC2-42BF-AC6F-D683ADDC1824") ||
           (UserTypeID == new Guid("B3728982-0016-4562-BF73-E9B8B99BD501"))))
        {
            objVisitorsList = db.View_VisitorsForm.Where(X => X.NextAppointment == TodayDate).ToList();
        }
        else
        {
            objVisitorsList = db.View_VisitorsForm.Where(x => x.NextAppointment == TodayDate && x.EmployeeID == EmployeeID).ToList();
        }
        CustomerTypeViewModel objvvm = new CustomerTypeViewModel();
        objvvm.Visits = objVisitorsList;
        return View("Dashboard",objvvm);
    }

我的观点

在这个视图中,我给出的模型就像这样意味着它显示错误

   @model CostToWafe.Areas.Sales.Models.CustomerTypeViewModel
   @using CostToWafe.Areas.Sales.Models

它显示

附近的错误
 @Model.Select(x => x.CustomerName).Count()

如果我给出模型名称与IEnumerable像

   @model IEnumerable<CostToWafe.Areas.Sales.Models.CustomerTypeViewModel>
   @using CostToWafe.Areas.Sales.Models

它显示了

表(Model.Visits)附近的错误
         @foreach (View_VisitorsForm item in Model.Visits)

我的完整视图

@model CostToWafe.Areas.Sales.Models.CustomerTypeViewModel
@using CostToWafe.Areas.Sales.Models
@{
ViewBag.Title = "Dashboard";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container body">
<div class="main_container">
  <div class="right_col" role="main">
        <!-- top tiles -->
   <div class="row tile_count">

   <div class="right">
   <span class="count_top"><i class="fa fa-user"></i> Total Customer</span>
   <div class="count">@Model.Select(x => x.CustomerName).Count()</div>
   </div>

  <div class="right">
  <span class="count_top"><i class="fa fa-user"></i> Existing Customer</span>
  <div class="count">@Model.Where(x => x.CustomerType == "Existing Customer").Count()</div>
  </div>

  <div class="row">
  <table>
  <thead>
         <tr>
                <th>Employee </th>
                <th>Customer Name</th>
                <th>Purpose of Visit</th>
         </tr>
  <thead>
 <tbody>
          @foreach (View_VisitorsForm item in Model.Visits)
          {
          <tr>
               <td>@item.Employee;</td>
               <td>@item.CustomerName;</td>
               <td>@item.POVisit;</td>
          </tr>
          }
 <tbody>
 </table>
  </div>
  </div>
  </div>
  </div>
  </div>

我的问题不长。我尽力解释这个问题。任何人都理解我的问题并帮助我解决这个问题。

谢谢..

1 个答案:

答案 0 :(得分:1)

根据评论和提供的屏幕截图(https://i.stack.imgur.com/DomTM.jpg),我想我现在明白了你想要实现的目标。

问题在于你的方法存在许多逻辑缺陷。

1)您的视图的模型定义为CostToWafe.Areas.Sales.Models.CustomerTypeViewMo‌​del,但您的Dashboard操作正在尝试提供IEnumerable<CostToWafe.Areas.Sales.Models.CustomerTypeViewMo‌​del>作为模型。这两个是不兼容的类型。

2)在问题中,您询问是否可以在单个视图中使用多个操作。答案是肯定的(假设他们都提供正确的模型类型)。但是,您无法同时在同一个View 上调用两个操作(即在同一请求期间)。根据您的要求,您似乎希望DashboardNextFollowUp Action方法返回的数据在单个View中一次显示。使用两种操作方法是不可能的。如果您希望View在不同时间具有不同的内容,则您只能使用多种操作方法。

3)在CustomerTypeViewMo‌​del课程中,您已将List<View_VisitorsForm> Visits定义为班级的属性。这意味着Vists列表以某种方式连接到特定的CustomerType,即CustomerTypeViewMo‌​del的任何一个实例中该列表中包含的vists将仅与仅由该实例表示的CustomerType相关联。现在从要求中可以清楚地看出情况并非如此。相反,访问列表中包含的数据不是由客户类型确定的,而是由当前系统用户确定的。因此,将此列表设为CustomerType的属性是一种不合逻辑的关联,会引起一些混淆。

4)在视图代码中,因为@model被错误地定义为CustomerTypeViewMo‌​del而不是IEnumerable<CustomerTypeViewMo‌​del>的单个实例。尽管如此,您还是尝试使用@Model.Select(x => x.CustomerName).Count()以某种方式计算列表中的对象数。这不起作用,因为View并不认为@ModelIEnumerable<T>,因此您无法对其进行Select

5)CustomerTypeViewModel类似乎更像是客户的表示而不是客户类型 - 它包含客户名称和销售计数等字段,这些字段甚至不需要此视图。所以这是另一个逻辑问题。如果ViewModel被称为CustomerType,则它应该完全代表客户类型,而不是客户,并且不应包含不相关的字段。

鉴于所有这些,您的设计需要彻底重新思考。您需要一个更高级别的ViewModel对象,该对象将包括CustomerTypes列表以及Visits列表。然后可以将其返回到视图,您可以

a)循环显示CustomerTypes列表以显示所有统计信息

b)遍历访问列表以显示所有访问者。

因此,Dashboard操作将构建此DashboardViewModel对象并将其返回到View。不再需要NextFollowUp操作,可以将其删除。

代码应如下所示。如果有任何语法错误或类似问题,我还没有对它进行测试,所以道歉。

查看模型

//This no longer includes Visits, because they aren't specific to a CustomerType
public class CustomerType
{
  public string CustomerTypeDescription { get; set; }
  public int CustomerCount { get; set; }
}

//This is now the ViewModel used by the View:
public class DashboardViewModel
{
   public List<CustomerType> CustomerTypes { get; set; }
   public List<View_VisitorsForm> Visits { get; set; }
}

行动方法

public ActionResult Dashboard()
{
    //first work out the customer type statistics
    List<Customer> customers = (from c in db.Customers where c.IsDeleted == false select c).ToList();

    CustomerType allCustomers = new CustomerType();
    allCustomers.CustomerTypeDescription = "Total Customers";
    allCustomers.CustomerCount = customers.Count;

    CustomerType existingCustomers = new CustomerType();
    existingCustomers.CustomerTypeDescription = "Existing Customers";

    CustomerType potentialCustomers = new CustomerType();
    potentialCustomers.CustomerTypeDescription = "Potential Customers";

    CustomerType newCustomers = new CustomerType();
    newCustomers.CustomerTypeDescription = "New Customers";


    foreach (Customer cus in customers)
    {
        var ordercount = (from oc in db.SalesOrders where oc.CustomerID == cus.CustomerID && oc.CreatedDate >= cus.CreatedDate && oc.CreatedDate <= DateTime.Now.Date select oc.SalesOrderID).Count();

        if (ordercount >= 3)
        {
          existingCustomers.CustomerCount++;
        }
        else if (ordercount == 2 || ordercount == 1)
        {
          potentialCustomers.CustomerCount++;
        }
        else if (ordercount <= 0)
        {
          newCustomers.CustomerCount++;
        }
    }

    //now get the list of visits
    var userID = System.Web.HttpContext.Current.Session["UserID"].ToString();
    var currentUser = db.UserRightsSettings.Where(u => u.UserID.ToString() == userID).Select(e => new
    {
        employeeID = e.EmployeeID,
        departmentID = e.DepartmentID,
        usertypeID = e.UserTypeID
    }).FirstOrDefault();

    List<View_VisitorsForm> visitList = new List<View_VisitorsForm>();
    if (currentUser.departmentID == new Guid("47D2C992-1CB6-44AA-91CA-6AA3C338447E") &&
       (currentUser.usertypeID == new Guid("106D02CC-7DC2-42BF-AC6F-D683ADDC1824") ||
       (currentUser.usertypeID == new Guid("B3728982-0016-4562-BF73-E9B8B99BD501")))
    {
        visitList = db.View_VisitorsForm.Where(X => X.NextAppointment == DateTime.Now.Date).ToList();
    }
    else
    {
        visitList = db.View_VisitorsForm.Where(x => x.NextAppointment == DateTime.Now.Date && x.EmployeeID == currentUser.employeeID).ToList();
    }

    //finally bring it all together to create the ViewModel
    DashboardViewModel vm = new DashboardViewModel();
    vm.CustomerTypes = new List<CustomerType>();
    vm.CustomerTypes.Add(allCustomers);
    vm.CustomerTypes.Add(existingCustomers);
    vm.CustomerTypes.Add(potentialCustomers);
    vm.CustomerTypes.Add(newCustomers);
    vm.Visits = visitList;

    return View("Dashboard", vm);
}

查看

@model CostToWafe.Areas.Sales.Models.DashboardViewModel
@using CostToWafe.Areas.Sales.Models
@{
  ViewBag.Title = "Dashboard";
  Layout = "~/Views/Shared/_Layout.cshtml";
}

<div class="container body">
  <div class="main_container">
    <div class="right_col" role="main">
      <!-- top tiles -->
      <div class="row tile_count">
      @foreach (CustomerType cusType in Model.CustomerTypes)
      {
        <div class="right">
         <span class="count_top"><i class="fa fa-user"></i>@cusType.CustomerTypeDescription</span>
         <div class="count">@cusType.CustomerCount</div>
        </div>
      }
      </div>

      <div class="row">
        <table>
          <thead>
            <tr>
              <th>Employee </th>
              <th>Customer Name</th>
              <th>Purpose of Visit</th>
            </tr>
          </thead>
          <tbody>
          @foreach (View_VisitorsForm visit in Model.Visits)
          {
            <tr>
              <td>@visit.Employee;</td>
              <td>@visit.CustomerName;</td>
              <td>@visit.POVisit;</td>
            </tr>
          }
          </tbody>
        </table>
      </div>
    </div>
  </div>
</div>

我希望这对你有用,并有助于澄清你的想法。将来,如果您事先仔细设计ViewModel并考虑所需的可能数据,并确保您创建的任何类实际上代表他们以其命名的逻辑实体,并且不包含项目与该实体无关,那么理解自己的代码并使事情顺利进行将会容易得多。

关于您的代码的其他一些简短评论:

  • 你有一些冗余变量(特别是var salescount)。不要将代码留在不被使用的地方 - 这会让事情变得混乱。

  • 有一些不正确的HTML(例如,您有两次<thead><thead>... instead of closing the tag properly: ...`。

  • 代码更加冗长,需要它。例如,EmployeeID,DepartmentID的所有声明,然后再次使用。它们是来自早期变量的直接映射,因此只需使用它。

  • 使用有意义的变量名称,可以在整个代码中理解,而无需回顾定义(例如,使用List<Customer> customers代替客户列表而不是List<Customer> n,并且不要使用obj称之为简单objEmpDepUTID - 没有机会知道它是什么。

  • C#是一种强类型语言,因此您并不需要使用Hungarian Notation作为变量名称的前缀(即objVisitorsListobj)。在任何情况下,当变量的类型实际上是像字符串或int的原语而根本不是对象时,你在许多地方也错误地使用了{{1}}前缀。关于使用它的意见各不相同,但一般来说,我发现它只会使代码混乱,并且不会通过读取其余代码(或使用Visual中的Intellisense)来传达任何已经看不到的信息。工作室)。

N.B。从屏幕截图中可以看出,View还有一些其他内容(设备使用,快速设置等),但您还没有提供这些内容的详细信息,因此我假设您将这些内容添加到ViewModel中后面。