【发布时间】:2017-11-21 01:45:49
【问题描述】:
我知道这个问题被问过很多次,但很遗憾,没有一个答案对我有帮助。
我有树 POCO 模型,它们是 Pharmacy、Address 和 Company 聚集到一个 ViewModel PharmacyVM 中:
public class PharmacyVM
{
public Pharmacy pharmacyProp { get; set; }
public Address addressProp { get; set; }
public Company companyProp { get; set; }
public int CityId { get; set; }
public PharmacyVM()
{
pharmacyProp = new Pharmacy();
addressProp = new Address();
companyProp = new Company();
}
}
不要嘲笑属性名称;一开始,他们是正常的(地址,公司和药房)我根据这里的很多答案之一改变了他们,但是......它没有帮助:(
在 Create 方法的 Get 操作中,我尝试手动创建 PharmacyVM 对象并将其传递给视图:
public ActionResult Create()
{
ViewBag.CityId = new SelectList(db.Cities, "Id", "Name");
ViewBag.CompanyId = new SelectList(db.Companies, "Id", "Name");
ViewBag.AddressId = new SelectList(db.Addresses, "Id", "Name");
ViewBag.CityId = new SelectList(db.Cities, "Id", "Name");
ViewBag.RegionId = new SelectList(db.Regions, "Id", "Name");
ViewBag.DistrictId = new SelectList(db.Districts, "Id", "Name");
ViewBag.MicrodistrictId = new SelectList(db.Microdistricts, "Id", "Name");
ViewBag.StreetId = new SelectList(db.Streets, "Id", "Name");
ViewBag.VillageId = new SelectList(db.Villages, "Id", "Name");
var pharmacyVM = new PharmacyVM();
return View(pharmacyVM);
}
视图中有一个标准的 Razor 代码:
@model MEDONET.Models.PharmacyVM
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm("Create", "Pharmacies", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>pharmacyProp</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.companyProp, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("CompanyId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.companyProp.Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.pharmacyProp.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.pharmacyProp.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.pharmacyProp.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.addressProp.City, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("CityId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CityId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CityId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("CityId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CityId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.addressProp.Village, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("VillageId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.addressProp.VillageId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.addressProp.District, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("DistrictId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.addressProp.DistrictId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.HiddenFor(model => model.addressProp.RegionId)
@Html.LabelFor(model => model.addressProp.Region, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("RegionId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.addressProp.RegionId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.addressProp.Microdistrict, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("MicrodistrictId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.addressProp.MicrodistrictId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.addressProp.Building, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.addressProp.Building, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.addressProp.Building, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.addressProp.Street, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("MicrodistrictId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.addressProp.MicrodistrictId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.pharmacyProp.IsGov, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.pharmacyProp.IsGov)
@Html.ValidationMessageFor(model => model.pharmacyProp.IsGov, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.companyProp, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("companyId", null, "", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.pharmacyProp.CompanyId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.pharmacyProp.LargeImage, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="LargeImageFile" required />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div> @Html.ActionLink("Back to List", "Index")</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
然后在 Create 方法的 Post 动作中,我尝试创建 b 和 c 变量:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(PharmacyVM model, HttpPostedFileBase LargeImageFile)
{
if (ModelState.IsValid)
{
string LargeImageFileName = Path.GetFileNameWithoutExtension(LargeImageFile.FileName);
string LargeImageExtansion = Path.GetExtension(LargeImageFile.FileName);
LargeImageFileName = LargeImageFileName + DateTime.Now.ToString("yymmssfff") + LargeImageExtansion;
LargeImageFileName = Path.Combine(Server.MapPath("~/Images/Pharmacy/Banners/"), LargeImageFileName);
int b = model.CityId;
int c = model.addressProp.RegionId.Value;
//Address address = new Address()
//{
// Id = 12,//db.Addresses.AsEnumerable().Last().Id + 1,
// RegionId = PharmacyVM.Address.RegionId,
// DistrictId = PharmacyVM.Address.DistrictId,
// CityId = PharmacyVM.Address.CityId,
// MicrodistrictId = PharmacyVM.Address.MicrodistrictId,
// StreetId = PharmacyVM.Address.StreetId,
// VillageId = PharmacyVM.Address.VillageId,
// Building = PharmacyVM.Address.Building,
// Cab = PharmacyVM.Address.Cab
//};
//Address address = new Address
//{
// Id = 12,//db.Addresses.AsEnumerable().Last().Id + 1,
// RegionId = 1,
// DistrictId = 1,
// CityId = 1,
// MicrodistrictId = 1,
// StreetId = 1,
// VillageId = 1,
// Building = "1",
// Cab = "1"
//};
//db.Addresses.Add(address);
db.SaveChanges();
var pharmacy = new Pharmacy
{
Name = model.pharmacyProp.Name,
//AddressId = address.Id,
IsGov = model.pharmacyProp.IsGov,
CompanyId = model.pharmacyProp.CompanyId,
LargeImage = "~/Images/Pharmacy/Banners/" + LargeImageFileName
};
LargeImageFile.SaveAs(LargeImageFileName);
db.Pharmacies.Add(pharmacy);
db.SaveChanges();
ModelState.Clear();
return RedirectToAction("Index");
}
}
与第一个变量 b 不同,第二个变量 c 将是 null,因为 addressProp 属性是 null。
那为什么这么奇怪呢?如何在不复制原始模型字段的情况下使用 ViewModel?
【问题讨论】:
-
这里有太多糟糕的代码,很难知道从哪里开始。查看模型不包含数据模型。它们包含视图中所需的各种模型的属性。当使用视图模型时,您将从不使用
ViewBag(您的视图模型将包含下拉列表的IEnumerable<SelectListItem>属性)。而且您没有创建与您的addressProp模型相关的任何表单控件,因为您的命名然后VillageId和您的PharmacyVM模型不包含名为VillageId的属性(但您的addressProp模型包含) -
建议您首先查看this Q/A 中的代码,以了解如何正确定义视图模型并在视图中生成下拉列表
-
你能举个小例子吗?我只想在我的视图模型中使用这三个字段代表三个 POCO 类。
-
我给你的链接包含一个例子。您的视图模型将包含属性(例如)
int? CompanyId和IEnumerable<SelectListItem> CompanyList,然后将@Html.DropDownList("CompanyId", null, ...)替换为@Html.DropDownListFor(m => m.CompanyId, Model.CompanyList, ...)。它将包含(比如)int? Microdistrict和IEnumerable<SelectListItem> MicrodistrictList,您将用@Html.DropDownListFor(m => m.Microdistrict, Model.IEnumerable, ...)替换@Html.DropDownList("MicrodistrictId", null, ... ),所有其他属性同上 -
它还将包含一个属性
HttpPostedFileBase LargeImageFile和视图@Html.TextBoxFor(m => m.LargeImageFile, new { type = "file" })用于强绑定到文件输入
标签: c# asp.net model-view-controller viewmodel