none
como pasar varios datos de un View a un metodo (ActionResult)

    Question

  • Hola, he avanzado bastante pero todavia no me pasa varios parametros desde la view al controlador (primero le mando datos a la view "index" con el viewdata), luego tengo que enviar esos datos a otra view y siempre llegan "null". este es el codigo del "Index.aspx":

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    	Cuestionario Principal
    </asp:Content>
    
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    
      <h2>Cuestionario</h2>
    <form action="/Cuestionario/Index2" method="post">
    <% using (Html.BeginForm("Index2","Cuestionario"))
        { %>
      <% %>
      <% %>
      <% %>
      <table>
        <tr>
          <th>
            <div><h3>Contrato de trabajo :</h3><div>Cumplimiento del Contrato</div>
          &nbsp;</div> 
          </th>
      
        </tr>
        <tr>
          <td>
     <%--asigno los datos a los variables creadas en la View--%>
     <% string idAuto = ViewData["idAutoevaluacion"].ToString(); %>
     <% string idCorre = ViewData["correlativoAuto"].ToString(); %>
     <% string pregunta = ViewData["criterioCumplimiento"].ToString(); %>
     <% string rutEmpresa = ViewData["RutEmpresa"].ToString(); %>
     <% string contadorPreguntas = "2"; %>
     <div> El rut de la empresa es: <%= Html.Label(rutEmpresa) %> </div>
     <div>El codigo de la autoevaluacion es: <%= Html.Label(idAuto) %> </div>
     <br />
     <br /> <div>El correlativo es: <%= Html.Label(idCorre)%></div>
     <br />
     <div> <%= pregunta %></div>
          </td>
          
        </tr>
     </table>
    
      <%--LAS OPCIONES SON--%>
      <br />
      <br />
      <% if (Convert.ToInt32(ViewData["idAlternativa"]) == 1)
       {%>
      <div><%= Html.RadioButton("respuestaOpcion", "1", true)%>Sí cumple <%= Html.RadioButton("respuestaOpcion", "2", false)%> No cumple <%= Html.RadioButton("respuestaOpcion", "3", false)%> No se ha aplicado <%= Html.RadioButton("respuestaOpcion", "4", false)%> No corresponde </div>
      <%} %>
      <% if (Convert.ToInt32(ViewData["idAlternativa"]) == 2)
       {%>
      <div><%= Html.RadioButton("respuestaOpcion", "1", false)%>Sí cumple <%= Html.RadioButton("respuestaOpcion", "2", true)%> No cumple <%= Html.RadioButton("respuestaOpcion", "3", false)%> No se ha aplicado <%= Html.RadioButton("respuestaOpcion", "4", false)%> No corresponde </div>
      <%} %>
      <% if (Convert.ToInt32(ViewData["idAlternativa"]) == 3)
       {%>
      <div><%= Html.RadioButton("respuestaOpcion", "1", false)%>Sí cumple <%= Html.RadioButton("respuestaOpcion", "2", false)%> No cumple <%= Html.RadioButton("respuestaOpcion", "3", true)%> No se ha aplicado <%= Html.RadioButton("respuestaOpcion", "4", false)%> No corresponde </div>
      <%} %>
      <% if (Convert.ToInt32(ViewData["idAlternativa"]) == 4) %>
      <%{ %>
      <div><%= Html.RadioButton("respuestaOpcion", "1", false)%>Sí cumple <%= Html.RadioButton("respuestaOpcion", "2", false)%> No cumple <%= Html.RadioButton("respuestaOpcion", "3", false)%> No se ha aplicado <%= Html.RadioButton("respuestaOpcion", "4", true)%> No corresponde </div>
      <%} %>
      &nbsp;<p>
      <% AutoEvaluacion.Controllers.CuestionarioController cuestiControl = new AutoEvaluacion.Controllers.CuestionarioController(); %> 
           <%--BOTON SIGUIENTE<% }%>--%>
      <input type="submit" value="Siguiente"/> 
      </p>
      </form>
      <%} %>
    </asp:Content>
    
    

    y este es el metodo que deben llegar los parametros:

        //RECIBE LOS VALORES DE LA VISTA DE RESPUESTA Y INGRESA DATOS(UPDATE)<br/>
        [AcceptVerbs(HttpVerbs.Post)]<br/>
        public ActionResult Index2(string idAuto, string contadorPreguntas, string idCorre, string rutEmpresa)<br/>
        {<br/>
          int idRespuesta = Convert.ToInt32(Request.Form["respuestaOpcion"]);<br/>
          <br/>
          //ACCION QUE RETORNA LOS VALORES INGRESADOS POR EL USUARIO EN LAS RESPUESTAS.<br/>
          try<br/>
          {<br/>
            if (idRespuesta != 0 && rutEmpresa.Equals("0"))<br/>
            {<br/>
              //codigo<br/>
              return View();<br/>
            }<br/>
            if (contadorPreguntas < 34 && contadorPreguntas != 0 && rutEmpresa.Equals("0"))<br/>
            {<br/>
              //codigo <br/>
              return View();
            }
            if (contadorPreguntas == 34 && idRespuesta != 0 && rutEmpresa.Equals("0"))
            {
             //codigo <br/>
            }<br/>
            else<br/>
            {<br/>
             //codigo<br/>
              return View("Error");
            }
          }
          catch (Exception ex)
          {
            //ERROR EN EL INGRESO DE RESPUESTA
            return View(ex.Message);
          }
        }
    

    Como se podria lograr pasar los datos?.

    saludos y gracias.

     

    Wednesday, March 16, 2011 9:02 PM

