gpt4 book ai didi

c# - 不同情况下呈现的 bool 字段

转载 作者:可可西里 更新时间:2023-11-01 08:28:47 25 4
gpt4 key购买 nike

对于任何有想法的人来说,这有点奇怪……我正在特定页面上渲染一个隐藏的 bool 字段。但是,根据特定事件是否在流程之前发生,我会为同一字段获得两个略有不同的标记。正在生成的两个字段是;

<input id="HasPreviouslyIssuedCard" name="HasPreviouslyIssuedCard" type="hidden" value="false" />


<input id="HasPreviouslyIssuedCard" name="HasPreviouslyIssuedCard" type="hidden" value="False" />

问题是“value”属性中的文本的情况,您会注意到它是不同的,并且稍后会影响 JS 条件。生成这个的 Razor 标记是;
@Html.Hidden("HasPreviouslyIssuedCard", Model.HasPreviouslyIssuedCard?.ToString(), new { id = nameof(Model.HasPreviouslyIssuedCard) })

但是,我也尝试了使用以下内容的变体,在渲染隐藏字段方面具有相同的区别;
@Html.HiddenFor(m => m.HasPreviouslyIssuedCard)

我该怎么做才能获得这种差异?为了获得大写的变体,我在进入相关页面之前点击了浏览器的后退按钮。这两种方法都以相同的方式加载数据,并以相同的方式将相同的值传递给渲染器。两种不同的输出。

请记住,这是一个正在呈现的 bool 值类型字段。应该没有太大的修补余地。有多种方法可以解决这个问题,但由于我们在 backlog 中有几个与 bool 字段和后退按钮相关的项目,我想解释一下而不是解决它。

我最好的猜测是,点击后退按钮以某种方式改变了渲染器的状态,或者模型中的其他一些标志不同(有 70 多个字段,因为它是一个向导)正在改变渲染器解释如何区分 bool 值的方式值(value)。值相同,页相同,数据读取方式相同。

基于此页面 ( Why does Boolean.ToString output "True" and not "true" ),假设我们应该一直获得大写变体,但这不是结果。

任何接受者/想法/想法?

编辑 1

HiddenFor() 中挖掘 MVC 的渲染逻辑方法,最终 Convert.ToString(value, CultureInfo.CurrentCulture)叫做。当直接调用时,我无法让它产生一个小写的 bool 值,但它显然是这样做的。我当前的文化代码设置为 en-IE但是在直接调用它时我看到的是大写的 bool 值。

编辑 2

我已经对我的应用程序进行了更多的修补和跟踪,并且可以提供有关正在发生的事情的更多详细信息,尽管我还没有能够在更简单的应用程序中重现这一点。

