2012-01-27 22 views
7

Tengo un proceso de configuración de varios pasos en el que me gustaría pasar los argumentos de cadena de consulta anexados a la URL solo si son relevantes.MVC3 Html.BeginForm - pasar argumentos como RouteValueDictionary falla

http://localhost:6618/Account/Profile?wizard=true&cats=dogs

@using(Html.BeginForm())

funcionaba muy bien. Dio como resultado: <form action="/Account/Profile?setup=true&amp;cats=dogs" method="post"> es decir, pasó a la acción POST cualquiera de los parámetros de la cadena de consulta original, y luego en esa acción del Controlador pude elegir cuáles eran relevantes para pasar a mi próximo paso, o necesario agregar, añadiendo a los Valores de Ruta y un RedirectToResult.

Sin embargo, tengo que asignar una clase a mi formulario para fines de diseño.

I intentado:

@using(Html.BeginForm("Profile", "Account", args, FormMethod.Post, new { @class = "mainForm" }))

que produce:

<form action="/Account/Profile?Count=1&amp;Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&amp;Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D" class="mainForm" method="post">

(args fue generado por un filtro, y es un RouteValueDictionary). La especificación http://msdn.microsoft.com/en-us/library/dd505151.aspx indica que puede pasar argumentos con System.Web.Routing.RouteValueDictionary.

Lo que yo quiero es <form action="/Account/Profile?setup=true&amp;cats=dogs" class="mainForm" method="post">

debería mencionar que preferiría no hacer algo como pasa en new {key = value} lugar, ya que hay una buena cantidad de lógica para determinar lo que voy a pasar a lo largo con el siguiente paso.

¿Alguna sugerencia sobre qué hacer aquí?

Estoy obstruido por esta tarea aparentemente simple, y seguramente me falta algo terriblemente obvio.

+0

Tal vez la respuesta en esta otra publicación podría ayudar un poco? http://stackoverflow.com/questions/1219223/asp-net-mvc-getting-html-beginform-to-remember-querystring-params-when-submi – summea

Respuesta

10

args fue generada por un filtro, y es un RouteValueDictionary

Ese es el punto clave aquí. En este caso, asegúrese de que está utilizando el correct overload del método BeginForm:

@using(Html.BeginForm(
    "Profile", 
    "Account", 
    args, 
    FormMethod.Post, 
    new RouteValueDictionary(new { @class = "mainForm" }) 
)) 
{ 
    ... 
} 

Aviso el último argumento? Debe ser un IDictionary<string, object> para que esto funcione.

En su ejemplo, es this overload que se recoge. Pero dado que está pasando un RouteValueDictionary para el parámetro routeValues ​​en lugar de un objeto anónimo, se arruina.

Por lo tanto, debe tener tanto routeValues ​​como htmlAttributes como diccionarios o ambos como objetos anónimos.

+0

@Darin Dimitrov Puedes consultar mi pregunta, existen algunas similitudes: http://stackoverflow.com/questions/12142356/send-an-object-as-a-parameter-to-post-action-in-asp-net -mvc3 – Saeid

+0

Tu solución funcionó para mi situación, pero no entiendo por qué @ se usa antes de la variable de clase. ¿Alguien puede explicar lo que está pasando aquí? Gracias. – northben

+0

@northben, se usa porque 'clase' es una palabra clave reservada en C#. Puede leer más sobre esto en la especificación C#: http://msdn.microsoft.com/en-us/library/aa664670.aspx –

0

Solo un pensamiento, pero, incluso para una forma de varios pasos, ¿no le gustaría elegir hacer que todo GET o POST? En el ejemplo de arriba ... parece que estás usando POST con el formulario ... pero aún tratando de usar GET en el camino.

¿Por qué no utilizar valores ocultos de POST (utilizando entradas HTML,) en el camino?

De lo contrario, los usuarios podrían cambiar los valores más fácilmente, ¿no? (Aunque, eso no podría ser importante en esta solicitud Y esto es más que nada para la reflexión..)

0

Así que usted está usando esta sobrecarga:

http://msdn.microsoft.com/en-us/library/dd460542.aspx

¿Es posible hacer un args simples objeto con claves y valores? Creo que eso podría resolver tu problema.

Según docs:

Los parámetros se recuperan a través de la reflexión mediante el examen de las propiedades del objeto. Este objeto normalmente se crea utilizando la sintaxis del inicializador de objetos. - esto parece ser lo que está sucediendo-- está usando reflexiones para obtener las propiedades del diccionario de ruta - las propiedades son claves (colección de cadenas) y valores (colección de objetos)

Otra opción sería no utilizar el html helper y crea la etiqueta de forma de forma manual, aunque eso de alguna manera frustraría el propósito de tener los helpers html.

+0

Debería haber mencionado antes en mi publicación - se necesita un poco de lógica para determinar qué exactamente quiero mantener/desinfectar/agregar a los argumentos. ¿Tal vez debería buscar un HtmlHelper personalizado? – Erica

+0

No estoy seguro de qué es lo que un HtmlHelper personalizado le compra aquí. La lógica tiene que ir a algún lado. –

4

A continuación funcionará.

@using (Html.BeginForm("Profile", "Account", new { id=122}, FormMethod.Post, new { @class = "mainForm" })) 

el valor ruta es creado por objeto inicializar sintaxis es decir nueva {key = value}

+0

Debería haber mencionado que preferiría no usar la sintaxis de inicialización del objeto directamente, es decir, {key = value} nuevo, ya que requiere un poco de lógica en mi código para determinar qué me gustaría pasar. – Erica

Cuestiones relacionadas