2010-02-24 11 views
5

Estoy intentando migrar a ASP.Net MVC 2 y resolver algunos problemas. Aquí hay uno: Necesito vincular directamente un Dictionary como resultado de una publicación de vista.MVC 2, IModelBinder & ValueProvider changes

En ASP.Net MVC 1 funcionó a la perfección usando una costumbre 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 
} 

trabajó en par con un poco de HtmlBuilder inteligente que muestra el diccionario de datos.

El problema que me encuentro ahora es que ValueProvider no es un diccionario <> más, es un IValueProvider que sólo permite obtener valores cuyo nombre se conoce

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

Esto no es realmente genial, ya que no puede realizar mi análisis inteligente ...

pregunta:

  1. ¿hay otra manera de conseguir todas las llaves?
  2. ¿Conoce otra manera de enlazar una colección de elementos HTML a un diccionario

Gracias por sus sugerencias

O.

+0

Ver aquí: http://stackoverflow.com/questions/2290473/ivalueprovider-in-mvc-2-rc-2/2290520 # 2290520 – tvanfosson

Respuesta

1

No creo que usted será capaz de hacer de esta manera ya en MVC 2.
Alternativamente, podría extender DefaultModelBinder y reemplazar uno de sus métodos virtuales como GetModelProperties y luego cambiar el ModelName dentro de ModelBindingContext. Otra opción sería implementar un MetadataProvider personalizado para su tipo de Diccionario, también puede cambiar el nombre del modelo allí.

2

Aunque esta pregunta ha sido marcada como "respondida", creo que lo siguiente puede ser útil. Tuve el mismo problema y eché un vistazo al código fuente del System.Web.Mvc.DefaultValueProvider. Obtiene sus valores de RouteData, la cadena de consulta o del envío de un formulario de solicitud (en ese orden exacto). Para recopilar todas las claves (que es lo que pides en tu primera pregunta) escribí el siguiente método de ayuda.

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; 
} 

Puede utilizar este método para enumerar las llaves:

foreach (string key in GetKeys(controllerContext)) 
{ 
    // Do something with the key value. 
} 
+0

Ahora veo que mi enfoque no permite una fácil prueba de unidad de un archivador de modelo personalizado ya que el código GetKeys accede directamente a Request.Form y Request.QueryString. Verificare si puedo mejorar esto. – Jeroen

Cuestiones relacionadas