我正在尝试使用乔伊·史蒂文(Je Steven)的博客在此处讨论的经过编辑的BeginCollectionItem版本通过MVC 5中的表单提交来一次绑定我的所有模型数据。
该模型Company有个List<Pa_Ipv4>,而类Pa_Ipv4又有一个List<IpAllocation>,我想访问IpAllocation每个中的所有属性并将其保存到数据库中Pa_Ipv4。
Company
List<Pa_Ipv4>
Pa_Ipv4
List<IpAllocation>
IpAllocation
IE浏览器: Model.pa_ipv4s[x].requestedIps[x].subnet
Model.pa_ipv4s[x].requestedIps[x].subnet
主页使用的是模型Company,它具有部分接受Pa_Ipv4,它具有部分接受IpAllocation。
问题1: 在控制器中,我为列表中的第一项(requestedIp)设置了字符串属性,但是当我提交和回发时,该属性(allocationType)为null,该属性需要进行硬编码,因为它是内部使用的在数据库中使用- 为什么要重置?
allocationType
原因: 该属性不在post方法中,因此最初声明的内容由于不在最终发布中而被丢弃。
可能的解决方案: 在表单中使用隐藏的属性,以便在发布表单且用户无法访问该属性时显示该属性。
问题2: BeginCollectionItem在适当地命名属性,即IE:,pa_ipv4s[8e075d50-a5fb-436f-9cef-85abfb6910e3].requestedIps[b693b83c-b6b1-4c42-b983-4d058e766d4c].subnet但是只有初始模型,然后它忽略了创建的任何其他模型,我做错了什么?
pa_ipv4s[8e075d50-a5fb-436f-9cef-85abfb6910e3].requestedIps[b693b83c-b6b1-4c42-b983-4d058e766d4c].subnet
原因: Pa_Ipv4节BeginCollectionItem生成的前缀所需的GUID无法由IpAllocation BeginCollectionItem访问,因为只有初始内容具有正确的前缀,此后添加的任何内容都缺少必需的前缀。
另一个可能的解决方案本质上是相同的概念,但是不要使用div,而应使用html data属性,以便可以访问它。
我认为我遇到的两个问题都与我如何设置控制器有关,但是我也在下面包括了“视图和模型”。该模型包含所有属性,在我看来,其中的许多属性已删除,以节省空间,因为这些不会引起问题。
创造
@model Company @{ Layout = "~/Views/Shared/_Layout.cshtml"; } @using (Html.BeginForm()) { <div class="jumboservice"> <div data-role="page"> <div data-role="header"> <h2>PA IPv4 Request Form</h2> </div> <div class="ui-content" data-role="main"> <h3>Company Details</h3> <div class="ui-grid-c ui-responsive"> <div class="ui-block-a"> <p class="lblStyle">Company Name</p> <span> @Html.EditorFor(m => m.name) @Html.ValidationMessageFor(m => m.name) </span> </div> </div> </div> <br /> @foreach (var i in Model.pa_ipv4s) { @Html.Partial("Pa_IPv4View", i) } <br /> <div data-role="main" class="ui-content"> <div data-role="controlgroup" data-type="horizontal"> <input type="submit" class="ui-btn" value="Create" /> </div> </div> </div> </div> } <script type="text/javascript"> $(function () { $('#addItemRIpM').on('click', function () { $.ajax({ url: '@Url.Action("RequestedManager")', cache: false, success: function (html) { $("#editorRowsRIpM").append(html); } }); return false; }); $('#editorRowsRIpM').on('click', '.deleteRow', function () { $(this).closest('.editorRow').remove(); }); }); </script>
Pa_Ipv4部分
@model Pa_Ipv4 @using (HtmlHelpers.BeginCollectionItem.HtmlPrefixScopeExtensions.BeginCollectionItem(Html,"pa_ipv4s")) { @Html.AntiForgeryToken() <div class="ui-grid-c ui-responsive"> <div class="ui-block-a"> <p class="lblStyle">Subnet</p> </div> <div class="ui-block-b"> <p class="lblStyle">Size(CIDR)</p> </div> <div class="ui-block-c"> <p class="lblStyle">Mask</p> </div> <div class="ui-block-d"> </div> </div> @*Request IP Address Space List*@ <div id="editorRowsRIpM"> @foreach (var item in Model.requestedIps) { @Html.Partial("RequestedIpView", item) } </div> @Html.ActionLink("Add", "RequestedManager", null, new { id = "addItemRIpM", @class = "button" }) }
RequestedIp部分
@model IpAllocation <div class="editorRow"> @using (HtmlHelpers.BeginCollectionItem.HtmlPrefixScopeExtensions.BeginCollectionItem(Html, "requestedIps")) { <div class="ui-grid-c ui-responsive"> <div class="ui-block-a"> <span> @Html.TextBoxFor(m => m.subnet) </span> </div> <div class="ui-block-b"> <span> @Html.TextBoxFor(m => m.cidr) </span> </div> <div class="ui-block-c"> <span> @Html.TextBoxFor(m => m.mask) <span class="dltBtn"> <a href="#" class="deleteRow">Remove</a> </span> </span> </div> </div> } </div>
控制者
public ActionResult Create() { var cmp = new Company(); cmp.contacts = new List<Contact> { new Contact { email = "", name = "", telephone = "" } }; cmp.pa_ipv4s = new List<Pa_Ipv4> { new Pa_Ipv4 { ipType = "Pa_IPv4", registedAddress = false, existingNotes = "", numberOfAddresses = 0, returnedAddressSpace = false, additionalInformation = "", requestedIps = new List<IpAllocation> { new IpAllocation { allocationType = "Requested", cidr = "", mask = "", subnet = "" } // allocationType is null in cmp in the Create[HttpPost] } } }; return View(cmp); } public ActionResult Pa_IPv4Manager() { return PartialView("Pa_IPv4View", new Pa_Ipv4()); } public ActionResult RequestedManager() { return PartialView("RequestedIpView", new IpAllocation { allocationType = "Requested" }); // allocationType is null in cmp in the Create[HttpPost] } // POST: Pa_Ipv4/Create [HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(Company cmp) //only one requestedIps count regardless of how many add { if (ModelState.IsValid) { db.companys.Add(cmp); db.SaveChanges(); return RedirectToAction("Index"); }
模型
[Table("Ipv_Base")] public class Ipv_Base { [Key] public int ipv_baseId { get; set; } public int companyId { get; set; } [ForeignKey("companyId")] public Company company { get; set; } public string ipType { get; set; } [Required] public bool registedAddress { get; set; } [Required] [DataType(DataType.MultilineText)] public string existingNotes { get; set; } [Required] public int numberOfAddresses { get; set; } [Required] public bool returnedAddressSpace { get; set; } [DataType(DataType.MultilineText)] public string additionalInformation { get; set; } // navigation properties public virtual IList<IpAllocation> requestedIps { get; set; } } [Table("Company")] public class Company { [Key] public int companyId { get; set; } [Required] public string name { get; set; } [Required] public string telephone { get; set; } [Required] public string regNumber { get; set; } // navigation properties to keep track of the models that belong to the company public virtual IList<Pa_Ipv4> pa_ipv4s { get; set; } } [Table("IpAllocation")] public class IpAllocation { [Key] public int ipAllocationId { get; set; } public int ipv_BaseId { get; set; } [ForeignKey("ipv_BaseId")] public Ipv_Base ipv_Base { get; set; } [Required] public string allocationType { get; set; } [Required] public string subnet { get; set; } [Required] public string cidr { get; set; } [Required] public string mask { get; set; } } public class Pa_Ipv4 : Ipv_Base { public Pa_Ipv4() { ipType = "pa_ipv4"; } }
问题1解决方案:
Q1的问题在于,我在控制器中分配的属性值未从表单发布中解析出来,因为该属性不存在。
为该属性添加了一个隐藏字段,以纠正讨厌的null。
<div class="ui-block-a"> <span> @Html.HiddenFor(m => m.allocationType) @Html.TextBoxFor(m => m.subnet, new { @class = "checkFiller" }) </span> </div>
问题2解决方案:
我将第一个模型的GUID作为第二个模型的前缀附加在一起时遇到的问题,很大程度上是由于我如何使用AJAX向控制器操作方法发送数据。
下面显示的代码段解决了这些问题,并显示了正确绑定的GUID。
name="pa_ipv4s[f7d8d024-5bb6-451d-87e3-fd3e3b8c1bba].requestedIps[d5c08a43-f65e-46d1-b224-148225599edc].subnet" 现在显示在动态创建的模型属性上,而不仅仅是最初创建的。
name="pa_ipv4s[f7d8d024-5bb6-451d-87e3-fd3e3b8c1bba].requestedIps[d5c08a43-f65e-46d1-b224-148225599edc].subnet"
在Visual Studio中的调试中运行并将鼠标悬停在模型上时,深入挖掘数据将显示模型列表的正确计数。
控制器ActionMethod:
public ActionResult ExistingManager(string containerPrefix) { ViewData["ContainerPrefix"] = containerPrefix; return PartialView("ExistingIpView", new IpAllocation { allocationType = "Existing" }); }
调用Controller ActionMethod的AJAX GET方法:
$('#addItemEIpM').on('click', function () { $.ajax({ url: '@Url.Action("ExistingManager")', cache: false, data: 'containerPrefix=' + $('#addItemEIpM').data('containerprefix'), success: function (html) { $("#editorRowsEIpM").append(html); } }); return false; });