我有一个简单的强类型视图,当我提交表单时,其中一个ViewModel属性有时对某些数据是NULL;对于大多数数据,它工作正常。我已将我的视图调整为仍然重现错误的最简单形式:
@model eNPSWeb.Models.Survey_c.StartModel
@{
Layout = null;
}
<html>
<head>
@Html.DevExpress().GetScripts(new Script { ExtensionSuite = ExtensionSuite.Editors })
</head>
<body>
@using (Html.BeginForm())
{
@Html.HiddenFor(model => model.EmployeeSurveyName)
<input type="submit" />
for (int x = 0; x < Model.Employees.Count(); ++x)
{
@Html.HiddenFor(model => model.Employees[x].Name)
@Html.HiddenFor(model => model.Employees[x].ExternalId)
@Html.HiddenFor(model => model.Employees[x].Included)
}
for (int x = 0; x < Model.Questions.Count(); ++x)
{
<div>
<input type="hidden" name="@string.Format("{0}a", Model.Questions[x].ExternalId)" />
<input type="hidden" name="@string.Format("{0}b", Model.Questions[x].ExternalId)" />
@Html.HiddenFor(m => m.Questions[x].Id)
@Html.HiddenFor(m => m.Questions[x].ExternalId)
@Html.HiddenFor(m => m.Questions[x].Text)
@Html.HiddenFor(m => m.Questions[x].Type)
@Html.HiddenFor(m => m.Questions[x].AskWhy)
@Html.HiddenFor(m => m.Questions[x].Mandatory)
@Html.HiddenFor(m => m.Questions[x].Origin)
@Html.HiddenFor(m => m.Questions[x].CommentText)
@Html.HiddenFor(m => m.Questions[x].BeenUsed)
@Html.HiddenFor(m => m.Questions[x].Included)
</div>
}
}
</body>
</html>
这会生成以下HTML:
<html>
<head>
<script id="dxis_1397937255" src="/DXR.axd?r=1_142-_ND58" type="text/javascript"></script>
<script id="dxis_29183559" src="/DXR.axd?r=1_80-_ND58" type="text/javascript"></script>
<script id="dxis_1801595362" src="/DXR.axd?r=1_135-_ND58" type="text/javascript"></script>
<script id="dxis_40984204" src="/DXR.axd?r=1_91-_ND58" type="text/javascript"></script>
<script id="dxis_1510326740" src="/DXR.axd?r=14_0-VND58" type="text/javascript"></script>
<script id="dxis_955216353" src="/DXR.axd?r=1_98-_ND58" type="text/javascript"></script>
<script id="dxis_1818762533" src="/DXR.axd?r=1_104-_ND58" type="text/javascript"></script>
<script id="dxis_1042080475" src="/DXR.axd?r=1_105-_ND58" type="text/javascript"></script>
<script id="dxis_2035868379" src="/DXR.axd?r=1_101-_ND58" type="text/javascript"></script>
<script id="dxis_237603203" src="/DXR.axd?r=1_84-_ND58" type="text/javascript"></script>
<script id="dxis_964747995" src="/DXR.axd?r=1_109-_ND58" type="text/javascript"></script>
<script id="dxis_787399442" src="/DXR.axd?r=14_23-VND58" type="text/javascript"></script>
<script id="dxis_1504896761" src="/DXR.axd?r=1_92-_ND58" type="text/javascript"></script>
<script id="dxis_1295258881" src="/DXR.axd?r=14_1-VND58" type="text/javascript"></script>
<script id="dxis_1524734997" src="/DXR.axd?r=1_77-_ND58" type="text/javascript"></script>
<script id="dxis_691625841" src="/DXR.axd?r=1_128-_ND58" type="text/javascript"></script>
<script id="dxis_799056015" src="/DXR.axd?r=1_126-_ND58" type="text/javascript"></script>
<script id="dxis_382503299" src="/DXR.axd?r=1_94-_ND58" type="text/javascript"></script>
<script id="dxis_1728027670" src="/DXR.axd?r=1_97-_ND58" type="text/javascript"></script>
<script id="dxis_879896160" src="/DXR.axd?r=1_95-_ND58" type="text/javascript"></script>
<script id="dxis_1869190171" src="/DXR.axd?r=1_96-_ND58" type="text/javascript"></script>
<script id="dxis_908190427" src="/DXR.axd?r=1_106-_ND58" type="text/javascript"></script>
<script id="dxis_1718746384" src="/DXR.axd?r=14_4-VND58" type="text/javascript"></script>
<script id="dxis_824974629" src="/DXR.axd?r=1_100-_ND58" type="text/javascript"></script>
<script id="dxis_350755308" src="/DXR.axd?r=1_117-_ND58" type="text/javascript"></script>
<script id="dxis_1538974427" src="/DXR.axd?r=1_103-_ND58" type="text/javascript"></script>
<script id="dxis_395477619" src="/DXR.axd?r=14_12-VND58" type="text/javascript"></script>
<script id="dxis_758481523" src="/DXR.axd?r=14_13-VND58" type="text/javascript"></script>
<script id="dxis_1901978331" src="/DXR.axd?r=1_102-_ND58" type="text/javascript"></script>
<script id="dxis_742498447" src="/DXR.axd?r=1_129-_ND58" type="text/javascript"></script>
<script id="dxis_691084581" src="/DXR.axd?r=1_107-_ND58" type="text/javascript"></script>
</head>
<body>
<form action="/Survey/Start/03926d2d-6bc4-4856-ba1d-9c751ea31529" method="post">
<input data-val="true" data-val-length="The field EmployeeSurveyName must be a string with a maximum length of 250." data-val-length-max="250" data-val-required=" * Required" id="EmployeeSurveyName" name="EmployeeSurveyName" type="hidden" value="" />
<input type="submit" />
<input id="Employees_0__Name" name="Employees[0].Name" type="hidden" value="" />
<input id="Employees_0__ExternalId" name="Employees[0].ExternalId" type="hidden" value="" />
<input id="Employees_0__Included" name="Employees[0].Included" type="hidden" value="" />
<input id="Employees_1__Name" name="Employees[1].Name" type="hidden" value="" />
<input id="Employees_1__ExternalId" name="Employees[1].ExternalId" type="hidden" value="" />
<input id="Employees_1__Included" name="Employees[1].Included" type="hidden" value="" />
<div>
<input type="hidden" name="E5C665C9-1EA5-4DD5-97C6-20A47813A61Fa" />
<input type="hidden" name="E5C665C9-1EA5-4DD5-97C6-20A47813A61Fb" />
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Questions_0__Id" name="Questions[0].Id" type="hidden" value="0" />
<input id="Questions_0__ExternalId" name="Questions[0].ExternalId" type="hidden" value="E5C665C9-1EA5-4DD5-97C6-20A47813A61F" />
<input data-val="true" data-val-length="The field Text must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_0__Text" name="Questions[0].Text" type="hidden" value="" />
<input data-val="true" data-val-required="The Type field is required." id="Questions_0__Type" name="Questions[0].Type" type="hidden" value="ZeroToTen" />
<input data-val="true" data-val-required="The AskWhy field is required." id="Questions_0__AskWhy" name="Questions[0].AskWhy" type="hidden" value="False" />
<input data-val="true" data-val-required="The Mandatory field is required." id="Questions_0__Mandatory" name="Questions[0].Mandatory" type="hidden" value="False" />
<input data-val="true" data-val-required="The Origin field is required." id="Questions_0__Origin" name="Questions[0].Origin" type="hidden" value="Template" />
<input data-val="true" data-val-length="The field CommentText must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_0__CommentText" name="Questions[0].CommentText" type="hidden" value="" />
<input data-val="true" data-val-required="The BeenUsed field is required." id="Questions_0__BeenUsed" name="Questions[0].BeenUsed" type="hidden" value="False" />
<input data-val="true" data-val-required="The Included field is required." id="Questions_0__Included" name="Questions[0].Included" type="hidden" value="False" />
</div>
<div>
<input type="hidden" name="F34DF428-AAC7-48F0-8236-670FD197B189a" />
<input type="hidden" name="F34DF428-AAC7-48F0-8236-670FD197B189b" />
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Questions_1__Id" name="Questions[1].Id" type="hidden" value="0" />
<input id="Questions_1__ExternalId" name="Questions[1].ExternalId" type="hidden" value="F34DF428-AAC7-48F0-8236-670FD197B189" />
<input data-val="true" data-val-length="The field Text must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_1__Text" name="Questions[1].Text" type="hidden" value="" />
<input data-val="true" data-val-required="The Type field is required." id="Questions_1__Type" name="Questions[1].Type" type="hidden" value="ZeroToTen" />
<input data-val="true" data-val-required="The AskWhy field is required." id="Questions_1__AskWhy" name="Questions[1].AskWhy" type="hidden" value="False" />
<input data-val="true" data-val-required="The Mandatory field is required." id="Questions_1__Mandatory" name="Questions[1].Mandatory" type="hidden" value="False" />
<input data-val="true" data-val-required="The Origin field is required." id="Questions_1__Origin" name="Questions[1].Origin" type="hidden" value="Template" />
<input data-val="true" data-val-length="The field CommentText must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_1__CommentText" name="Questions[1].CommentText" type="hidden" value="" />
<input data-val="true" data-val-required="The BeenUsed field is required." id="Questions_1__BeenUsed" name="Questions[1].BeenUsed" type="hidden" value="False" />
<input data-val="true" data-val-required="The Included field is required." id="Questions_1__Included" name="Questions[1].Included" type="hidden" value="False" />
</div>
<div>
<input type="hidden" name="ab75f0d9-2be9-4f04-baab-e3157651ac14a" />
<input type="hidden" name="ab75f0d9-2be9-4f04-baab-e3157651ac14b" />
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Questions_2__Id" name="Questions[2].Id" type="hidden" value="0" />
<input id="Questions_2__ExternalId" name="Questions[2].ExternalId" type="hidden" value="ab75f0d9-2be9-4f04-baab-e3157651ac14" />
<input data-val="true" data-val-length="The field Text must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_2__Text" name="Questions[2].Text" type="hidden" value="" />
<input data-val="true" data-val-required="The Type field is required." id="Questions_2__Type" name="Questions[2].Type" type="hidden" value="ZeroToTen" />
<input data-val="true" data-val-required="The AskWhy field is required." id="Questions_2__AskWhy" name="Questions[2].AskWhy" type="hidden" value="False" />
<input data-val="true" data-val-required="The Mandatory field is required." id="Questions_2__Mandatory" name="Questions[2].Mandatory" type="hidden" value="False" />
<input data-val="true" data-val-required="The Origin field is required." id="Questions_2__Origin" name="Questions[2].Origin" type="hidden" value="Template" />
<input data-val="true" data-val-length="The field CommentText must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_2__CommentText" name="Questions[2].CommentText" type="hidden" value="" />
<input data-val="true" data-val-required="The BeenUsed field is required." id="Questions_2__BeenUsed" name="Questions[2].BeenUsed" type="hidden" value="False" />
<input data-val="true" data-val-required="The Included field is required." id="Questions_2__Included" name="Questions[2].Included" type="hidden" value="False" />
</div>
<div>
<input type="hidden" name="9f98d45b-e988-4578-a8ab-625edb2c4bd9a" />
<input type="hidden" name="9f98d45b-e988-4578-a8ab-625edb2c4bd9b" />
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Questions_3__Id" name="Questions[3].Id" type="hidden" value="0" />
<input id="Questions_3__ExternalId" name="Questions[3].ExternalId" type="hidden" value="9f98d45b-e988-4578-a8ab-625edb2c4bd9" />
<input data-val="true" data-val-length="The field Text must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_3__Text" name="Questions[3].Text" type="hidden" value="" />
<input data-val="true" data-val-required="The Type field is required." id="Questions_3__Type" name="Questions[3].Type" type="hidden" value="ZeroToTen" />
<input data-val="true" data-val-required="The AskWhy field is required." id="Questions_3__AskWhy" name="Questions[3].AskWhy" type="hidden" value="False" />
<input data-val="true" data-val-required="The Mandatory field is required." id="Questions_3__Mandatory" name="Questions[3].Mandatory" type="hidden" value="False" />
<input data-val="true" data-val-required="The Origin field is required." id="Questions_3__Origin" name="Questions[3].Origin" type="hidden" value="Template" />
<input data-val="true" data-val-length="The field CommentText must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_3__CommentText" name="Questions[3].CommentText" type="hidden" value="" />
<input data-val="true" data-val-required="The BeenUsed field is required." id="Questions_3__BeenUsed" name="Questions[3].BeenUsed" type="hidden" value="False" />
<input data-val="true" data-val-required="The Included field is required." id="Questions_3__Included" name="Questions[3].Included" type="hidden" value="False" />
</div>
<div>
<input type="hidden" name="41321194-3EDB-4712-8548-0FFD7B732AC9a" />
<input type="hidden" name="41321194-3EDB-4712-8548-0FFD7B732AC9b" />
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Questions_4__Id" name="Questions[4].Id" type="hidden" value="0" />
<input id="Questions_4__ExternalId" name="Questions[4].ExternalId" type="hidden" value="41321194-3EDB-4712-8548-0FFD7B732AC9" />
<input data-val="true" data-val-length="The field Text must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_4__Text" name="Questions[4].Text" type="hidden" value="" />
<input data-val="true" data-val-required="The Type field is required." id="Questions_4__Type" name="Questions[4].Type" type="hidden" value="ZeroToTen" />
<input data-val="true" data-val-required="The AskWhy field is required." id="Questions_4__AskWhy" name="Questions[4].AskWhy" type="hidden" value="False" />
<input data-val="true" data-val-required="The Mandatory field is required." id="Questions_4__Mandatory" name="Questions[4].Mandatory" type="hidden" value="False" />
<input data-val="true" data-val-required="The Origin field is required." id="Questions_4__Origin" name="Questions[4].Origin" type="hidden" value="Template" />
<input data-val="true" data-val-length="The field CommentText must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_4__CommentText" name="Questions[4].CommentText" type="hidden" value="" />
<input data-val="true" data-val-required="The BeenUsed field is required." id="Questions_4__BeenUsed" name="Questions[4].BeenUsed" type="hidden" value="False" />
<input data-val="true" data-val-required="The Included field is required." id="Questions_4__Included" name="Questions[4].Included" type="hidden" value="False" />
</div>
<div>
<input type="hidden" name="F2DD07DB-B107-493B-A9DD-523CCD6DDD4Fa" />
<input type="hidden" name="F2DD07DB-B107-493B-A9DD-523CCD6DDD4Fb" />
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." id="Questions_5__Id" name="Questions[5].Id" type="hidden" value="0" />
<input id="Questions_5__ExternalId" name="Questions[5].ExternalId" type="hidden" value="F2DD07DB-B107-493B-A9DD-523CCD6DDD4F" />
<input data-val="true" data-val-length="The field Text must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_5__Text" name="Questions[5].Text" type="hidden" value="" />
<input data-val="true" data-val-required="The Type field is required." id="Questions_5__Type" name="Questions[5].Type" type="hidden" value="ZeroToTen" />
<input data-val="true" data-val-required="The AskWhy field is required." id="Questions_5__AskWhy" name="Questions[5].AskWhy" type="hidden" value="False" />
<input data-val="true" data-val-required="The Mandatory field is required." id="Questions_5__Mandatory" name="Questions[5].Mandatory" type="hidden" value="False" />
<input data-val="true" data-val-required="The Origin field is required." id="Questions_5__Origin" name="Questions[5].Origin" type="hidden" value="Template" />
<input data-val="true" data-val-length="The field CommentText must be a string with a maximum length of 1000." data-val-length-max="1000" id="Questions_5__CommentText" name="Questions[5].CommentText" type="hidden" value="" />
<input data-val="true" data-val-required="The BeenUsed field is required." id="Questions_5__BeenUsed" name="Questions[5].BeenUsed" type="hidden" value="False" />
<input data-val="true" data-val-required="The Included field is required." id="Questions_5__Included" name="Questions[5].Included" type="hidden" value="False" />
</div>
</form>
</body>
</html>
当我提交此表单时,Employees属性为NULL,但它应该是包含2个项目的列表。但真正奇怪的是,HTML或底层剃须刀的各种细微变化都会使其变为正常工作:
string.Format("{0}a", Model.Questions[x].ExternalId)
中的第一个隐藏输入的名称更改为string.Format("a{0}", Model.Questions[x].ExternalId)
,则会有效。基本上,似乎不是由Html.HiddenFor()创建的2个输入的名称可能是潜在原因,因为将其名称更改为不以GUID开头似乎可以修复它。但是特定的GUID怎么可能导致这种情况呢?
我尝试过进入MVC模型绑定代码;我无法找到它工作的时间和不工作的时间之间的差异。我还覆盖了BindProperty()并使用了自定义模型绑定器,因此我可以查看BindingContext和PropertyDescriptors。在它工作的时间和不工作的时间之间,一切看起来都是相同的。当它工作时,在“Employees”上调用BindProperty之后,它会在每个属性上为每个雇员(Name,ExternalId,Included)调用它。然后它在我的视图模型中调用我的setter for Employees列表。如果它不起作用,在它调用Employees上的BindProperty之后,它就会移到问题上。
无论如何,我现在已经尝试了所有这些不同的事情了好几个小时;我甚至无法开始考虑可能的解释,也许我的随机生成的GUID恰好以特定的字符序列开始,当与表单上的其他元素结合时,会导致某种GUID冲突与散列值形式或类似的疯狂......
编辑我进一步简化了我的观点;只保留导致问题的最简单的输入:
@model eNPSWeb.Models.Survey_c.StartModel
@{
Layout = null;
}
<html>
<head>
<title>What the...</title>
</head>
<body>
@Html.DevExpress().GetScripts(new Script { ExtensionSuite = ExtensionSuite.Editors })
@using (Html.BeginForm())
{
<input type="hidden" name="EmployeeSurveyName" />
<input type="submit" />
<input name="Employees[0].Name" />
<input name="Employees[0].ExternalId" />
<input name="Employees[0].Included" />
<input name="Employees[1].Name" />
<input name="Employees[1].ExternalId" />
<input name="Employees[1].Included" />
<input name="a" />
<input name="b" />
<input name="c" />
<input name="d" />
<input name="e" />
<input name="f" />
<input name="g" />
<input name="h" />
<input name="i" />
<input name="2" />
<div>
<input type="hidden" name="Questions[0].Id" />
<input type="hidden" name="Questions[0].ExternalId" />
<input type="hidden" name="Questions[0].Text" />
<input type="hidden" name="Questions[0].Type" />
<input type="hidden" name="Questions[0].AskWhy" />
<input type="hidden" name="Questions[0].Mandatory" />
<input type="hidden" name="Questions[0].Origin" />
<input type="hidden" name="Questions[0].CommentText" />
<input type="hidden" name="Questions[0].BeenUsed" />
<input type="hidden" name="Questions[0].Included" />
</div>
<div>
<input type="hidden" name="Questions[1].Id" />
<input type="hidden" name="Questions[1].ExternalId" />
<input type="hidden" name="Questions[1].Text" />
<input type="hidden" name="Questions[1].Type" />
<input type="hidden" name="Questions[1].AskWhy" />
<input type="hidden" name="Questions[1].Mandatory" />
<input type="hidden" name="Questions[1].Origin" />
<input type="hidden" name="Questions[1].CommentText" />
<input type="hidden" name="Questions[1].BeenUsed" />
<input type="hidden" name="Questions[1].Included" />
</div>
<div>
<input type="hidden" name="Questions[2].Id" />
<input type="hidden" name="Questions[2].ExternalId" />
<input type="hidden" name="Questions[2].Text" />
<input type="hidden" name="Questions[2].Type" />
<input type="hidden" name="Questions[2].AskWhy" />
<input type="hidden" name="Questions[2].Mandatory" />
<input type="hidden" name="Questions[2].Origin" />
<input type="hidden" name="Questions[2].CommentText" />
<input type="hidden" name="Questions[2].BeenUsed" />
<input type="hidden" name="Questions[2].Included" />
</div>
<div>
<input type="hidden" name="Questions[3].Id" />
<input type="hidden" name="Questions[3].ExternalId" />
<input type="hidden" name="Questions[3].Text" />
<input type="hidden" name="Questions[3].Type" />
<input type="hidden" name="Questions[3].AskWhy" />
<input type="hidden" name="Questions[3].Mandatory" />
<input type="hidden" name="Questions[3].Origin" />
<input type="hidden" name="Questions[3].CommentText" />
<input type="hidden" name="Questions[3].BeenUsed" />
<input type="hidden" name="Questions[3].Included" />
</div>
<div>
<input type="hidden" name="Questions[4].Id" />
<input type="hidden" name="Questions[4].ExternalId" />
<input type="hidden" name="Questions[4].Text" />
<input type="hidden" name="Questions[4].Type" />
<input type="hidden" name="Questions[4].AskWhy" />
<input type="hidden" name="Questions[4].Mandatory" />
<input type="hidden" name="Questions[4].Origin" />
<input type="hidden" name="Questions[4].CommentText" />
<input type="hidden" name="Questions[4].BeenUsed" />
<input type="hidden" name="Questions[4].Included" />
</div>
}
</body>
</html>
当我弄乱输入a,b,c等的名字时;我得到了非常令人惊讶的结果:
工作正常:
<input name="a" />
<input name="b" />
<input name="c" />
<input name="d" />
<input name="e" />
<input name="f" />
<input name="g" />
<input name="h" />
<input name="1" />
<input name="2" />
不起作用(Employees为null):
<input name="a" />
<input name="b" />
<input name="c" />
<input name="d" />
<input name="e" />
<input name="f" />
<input name="g" />
<input name="h" />
<input name="i" />
<input name="2" />
工作正常:
<input name="a" />
<input name="b" />
<input name="c" />
<input name="d" />
<input name="e" />
<input name="f" />
<input name="g" />
<input name="h" />
<input name="i" />
<input name="j" />
不起作用:
<input name="b" />
<input name="c" />
<input name="d" />
<input name="e" />
<input name="f" />
<input name="g" />
<input name="h" />
<input name="i" />
<input name="2" />
<input name="3" />
就好像非常具体的输入名称组合会导致它中断。 (在整个页面中,输入名称来自GUID)。
答案 0 :(得分:0)
这似乎是MVC中的已知错误:https://aspnetwebstack.codeplex.com/workitem/616,http://forums.asp.net/t/1856357.aspx。我很快就找不到任何东西因为我无法知道查找PrefixContainer,直到我将DefaultModelBinder代码复制到我自己的自定义模型绑定器中并逐步完成它。修复或破坏页面的看似随机的更改必须刚刚改变二进制搜索的顺序,以便它通常首先找到正确的元素。