MVC 5 应用程序:它有;
  • 初始登录页面,其 URL 位于根域 /通过 HTTP 检索 GET . bool input标签呈现为 True/False
  • 位于 URL /Apply 的向导中的第一页通过 HTTP 检索 GET . bool input标签呈现为 True/False
  • 用户在第 2 步提交页面后,向导中位于相同 URL 的第二页。通过 HTTP POST 检索. input案例标签现在呈现为 true/false .
  • 点击浏览器的后退按钮并点击陷阱页面(我们将浏览器历史设置为总是在后退上点击陷阱页面,因为它与向导一起玩得很开心)。
  • 用户点击陷阱页面上的按钮将他们带回他们离开的应用程序。 input标签现在以大写形式返回渲染(最初报告的问题)。

  • 我一直在深入研究 MVC 库,使用 ILSpy 尝试扫描,MVC(如果我正确阅读代码)实际上使用了 IConverter 的实现。写入 bool 值,而不是 Convert.ToString(value, CultureInfo.CurrentCulture)正如我最初的想法。

    从对 HiddenFor() 的调用跟踪的代码堆栈是(我认为);
  • System.Web.Mvc.InputExtentions.HiddenFor() (公共(public)功能)
  • System.Web.Mvc.InputExtentions.HiddenHelper() (私有(private)函数,这里有一些用于数组的逻辑,但不适用于我们的情况)
  • System.Web.Mvc.InputExtentions.InputHelper() (私有(private)函数,魔法在这里发生)
  • System.Web.Mvc.InputExtentions.InputHelper()的反编译代码;
    private static MvcHtmlString InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format, IDictionary<string, object> htmlAttributes)
    {
    string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
    if (string.IsNullOrEmpty(fullHtmlFieldName))
    {
    throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
    }
    TagBuilder tagBuilder = new TagBuilder("input");
    tagBuilder.MergeAttributes<string, object>(htmlAttributes);
    tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
    tagBuilder.MergeAttribute("name", fullHtmlFieldName, true);
    string text = htmlHelper.FormatValue(value, format);
    bool flag = false;
    switch (inputType)
    {
    case InputType.CheckBox:
    {
    bool? flag2 = htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof(bool)) as bool?;
    if (flag2.HasValue)
    {
    isChecked = flag2.Value;
    flag = true;
    }
    break;
    }
    case InputType.Hidden:
    goto IL_131;
    case InputType.Password:
    if (value != null)
    {
    tagBuilder.MergeAttribute("value", text, isExplicitValue);
    goto IL_16C;
    }
    goto IL_16C;
    case InputType.Radio:
    break;
    default:
    goto IL_131;
    }
    if (!flag)
    {
    string text2 = htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof(string)) as string;
    if (text2 != null)
    {
    isChecked = string.Equals(text2, text, StringComparison.Ordinal);
    flag = true;
    }
    }
    if (!flag && useViewData)
    {
    isChecked = htmlHelper.EvalBoolean(fullHtmlFieldName);
    }
    if (isChecked)
    {
    tagBuilder.MergeAttribute("checked", "checked");
    }
    tagBuilder.MergeAttribute("value", text, isExplicitValue);
    goto IL_16C;
    IL_131:
    string text3 = (string)htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof(string));
    tagBuilder.MergeAttribute("value", text3 ?? (useViewData ? htmlHelper.EvalString(fullHtmlFieldName, format) : text), isExplicitValue);
    IL_16C:
    if (setId)
    {
    tagBuilder.GenerateId(fullHtmlFieldName);
    }
    ModelState modelState;
    if (htmlHelper.ViewData.ModelState.TryGetValue(fullHtmlFieldName, out modelState) && modelState.Errors.Count > 0)
    {
    tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
    }
    tagBuilder.MergeAttributes<string, object>(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));
    if (inputType == InputType.CheckBox)
    {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
    TagBuilder tagBuilder2 = new TagBuilder("input");
    tagBuilder2.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
    tagBuilder2.MergeAttribute("name", fullHtmlFieldName);
    tagBuilder2.MergeAttribute("value", "false");
    stringBuilder.Append(tagBuilder2.ToString(TagRenderMode.SelfClosing));
    return MvcHtmlString.Create(stringBuilder.ToString());
    }
    return tagBuilder.ToMvcHtmlString(TagRenderMode.SelfClosing);
    }

    编辑 3

    只是重申一下,因为有一些关于 javascript 方面的评论。我很早就在尝试诊断问题时考虑过这一点。为了排除任何潜在的 JS 干扰/操纵,我使用 Fiddler 来捕获传输中的 HTML。 MVC 生成的 HTML 正在改变大小写 - 我可以在 Fiddler 中看到这一点,甚至在 JS 加载之前,更不用说运行了。这不是JS问题。

    最佳答案

    看来我错了,毕竟是 JS,虽然不是在我试图排除它的时候。重现这一点的事件序列;

  • 创建 HTML form带有 bool 隐藏字段 + 非提交按钮
  • onclick按钮的事件,有一段 JS 将 bool 字段设置为 true (小写)
  • 在 Controller 中的 POST 操作中,呈现相同的 View

  • 在 POST 之后, bool 字段将具有小写值而不是大写值。

    这是怎么回事?那么, HiddenFor() (及其变体)将呈现来自 ViewData.ModelState 的 bool 值而不是模型属性的 ToString()如果 key 存在于 ModelState 中,则值收藏。看起来很直观,但可以(对我来说)可以抛出的是所有其他数据类型,模型绑定(bind)器非常具体 - ModelState value 和您模型的属性值将相同。除了 bool 值 - 模型绑定(bind)器足够智能来处理 Truetrue与转换 POST 时相同,但这会留下 ModelState如果它是通过 JS bool 值设置的,则 value 和您的字符串化属性值不正常。 JS 会设置 ModelState值为 true而您的模型属性的 ToString()值显示为 True .而在 JS 中, "true" !== "True" .

    至于为什么在点击浏览器的“后退”按钮后对我重置 - 我们拥有的陷阱页面没有表单值,并且没有通过 HTTP GET 链接回应用程序,这会导致 HiddenFor调用模型属性的 .ToString()而不是从 ModelState 中拉出来因为在那个时间点它不在那里。同样,在我的测试中,用户会在通过 JS 设置之后很久才处于向导中的某个点,因此当他们继续通过向导时,它会保持大写。

    我的假设是 JS 在页面加载后启动。这实际上是由于 JS 在开始 POST 之前设置了一个值,并且该小写值通过 ModelState 在页面生命周期中持续存在。 .去搞清楚。

    编辑

    复制代码;

    模型;
    public class Test
    {
    public bool Sample { get; set; }
    }

    Razor 标记;
    @model TestModelValueCase.Models.Test
    @{
    ViewBag.Title = "Test Page";
    }

    @using (Html.BeginForm())
    {
    @Html.HiddenFor(m => m.Sample)
    <div>
    <label>Hidden Value:</label>
    <span id="_uiValue"></span>
    </div>
    <button type="submit">Try Post</button>
    }
    @section scripts
    {
    <script type="text/javascript" language="javascript">
    $(document).ready(function() {
    var source = $('#@nameof(Model.Sample)');
    $('#_uiValue').html(source.val());
    source.val(true);
    });
    </script>
    }

    Controller ;
        public ActionResult Index()
    {
    Test model = new Test();
    return View(model);
    }

    [HttpPost]
    public ActionResult Index(Test model)
    {
    return View(model);
    }

    关于c# - 不同情况下呈现的 bool 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44720485/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com