2010-02-04 6 views
11

(Soy nuevo en MVC).ASP.NET MVC: ¿Qué pasa si su modelo es solo un diccionario?

En mi aplicación no tengo un modelo en el sentido de una clase con propiedades. Oh no, es mucho más simple: mis usuarios básicamente completan un conjunto de valores de cadena para varias teclas configuradas en otro lugar del sistema (las claves son arbitrarias y no se conocen de antemano, por lo tanto no hay clases precodificadas) .

Mi "modelo" por lo tanto es simplemente:

Dictionary<string, string> 

bastante simple.

Según tengo entendido, el enlace del modelo, los helpers html, el estado del modelo, los resúmenes de validación se basan en la reflexión de una clase arbitraria 'propiedades. Pero, ¿pueden simplemente usar las claves/valores en mi diccionario?

Por ejemplo, puedo tener:

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

y:

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

y tienen MVC usar la "Name" clave/valor que se encuentra en mi "modelo" Dictionary<string, string> para hacer todo su detrás- la magia de las escenas? (MVC 1.0 preferiblemente, pero por favor arroje algo de luz si esto se aborda mejor en 2.0 ya que aún me gustaría saber).


1: sounds silly Estoy seguro. Es para una aplicación de informes, donde las "claves" son los nombres de los parámetros de informe y los "valores" son los valores con los que se ejecutará el informe.

+0

¿Podría darnos más información sobre lo que su aplicación (o esa parte específica) logra? Podría darse una solución alternativa a un "Diccionario", un poco más de detalle ayudaría. – Omar

+0

@Baddie: es una IU dinámica que recopila entradas para un informe SSRS, donde las "claves" son los nombres de los parámetros de informe (nombrados por nuestro desarrollador de informes) y los "valores" son los valores con los que se ejecutará el informe, ingresados ​​por el usuario. Cada informe es diferente, con diferentes nombres de parámetros. – JPot

Respuesta

4

La carpeta de modelo predeterminada en MVC 1.0 puede vincularse a un diccionario siempre que use los identificadores de campo de formulario mágico 'dictionaryName [index] .key' y 'dictionaryName [index] .value', donde dictionaryName es el nombre de su parámetro de diccionario e índice es 0, número secuencial basado en. Normalmente, el valor 'clave' será un campo oculto, y el valor 'valor' es su campo de texto. En su ejemplo:

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

Según tengo entendido, el enlace a los diccionarios es diferente en MVC 2.

+0

He creado algunos métodos de extensión de ayuda HTML para hacer esto para usted: vea https://github.com/ErikSchierboom/aspnetmvcdicationaryserialization –

0

Es cierto que un modelo puede ser tan simple como una colección de pares de nombre/valor. Puedes ir por esa ruta, pero te sugiero que al menos envuelvas tu diccionario en una clase y usas propiedades o getters como mínimo para permitirte algo de flexibilidad en el camino.

Y sí, puede enlazar colecciones, pero solo en escenarios de lista/cuadrícula/cuadro combinado. P.ej. Controles de interfaz de usuario que están diseñados para contener colecciones. Realmente no se puede usar la reflexión para vincular arbitrariamente a un valor dado dentro de una colección.

EDIT: No creo que una etiqueta/cuadro de texto sea la IU correcta para su escenario. Pruebe con una grilla o una lista.

+0

A menos que C# proporcione acceso dinámico, no puedo usar propiedades ya que no sé cómo nombrarlas. Son dinámicos por naturaleza. Esa es una de las claves del problema. – JPot

+0

No creo que una etiqueta/cuadro de texto sea la UI correcta para su escenario. Pruebe con una grilla o una lista. –

+0

@Paul Sasik: entonces, ¿qué hago dentro de cada iteración de pares clave/valor? Represento un cuadro de texto cuyo nombre coincide con mi clave, y cuyo valor MVC puede (con suerte) extraer del diccionario o del modelo de estado, ¿verdad? – JPot

