Булевое поле, созданное в разных случаях
Немного странное для тех, у кого есть мысли об этом... Im визуализирует скрытое логическое поле на определенной странице. Тем не менее, я получаю две слегка разные разметки для одного и того же поля в зависимости от того, произошло ли какое-либо событие ранее в процессе. Создаются два поля:
<input id="HasPreviouslyIssuedCard" name="HasPreviouslyIssuedCard" type="hidden" value="false" />
и
<input id="HasPreviouslyIssuedCard" name="HasPreviouslyIssuedCard" type="hidden" value="false" />
Проблема заключается в том, что текст в атрибуте "значение", который вы считаете, отличается, а затем влияет на условия JS. Разметка бритвы, создающая это:
@Html.Hidden("HasPreviouslyIssuedCard", Model.HasPreviouslyIssuedCard?.ToString(), new { id = nameof(Model.HasPreviouslyIssuedCard) })
Однако Ive также попробовал вариант с использованием следующего с той же разницей в визуализации скрытого поля;
@Html.HiddenFor(m => m.HasPreviouslyIssuedCard)
Какое событие я могу сделать, чтобы получить эту разницу? Чтобы получить вариант верхнего регистра, я нажимаю кнопку "Назад" браузера, прежде чем перейти на соответствующую страницу. Оба метода загружают данные одинаково и одинаково передают одно и то же значение в рендеринг. Два разных выхода.
Имейте в виду, что это булевское поле типа значения, которое визуализируется. Там не должно быть много возможностей для возиться с. Существует множество способов обойти это, но поскольку у нас есть пара элементов, относящихся к логическим полям и обратной кнопке, Id нравится объяснять это, а не работать вокруг него.
Мое лучшее предположение заключается в том, что нажатие кнопки "назад" каким-то образом изменяет состояние рендерера или что другой флаг в модели отличается (имеется 70+ полей, так как это мастер) меняет способ визуализации визуализатора как введите логическое значение. Значение одно и то же, страница одна и та же, данные читаются одинаково.
Основываясь на этой странице (Почему вывод Boolean.ToString "true" и не "true" ?), мы должны гипотетически получить в верхнем регистре все но это не результат.
Любые участники/идеи/мысли?
РЕДАКТИРОВАТЬ 1
Выкапывание через визуализацию MVC в методе HiddenFor()
, в конечном итоге вызывается Convert.ToString(value, CultureInfo.CurrentCulture)
. Я не могу заставить это создавать строчные логические значения при вызове напрямую, но это явно делает. Мой текущий код культуры установлен на en-IE
, но при вызове его я вижу заглавные логические значения.
РЕДАКТИРОВАТЬ 2
Я сделал немного больше мастеринга и отслеживания через свое приложение и могу предоставить немного более подробную информацию о том, что происходит, хотя я еще не смог воспроизвести это в более простом приложении.
MVC 5 Приложение: оно имеет:
- Начальная целевая страница с URL-адресом в корневом домене
/
, полученном через HTTP GET
. Boolean input
теги отображаются как True
/False
- Первая страница в мастере по URL
/Apply
, полученная через HTTP GET
. Boolean input
теги отображаются как True
/False
- Вторая страница в мастере с тем же URL-адресом после отправки пользователем страницы на шаге 2. Получено через HTTP
POST
. Пример тегов input
теперь отображается как True
/False
.
- Нажмите кнопку "Назад" браузера и нажмите страницу ловушки (мы устанавливаем историю браузера, которая всегда попадает на страницу ловушки на "Назад" , когда она играет с адским волшебником).
- Пользователь нажимает кнопку на странице ловушки, чтобы вернуть их в приложение, где они остановились. Теги
input
теперь возвращают рендеринг в верхнем регистре (исходная ошибка).
Я вникал в библиотеку MVC, используя ILSpy, чтобы попробовать и проверить, и MVC (если я правильно читаю код) фактически использует реализацию IConverter
для записи логического значения, а не Convert.ToString(value, CultureInfo.CurrentCulture)
как Я изначально думал.
Стек кода, прослеживаемого от вызова HiddenFor()
, (я думаю),
-
System.Web.Mvc.InputExtentions.HiddenFor()
(публичная функция)
-
System.Web.Mvc.InputExtentions.HiddenHelper()
(частная функция, некоторая логика здесь для массивов, но не применима в нашей ситуации)
-
System.Web.Mvc.InputExtentions.InputHelper()
(частная функция, здесь происходит магия)
Декомпилированный код для 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 в передаче. HTML, который генерирует MVC, меняет регистр - и я могу видеть это в Fiddler, в момент, когда JS будет даже загружаться, не стоит запускать. Это не проблема JS.
Ответы
Ответ 1
Кажется, я был неправ, это был JS в конце концов, хотя и не в том месте, где я пытался это исключить. Последовательность событий для повторного создания этого;
- Создать HTML
form
с булевым скрытым полем + кнопка без отправки
- В событии
onclick
для кнопки используйте кусок JS, который устанавливает логическое поле в true
(строчный)
- В вашем действии POST в контроллере отобразите тот же вид
После POST булевское поле будет иметь строчное значение, а не в верхнем регистре.
Что происходит? Ну, HiddenFor()
(и его варианты) выдаст логическое значение из ViewData.ModelState
, а не логическое значение модели, если оно присутствует в коллекции ModelState
. Кажется интуитивным, но что может (и сделал для меня) бросить вас в том, что все другие типы данных, привязка к модели довольно специфичны - значение ModelState
и ваши значения свойств модели будут одинаковыми. За исключением случая для логического - модельное связующее достаточно умен, чтобы обрабатывать true
и true
как одно и то же, но это оставляет значение ModelState
и значение вашего строкового значения из-за удара, если оно было задано с помощью буфера JS.
Что касается этого reset для меня после нажатия кнопки "Назад назад" - страница ловушки, которой у нас нет, не имеет значений формы и ссылок обратно в приложение через HTTP GET, что вызывает вызов HiddenFor
модели свойство .ToString()
вместо того, чтобы вытащить его из ModelState
, поскольку он не находится там в этот момент времени. Аналогичным образом, в моих тестах пользователь будет находиться в точке мастера после того, как он будет установлен через JS, поэтому он останется в верхнем регистре, когда они продолжат работу с мастером.
Мое предположение заключалось в том, что JS загружался после загрузки страницы. Фактически это произошло из-за того, что JS установил значение перед тем, как начать POST, и это значение нижнего регистра сохранилось в течение жизненного цикла страницы через ModelState
. Наведите указатель мыши.
ИЗМЕНИТЬ
Код для воспроизведения;
Модель;
public class Test
{
public bool Sample { get; set; }
}
Разметка бритвы;
@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>
}
контроллер;
public ActionResult Index()
{
Test model = new Test();
return View(model);
}
[HttpPost]
public ActionResult Index(Test model)
{
return View(model);
}
Ответ 2
Случай логического компиляции с контроллера очень сложный, поскольку большая часть времени интерпретируется как строка .
Это похоже на @Hidden.
Для меня более простой способ добиться этого - создать флажок и установить отображение на "none"
@html.CheckBoxFor(m=> m.HasPreviouslyIssuedCard, new { style ="display:none"}))
С помощью этого решения у вас будет более типизированная переменная на обоих языках (С# и JavaScript).