C# 如何在运行时从现有数据模型中的数据构建自定义的动态ViewModel?
因此,我正在开发一个web应用程序,遇到了一个新的挑战,我已经坚持了几个星期。我将提供有关我的应用程序和数据模型的背景信息,以及期望的最终结果 问题的基本应用程序信息和上下文: 我的应用程序旨在作为一种工具,供景观承包商使用,以帮助管理其业务运营。我的应用程序将提供一个地方,他们可以创建一个帐户,然后输入他们的所有客户信息(“客户”数据模型),以及他们为每个客户所做工作的信息(“工作”数据模型)。客户机和作业之间存在一对多关系(一个客户机可以有多个作业,但任何给定作业只能有一个客户机) 背景: 我有两个简单的数据模型,“客户”和“工作”。我的应用程序正在ASP.net MVC3框架中构建。使用实体框架脚手架机制,我为每个数据模型(创建、读取、更新、删除)创建了基本CRUD视图。这在很大程度上是很好的(我可以创建新的客户和工作,并且可以很容易地编辑现有的客户和工作) 业务问题: 我需要允许在我的应用程序中批量创建新工作。我希望我的用户(景观承包商)能够输入他们当天完成的所有割草作业。因此,我想让我的视图为这个过程填充一个包含所有活动客户端的表,每个活动客户端在行旁边都有一个复选框。然后,我希望用户能够选中他们为每个客户做了新工作(修剪草坪)的复选框,并提交表单(输入jobs done),其中的结果将是为每个客户创建新的工作 技术问题: 我的最佳猜测是,我需要在控制器中创建一个自定义ViewModel并将其发送到视图,其中ViewModel是基于当前活动客户端创建的新作业列表。然后在视图中,复选框可以将Client_ID(客户端的唯一标识符)作为其值(这将是ViewModel的一部分。当用户提交表单时,视图会将ViewModel传递回控制器。然后控制器可以浏览ViewModel作业列表,并为选中复选框的每个ViewModel作业创建新作业 因此,我的问题是-如何使用控制器执行以下操作: 1.)基于客户机列表(“客户机”数据模型)中的数据,在运行时构建ViewModel作业列表? 2.)然后如何将其传递给视图? 3.)一旦返回控制器,我如何迭代列表并相应地修改其他数据模型(创建新的“作业”项) 我创建了自定义ViewModel,其中包含构建新作业条目所需的客户机和作业属性(客户机名称、客户机地址、客户机id、作业说明、班组、班组大小、工作时间、指示完成的复选框等)。假设用户有50个客户端,他为这些客户端修剪草坪。我想构建一个包含50行的ViewModel(表示可能会修剪草坪的每个客户机)。然后我想把它发送到视图,并用复选框显示它,这些复选框指示草坪是否被修剪。当模型返回到视图时,控制器将在复选框中获取带有复选框的行,并在该表中创建新的“作业”行 提前感谢你们提供的任何帮助,我知道这对你们中的许多人来说可能是一个简单的过程。我不熟悉C#和MVC3 更新: 这是我的密码- 工作模式C# 如何在运行时从现有数据模型中的数据构建自定义的动态ViewModel?,c#,asp.net,sql-server,asp.net-mvc-3,C#,Asp.net,Sql Server,Asp.net Mvc 3,因此,我正在开发一个web应用程序,遇到了一个新的挑战,我已经坚持了几个星期。我将提供有关我的应用程序和数据模型的背景信息,以及期望的最终结果 问题的基本应用程序信息和上下文: 我的应用程序旨在作为一种工具,供景观承包商使用,以帮助管理其业务运营。我的应用程序将提供一个地方,他们可以创建一个帐户,然后输入他们的所有客户信息(“客户”数据模型),以及他们为每个客户所做工作的信息(“工作”数据模型)。客户机和作业之间存在一对多关系(一个客户机可以有多个作业,但任何给定作业只能有一个客户机) 背景:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace LawnTracker.Models
{
public class Job
{
[Key]
public int Job_ID { get; set; }
public int Client_ID { get; set; }
public int Account_ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public string Notes { get; set; }
public string SvcRoute { get; set; }
public string Service { get; set; }
public string Date { get; set; }
public double SvcPriceOverride { get; set; }
public float SvcQty { get; set; }
public string UofM { get; set; }
public bool Invoiced { get; set; }
public string Crew { get; set; }
public int TechCount { get; set; }
public string TimeStart { get; set; }
public string TimeFinish { get; set; }
public double TimeSpent { get; set; }
public string Image1 { get; set; }
public string Image2 { get; set; }
public string Image3 { get; set; }
public double MulchUsed { get; set; }
public double FertUsed { get; set; }
public double HerbUsed { get; set; }
public string NextDue { get; set; }
}
}
我的割草作业视图模型-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LawnTracker.Models
{
public class MowingJobViewModel
{
public int Client_ID { get; set; }
public bool Completed { get; set; }
public string Name { get; set; }
public string Street { get; set; }
public string City { get; set; }
public double SvcPriceOverride { get; set; }
public string UofM { get; set; }
public int SvcQty { get; set; }
public string Notes { get; set; }
public string Date { get; set; }
public string Crew { get; set; }
public int TechCount { get; set; }
public string SvcRoute { get; set; }
public string Schedule { get; set; }
}
}
// GET: /Job/CreateMowing
public ActionResult CreateMowing(string route = "", string sched = "")
{
List<SelectListItem> listItems = new List<SelectListItem>();
listItems.Add(new SelectListItem()
{
Value = "Lump Sum",
Text = "Lump Sum"
});
listItems.Add(new SelectListItem()
{
Value = "Hours",
Text = "Hours"
});
ViewBag.Units = new SelectList(listItems, "Value", "Text");
ViewBag.Routes = db.Clients.Select(r => r.SvcRoute).Distinct();
ViewBag.Sched = db.Clients.Select(r => r.MowSched).Distinct();
var model = from r in db.Clients
orderby r.SvcRoute
where (r.Mowing == true) &&
(r.Status == "Active") &&
(r.SvcRoute == route || (route == "")) &&
(r.MowSched == sched || (sched == ""))
select r;
if (model.Count() > 0)
{
ViewBag.total = model.Select(r => r.MowPrice).Sum();
}
else
{
ViewBag.total = 0.00;
}
/* Build a list of MowingJobViewModel objects based on the above defined list of clients
* who are subscribed to mowing and active. This will enable batch entry for new jobs done.
* This list of MowingJobViewModel objects will be sent to the client after a HTTP GET
* request for the CreateMowing view. The user will be able to check boxes associated
* with each client in the client list. When the form is submitted, the controller
* receives the model back with the updated information (completed, notes, etc.) about
* each job. Then the controller must update the jobs table, adding the new jobs based on
* the view model returned from the view / client.
*
*/
//Create a new list of MowingJobViewModel objects
IEnumerable<MowingJobViewModel> mjList = new List<MowingJobViewModel>();
//iterate through the list of clients built from earlier (in model)...
foreach (var item in model)
{
//create new MowingJobViewModel object MJ and add it to the list
mjList.Add(new MowingJobViewModel()
{
Client_ID = item.Client_ID,
Completed = false,
Name = (item.FirstName + " " + item.LastName),
Street = item.Address1,
City = item.City,
SvcPriceOverride = item.MowPrice,
UofM = "Lump Sum",
SvcQty = 1,
Notes = "",
Date = "",
Crew = "",
TechCount = 2,
SvcRoute = item.SvcRoute,
Schedule = item.MowSched,
});
}
return View(mjList);
}
**I don't have my view ("CreateMowing.cshtml") worked out correctly, but here is what I have-**
@model IEnumerable<LawnTracker.Models.MowingJobViewModel>
@{
ViewBag.Title = "Enter Mowing Jobs";
}
<h2>Enter Mowing Jobs</h2>
<div style="float: left; clear:both; width: 100%;">
<b>Total Jobs: @Html.Encode(Model.Count())</b><br />
<b>Total Revenue: $@Html.Encode(ViewBag.total)</b><br /><br />
</div>
<p></p>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<div style="float: right; clear:both; width: 100%;">
@using (Html.BeginForm("CreateMowing", "Job", FormMethod.Get))
{
<table>
<tr>
<th></th>
<th>
Route
</th>
<th>Schedule</th>
<th></th>
</tr>
<tr>
<td>
Show:
</td>
<td>
@Html.DropDownList("route", new SelectList(ViewBag.Routes), "--ALL--")
</td>
<td>
@Html.DropDownList("sched", new SelectList(ViewBag.Sched), "--ALL--")
</td>
<td>
<input type="submit" value="Filter" />
</td>
</tr>
</table><br /><br />
}
</div>
<table>
<tr>
<th>
Completed
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Street
</th>
<th>
City
</th>
<th>
Service Route
</th>
<th>
Price
</th>
<th>
Units
</th>
<th>
Qty
</th>
<th>
Notes
</th>
<th>
Schedule
</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
<input type="checkbox" name="invoiced" value="@item.Client_ID" >
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Address1)
</td>
<td>
@Html.DisplayFor(modelItem => item.City)
</td>
<td>
@Html.DisplayFor(modelItem => item.SvcRoute)
</td>
<td>
@Html.DisplayFor(modelItem => item.MowPrice)
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
@Html.DisplayFor(modelItem => item.MowSched)
</td>
</tr>
}
</table>
<div>
<br />
@Html.ActionLink("Back to List", "Index")
</div>
和我的JobController-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LawnTracker.Models
{
public class MowingJobViewModel
{
public int Client_ID { get; set; }
public bool Completed { get; set; }
public string Name { get; set; }
public string Street { get; set; }
public string City { get; set; }
public double SvcPriceOverride { get; set; }
public string UofM { get; set; }
public int SvcQty { get; set; }
public string Notes { get; set; }
public string Date { get; set; }
public string Crew { get; set; }
public int TechCount { get; set; }
public string SvcRoute { get; set; }
public string Schedule { get; set; }
}
}
// GET: /Job/CreateMowing
public ActionResult CreateMowing(string route = "", string sched = "")
{
List<SelectListItem> listItems = new List<SelectListItem>();
listItems.Add(new SelectListItem()
{
Value = "Lump Sum",
Text = "Lump Sum"
});
listItems.Add(new SelectListItem()
{
Value = "Hours",
Text = "Hours"
});
ViewBag.Units = new SelectList(listItems, "Value", "Text");
ViewBag.Routes = db.Clients.Select(r => r.SvcRoute).Distinct();
ViewBag.Sched = db.Clients.Select(r => r.MowSched).Distinct();
var model = from r in db.Clients
orderby r.SvcRoute
where (r.Mowing == true) &&
(r.Status == "Active") &&
(r.SvcRoute == route || (route == "")) &&
(r.MowSched == sched || (sched == ""))
select r;
if (model.Count() > 0)
{
ViewBag.total = model.Select(r => r.MowPrice).Sum();
}
else
{
ViewBag.total = 0.00;
}
/* Build a list of MowingJobViewModel objects based on the above defined list of clients
* who are subscribed to mowing and active. This will enable batch entry for new jobs done.
* This list of MowingJobViewModel objects will be sent to the client after a HTTP GET
* request for the CreateMowing view. The user will be able to check boxes associated
* with each client in the client list. When the form is submitted, the controller
* receives the model back with the updated information (completed, notes, etc.) about
* each job. Then the controller must update the jobs table, adding the new jobs based on
* the view model returned from the view / client.
*
*/
//Create a new list of MowingJobViewModel objects
IEnumerable<MowingJobViewModel> mjList = new List<MowingJobViewModel>();
//iterate through the list of clients built from earlier (in model)...
foreach (var item in model)
{
//create new MowingJobViewModel object MJ and add it to the list
mjList.Add(new MowingJobViewModel()
{
Client_ID = item.Client_ID,
Completed = false,
Name = (item.FirstName + " " + item.LastName),
Street = item.Address1,
City = item.City,
SvcPriceOverride = item.MowPrice,
UofM = "Lump Sum",
SvcQty = 1,
Notes = "",
Date = "",
Crew = "",
TechCount = 2,
SvcRoute = item.SvcRoute,
Schedule = item.MowSched,
});
}
return View(mjList);
}
**I don't have my view ("CreateMowing.cshtml") worked out correctly, but here is what I have-**
@model IEnumerable<LawnTracker.Models.MowingJobViewModel>
@{
ViewBag.Title = "Enter Mowing Jobs";
}
<h2>Enter Mowing Jobs</h2>
<div style="float: left; clear:both; width: 100%;">
<b>Total Jobs: @Html.Encode(Model.Count())</b><br />
<b>Total Revenue: $@Html.Encode(ViewBag.total)</b><br /><br />
</div>
<p></p>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<div style="float: right; clear:both; width: 100%;">
@using (Html.BeginForm("CreateMowing", "Job", FormMethod.Get))
{
<table>
<tr>
<th></th>
<th>
Route
</th>
<th>Schedule</th>
<th></th>
</tr>
<tr>
<td>
Show:
</td>
<td>
@Html.DropDownList("route", new SelectList(ViewBag.Routes), "--ALL--")
</td>
<td>
@Html.DropDownList("sched", new SelectList(ViewBag.Sched), "--ALL--")
</td>
<td>
<input type="submit" value="Filter" />
</td>
</tr>
</table><br /><br />
}
</div>
<table>
<tr>
<th>
Completed
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Street
</th>
<th>
City
</th>
<th>
Service Route
</th>
<th>
Price
</th>
<th>
Units
</th>
<th>
Qty
</th>
<th>
Notes
</th>
<th>
Schedule
</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
<input type="checkbox" name="invoiced" value="@item.Client_ID" >
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Address1)
</td>
<td>
@Html.DisplayFor(modelItem => item.City)
</td>
<td>
@Html.DisplayFor(modelItem => item.SvcRoute)
</td>
<td>
@Html.DisplayFor(modelItem => item.MowPrice)
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
@Html.DisplayFor(modelItem => item.MowSched)
</td>
</tr>
}
</table>
<div>
<br />
@Html.ActionLink("Back to List", "Index")
</div>
//获取:/Job/CreateMowing
public ActionResult CreateMowing(字符串route=“”,字符串sched=“”)
{
List listItems=新列表();
添加(新建SelectListItem()
{
Value=“一次性付款”,
Text=“一次性付款”
});
添加(新建SelectListItem()
{
Value=“小时”,
Text=“小时”
});
ViewBag.Units=新选择列表(列表项,“值”、“文本”);
ViewBag.Routes=db.Clients.Select(r=>r.SvcRoute.Distinct();
ViewBag.Sched=db.Clients.Select(r=>r.MowSched.Distinct();
var model=来自数据库中的r.Clients
orderby r.svc路由
式中(r.割草==真)&&
(r.状态==“活动”)&&
(r.SvcRoute==route | |(route==“”)&&
(r.MowSched==sched | |(sched==“”)
选择r;
如果(model.Count()>0)
{
ViewBag.total=model.Select(r=>r.MowPrice.Sum();
}
其他的
{
ViewBag.total=0.00;
}
/*基于上面定义的客户端列表,构建MowingJobViewModel对象列表
*已订阅割草并处于活动状态的用户。这将为完成的新作业启用批输入。
*此MowingJobViewModel对象列表将在HTTP GET后发送到客户端
*请求CreateMowing视图。用户将能够选中相关的复选框
*客户端列表中的每个客户端。提交表单时,控制器
*接收带有更新信息(已完成、注释等)的模型
*然后,控制器必须更新作业表,根据
*从视图/客户端返回的视图模型。
*
*/
//创建割草作业视图模型对象的新列表
IEnumerable mjList=新列表();
//伊特拉