0

Sugeriría crear un modelo para un par nombre-valor de informe y luego usar un método como el delineado en this (ver la discusión del ayudante de BeginCollectionItem html) para lograr enlazar una colección de estos.

La validación se podría insertar en el modelo de pares de nombres y valores según sea necesario, según las reglas para la instancia particular.

+0

Una pregunta que plantea el artículo para mí: puede 'TextBoxFor (x => x [" foo "])' trabajar ? Creo que los helpers 'XxxFor()' solo funcionan con * accessors de propiedad * ... – JPot

+0

Es por eso que sugiero que utilices una colección de un modelo concreto como KeyValuePairModel (es decir, IEnumerable ) que tiene propiedades Key y Value que puedes unir/reflejar –

+1

TextBoxFor (x => x ["foo"]) no funcionará porque MVC no podrá crear id. Significativa para la etiqueta html de entrada producida por el helper TextBoxFor. En su lugar, se lanza la excepción "InvalidOperationException: las plantillas se pueden usar solo con expresiones de acceso de campo y de propiedad". – PanJanek

0

De acuerdo con ASP.arquitectura NET MVC tendrá que seguir los siguientes pasos:

  1. Cree su propia carpeta (un ejemplo adecuado encontré here) enlazador predeterminado

    public class DefaultDictionaryBinder : DefaultModelBinder 
    { 
        //... 
    } 
    
  2. Sustitución entra Application_Start

    ModelBinders.Binders.DefaultBinder = new DefaultDictionaryBinder(); 
    
  3. Crear filtro de acción

    public class DictionaryFilter : ActionFilterAttribute 
    { 
        public override void OnActionExecuting(ActionExecutingContext filterContext) 
        { 
         // Process filterContext.HttpContext.Request.InputStream here 
        }  
        //... 
    } 
    
  4. Ahora aplicar el filtro a su acción

    [DictionaryFilter] 
    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Create(Dictionary<string, string> valuesEntered) 
    { 
        //... 
    } 
    
  5. disfrute de su trabajo :-)

0

Creación de la carpeta de modelo personalizado es una buena sugerencia, sin embargo, veo un gran problema con el uso de un diccionario para suministrar los valores: ¿cómo obtiene el modelo basado en el diccionario las claves? Según su comentario, planea dar a sus controles los mismos nombres que sus claves. Entonces, si ya conoce los nombres de sus claves, ¿por qué tomarse la molestia de crear un diccionario?

Puede lograr el mismo resultado creando un único objeto ViewModel que contenga todos los parámetros que usará para sus informes como propiedades. Complete los valores que necesita, ignore los que no.

Por ejemplo:

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... 
    // 
} 

Asegúrese de que todos sus métodos de acción del controlador responsables de la generación de informes puede aceptar una instancia de ReportParameterViewModel y asegúrese de que todas sus vistas de informes heredan de ReportParameterViewModel. La idea del diccionario simplemente suena como más trabajo de lo necesario, dado el hecho de que las vistas de sus informes probablemente sean estáticas.

+0

Gracias por la respuesta. El ejemplo solo tenía que ser trivial. no * sé las claves, en absoluto. El modelo es más bien como 'IEnumerable ', donde 'ParameterValue' es básicamente' KeyValuePair' y por lo tanto, un diccionario. – JPot

0

Otra alternativa podría ser recorrer el diccionario para generar los campos, usando la tecla como el nombre del campo. En este caso, sin embargo, la etiqueta podría tener que ser extraída de otra ubicación.

Antes de publicar el formulario, utilice jquery.form.js para combinar los datos que se publican de nuevo en una representación de cadena json para un diccionario y luego use el JavaScriptSerializer para convertir el strin json en un diccionario. Tal vez, incluso hay soporte para hacer esto automáticamente.

Para la validación también puede cambiar a la validación del lado del cliente, por ejemplo, usando jquery.validate.js y compilar el java scipt automáticamente.

Cuestiones relacionadas