Answers

  • Un par de cosillas...

    1. Que hace el BeginForm que usas? Para que quieres poner un formulario? Donde vas a hacer submit? Además estás mezclando tags <script> dentro de un <form> y eso no es muy bonito que digamos :)
    2. Lo que me lleva a pensar que... no tendrás decorada la acción Reporte del controlador Home con [HttpPost] verdad? El método load() de jQuery utiliza GET para realizar la petición y no POST...

    También decirte que si quieres ejecutar scripts de jQuery cuando se carga la página, es mejor usar siempre document.ready. Por ejemplo para lanzar la carga jQuery y asignar el evento click, hazlo todo en un solo tag <script>:

     <script type="text/javascript">
     $(document).ready(function() {
      $("#modal").load("<%=Url.Action("Reporte","Home", new {id = rutEmpresa})%>");
      $('#reporte').click(function (){
        $("#modal").modal();
     });
     });
    </script><br/>
    

    A document.ready se le pasa una función que es el código a ejecutar cuando la página esté cargada. Document.ready es como el <body onload=""> de antes, pero a lo jQuery. ;-)

    Incluso, otra solución "más segura" es sólo habilitar el click del link #reporte, cuando se haya cargado el contenido via ajax. Por ello puedes pasar un segundo parámetro a load() que es el método a ejecutar cuando la carga esté completa:

     <script type="text/javascript">
     $(document).ready(function() {
      $("#modal").load("<%=Url.Action("Reporte","Home", new {id = rutEmpresa})%>", function() { 
          $('#reporte').click(function (){
            $("#modal").modal();
          });
       });
     });
    </script>
    

    Ya me dirás si con esos cambios (eliminar el <form> y ponerlo todo en un solo tag <script> te funciona.

    PD: He escrito el código de memoria, así que igual hay algún gazapo... :P


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Monday, March 28, 2011 7:09 PM
  • Muy buenas!

    Quieres que al pulsar en un link se envien datos via POST? Por defecto no se puede, los links siempre van via GET. Si quieres hacerlo debes usar javascript ;-)

    Entiendo que los datos que envías via POST provienen de un formulario, no? Si el <form> tiene el id="myform", para enviar via POST el formulario puedes usar:

    $(document).ready(function() {
      $("#mylink").click(function() {
        $("#myform).attr("action", "<%= Url.Action(...) %>");
        $("#myform").submit();
      });
    });
    

    En el click del enlace "mylink" modificamos el atributo action del <form> "myform" para que apunte a la Url que queremos, y luego enviamos (submit) el form. Por supuesto, el <form> debe tener el atributo method="post".

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Friday, April 01, 2011 1:18 PM

All replies

  • Buenas!

    ViewData sirve para pasar datos desde el controlador a la vista, pero no al revés. Para pasar datos de la vista al controlador hay básicamente tres posibilidades:

    1. RouteData (es decir usar urls tipo /{controller}/{action}/{id} -> En este caso {id} es el route data
    2. Querystring (es decir usar urls tipo /{controller}/{action}?param1=value&param2=value -> En este caso param1 y param2 son los parámetros de querystring
    3. Post Data (es decir usar urls tipo /{controller}/{action} y enviar (submit) un formulario

    Las 3 opciones pueden combinarse entre ellas, no son excluyentes.

    Tu estás enviando un formulario, para pasar datos de la vista al controlador se aplica una norma muy sencilla:

    • El valor del atributo name del control html del <form> debe corresponderse con el nombre del parámetro en la acción.

    P.ej. si tengo el siguiente formulario:

    <form action="/Cuestionario/Index2" method="post">
      <input type="text" name="idAuto" /> <br />
      <input type="text" name="contadorPreguntas" /> <br />
    </form>
    
    

    Entonces la acción la puedo definir como:

    public ActionResult Index2 (string idAuto, string contadorPreguntas) {
      // Código
    }
    

    En tu caso las llamadas a Html.RadioButton que haces usan los atributos name respuestaOpcion1, respuestaOpcion2, respuestaOpcion3 y respuestaOpcion4. Por lo que esos deben ser los parámetros que recibe el controlador.

    Dicho esto un par de cosillas...

    1. Nunca usas URLS hard-coded. En lugar de action="/Cuestionario/Index2 usa action="<%= Url.Action("Index2","Cuestionario") %>" y deja que el motor de asp.net mvc construya la url por tí. La razón es que si usas URLs hard-coded te saltas a la torera la tabla de rutas.
    2.  No entiendo la línea <% AutoEvaluacion.Controllers.CuestionarioController cuestiControl = new AutoEvaluacion.Controllers.CuestionarioController(); %>. No tiene ningún sentido, que estás intentando hacer?

    Saludos! ;-)


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Thursday, March 17, 2011 7:19 AM
  • Perfecto, gracias...ya pude hacer para pasar los parametros perfectamente.

    Ahora tengo otra duda, como podria dejar un boton INPUT ("atras") invisible en el 1 y ultimo contador para retroceder en las preguntas..lo hice asi en la view:

    <%--BOTON SIGUIENTE<% }%>--%>
      <input type="submit" value="Siguiente"/> 
      <%-- BOTON ATRAS--%>
       <% bool VisibleAtras;%>
      <% if ((Convert.ToInt32(contadorPreguntas) > 1) && (Convert.ToInt32(contadorPreguntas) < 34))
       { %>
        <% VisibleAtras = true;%>
      <% } %>
      <% else %>
      <%{ %>
      <% VisibleAtras = false;%>
      <%} %>
      <input type="submit" value="Atras" visible="<%=VisibleAtras%>" style="width: 82px" />
      <%} %>
      </p>
      </form>
    
    pero no funciona pues muestra siempre el boton.

     

    Saludos.

    Thursday, March 17, 2011 3:33 PM
  • Buenas,

    El atributo "visible" no existe en HTML ;-)

    Cambia la definición del input por:

    <input type="submit" value="Atras" style="width: 82px; visibility: <%= VisibleAtras ? "visible" : "hidden" %>;" />
    

    Es decir, usar el estilo "visibility" con el valor visible o hidden según quieras mostrar o no el botón.

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Thursday, March 17, 2011 4:18 PM
  • Muchas gracias...lo pude hacer perfectamente.

    ya me salvaste dos veces!...

    otra duda si me podrias ayudar, tengo que en una tabla, enla primera fila son campos que traigo de la base de datosy quiero que sea una link a una accion de otro control(estoy en categorias.aspx de home y quiero ir a index de cuestionario) y lo pongo asi:

    <td class="categoria" ><a href="<%= Url.Action("Index","Cuestionario")%>" ><strong><%=cate1%></strong></a></td>
    
    pero me manda un error, se podria hacer de otra forma? ..la accion index del control "cuestionario" es un ActionResult que realiza accion según el parametro que se enviá y retorna otras vistas.

     

    Saludos y gracias!

     

     

     

    Wednesday, March 23, 2011 1:33 AM
  • Buenas!

    No dices que error te manda, pero lo que veo es que no le estás mandando el parámetro a la acción Index del controlador cuestionario. Si la acción Index tiene el parámetro id, prueba de pasárselo usando:

    Url.Action("Index","Cuestionario", new {id=idcate1})
    

    Por supuesto, idcate1 sería la variable que tiene el id de la categoria.

    Un saludo!

     


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Wednesday, March 23, 2011 7:12 AM
  • gracias...de nuevo.

    Ya lo pude hacer...me funciono bien.

    alguna idea de como crear un popup?, necesito que se abra una ventana de ayuda.

    he buscado por internet y salen soluciones como:

    <%= Html.ActionLink("Click me", "ActionName", null, new {target="_blank"}) %>

    necesito pasarle un parametro a esa ventana(que seria un ascx o una view fuera de la master) o controlador(que retorne una view), que apunte a una accion del controlador para que pueda realizar consultas sql para obtener la ayuda segun el tema tratado(para eso es el parametro//id_tema).

     

    saludos y gracias.


    Wednesday, March 23, 2011 3:14 PM
  • Buenas!

    Es lo mismo que en la respuesta anterior. Abres un popup (target="_blank") pero ese popup va hacia una acción de un controlador. Usa el tercer parámetro (el que tu pones a null en tu ejemplo) para pasarle valores en el controlador:

    <%= Html.ActionLink("Click me", "ActionName", new {idtema="xxx"}, new {target="_blank"}) %>
    
    

    Y en tu controlador:

    public ActionResult ActionName(string idtema)
    {
       // ....
       return View(...);
    }
    

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Wednesday, March 23, 2011 4:34 PM
  • buena..gracias..

    no se puede ocupar datagridview en mvc no?.. pero se le puede pasar un datatable a una vista?

    y como accedo a el desde la vista desde el controlador?..pues tengo una consulta que deberia llenar un datagrid, pero como no puede ocuparlos en mvc podria pasar el datatable y hacer un foreach por cada fila(row) del resultado de la consulta?. lo puedo hcer con los viewdata, pero la consulta puede traer segun sea el caso 5 o mas filas.

    los resultados del datable son de diferentes tablas.

    saludos.
    Wednesday, March 23, 2011 8:24 PM
  • Buenas!

     >no se puede ocupar datagridview en mvc no?

    No, no se puede. El DataGridView es un WebControl y, por norma general, los WebControls no están aceptados en MVC.

    >se le puede pasar un datatable a una vista?

    Sí. No hay problema, del mismo modo que le pasas cualquier otra clase:

    En el controlador:

    public ActionResult Foo()
    {
      DataTable dt = ...
      return View(dt);
    }
    

    Y en la vista Foo.aspx, declaras que su tipo de modelo es DataTable:

    <%@ Page Language="C#" Inherits="System.Data.DataTable" %>
    

    Y cuando quieras acceder al DataTable desde la vista, pues usas Model:

    <% foreach (DataRow in Model.Rows) { %>
      <!-- Hacer algo -->
    <% } %>
    

    Y listos.

    Que los datos del DataTable sean de una misma tabla o varias da igual, porque tu lo que tienes es un solo DataTable. De todas formas date cuenta que igual que le pasas un DataTable le podrías pasar un DataSet (simplemente debes modificar el valor de Inherits).

    Luego, ya, existen mecanismos "más avanzados" como usar algún plugin de jQuery para las grids o bien algún helper que te genere tablas (MVC3 viene con un helper llamado WebGrid), o usar algun componente (usualmente helper) de terceros. P.ej. sin ánimos de hacer propaganda Telerik tiene una grid para MVC: http://www.telerik.com/products/aspnet-mvc/grid.aspx (no la he probado).

    Saludos


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Thursday, March 24, 2011 7:30 AM
  • Me salvaste de nuevo. gracias.

     

    Ahora (si puedo abusar de tu ayuda una vez mas)...necesito hacer que se depliege una ventana modal con la ayuda de la pagina, esta ayuda la traigo de la BD mediante dos PA que guardo en sus DT respectivos.

    como podría realizarlo?..podria crear las tablas de la misma forma que hago en las vistas pero la idea  no es esa, sino que parezca una ventana en la misma  pagina.

    otra duda que tengo es...puedo pasar un DT a una vista y ademas datos en view data?

    por ejemplo asi..

     

     datatable dtvista = new datatable();
    dtvista = this.metodoObtenerDatos(idCat);
    viewdata["dato1"]=dato1; viewdata["dato2"]=dato2;
    return view("final",dtVista);
    

     

    saludos y gracias.



    Monday, March 28, 2011 2:22 AM
  • Buenas!

    A ver, por turnos ;-)

    1. Es posible pasar datos en la viewdata y a la vista a la vez. Lo que haces en tu ejemplo te funcionará perfectamente. Desde la vista usando Model accederás al DataTable y usando ViewData["dato1"] accederás al dato1, ni hay problema. Aunque, si siempre van a ir juntos un DataTable y los dos datos del viewdata para esta vista, igual puedes crearte una clase que contenga el DataTable, dato1 y dato2.
    2. Para crear una "ventana modal", debe usarse javascript, no es algo que esté soportado directamente en todos los navegadores. Yo te recomiendo usar jQuery y el plugin de jQuery llamado SimpleModal (http://www.ericmmartin.com/projects/simplemodal/). SimpleModal es una pequeña maravilla que te permite crear fácilmente una ventana "modal".

    Una forma rápida de crear la ventana modal con SimpleModal, seria: Primero definir un <div> vació que será el que contendrá la "ventana modal". Donde lo pongas en el HTML da igual, SimpleModal ya modificará su posición:

    <div id="modal" style="display:none"></div>
    

    Luego haces una llamada via Ajax (usando jQuery) para cargar los contenidos de una acción en el div:

    $("#modal").load("<%=Url.Action("Accion","Controlador")%>");
    

    Este código javascript carga el HTML especificado dentro del div cuyo id sea "modal". Por supuesto, la acción debe volver una PartialView con el contenido.

    Finalmente llamas al plugin de SimpleModal para transformar el div en una ventana modal:

    $("#modal").modal();

    Para que esto te funcione debes tener los scripts de jQuery y de SimpleModal referenciados en los tag <script> de tu página.

    Echale un vistazo a este plugin y todas sus opciones, porque realmente la vale la pena!

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Monday, March 28, 2011 6:15 AM
  • y como lo linkeo a un vinculo?

     lo estoy haciendo asi:

     

    //tengo referncia estos dos script en la pagina aspx
     <script src="../../Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script type="text/javascript" src="../../Scripts/jquery.simplemodal-1.4.1.js"></script>

     
    //abro un html form donde indico el controlador donde ira a buscar los datos("home") y la accion("reporte")
    <%using (Html.BeginForm("Reporte", "Home")) { %> //paso el parametro de la view data a una variable, para que se envie mediante la ventana modal

    <%
    int rutEmpresa = Convert.ToInt32(ViewData["rutEmpresa"]); %>
    //link para que el usuario pueda ver el reporte(si hace click en el )
    <a href="#modal" id="reporte">ver reporte</a> //aqui estoy cargando el contenido de la accion en el div?..es asi?..entonces en el div no tengo que poner nada,
      //solo en la accion "Reporte" retorno una partialview con el contenido y lo mostrara dentro del div, es asi?..
    //asi le paso el parametro a la accion.

    <script type="text/javascript"> $("#modal").load("<%=Url.Action("Reporte","Home", new {id = rutEmpresa})%>"); </script> //este el el div
    <
    div id="modal" style="display:none"></div> //aqui se supone que se carga cuando hace click en el vinculo, demas esta decir que no me funca. 
    <
    script type="text/javascript"> $('#reporte').click(function (){ $("#modal").modal(); }); </script>
    <%} %>
    saludos y gracias.

     




    Monday, March 28, 2011 4:27 PM
  • Un par de cosillas...

    1. Que hace el BeginForm que usas? Para que quieres poner un formulario? Donde vas a hacer submit? Además estás mezclando tags <script> dentro de un <form> y eso no es muy bonito que digamos :)
    2. Lo que me lleva a pensar que... no tendrás decorada la acción Reporte del controlador Home con [HttpPost] verdad? El método load() de jQuery utiliza GET para realizar la petición y no POST...

    También decirte que si quieres ejecutar scripts de jQuery cuando se carga la página, es mejor usar siempre document.ready. Por ejemplo para lanzar la carga jQuery y asignar el evento click, hazlo todo en un solo tag <script>:

     <script type="text/javascript">
     $(document).ready(function() {
      $("#modal").load("<%=Url.Action("Reporte","Home", new {id = rutEmpresa})%>");
      $('#reporte').click(function (){
        $("#modal").modal();
     });
     });
    </script><br/>
    

    A document.ready se le pasa una función que es el código a ejecutar cuando la página esté cargada. Document.ready es como el <body onload=""> de antes, pero a lo jQuery. ;-)

    Incluso, otra solución "más segura" es sólo habilitar el click del link #reporte, cuando se haya cargado el contenido via ajax. Por ello puedes pasar un segundo parámetro a load() que es el método a ejecutar cuando la carga esté completa:

     <script type="text/javascript">
     $(document).ready(function() {
      $("#modal").load("<%=Url.Action("Reporte","Home", new {id = rutEmpresa})%>", function() { 
          $('#reporte').click(function (){
            $("#modal").modal();
          });
       });
     });
    </script>
    

    Ya me dirás si con esos cambios (eliminar el <form> y ponerlo todo en un solo tag <script> te funciona.

    PD: He escrito el código de memoria, así que igual hay algún gazapo... :P


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Monday, March 28, 2011 7:09 PM
  • Gracias de nuevo.

    tengo otra duda:).

    tengo en una pagina que se pueden elegir 2 opciones de caminos distintos, entonces son como 2 columnas con una imagen cada una y texto debajo, justo abajo de la imagen tengo un link que dice "entrar"..ahora envio los datos en forma post por eso la imagen es un vinculo input de tipo imagen, alli perfeto, pero no se como hacer el link para que me made a la accion mediante post(el link tiene que tener el estilo predefinicdo en el css).

    pongo el codigo:

    //imagen con vinculo
    <input type="image" src="../img/pic02.jpg" style="width:300 ;height:200" class="img" name="opcionTema" value="salud" />
    
    <input type="hidden" name="opcionTemaHiden" value="salud" visible="false" />
    //aqui deberia venir el link a "entrar", con url action no me funciona.
    <span class="lnk1"><a href="<%=Url.Action()%>">Entrar</a></span>
    
    
    

    accion inicio2, controlador home

     

    saludos y gracias de nuevo.

    Friday, April 01, 2011 1:06 PM
  • Muy buenas!

    Quieres que al pulsar en un link se envien datos via POST? Por defecto no se puede, los links siempre van via GET. Si quieres hacerlo debes usar javascript ;-)

    Entiendo que los datos que envías via POST provienen de un formulario, no? Si el <form> tiene el id="myform", para enviar via POST el formulario puedes usar:

    $(document).ready(function() {
      $("#mylink").click(function() {
        $("#myform).attr("action", "<%= Url.Action(...) %>");
        $("#myform").submit();
      });
    });
    

    En el click del enlace "mylink" modificamos el atributo action del <form> "myform" para que apunte a la Url que queremos, y luego enviamos (submit) el form. Por supuesto, el <form> debe tener el atributo method="post".

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    Friday, April 01, 2011 1:18 PM