我正在使用非常复杂的模型和绑定。到目前为止,我已经能够使用代码设置here来使事情有效。但是,其中一个嵌套模型可以将自身作为嵌套模型。当我在编辑器模板中放置相同类型的设置时,它会创建一个无限循环并导致堆栈溢出错误。由于隐私问题,我无法详细介绍我的实际代码,但我的模型设置如下:
父对象:
第1场
Field 2
儿童对象的集合
子对象:
字段A
B栏
儿童对象的集合
两个对象中的集合可以为空。以下是“父”视图的简化示例:
@using (Html.BeginForm("LetterEntry", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<div class="editor-label">
@Html.LabelFor(model => model.Field1)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Field1)
@Html.ValidationMessageFor(model => model.Field1)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Field2)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Field2)
@Html.ValidationMessageFor(model => model.Field2)
</div>
<div>
<div class="editor-label" id="ChildFieldsLabel">
@Html.Label("Has child fields?")
</div>
<div class="editor-field" id="ChildFieldsField">
@Html.CheckBox("ChildFieldsCheckBox", new { @onclick = "ChildFieldsChecked(this)" })
</div>
<div class="display-none" id="outer-ChildFieldsDiv">
<div id="ChildFieldsDiv">
@* individual child field entries go here *@
</div>
@Html.AddLink("Add Child Field", "#ChildFieldsDiv", ".child-field-single-div", "ChildFields", typeof(Project.Datalayer.ChildFields))
</div>
</div>
<p>
<input type="submit" value="Create" />
</p>
}
儿童编辑模板:
<div class="required-field-single-div">
<div class="editor-label">
@Html.LabelFor(model => model.FieldA)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FieldA)
@Html.ValidationMessageFor(model => model.FieldA)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.FieldB)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FieldB)
@Html.ValidationMessageFor(model => model.FieldB)
</div>
<div>
<div class="editor-label" id="ChildFieldsLabel">
@Html.Label("Has sub-requirements?")
</div>
<div class="editor-field-noborder" id="ChildFieldsField">
@Html.CheckBox("Sub-ChildFieldsCheckBox", new { @onclick = "Sub-ChildFieldsChecked(this)" })
</div>
<div class="display-none" id="outer-Sub-ChildFieldsDiv">
<div id="Sub-ChildFieldsDiv">
@* individual child entries go here *@
</div>
@Html.AddLink("Add Sub-Child Field", "#Sub-ChildFieldsDiv", ".child-field-single-div", "ChildFields.ChildFields", typeof(Project.Datalayer.ChildFields))
</div>
</div>
</div>
我没有为复选框添加Javascript,因为它只是显示隐藏的div。一切都运行良好,直到我在子编辑器模板中添加AddLink行。
确切错误是:{无法计算表达式,因为当前线程处于堆栈溢出状态。}
我已逐步完成AddLink代码,并确定此处的“Editor For(nestedObject)”部分发生错误:
public static IHtmlString AddLink<TModel>(this HtmlHelper<TModel> htmlHelper, string linkText, string containerElement, string counterElement, string collectionProperty, Type nestedType)
{
var ticks = DateTime.UtcNow.Ticks;
var nestedObject = Activator.CreateInstance(nestedType);
var partial = htmlHelper.EditorFor(x => nestedObject).ToHtmlString().JsEncode();
partial = partial.Replace("id=\\\"nestedObject", "id=\\\"" + collectionProperty + "_" + ticks + "_");
partial = partial.Replace("name=\\\"nestedObject", "name=\\\"" + collectionProperty + "[" + ticks + "]");
var js = string.Format("javascript:addNestedForm('{0}','{1}','{2}','{3}');return false;", containerElement, counterElement, ticks, partial);
TagBuilder tb = new TagBuilder("a");
tb.Attributes.Add("href", "#");
tb.Attributes.Add("onclick", js);
tb.InnerHtml = linkText;
var tag = tb.ToString(TagRenderMode.Normal);
return MvcHtmlString.Create(tag);
}
我已经做了大量的搜索以尝试找到答案,但是我只能在您更深入时找到有关更多列表的嵌套模型的信息。我还没有发现模型中的子对象何时可以拥有自己类型的子对象。
我现在完全失去了,所以任何想法都会受到赞赏。
答案 0 :(得分:0)
经过一系列的反复试验,我为我的问题创建了一个仅限JavaScript的解决方案。父视图仍然使用原始代码,但这是新的子编辑器模板:
<div class="required-field-single-div">
<div class="editor-label">
@Html.LabelFor(model => model.FieldA)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FieldA)
@Html.ValidationMessageFor(model => model.FieldA)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.FieldB)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FieldB)
@Html.ValidationMessageFor(model => model.FieldB)
</div>
<div class="single-field">
<div id="outer-SubChildFieldsDiv">
<div id="SubChildFieldsDiv">
@* individual entries go here*@
</div>
@{ string jsText = "addNestedForm2('#SubChildFieldsDiv','.sub-child-field-single-div','ChildFields[0].ChildFields1')"; }
<a href="#" onclick=@jsText>Add Sub-Child Field</a>
</div>
</div>
</div>
&#13;
JavaScript文件中的新功能:
function addNestedForm2(container, counter, collectionProperty) {
var nextIndex = $(counter).length;
var nestPattern = new RegExp("nestedObject", "gi");
var countPattern = new RegExp("ReplaceMeWithCount", "gi");
var counterPattern = new RegExp("counterClass", "gi");
var incrementedIdPattern = new RegExp("incrementedId", "gi");
var counterObj = document.getElementById("counter");
var incrementedId = Number.parseInt(counterObj.value);
var counterClass = counter.substring(1);
var content = ReturnContent().replace(nestPattern, collectionProperty).replace(countPattern, nextIndex)
.replace(counterPattern, counterClass).replace(incrementedIdPattern, incrementedId);
counterObj.value = incrementedId + 1;
$(container).append(content);
};
function ReturnContent() {
var content = "<div class=\"child-field-single-div counterClass\">" +
"<div class=\"editor-label-noborder\"> " +
"<label for=\"nestedObject_FieldA\">FieldA</label> " +
"</div> " +
"<div class=\"editor-field-noborder\"> " +
"<input class=\"check-box\" id=\"nestedObject_ReplaceMeWithCount__FieldA\" name=\"nestedObject[ReplaceMeWithCount].FieldA\" type=\"checkbox\" value=\"true\" />" +
"<input name=\"nestedObject[ReplaceMeWithCount].FieldA\" type=\"hidden\" value=\"false\" /> " +
"<span class=\"field-validation-valid\" data-valmsg-for=\"nestedObject.FieldA\" data-valmsg-replace=\"true\"></span> " +
"</div> " +
"<div class=\"editor-label-noborder\"> " +
"<label for=\"nestedObject_FieldB\">FieldB</label> " +
"</div> " +
"<div class=\"editor-field-noborder\"> " +
"<input class=\"text-box single-line\" id=\"nestedObject_ReplaceMeWithCount__FieldB\" name=\"nestedObject[ReplaceMeWithCount].FieldB\" type=\"text\" value=\"\" /> " +
"<span class=\"field-validation-valid\" data-valmsg-for=\"nestedObject.FieldB\" data-valmsg-replace=\"true\"></span> " +
"</div> " +
"</div>" +
"<div id=\"outer-SubChildFieldsDiv\"> " +
"<div id=\"SubChildFieldsDiv_incrementedId\"> " +
"</div\> " +
"<a href=\"#\" onclick=addNestedForm2('#SubChildFieldsDiv_incrementedId','.child-field-single-div_incrementedId','nestedObject[ReplaceMeWithCount].ChildFields1')\>Add Sub-Child Field</a\> " +
"</div\> ";
return content;
};
&#13;
ReturnContent函数中的代码是从chrome中的开发人员工具中提取的,是生成内容的编辑版本,尽管它与子编辑器模板基本相同。代码中的incrementdedId对象用于确保每个新级别都是唯一标识的,并将链接到正确的父对象。我还在父视图的开头添加了一个隐藏的输入字段:
<input type="hidden" name="counter" id="counter" value="0">
&#13;
它不是那么可重复使用,但我认为它可以很容易地被编辑为更通用,并且有多个&#34; returnContent&#34;函数返回正在使用的编辑器模板的必要内容。
希望如果其他人遇到与AddLink代码相同的问题,这将会有所帮助。