ASP.NET MVC: Что делать, если ваша модель - это просто словарь?

(Я новичок в MVC).

В моем приложении у меня нет модели в смысле класса со свойствами. О нет, это намного проще: мои пользователи в основном заполняют кучу строковых значений для разных ключей, устанавливаемых в другом месте в системе (ключи произвольны и не известны заранее, поэтому нет предварительно кодированного класса) 1.

Моя "модель", таким образом, справедлива:

Dictionary<string, string>

Довольно просто.

Как я понимаю, привязка модели, html-помощники, состояние модели, сводки валидации все опираются на отражение свойств произвольного класса. Но могут ли они просто использовать ключ/значения в моем словаре?

Например, могу ли я:

<label for="Name">Name:</label>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %>

и

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dictionary<string, string> valuesEntered)
{            
    // ...
}

и MVC использует ключ/значение "Name", найденный в моей модели Dictionary<string, string>, чтобы выполнить все его закулисную магию? (MVC 1.0 предпочтительнее, но прошу пролить немного света, если это лучше рассмотреть в версии 2.0, как мне все еще хотелось бы знать)?


1: звучит глупо, я уверен. Это приложение для отчетов, где "ключи" - это имена параметров отчета, а "значения" - значения, с которыми будет работать отчет.

Ответ 1

Стандартное связующее устройство в MVC 1.0 может привязываться к словарю, если оно использует имя словаря волшебной формы "dictionaryName [index].key" и "dictionaryName [index].value", где dictionaryName - это имя вашего параметр словаря, а индекс - 0 последовательный номер. Обычно значение "ключ" будет скрытым полем, а значением "значение" является ваше текстовое поле. В вашем примере:

<%= Html.Hidden("valuesEntered[0].key", "Name") %>
<%= Html.TextBox("valuesEntered[0].value") %>
<%= Html.ValidationMessage("valuesEntered[0].value", "*") %>

Как я понимаю, привязка к словарям отличается от MVC 2.

Ответ 2

Правда, модель может быть такой же простой, как набор пар имя/значение. Вы можете пойти по этому маршруту, но я бы предложил по крайней мере обернуть ваш Словарь в классе и, по крайней мере, использовать свойства или геттеры, чтобы позволить себе некоторую гибкость в будущем.

И да, вы можете связывать коллекции, но только в сценариях типа list/grid/combobox. Например. Пользовательский интерфейс, предназначенный для хранения коллекций. Вы не можете использовать отражение для произвольного привязки к заданному значению внутри коллекции.

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

Ответ 3

Я бы предложил создать модель для пары имя-значение отчета, а затем использовать метод, описанный в this (см. BeginCollectionItem html helper), чтобы добиться привязки их коллекции.

После этого валидация может быть вставлена ​​в модель пары имен и значений в зависимости от правил для конкретного экземпляра.

Ответ 4

В соответствии с архитектурой ASP.NET MVC вам необходимо выполнить следующие шаги:

  • Создайте собственное связующее (подходящий пример, который я нашел здесь)

    public class DefaultDictionaryBinder : DefaultModelBinder  
    {  
        //...  
    }
    
  • Замените связующее по умолчанию в Application_Start

    ModelBinders.Binders.DefaultBinder = new DefaultDictionaryBinder();
    
  • Создать фильтр действий

    public class DictionaryFilter : ActionFilterAttribute  
    {  
        public override void OnActionExecuting(ActionExecutingContext filterContext)  
        {  
            // Process filterContext.HttpContext.Request.InputStream here  
        }    
        //...  
    }
    
  • Теперь примените фильтр к вашему действию

    [DictionaryFilter]  
    [AcceptVerbs(HttpVerbs.Post)]  
    public ActionResult Create(Dictionary<string, string> valuesEntered)  
    {  
        //...  
    }  
    
  • Наслаждайтесь своей работой: -)

Ответ 5

Создание настраиваемого связующего является хорошим предложением, однако я вижу одну большую проблему с использованием словаря для доставки значений: как модель на основе словаря получает ключи? Согласно вашему комментарию, вы планируете предоставить своим элементам управления те же имена, что и ваши ключи. Итак, если вы уже знаете имена ваших ключей, почему вы не можете создать словарь?

Вы можете добиться того же результата, создав один объект ViewModel, который содержит все параметры, которые будут использоваться для ваших отчетов в качестве свойств. Заполните нужные значения, игнорируйте те, которые у вас нет.

Например:

public class ReportParameterViewModel
{
    public DateTime OrderRangeBegin { get; set; }
    public DateTime OrderRangeEnd { get; set; }
    public string Department { get; set; }
    public int Customer_Number { get; set; }
    public double Commission_Rate { get; set; }
    public int Page_Start { get; set; }
    public int Page_End { get; set; }
    public bool IsExecutiveVersion { get; set; }
    //
    // ...and so on...
    //
}

Убедитесь, что все методы управления вашим контроллером, ответственные за создание отчетов, могут принимать экземпляр ReportParameterViewModel и убедиться, что все ваши представления отчетов наследуются от ReportParameterViewModel. Идея словаря просто звучит как больше работы, чем это необходимо, учитывая тот факт, что представления для ваших отчетов, скорее всего, будут статическими.

Ответ 6

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

Перед отправкой формы используйте jquery.form.js, чтобы объединить данные, отправленные обратно в текстовое представление json для словаря, а затем использовать JavaScriptSerializer для преобразования json strin в словарь. Возможно, есть даже поддержка для этого автоматически.

Для проверки вы также можете переключиться на проверку на стороне клиента, например, с помощью jquery.validate.js и автоматически создать java-скрипт.