#c# #asp.net-mvc #visual-studio
#c# #asp.net-mvc #visual-studio
Вопрос:
На данный момент это скорее теоретический вопрос, но здесь он все равно идет.
Короткая версия: есть ли какой-нибудь способ заставить моего собственного помощника html заменить стандартный помощник html (например EditBoxFor
), не переходя по маршруту replace all (переопределяя помощника по умолчанию?) Или ограничить функцию replace all в VS только представлениями?
Длинная версия: мы создали приложение MVC, которое имеет много-много просмотров, но теперь наш клиент хочет, чтобы мы добавили функциональность, которая позволит ему изменять различный текст в приложении. Это связано с такими вещами, как метки для входных данных, заполнители и некоторые подобные. Я уже написал свою собственную замену помощника html для EditBoxFor
(в глубине души он все еще использует и EditBoxFor
), Который загружает заполнитель и т. Д. Из базы данных, помещает его в кеш и так далее. Я назвал его (о, так умно) EditBoxFor2
, и он принимает те же входные данные, EditBoxFor
что и, поэтому в представлении я могу просто добавить 2
к имени помощника, и он поддерживает эту новую текстовую функциональность. EditBoxFor
используется в системе много-много раз, и это не единственный html-помощник, который мы модифицируем. Вероятно, я мог бы заменить все EditBoxFor
на EditBoxFor
(или еще лучше Html.EditBoxFor(
на Html.EditBoxFor2(
) вместо того, чтобы изменять несколько тысяч строк кода вручную, но очень вероятно, что таким образом я нарушу некоторые представления контроллеры другие помощники (возможно, я забыл реализовать несколько вариантов EditBoxFor
в моем Html.EditBoxFor2
). Итак, мне было интересно, есть ли какой-то способ переопределить (с тем же именем и теми же входными параметрами) помощников по умолчанию моими собственными?
Комментарии:
1. Хорошего способа добиться этого нет, и для этого есть причина. Даже если вы единственный разработчик, работающий над чем-то прямо сейчас, это может быть не всегда так. Вы можете уйти на более зеленые пастбища, или ваша организация может привлечь кого-то другого. Переопределение подобных вещей только создает путаницу в вашей кодовой базе. Используя помощник с другим именем, вы даете понять, что он отличается.
2. Конечно, это решение должно быть оставлено на усмотрение команды разработчиков? Чем это отличается от переопределения любого другого типа поведения по умолчанию, такого как
ModelMetadataProviders
или даже глобальных фильтров действий?
Ответ №1:
Вы можете сделать это, определив шаблон отображения или шаблон редактора (это ключевые слова, которые вы можете использовать в Google).
Короче говоря, вы создаете папку «DisplayTemplates» и папку «EditorTemplates» в вашей папке ~/Views/Shared. Это условность.
Затем в эти папки вы можете добавить шаблон для каждого редактора по умолчанию.
Я использую его, например, для предоставления шаблона для моих телефонных номеров.
PhoneNumber.cshtml (должно быть именем вашего класса)
@model MyProject.Common.Models.PhoneNumber
<div class="editor-field">
@Html.DisplayFor(model => model.PhoneNumberType)
@Html.DisplayFor(model => model.Phone)
</div>
Я также использую его для отображения моих перечислений
DisplayTemplates/Строка.cshtml
@using MyProject.Website.Helpers
@{
var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;
@(typeof(Enum).IsAssignableFrom(type) ? EnumViewsHelpers.GetResourceValueForEnumValue(Model) : Model)
}
Таким образом, каждый раз, когда у меня есть поле типа enum для отображения, оно будет вызывать моего помощника для его отображения. Помощник будет искать соответствующую строку в resources.resx.
Что касается редактора, он отобразит выпадающий список для выбора нужного вам перечисления
EditorTemplates/String.cshtml
@using System.Web.Mvc.Html
@using MyProject.Website.Helpers
@{
var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;
@(typeof(Enum).IsAssignableFrom(type) ? Html.ExtEnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}
Это и есть помощник
public static class EnumViewsHelpers
{
public static IHtmlString ExtEnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;
var enumValues = Enum.GetValues(enumType).Cast<object>();
var items = from enumValue in enumValues
select new SelectListItem
{
Text = GetResourceValueForEnumValue(enumValue),
Value = ((int)enumValue).ToString(),
Selected = enumValue.Equals(metadata.Model)
};
return html.DropDownListFor(expression, items, string.Empty, null);
}
public static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);
return Resource.ResourceManager.GetString(key) ?? enumValue.ToString();
}
}
Я думаю, вы можете использовать ту же технику для своих редакторов
Комментарии:
1. Спасибо за ответ, я слышал о шаблонах редактора, но я думал, что могу использовать их только с помощником EditorFor, думаю, мне придется изучить его немного подробнее. P.S. В вашем втором примере кода произошла утечка одного «}» за пределами блока кода.
2. Вы можете использовать их только в сочетании с
EditorFor
илиDisplayFor
. Я полагаю, @MarcinHabuszewski не читал это внимательно и принялEditBoxFor
заEditorFor
. Я изначально прочитал это так же.
Ответ №2:
Как писал Крис Пратт, хорошего способа сделать это нет, и, возможно, это не такая уж хорошая идея, чтобы сделать это в первую очередь. Это может привести к крайней путанице для других людей, работающих над проектом (я уже сталкивался с этим, когда другие разработчики изменяли какое-то базовое поведение приложения MVC, а затем мне приходилось тратить часы, чтобы найти причину, по которой что-то базовое не работает ожидаемым образом).