TL; DR:
Подумайте о том, чтобы поместить текст в помощники тегов в тех случаях, когда вам действительно что-то нужно
отличается от сгенерированного значения.
Полный ответ
Вы практически можете найти решение самостоятельно, но я думаю, что я все еще могу добавить сюда свои два цента.
Большинство помощников по тегам работают так, чтобы генерировать контент в условии, когда его содержимое пустое или содержит только пробельные символы. Например, ValidationMessageTagHelper
проверяет это следующим образом:
var tagHelperContent = await output.GetChildContentAsync();
// We check for whitespace to detect scenarios such as:
// <span validation-for="Name">
// </span>
if (!tagHelperContent.IsEmptyOrWhiteSpace)
{
message = tagHelperContent.GetContent();
}
Он получает содержимое тега и затем заполняет переменную message
, если содержимое имеет значение null, пусто или пропущено. Переменная message
затем используется для генерации сообщения проверки:
var tagBuilder = Generator.GenerateValidationMessage(
ViewContext,
For.ModelExplorer,
For.Name,
message: message,
tag: null,
htmlAttributes: htmlAttributes);
Если message
равен null
или пуст, тогда генератор выдаст ошибку модели (см. строка 858 из DefaultHtmlGenerator
);
if (!string.IsNullOrEmpty(message))
{
tagBuilder.InnerHtml.SetContent(message);
}
else if (modelError != null)
{
modelExplorer = modelExplorer ?? ExpressionMetadataProvider.FromStringExpression(
expression,
viewContext.ViewData,
_metadataProvider);
tagBuilder.InnerHtml.SetContent(
ValidationHelpers.GetModelErrorMessageOrDefault(modelError, entry, modelExplorer));
}
GetModelErrorMessageOrDefault()
из ValidationHelpers
:
public static string GetModelErrorMessageOrDefault(
ModelError modelError,
ModelStateEntry containingEntry,
ModelExplorer modelExplorer)
{
Debug.Assert(modelError != null);
Debug.Assert(containingEntry != null);
Debug.Assert(modelExplorer != null);
if (!string.IsNullOrEmpty(modelError.ErrorMessage))
{
return modelError.ErrorMessage;
}
// Default in the ValidationMessage case is a fallback error message.
var attemptedValue = containingEntry.AttemptedValue ?? "null";
return modelExplorer.Metadata.ModelBindingMessageProvider.ValueIsInvalidAccessor(attemptedValue);
}
Так что да, если вы поместите какой-либо текст в тег проверки <span>
, помощник тега выберет ваш текст вместо ошибки проверки из состояния модели. Подобное поведение происходит, если вы помещаете текст внутри тега <label
>, как вы это сделали:
<label class="control-label" asp-for="Firstname">Firstname</label>
Помощник по тегам не будет перезаписывать значение Firstname
, которое вы поместили внутри тега. Это может показаться плохим поведением, но если вы хотите использовать отображаемое имя для свойства Firstname
:
[Display(Name = "Fancy first name")]
public string Firstname { get; set; }
Вы не увидели бы, как это работает! Поскольку помощник по тегам снова выберет текст, который вы поместите между тегами <label>
, вместо отображаемого имени для Firstname
.
Что вам нужно сделать, так это оставить все как можно проще:
<label class="control-label" asp-for="Firstname"></label>
Подумайте о том, чтобы поместить текст в помощники тегов в тех случаях, когда вам действительно что-то нужно
отличается от сгенерированного значения.
В самом начале я сказал, что большинство помощников тегов работают именно так. Большинство из них, но не все. Например, SelectTagHelper
позволяет помещать любой произвольный текст внутри тега, и если вы предоставляете список выбора, он генерирует параметры, добавляя их к существующему контенту. Это очень удобно для добавления пользовательских тегов <option>
. Например, я могу легко добавить выбранный и отключенный параметр, чтобы раскрывающийся список не имел начального значения, поэтому пользователь вынужден вручную выбирать параметр. Эти строки кода:
<select asp-for="LevelId" asp-items="@Model.Levels" class="custom-select">
<option selected disabled>Select option</option>
</select>
приведет к:
<select class="custom-select" data-val="true" data-val-required="'Level Id' must not be empty." id="LevelId" name="LevelId">
<option selected disabled>Select parking level</option>
<option value="9">-2</option>
<option value="8">-1</option>
<option value="7">0</option>
</select>