ASP.Net MVC 2 - привязка модели и словарь <int, int> - PullRequest
0 голосов
/ 25 мая 2010

В моем интерфейсе у меня есть список текстовых полей, что-то вроде этого: http://screencast.com/t/YjIxNjUyNmU

Количество текстовых полей неизвестно, так как каждое из них связано с шаблоном. На моей странице цель состоит в том, чтобы связать число с некоторыми из этих шаблонов.

Вот пример HTML-кода:

<%  // loop on the templates
    foreach(ITemplate template in templates)
    {
        // get the content from the input dictionary
        int val;
        content.TryGetValue(template.Id, out val);
        // convert it as a string
        string value = ((val > 0) ? val.ToString() : string.Empty);

        // compute the element name/id (for dictionary binding)
        string id = ??????????
        string name = ??????????????
%>
        <label for="<%= name %>"><%= template.Name %></label>
        <input type="text" id="<%= id %>" name="<%= name %>" value="<%= value %>" />
        <br />
<%  }
%>

В моем контроллере я ожидаю получить IDictionary, где первое int - это идентификатор шаблона, а другое - число, указанное пользователем.

Вот что я хочу:

public ActionResult Save(int? id, Dictionary<int, int> countByTemplate)

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

Вопросы:

  • Есть ли хороший ресурс о том, как работает связывание моделей? Я хотел бы получить исчерпывающую информацию, я устал от блогов 84093043, в которых говорится о данном конкретном примере.
  • как мне построить свой HTML, используя для получения IDictionary (или даже IDictionary в действии моего контроллера?

Большое спасибо за вашу помощь

Ответы [ 2 ]

1 голос
/ 26 мая 2010

Хорошо ... Благодаря Леви я смог найти решение.Не более чистый, но он работает.

HTML должен быть написан так:

<%
int counter = 0;
// loop on the templates
foreach(ITemplate template in templates)
{
        // get the value as text
        int val;
        content.TryGetValue(template.Id, out val);
        var value = ((val > 0) ? val.ToString() : string.Empty);

        // compute the element name (for dictionary binding)
        string id = "cbts_{0}".FormatMe(template.Id);
        string dictKey = "cbts[{0}].Key".FormatMe(counter);
        string dictValue = "cbts[{0}].Value".FormatMe(counter++);
%>
        <input type="hidden" name="<%= dictKey %>" value="<%= template.Id %>" />
        <input type="text" id="<%= id %>" name="<%= dictValue %>" value="<%= value %>" />
        <label for="<%= id %>"><%= template.Name %></label>
        <br />
<%  }
%>

Мне пришлось добавить скрытое поле для хранения значения.Я ввел «фальшивый» счетчик, чтобы просто перебрать словарь так, как этого хочет ASP.Net MVC.В результате я получил словарь, заполненный моими значениями и «0», когда текстовое поле пусто.

Появилась еще одна проблема: ModelState считался недействительным, поскольку «требуется значение».Я не хочу, чтобы мои значения требовались, но, глядя на код связывателя модели, я не нашел способа сообщить связующему, что значение НЕ требуется.

Поэтому я обманул ModelState в своемконтроллер, удаляющий все ошибки, например:

public ActionResult Save(int? id, Dictionary<int, int> cbts)
{
    // clear all errors from the modelstate
    foreach(var value in this.ModelState.Values)
        value.Errors.Clear();

Ну ... Я действительно нашел решение, но HTML-код теперь уродлив и контринтуитивен (используя индекс для циклического перемещения по неиндексированномуколлекция ??).И мне нужно обманывать каждый раз, когда я буду использовать этот вид привязки, чтобы все это работало должным образом.

Так что теперь я открою новую запись, чтобы сделать словарь-связыватель чем-то лучше.Вот оно: ASP.Net MVC 2 - улучшенная привязка модели для словаря

РЕДАКТИРОВАТЬ - благодаря Павлу Чучува существует более чистое решение.

В коде контроллера используйте значение nullable int в качестве значения словаря.Немного больше кода, чтобы добавить, но намного чище.

public ActionResult Save(int? id, Dictionary<int, int?> cbts)
{
    // this is our final dictionary<int, int>
    Dictionary<int, int> cbtsFinal = new Dictionary<int, int>();
    // loop on the dicitonary with nullable values
    foreach(var key in cbts.Keys)
    {
        // if we have a value
        if(cbts[key].HasValue)
            // then put it in the final dictionary
            cbtsFinal.Add(key, cbts[key].Value);
    }
1 голос
/ 25 мая 2010

Информацию о том, как записать элементы ввода для привязки к массивам, словарям и другим коллекциям, можно найти по адресу http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx.

...