首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >元数据与ViewData在HtmlHelper (DropDownListFor Bug?)

元数据与ViewData在HtmlHelper (DropDownListFor Bug?)
EN

Stack Overflow用户
提问于 2016-05-13 15:00:15
回答 1查看 307关注 0票数 0

我正在试验定制的ModelMetadataProvider。看起来像TextBoxFor这样的html助手很好地使用了这些工具。然而,在其他情况下,如DropDownListFor,他们更倾向于ViewData。例如,查看我看到的一些反射代码:

代码语言:javascript
运行
复制
  bool flag = false;
  if (selectList == null)
  {
    selectList = SelectExtensions.GetSelectData(htmlHelper, name);
    flag = true;
  }
  object defaultValue = allowMultiple ? htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof (string[])) : htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof (string));
  if (defaultValue == null && !string.IsNullOrEmpty(name))
  {
    if (!flag)
      defaultValue = htmlHelper.ViewData.Eval(name);
    else if (metadata != null)
      defaultValue = metadata.Model;
  }

注意所有获得"defaultValue“的不同尝试。使用metadata.Model是最后一次。为什么要在这里分开?如果通过该代码跟踪,最终会在调用ViewData.Eval时结束,该调用作为回退只是使用反射将模型的值从模型中提取出来。是否存在自定义ViewData提供程序来弥补这一差距?

编辑:我开始倾向于认为这是框架中的一个bug。

考虑两段代码:

代码语言:javascript
运行
复制
@Html.DropDownListFor(model => model.ErrorData.Shift, Model.ShiftOptions, new { @class = "form-control" })

上面的代码传入选项"Model.ShiftOptions“。因此,它不会传递条件"selectList==null“,因此”标志“永远不会设置,而是继续尝试通过反射( Eval调用)从类型获取默认值。

但是,使用此代码:

代码语言:javascript
运行
复制
@{ ViewData[Html.NameFor(m => m.ErrorData.Shift).ToString()] = Model.ShiftOptions;}
@Html.DropDownListFor(model => model.ErrorData.Shift,null, new { @class = "form-control" })

.“标志”现在被满足,默认值现在被检索到metadata.Model。为什么提供列表选项的不同机制会改变(甚至影响)从其中检索默认值的位置?

编辑#2

警告:如果在编辑器模板( ViewData )中调用复杂类型的DropDownListFor,上述DropDownListFor“修复”将无法工作。NameFor调用将返回属性的名称,包括从EditorFor调用的外部上下文,即MyViewModel.ErrorData.Shift。但是,顶部的原始代码片段中的DropDownListFor代码查找的是没有原始上下文的ViewData项,即ErrorData.Shift。他们都用

代码语言:javascript
运行
复制
ExpressionHelper.GetExpressionText((LambdaExpression) expression)

但是,NameOf对该结果使用html.Name。当DDLF最终开始生成它的名称时,它会做一些类似的事情,因此它的名称是正确的,但是在查找视图数据选项时,它不包括它的完整上下文是没有意义的。

EN

回答 1

Stack Overflow用户

发布于 2016-05-14 01:52:14

用于生成表单的所有HtmlHelper方法首先检查ModelState ( GetModelStateValue()方法)中是否存在属性的值,以处理表单被提交时使用无效值并返回视图的情况(请参阅这个答案的第2部分,以解释为什么这是默认行为)。

例如,在使用DropDownList()的情况下

代码语言:javascript
运行
复制
@Html.DropDownList("xxx", null, "--Please select--")

如果xxx是作为ViewBag属性添加的IEnumerable<SelectListItem>,则selectList的值为null,执行第一个if块中的代码,flag的值为true (还请注意,模型可能有或可能没有一个名为xxx的属性,这意味着< code >D15可能是null)。

或者,如果您使用强类型的DropDownListFor()方法,例如

代码语言:javascript
运行
复制
@Html.DropDownListFor(m => m.SomeProperty, Model.SomePropertyList, "--Please select--")

selectList的值不是null (假设SomePropertyListIEnumerable<SelectListItem>而不是null),flag的值是false

因此,各种检查只是考虑了使用DropDownList()DropDownListFor()生成<select>元素的不同方式,以及是否绑定到模型属性。

附带注意:实际代码(来自私有静态MvcHtmlString SelectInternal()方法)是bool usedViewData = false;,而不是bool flag = false;

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37213368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档