部分空例外内的部分 [英] Partial within a partial null exception
问题描述
我有一个MVC形式比我所有的其他的更复杂,利用三种模式。
公司 - > Base_IP - > RequestedIP
肚里视图模型 - > Partial1 - > Partial2
我使用BeginCollectionItem为这每一个模型的模型从下来的财产清单。 IE浏览器 - 公司有一个属性叫做baseIps的BaseIp类有一个属性叫做requestedIps,这是 requestedIps
这是回来了空,计有网页渲染,但不提交。
当提交到的后的Create(),我得到的'requestedIps'属性空数据库,这是为什么?
我添加违规控制器和部分code以下的样品,而不是因为它的庞大/冗余整个事情 - 有任何疑问,请让我知道
控制器 - [HTTPGET]创建()
公众的ActionResult的Create()
{
VAR CMP =新公司
{
接触=新的List<联系与GT;
{
新的联系人{电子邮件=,名称=,电话=}
},pa_ipv4s =新的List< Pa_Ipv4>
{
新Pa_Ipv4
{
X最多=Pa_IPv4,registedAddress =假,existingNotes =,numberOfAddresses = 0,returnedAddressSpace =假,additionalInformation =,
requestedIps =新的List< IpAllocation>
{
新IpAllocation {allocationType =请求,CIDR =,面具=,子网=}
}
}
}
};
返回查看(CMP);
}
控制器 - [HttpPost]创建()
[HttpPost]
[ValidateAntiForgeryToken]
公众的ActionResult创建(公司CMP)//不包含分配的属性/添加到视图渲染
{
如果(ModelState.IsValid)
{
db.companys.Add(CMP);
db.SaveChanges();
返回RedirectToAction(「指数」);
}
返回查看(CMP);
}
创建视图
@model公司
@using(Html.BeginForm())
{
< DIV ID =editorRowsAsn>
@foreach(在Model.pa_ipv4s VAR IP)
{
@ Html.Partial(Pa_IPv4View,IP)
}
< / DIV>
< BR />
< DIV数据角色=主类=UI内容>
< DIV数据角色=controlgroup数据类型=横向>
<输入类型=提交级=UI-BTNVALUE =创建/>
< / DIV>
< / DIV>
}
Pa_Ipv4查看
@model Pa_Ipv4
@using(Html.BeginCollectionItem(pa_ipv4s))
{
@ Html.AntiForgeryToken() < DIV ID =editorRowsRIpM>
@foreach(在Model.requestedIps VAR项)
{
@ Html.Partial(RequestedIpView项)
}
< / DIV>
@ Html.ActionLink(添加,RequestedManager,空,新的{ID =addItemRIpM,@class =按钮}}
RequestedIpView
@model IpAllocation
< DIV CLASS =editorRow>
@using(Html.BeginCollectionItem(requestedIps))
{
< DIV CLASS =UI网-C UI响应>
< DIV CLASS =UI-块一个>
<跨度>
@ Html.TextBoxFor(M = GT; m.subnet,新{@class =checkFiller})
< / SPAN>
< / DIV>
< DIV CLASS =UI块-B>
<跨度>
@ Html.TextBoxFor(M = GT; m.cidr,新{@class =checkFiller})
< / SPAN>
< / DIV>
< DIV CLASS =UI块-C>
<跨度>
@ Html.TextBoxFor(M = GT; m.mask,新{@class =checkFiller})
<跨度类=dltBtn>
< A HREF =#类=deleteRow>< IMG SRC =〜/图片/ DeleteRed.png的风格=宽度:15px的;高度:15px的; />&下; / A>
< / SPAN>
< / SPAN>
< / DIV>
< / DIV>
}
< / DIV>
您第一(外)部分会产生,涉及到你的模型正确的名称属性(您code不显示任何控制在 Pa_Ipv4.cshtml
的看法,但我认为你这样做有一定的),例如:
<输入名称=pa_ipv4s [XXX-XXX] .someProperty ...>
但是内部分不会因为 @using(Html.BeginCollectionItem(requestedIps))
将产生
<输入名称=requestedIps [XXX-XXX] .subnet ...>
<输入名称=requestedIps [XXX-XXX] .cidr ...>
他们应该是
<输入名称=pa_ipv4s [XXX-XXX] .requestedIps [YYY-YYY] .subnet ...>
<输入名称=pa_ipv4s [XXX-XXX] .requestedIps [YYY-YYY] .cidr ...>
通常你可以通过preFIX到部分使用附加视图数据(参见<一个href=\"http://stackoverflow.com/questions/29808573/getting-the-values-from-a-nested-complex-object-that-is-passed-to-a-partial-view/29809907#29809907\">this回答一个例子),但不幸的是,你不必进入由 BeginCollectionItem
的Guid >助手所以它不可能正确preFIX的名称
属性。
其他选项包括使用嵌套为
循环和包括集合索引,这将让你从集合中删除项目仍然能够绑定到你的模型的隐藏输入当您提交表单。
的for(int i = 0; I&LT; Model.pa_ipv4s.Count;我++)
{
对于(INT J = 0; J&LT; Model.pa_ipv4s [I] .requestedIps.Count; J ++)
{
变种名称=的String.Format(pa_ipv4s [{0}] requestedIps.Index。我);
@ Html.TextBoxFor(M = GT; m.pa_ipv4s [I] .requestedIps [J] .subnet)
@ Html.TextBoxFor(M = GT; m.pa_ipv4s [I] .requestedIps [J] .cidr)
...
&LT;输入类型=隐藏的名字=@名价值=@ J/&GT;
}
}
然而,如果你还需要动态地添加新的项目,你需要使用JavaScript来生成HTML(参见例<一个href=\"http://stackoverflow.com/questions/29161481/post-a-form-array-without-successful/29161796#29161796\">here和<一个href=\"http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308\">here)
I have a MVC form which is more complex than all of my others, utilising three models.
Company -> Base_IP -> RequestedIP
which goes ViewModel -> Partial1 -> Partial2
I am using BeginCollectionItem for this has each model has a property list of the the model down from it. IE - Company has a property called baseIps, the BaseIp class has a property called requestedIps, it is requestedIps
that is coming back null, the count is there on page render, but is not on submit.
When submitting to the database in the post
Create(), I get nulls on the 'requestedIps' property, why is this?
I've added the offending controller and partial code samples below, not the entire thing as it's massive/redundant - any questions, please let me know.
Controller - [HttpGet]Create()
public ActionResult Create()
{
var cmp = new Company
{
contacts = new List<Contact>
{
new Contact { email = "", name = "", telephone = "" }
}, 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 = "" }
}
}
}
};
return View(cmp);
}
Controller - [HttpPost]Create()
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Company cmp) // does not contain properties assigned/added to in view render
{
if (ModelState.IsValid)
{
db.companys.Add(cmp);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(cmp);
}
Create View
@model Company
@using (Html.BeginForm())
{
<div id="editorRowsAsn">
@foreach (var ip in Model.pa_ipv4s)
{
@Html.Partial("Pa_IPv4View", ip)
}
</div>
<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>
}
Pa_Ipv4 View
@model Pa_Ipv4
@using (Html.BeginCollectionItem("pa_ipv4s"))
{
@Html.AntiForgeryToken()
<div id="editorRowsRIpM">
@foreach (var item in Model.requestedIps)
{
@Html.Partial("RequestedIpView", item)
}
</div>
@Html.ActionLink("Add", "RequestedManager", null, new { id = "addItemRIpM", @class = "button" }
}
RequestedIpView
@model IpAllocation
<div class="editorRow">
@using (Html.BeginCollectionItem("requestedIps"))
{
<div class="ui-grid-c ui-responsive">
<div class="ui-block-a">
<span>
@Html.TextBoxFor(m => m.subnet, new { @class = "checkFiller" })
</span>
</div>
<div class="ui-block-b">
<span>
@Html.TextBoxFor(m => m.cidr, new { @class = "checkFiller" })
</span>
</div>
<div class="ui-block-c">
<span>
@Html.TextBoxFor(m => m.mask, new { @class = "checkFiller" })
<span class="dltBtn">
<a href="#" class="deleteRow"><img src="~/Images/DeleteRed.png" style="width: 15px; height: 15px;" /></a>
</span>
</span>
</div>
</div>
}
</div>
You first (outer) partial will be generating correct name attributes that relate to your model (your code does not show any controls in the Pa_Ipv4.cshtml
view but I assume you do have some), for example
<input name="pa_ipv4s[xxx-xxx].someProperty ...>
however the inner partial will not because @using (Html.BeginCollectionItem("requestedIps"))
will generate
<input name="requestedIps[xxx-xxx].subnet ...>
<input name="requestedIps[xxx-xxx].cidr ...>
where they should be
<input name="pa_ipv4s[xxx-xxx].requestedIps[yyy-yyy].subnet ...>
<input name="pa_ipv4s[xxx-xxx].requestedIps[yyy-yyy].cidr ...>
Normally you can pass the prefix to the partial using additional view data (refer this answer for an example), but unfortunately, you do not have access to the Guid
generated by the BeginCollectionItem
helper so its not possible to correctly prefix the name
attribute.
The articles here and here discuss creating your own helper for handling nested collections.
Other options include using nested for
loops and including hidden inputs for the collection indexer which will allow you to delete items from the collection and still be able to bind to your model when you submit the form.
for (int i = 0; i < Model.pa_ipv4s.Count; i++)
{
for(int j = 0; j < Model.pa_ipv4s[i].requestedIps.Count; j++)
{
var name = String.Format("pa_ipv4s[{0}].requestedIps.Index", i);
@Html.TextBoxFor(m => m.pa_ipv4s[i].requestedIps[j].subnet)
@Html.TextBoxFor(m => m.pa_ipv4s[i].requestedIps[j].cidr)
...
<input type="hidden" name="@name" value="@j" />
}
}
However if you also need to dynamically add new items you would need to use javascript to generate the html (refer examples here and here)
这篇关于部分空例外内的部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!