部分空例外内的部分 [英] Partial within a partial null exception

查看:135
本文介绍了部分空例外内的部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个MVC形式比我所有的其他的更复杂,利用三种模式。

公司 - > Base_IP - > RequestedIP 肚里视图模型 - > Partial1 - > Partial2

我使用BeginCollectionItem为这每一个模型的模型从下来的财产清单。 IE浏览器 - 公司有一个属性叫做baseIps的B​​aseIp类有一个属性叫做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())
{
            < D​​IV ID =editorRowsAsn>
                @foreach(在Model.pa_ipv4s VAR IP)
                {
                    @ Html.Partial(Pa_IPv4View,IP)
                }
            < / DIV>
            < BR />
            < D​​IV数据角色=主类=UI内容>
                < D​​IV数据角色=controlgroup数据类型=横向>
                    <输入类型=提交级=UI-BTNVALUE =创建/>
                < / DIV>
            < / DIV>
}

Pa_Ipv4查看

  @model Pa_Ipv4
@using(Html.BeginCollectionItem(pa_ipv4s))
{
    @ Html.AntiForgeryToken()    < D​​IV ID =editorRowsRIpM>
        @foreach(在Model.requestedIps VAR项)
        {
            @ Html.Partial(RequestedIpView项)
        }
    < / DIV>
    @ Html.ActionLink(添加,RequestedManager,空,新的{ID =addItemRIpM,@class =按钮}}

RequestedIpView

  @model IpAllocation
< D​​IV CLASS =editorRow>
    @using(Html.BeginCollectionItem(requestedIps))
    {
        < D​​IV CLASS =UI网-C UI响应>
            < D​​IV CLASS =UI-块一个>
                <跨度>
                    @ Html.TextBoxFor(M = GT; m.subnet,新{@class =checkFiller})
                < / SPAN>
            < / DIV>
            < D​​IV CLASS =UI块-B>
                <跨度>
                    @ Html.TextBoxFor(M = GT; m.cidr,新{@class =checkFiller})
                < / SPAN>
            < / DIV>
            < D​​IV 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