Изменения в MVC 2, IModelBinder и ValueProvider - PullRequest
5 голосов
/ 24 февраля 2010

Я пытаюсь перейти на ASP.Net MVC 2 и решить некоторые проблемы. Вот один из них: Мне нужно было напрямую связать словарь как результат просмотра сообщения.

В ASP.Net MVC 1 он отлично работал, используя пользовательский IModelBinder :

/// <summary>
/// Bind Dictionary<int, int>
/// 
/// convention : <elm name="modelName_key" value="value"></elm>
/// </summary>
public class DictionaryModelBinder : IModelBinder
{
    #region IModelBinder Members

    /// <summary>
    /// Mandatory
    /// </summary>
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        IDictionary<int, int> retour = new Dictionary<int, int>();

        // get the values
        var values = bindingContext.ValueProvider;
        // get the model name
        string modelname = bindingContext.ModelName + '_';
        int skip = modelname.Length;

        // loop on the keys
        foreach(string keyStr in values.Keys)
        {
            // if an element has been identified
            if(keyStr.StartsWith(modelname))
            {
                // get that key
                int key;
                if(Int32.TryParse(keyStr.Substring(skip), out key))
                {
                    int value;
                    if(Int32.TryParse(values[keyStr].AttemptedValue, out value))
                        retour.Add(key, value);
                }
            }
        }
        return retour;
    }

    #endregion
}

Он работал в паре с некоторым умным HtmlBuilder, который отображал словарь данных.

Проблема, с которой я сейчас сталкиваюсь, заключается в том, что ValueProvider больше не является словарем <>, это IValueProvider, который позволяет получать только значения, имя которых известно

public interface IValueProvider
{
    bool ContainsPrefix(string prefix);
    ValueProviderResult GetValue(string key);
}

Это действительно не круто, так как я не могу выполнить мой умный анализ ...

Вопрос:

  1. Есть ли другой способ получить все ключи?
  2. Знаете ли вы еще один способ привязать коллекцию элементов HTML к словарю

Спасибо за ваши предложения

О.

Ответы [ 2 ]

2 голосов
/ 18 января 2012

Хотя этот вопрос помечен как «ответ», я думаю, что может быть полезно следующее. У меня была та же проблема, и я взглянул на исходный код System.Web.Mvc.DefaultValueProvider. Он получает свои значения из RouteData, строки запроса или из отправки формы запроса (в этом точном порядке). Чтобы собрать все ключи (это то, что вы просите в своем первом вопросе), я написал следующий вспомогательный метод.

private static IEnumerable<string> GetKeys(ControllerContext context)
{
    List<string> keys = new List<string>();
    HttpRequestBase request = context.HttpContext.Request;
    keys.AddRange(((IDictionary<string,
        object>)context.RouteData.Values).Keys.Cast<string>());
    keys.AddRange(request.QueryString.Keys.Cast<string>());
    keys.AddRange(request.Form.Keys.Cast<string>());
    return keys;
}

Вы можете использовать этот метод для перечисления по ключам:

foreach (string key in GetKeys(controllerContext))
{
    // Do something with the key value.
}
1 голос
/ 26 февраля 2010

Я не думаю, что вы сможете сделать это больше в MVC 2.
Или же вы можете расширить DefaultModelBinder и переопределить один из его виртуальных методов, таких как GetModelProperties, а затем изменить ModelName внутри ModelBindingContext. Другим вариантом будет реализация пользовательского MetadataProvider для вашего типа словаря, вы также можете изменить название модели.

...