zoukankan      html  css  js  c++  java
  • 【原创】Asp.net MVC 学习笔记之为什么使用Html.TextBox方法会出现异常?

    在上篇文章:【原创】Asp.net MVC学习笔记之-基于类型来绑定Model的属性 中,例举了如何使用基于类型和基于用途2种方式结合来限制Model的绑定,由此引发了一个意想不到的问题。

    先看一下前台页面的代码:

    代码
    <p>
    <label for="Test1">Test1:</label>
    <%= Html.TextBox("Test1") %>
    <%= Html.ValidationMessage("Test1", "*") %>
    </p>
    <p>
    <label for="Test2">Test2:</label>
    <%= Html.TextBox("Test2") %>
    <%= Html.ValidationMessage("Test2", "*") %>
    </p>
    <p>
    <label for="Test3">Test3:</label>
    <%= Html.TextBox("Test3") %>
    <%= Html.ValidationMessage("Test3", "*") %>
    </p>
    <p>
    <label for="Test4">Test4:</label>
    <%= Html.TextBox("Test4") %>
    <%= Html.ValidationMessage("Test4", "*") %>
    </p>
    <p>
    <label for="Test5">Test5:</label>
    <%= Html.TextBox("Test5") %>
    <%= Html.ValidationMessage("Test5", "*") %>
    </p>

     当页面输入的数据在Controller里经过数据绑定之后,只剩下了Test3一项有值,其他几个都是null,然后当程序走到

    Html.TextBox的时候就出错了,报错如下:

    代码
    堆栈跟踪:


    [NullReferenceException: 未将对象引用设置到对象的实例。]
    System.Web.Mvc.HtmlHelper.GetModelStateValue(String key, Type destinationType) +63
    System.Web.Mvc.Html.InputExtensions.InputHelper(HtmlHelper htmlHelper, InputType inputType, String name, Object value, Boolean useViewData, Boolean isChecked, Boolean setId, Boolean isExplicitValue, IDictionary`2 htmlAttributes) +519
    System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Object value, IDictionary`2 htmlAttributes) +34
    System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name) +60
    ASP.views_dinners_create_aspx.__RenderContent2(HtmlTextWriter __w, Control parameterContainer) in e:\学习资料\我的学习文件\工作学习\【12】-网页方向\MVC\一步一步学asp.net_mvc\Projects\NerdDinner\NerdDinner\Views\Dinners\Create.aspx:30
    System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +256
    System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
    System.Web.UI.Control.Render(HtmlTextWriter writer) +10
    System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
    System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
    System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
    ASP.views_shared_site_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in e:\学习资料\我的学习文件\工作学习\【12】-网页方向\MVC\一步一步学asp.net_mvc\Projects\NerdDinner\NerdDinner\Views\Shared\Site.Master:26
    System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +256
    System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
    System.Web.UI.Control.Render(HtmlTextWriter writer) +10
    System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
    System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
    System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
    System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
    System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
    System.Web.UI.Page.Render(HtmlTextWriter writer) +29
    System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +59
    System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
    System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
    System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266


    找了半天也没找到原因,于是我把数据绑定的限制去掉试了一下,就没问题了,于是我想问题可能出在这个方法上面,祭出

    Reflector,直接打开C盘下的System.Web.MVC.Dll,看个究竟:

    通过HtmlHelper.TextBox方法,很容易跟到这个函数:

    代码
    private static string InputHelper(this HtmlHelper htmlHelper, InputType inputType, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, IDictionary<string, object> htmlAttributes)
    {
    ModelState state;
    if (string.IsNullOrEmpty(name))
    {
    throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
    }
    TagBuilder builder
    = new TagBuilder("input");
    builder.MergeAttributes
    <string, object>(htmlAttributes);
    builder.MergeAttribute(
    "type", HtmlHelper.GetInputTypeString(inputType));
    builder.MergeAttribute(
    "name", name, true);
    string str = Convert.ToString(value, CultureInfo.CurrentCulture);
    bool flag = false;
    switch (inputType)
    {
    case InputType.CheckBox:
    {
    bool? modelStateValue = htmlHelper.GetModelStateValue(name, typeof(bool)) as bool?;
    if (modelStateValue.HasValue)
    {
    isChecked
    = modelStateValue.Value;
    flag
    = true;
    }
    break;
    }
    case InputType.Password:
    if (value != null)
    {
    builder.MergeAttribute(
    "value", str, isExplicitValue);
    }
    goto Label_0152;

    case InputType.Radio:
    break;

    default:
    {
    string str3 = (string) htmlHelper.GetModelStateValue(name, typeof(string));
    builder.MergeAttribute(
    "value", str3 ?? (useViewData ? htmlHelper.EvalString(name) : str), isExplicitValue);
    goto Label_0152;
    }
    }
    if (!flag)
    {
    string a = htmlHelper.GetModelStateValue(name, typeof(string)) as string;
    if (a != null)
    {
    isChecked
    = string.Equals(a, str, StringComparison.Ordinal);
    flag
    = true;
    }
    }
    if (!flag && useViewData)
    {
    isChecked
    = htmlHelper.EvalBoolean(name);
    }
    if (isChecked)
    {
    builder.MergeAttribute(
    "checked", "checked");
    }
    builder.MergeAttribute(
    "value", str, isExplicitValue);
    Label_0152:
    if (setId)
    {
    builder.GenerateId(name);
    }
    if (htmlHelper.ViewData.ModelState.TryGetValue(name, out state) && (state.Errors.Count > 0))
    {
    builder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
    }
    if (inputType == InputType.CheckBox)
    {
    StringBuilder builder2
    = new StringBuilder();
    builder2.Append(builder.ToString(TagRenderMode.SelfClosing));
    TagBuilder builder3
    = new TagBuilder("input");
    builder3.MergeAttribute(
    "type", HtmlHelper.GetInputTypeString(InputType.Hidden));
    builder3.MergeAttribute(
    "name", name);
    builder3.MergeAttribute(
    "value", "false");
    builder2.Append(builder3.ToString(TagRenderMode.SelfClosing));
    return builder2.ToString();
    }
    return builder.ToString(TagRenderMode.SelfClosing);
    }




    这里注意Switch应该是走到default里,继续跟,发现这个函数有问题:

    代码
    internal object GetModelStateValue(string key, Type destinationType)
    {
    ModelState state;
    if (this.ViewData.ModelState.TryGetValue(key, out state))
    {
    return state.Value.ConvertTo(destinationType, null);
    }
    return null;
    }


    其中这句话怎么看怎么不爽:return state.Value.ConvertTo(destinationType, null);

    于是我在Controller里自己试了一把:

    代码
    System.Web.Mvc.ModelState state;
    if (this.ViewData.ModelState.TryGetValue("Test1", out state))
    {
    var result
    = state.Value.ConvertTo(typeof(string), null);

    }

    监视器打开,问题找到了

    至于这后面隐藏了MVC的什么内部实现,等我搞清楚了再回头看看。今天的问题算是告一段落了。


    本博客文章若非标记转载,均为原创,转载请注明出处~


  • 相关阅读:
    VMware ESXI 5.5 注册码
    NetScaler Active-Active模式
    Citrix NetScaler HA(高可用性)解析
    服务管理--systemctl命令
    CentOS7 安装 webgoat 7.1 简介
    Codefoces 723B Text Document Analysis
    Codefoces 723A The New Year: Meeting Friends
    ECJTUACM16 Winter vacation training #1 题解&源码
    信息学奥赛一本通算法(C++版)基础算法:高精度计算
    从零开始学算法:高精度计算
  • 原文地址:https://www.cnblogs.com/wbpmrck/p/1934028.html
Copyright © 2011-2022 走看看