У меня есть такая простая форма, которая использует расширение @ Html .EditorFor:
<form method="post">
@Html.EditorFor(x => x.SystemSettings.EmailFromAddress)
<submit-button title="Save"></submit-button>
</form>
Я хочу воспользоваться. NET Помощниками тегов Core, чтобы моя форма выглядела как это вместо этого:
<form method="post">
<editor asp-for="SystemSettings.EmailFromAddress"/>
<submit-button title="Save"></submit-button>
</form>
Я также в конечном итоге хотел бы иметь своих собственных помощников тегов, чтобы я мог сделать что-то вроде этого:
<text-box asp-for="SystemSettings.EmailFromAddress"></text-box>
У меня есть строка шаблон, который визуализируется расширением @ Html .EditorFor:
@model string
<div class="form-group">
<label asp-for="@Model" class="m-b-none"></label>
<span asp-description-for="@Model" class="help-block m-b-none small m-t-none"></span>
<div class="input-group">
<input asp-for="@Model" class="form-control" />
<partial name="_ValidationIcon" />
</div>
<span asp-validation-for="@Model" class="validation-message"></span>
</div>
Для этого я видел, как кто-то реализовал EditorTagHelper , который выглядит следующим образом:
[HtmlTargetElement("editor", TagStructure = TagStructure.WithoutEndTag,
Attributes = ForAttributeName)]
public class EditorTagHelper : TagHelper
{
private readonly IHtmlHelper _htmlHelper;
private const string ForAttributeName = "asp-for";
private const string TemplateAttributeName = "asp-template";
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
[HtmlAttributeName(TemplateAttributeName)]
public string Template { get; set; }
[ViewContext]
[HtmlAttributeNotBound]
public ViewContext ViewContext { get; set; }
public EditorTagHelper(IHtmlHelper htmlHelper)
{
_htmlHelper = htmlHelper;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (output == null)
throw new ArgumentNullException(nameof(output));
if (!output.Attributes.ContainsName(nameof(Template)))
{
output.Attributes.Add(nameof(Template), Template);
}
output.SuppressOutput();
(_htmlHelper as IViewContextAware).Contextualize(ViewContext);
output.Content.SetHtmlContent(_htmlHelper.Editor(For.Name, Template));
await Task.CompletedTask;
}
}
Однако, когда я использую EditorTagHelper, мне, кажется, не хватает ненавязчивых Javascript проверочных атрибутов:
При использовании @Html.EditorFor это визуализируется :
<input class="form-control valid" type="text" data-val="true" data-val-required="Email From Address cannot be empty" id="SystemSettings_EmailFromAddress" name="SystemSettings.EmailFromAddress" value="whatever@test.com" aria-required="true" aria-invalid="false" aria-describedby="SystemSettings_EmailFromAddress-error">
У него есть атрибуты data-val, поэтому применяется проверка на стороне клиента.
Когда я вместо этого использую EditorTagHelper , это будет визуализировано:
<input class="form-control valid" type="text" id="SystemSettings_EmailFromAddress" name="SystemSettings.EmailFromAddress" value="whatever@test.com" aria-invalid="false">
Ненавязчивые атрибуты проверки не применяются. Я использую FluentValidation, и я определил AbstractValidator следующим образом:
public class SystemSettingsValidator : AbstractValidator<SystemSettings>
{
public SystemSettingsValidator()
{
RuleFor(x => x.EmailFromAddress).NotEmpty()
.WithMessage("Email From Address cannot be empty");
}
}
Я обнаружил, что если я удалил AbstractorValidator и просто добавил атрибут [Required] в мое свойство модели, то проверка работала бы правильно. Это говорит о том, что с FluentValidation что-то не так. Возможно, есть проблема конфигурации.
Я использую Autofa c внедрение зависимостей для сканирования моих сборок и регистрации типов валидаторов:
builder.RegisterAssemblyTypes(Assembly.Load(assembly))
.Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
.AsImplementedInterfaces()
.PropertiesAutowired()
.InstancePerLifetimeScope();
Кажется, это работает нормально. В случае, если это не было хорошо, я также попытался зарегистрировать валидаторы из беглых опций проверки, как это:
.AddFluentValidation(fv =>
{
fv.RegisterValidatorsFromAssemblies(new List<Assembly>
{Assembly.GetExecutingAssembly(), Assembly.Load(nameof(Entities))});
})
Это также, похоже, было хорошо.
Одна вещь, на которую стоит обратить внимание, это то, что у меня была более ранняя проблема, заключающаяся в том, что использование сканирования сборок Autofa c разрушало приложение, когда в него были добавлены помощники тегов. Я добавил фильтр, чтобы гарантировать, что помощники по тегам не включаются при регистрации этих зависимостей, например:
builder.RegisterAutowiredAssemblyInterfaces(Assembly.Load(Web))
.Where(x => !x.Name.EndsWith("TagHelper"));
Я загрузил рабочий пример кода здесь: https://github.com/ciaran036/coresample2
Перейдите на страницу Настройки , чтобы увидеть поле, которое я пытаюсь проверить.
Эта проблема также влияет на компоненты вида.
Спасибо.