2012-07-02 2 views
1

У меня довольно сложная модель для одной из моих страниц; он состоит из нескольких вложенных объектов модели. В одной секции, которая использует дочерний объект с коллекцией детской, я использую EditorFor помощника, как так:MVC3: предоставление помощнику информации о местоположении объекта модели на графике

@Html.EditorFor(m => m.CAS.LERoles[i].LE, "TinyText") 

, я в конечном итоге что-то вроде:

<input id="CAS_LERoles_0__LE" class="tinyText" type="text" value="0" name="CAS.LERoles[0].LE" data-val-required="The Legal Entity field is required." data-val-number="The field Legal Entity must be a number." data-val="true"> 

... это здорово , Тем не менее, я написал свой собственный помощник для преобразования перечислений для выбора списков, например, так:

public static HtmlString EnumSelectListFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> forExpression, 
    object htmlAttributes, 
    bool blankFirstLine) 
    where TModel : class 
    where TProperty : struct 
{ 
    //MS, it its infinite wisdom, does not allow enums as a generic constraint, so we have to check here. 
    if (!typeof(TProperty).IsEnum) throw new ArgumentException("This helper method requires the specified model property to be an enum type."); 

    //initialize values 
    var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData); 
    var propertyName = metaData.PropertyName; 
    var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty(); 

    //build the select tag 
    var returnText = string.Format("<select id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName)); 
    if (htmlAttributes != null) 
    { 
     foreach (var kvp in htmlAttributes.GetType().GetProperties() 
      .ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null))) 
     { 
      returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key), 
       HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty())); 
     } 
    } 
    returnText += ">\n"; 

    if (blankFirstLine) 
    { 
     returnText += "<option value=\"\"></option>"; 
    } 

    //build the options tags 
    foreach (var enumName in Enum.GetNames(typeof(TProperty))) 
    { 
     var idValue = ((int)Enum.Parse(typeof(TProperty), enumName, true)).ToString(); 
     var displayValue = enumName; 

     // get the corresponding enum field using reflection 
     var field = typeof(TProperty).GetField(enumName); 
     var display = ((DisplayAttribute[])field.GetCustomAttributes(typeof(DisplayAttribute), false)).FirstOrDefault(); 
     var titleValue = string.Empty; 
     if (display != null) 
     { 
      // The enum field is decorated with the DisplayAttribute => 
      // use its value 
      displayValue = display.Name; 
      titleValue = display.Description.ToStringOrEmpty(); 
     } 

     returnText += string.Format("\t<option value=\"{0}\" title=\"{1}\"", 
      HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue)); 
     if (enumName == propertyValue) 
     { 
      returnText += " selected=\"selected\""; 
     } 
     returnText += string.Format(">{0}</option>\n", HttpUtility.HtmlEncode(displayValue)); 
    } 

    //close the select tag 
    returnText += "</select>\n"; 
    return new HtmlString(returnText); 
} 

и когда я использую это в моей странице так:

@Html.EnumSelectListFor(m => m.CAS.LERoles[i].APMasterRole) 

Я заканчиваю с этим:

<select name="APMasterRole" id="APMasterRole"> 
(stuff) 
</select> 

В ретроспективе, я полагаю, я предположил, что это будет переведено надлежащим образом, и теперь я понимаю, что был немного наивен. Я действительно надеюсь, что в структуру MVC встроен механизм, который я могу использовать для генерации правильного имени и id; иначе это выглядит как лабиринт отражения.

Итак, вопрос в том, существует ли механизм для создания имен и строк идентификаторов для сложного объекта модели, подобного этому? Если да, то как он будет использоваться? Если нет, существует ли относительно простой способ сгенерировать имя и идентификатор, чтобы данные формы могли быть привязаны к объектной модели?

Спасибо!

ответ

3

Я действительно надеюсь, что есть механизм, встроенный в структуру MVC , которую я могу использовать для генерации правильного имени и идентификатора; в противном случае это выглядит как лабиринт отражения.

Конечно, есть такой механизм. Как вы думаете, как это делают встроенные помощники? Вы когда-нибудь читали исходный код структуры ASP.NET MVC? Или использовать рефлектор или что-то еще?

string name = ExpressionHelper.GetExpressionText(forExpression); 
var ti = htmlHelper.ViewContext.ViewData.TemplateInfo; 
string fullHtmlFieldName = ti.GetFullHtmlFieldName(name); 
string id = ti.GetFullHtmlFieldId(fullHtmlFieldName); 
// Now go ahead and use fullHtmlFieldName and id 

var returnText = string.Format(
    "<select id=\"{0}\" name=\"{1}\"", 
    id, 
    fullHtmlFieldName 
); 

Ах и, прежде чем я забуду: Пожалуйста, используйте TagBuilder для создания DOM-элементов, таких как <select> вместо этого ужасных строк сцеплений, которые не кодируют должным образом ничего. Не говоря уже об операторе += о строках внутри цикла. Строки неизменяемы, и это стоит вам выделения памяти! По крайней мере, используйте StringBuilder.

+0

... Я думаю, что вы просто шутите о чтении исходного кода MVC Framework ... Надеюсь, вы. «TagBuilder» - это то, что я буду исследовать, хотя в моей защите все, что нужно закодировать, кодируется. Учитывая практические ограничения размера на поле выбора, я не думаю, что операции '+ =' обязательно являются большой проблемой, но да, это может быть лучше. –

+4

Нет, конечно, я не шучу о чтении исходного кода. Я даже не представляю, как люди могут разрабатывать продвинутые приложения с некоторыми рамками, не зная, как эта структура строится и работает. Я согласен с тем, что вы кодируете все, но почему вы должны делать это вручную? Зачем изобретать колеса, когда есть уже существующие механизмы, встроенные в рамки, которые помогают вам в этом аспекте? –

+0

Честно говоря, я не знал, что есть такие механизмы, которые являются причиной этого вопроса. Я всегда ищу способы улучшить свой код, но чтение исходного кода фреймворка ... кажется немного сложным. –

Смежные вопросы