Я создаю помощник, который позволит мне создавать каскадные раскрывающиеся списки, которые заполняются с помощью AJAX. Вспомогательный метод выглядит так:
public static MvcHtmlString AjaxSelectFor<TModel, TProperty>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TProperty>> expression,
Expression<Func<TModel, TProperty>> cascadeFrom,
string sourceUrl,
bool withEmpty = false)
{
string controlFullName = html.GetControlName(expression);
string cascadeFromFullName = html.GetControlName(cascadeFrom);
var selectBuilder = GetBaseSelect(controlFullName.GetControlId(), controlFullName, sourceUrl, withEmpty);
selectBuilder.Attributes.Add("data-selected-id", html.GetValue(expression));
selectBuilder.Attributes.Add("data-cascade-from", "#" + cascadeFromFullName.GetControlId());
return new MvcHtmlString(selectBuilder.ToString());
}
private static TagBuilder GetBaseSelect(string controlId, string controlName, string sourceUrl, bool withEmpty)
{
var selectBuilder = new TagBuilder("select");
selectBuilder.Attributes.Add("id", controlId);
selectBuilder.Attributes.Add("name", controlName);
selectBuilder.Attributes.Add("data-toggle", "ajaxSelect");
selectBuilder.Attributes.Add("data-source-url", sourceUrl);
selectBuilder.Attributes.Add("data-with-empty", withEmpty.ToString());
selectBuilder.AddCssClass("form-control");
return selectBuilder;
}
internal static string GetControlName<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression)
{
string controlName = ExpressionHelper.GetExpressionText(expression);
return html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(controlName);
}
internal static string GetControlId(this string controlName)
{
return TagBuilder.CreateSanitizedId(controlName);
}
Первое выражение нацелено на свойство, которое будет привязано к элементу управления, и у меня нет проблем с получением для него атрибутов id и name. Второй нацелен на свойство, из которого помощник будет каскадировать, но когда я прохожу через метод GetControlName, ExpressionHelper.GetExpressionText (выражение) возвращает пустую строку вместо имени свойства. Я добавил часы на "выражение", чтобы проверить, что пошло не так, и его значение следующее:
{model => Convert(model.TopCategoryId)}
Хотя я получаю следующее значение, когда получаю имя свойства для первого выражения:
{model => model.CategoryId}
Я действительно не понимаю, почему между этими двумя выражениями есть разница. Вот как я вызываю помощника на мой взгляд, если он так или иначе актуален:
@Html.AjaxSelectFor(model => model.CategoryId, model => model.TopCategoryId, "/api/Categories/GetSelectList", true)
Есть идеи, что здесь происходит?
TProperty
вexpression
совпадает сTProperty
в сигнатуре метода (ОК), ноTProperty
вcascadeFrom
- не так, поэтому его нельзя решить. - person   schedule 22.12.2016HtmlHelper
методов, прежде чем пытаться написать свои собственные, и любые методы расширения, которые вы пишете, должны по возможности использовать существующие встроенные методы. - person   schedule 22.12.2016return html.DropDownListFor(...)
с одной из перегрузок accepthtmlAttributes
. Простой пример см. В этом ответе - person   schedule 22.12.2016