none
MV5 CRUD EN EL MISMO CONTROLADOR Y VISTA RRS feed

  • Pregunta

  • Estimados, estoy continuando con un proyecto simple de MVC5, sé que mi consulta puede resultar sencilla, pero estoy iniciandome en MVC.

    El proyecto es básicamente este ejemplo:

    En la lista de la izquierda se muestran los trabajadores, en la derecha los servicios de cada trabajador, al seleccionar el trabajador se debe listar todos los servicios asignados a él. hasta ahora no tengo problemas con este listado, me funciona bien, pero ahora debo continuar con el create, uptdate y delete de los servicios de cada trabajador.

    Estoy usando razor, por ello pensé que debo hacer un @using (Html.BeginForm())
    {....   Sin embargo, no logro hacer esto. Me urge conocer y entender la forma para poder realizar estas actividades en cada boton al lado de los servicios, pero no termino de entender el funcionamiento de mvc.

    Adicionalmente, necesito que todas las acciones se ejecuten en la misma vista, por ello el insert, update y delete, deben aparecer a modo de popup. He logrado hacer los popups con bootstraps, pero no comprendo que contenido debo colocarle para saber que estoy trabajando con el servicio 1, 2 o n.

    Agradezco su apoyo.


    • Editado ArtechSoft martes, 6 de enero de 2015 16:02
    martes, 6 de enero de 2015 16:01

Todas las respuestas

  • No es necesario usar el mismo controlador para usar la misma vista si trabaja con popups.  Con llamadas Ajax usted puede cargar otras vistas (parciales) dentro del DIV del popup que apuntan a otros controladores.

    Yo tendría un controlador de servicios con actions que devuelven partial views para editar o crear servicios.  Luego un action para borrar un servicio que devuelve un JSON que dice si el resultado fue exitoso o no, y finalmente y si fuera necesario, un action que devuelve un view o partial view para mostrar los detalles de un servicio.

    Ejemplo:

    Controlador:  ServicesController.

    Acciones:

    • ActionResult Edit(int id), que sirve para nuevos servicios también. Verbo GET.  Pasar id = 0 para nuevo.
    • ActionResult Delete(int id).  Verbo DELETE o POST.
    • ActionResult Get(int id).  Verbo GET.

    Edit y Get devolverían partial views, o sea, HTML que se inserta en un DIV.  La llamada se hace a través de AJAX.  El formulario devuelto por Edit() apuntaría a un URL de un action que devuelve un JSON indicando si la grabación fue exitosa o no, y cuál es el ID del registro que recién se guardó.  Tal vez lo necesite para hacer algo más, como la asignación del servicio a un trabajador después de cerrar el popup.

    Para el Delete no se ocuparía un popup, excepto tal vez para preguntarle al usuario si está seguro.  Si lo está, se hace una llamada AJAX al URL de Delete con el ID a borrar y se recibe un JSON indicando si el resultado fue exitoso o no.

    Creo que eso sería lo más directo y fácil de mantener, porque si bien el usuario verá todo en la misma página, en realidad son controladores distintos y views distintos.


    Jose R. MCP
    Code Samples

    martes, 6 de enero de 2015 17:36
  • Estimado, y cual sería el código del lado de la vista?

    De momento muestro los datos enviados por el ViewBag en la vista, los recorro con forearch y voy cargando los servicios del trabajador.

    martes, 6 de enero de 2015 17:42
  • Pues no tengo el tiempo para hacerle un ejemplo funcional.  Lo que va en las vistas es lo que se necesita para cada trabajo.

    Por ejemplo en el partial view de Services/Edit use un @Html.BeginForm(), puede ser sin argumentos para que haga un POST de vuelta al mismo controlador y acción, y agregue elementos UI de edición como casillas de texto para que el usuario pueda digitar información.  Si el id es distinto de cero, llene los controles con los valores actuales del servicio con el ID especificado.  Si el id era cero, envíe valores por defecto o en blanco.

    En el lado del controlador escriba un método [HttpPost] ActionResult Edit(ClaseServicio servicio) o alguna otra variante según las posibilidades de MVC que devuelve un JSON.  Algo así:

    [HttpPost]
    public ActionResult Edit(ClaseSesion sesion)
    {
        dynamic result = null;
        try
        {
            //Grabar los datos del objeto sesion aquí.
            ...
            //Ahora señalizar el éxito de la operación.
            result = new { Result = 0, ID = sesion.ID }; //Result = 0 significa éxito.
        }
        catch (System.Exception ex)
        {
            result = new { Result = 1, ErrorMessage = ex.Message }; //Result = 1 significa error.
        }
        return Json(result);
    }

    Aquí lo único que hay que hacer es reemplazar el simple HTTP POST del formulario de eidición por una llamada Ajax que verifique que el JSON devuelto tiene la propiedad Result en cero.  Si es 1, algo malo pasó y hay un mensaje de error en el JSON en la propiedad ErrorMessage.

    Cambiar el comportamiento del <form> para que no haga el submit y en vez haga un Ajax es fácil usando jQuery.


    Jose R. MCP
    Code Samples

    martes, 6 de enero de 2015 17:53
  • hola

    podrias hacer que cada popup defina su propio Html.BeginForm() de esta forma serializas el form y lo envias por medio de $.ajax a un action en el controlador

    ASP.NET  MVC 3: Using jQuery .ajax() function to submit Ajax Form supporting  (unobtrusive) Client Side Validation and Server Side Validation

    puedes usar para todos los popup el mismo controlador si asi lo quieres

    Posting Data With jQuery AJAX In ASP.NET Razor Web Pages

    con esto tu controlas que informacion enviar al action del controlador

    en el delete por ejemplo podrias usar el $.post enviando solo el id del servicio y el trabajador para quitar la asociacion o eliminarlo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 6 de enero de 2015 19:56
  • Gracias Leandro, inmediatamente después de que contestaste estuve intentando con los ejemplos copiados. Sin embargo de igual modo me fue difícil comprender. Poco a poco logre entender la funcionalidad y forma de trabajo y logré esto:

    En el listado debo crear los botones/iconos, pero bajo un actionlink para poder enviar información al controlador, del siguiente modo:

    <div class="panel-body ">
        @Html.ActionLink("Crear", "RegistrarServicio", new { IdTrabajador = @ViewBag.IdTrabajador, Nivel = 1, IdUsuario = 20}, new { data_modal = "", id = "btnCreate", @class = "btn btn-small btn-primary pull-right" })
    </div>

    (*) cabe resaltar que la parte final de la línea de código "new {" corresponde al css.

    public ActionResult RegistrarServicio(int IdTrabajador, int Nivel, 
                int IdUsuario)
            {
                //de nuestro modelo
                Servicio s = new Servicio();
                t.IdServicio = IdServicio;
                t.IdTrabajador = IdTrabajador;
                t.Nivel = Nivel;
                
                //retornamos una vista parcial, donde tendremos el código del modelo
                return PartialView("_pvAgregarServicio", s);
            }

    En la vista colocamos algo así:

    @model SLBooking.Models.Servicio
    
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <h4 class="modal-title" id="myModalLabel">Agregar Servicio</h4>
    </div>                @*Contenido del registro de nuevo servicio@
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        <div class="modal-body">
            <div class="form-horizontal">
                <h4>Servicio</h4>
                <hr />
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    
                <div class="form-group">
                    @Html.LabelFor(model => model.Descripcion, htmlAttributes: new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.EditorFor(model => model.Descripcion, new { htmlAttributes = new { @class = "form-control" } })
                        @Html.ValidationMessageFor(model => model.Descripcion, "", new { @class = "text-danger" })
                    </div>
                </div>            
            </div>
        </div>
        <div>
            @Html.ActionLink("Volver", "Index")
        </div>
    
        <div class="modal-footer">
            <button class="btn" data-dismiss="modal">Cancel</button>
            <input class="btn btn-primary" type="submit" value="Save" />
        </div>
    }
    

    Luego en nuestro controlador agregamos el action del tipo POST para realizar el envío de información a la base de datos:

    [HttpPost]
            public ActionResult RegistrarServicio(Servicio s)
            {
                if (!ModelState.IsValid)
                {
                    ModelState.AddModelError("Descripcion", "Descripción es requerida");
                    //falta implementar el código de manejo de errores
                }
                else
                {
                    try
                    {
                        using (BDEntities contexto = new BDEntities())
                        {
                            String respuesta = contexto.SetServicio(t.IdServicio, t.Nivel, t.IdUsuario).FirstOrDefault().ToString();
                            if (respuesta.Equals("1"))
                            {
                                //si se insertó correctamente
                                return RedirectToAction("Listar", "Inicio", new { id = t.IdTrabajador });
                            }
                            else
                            {
                                //si no se insertó, veamos el error.
    
                            }
                        }
                    }
                    catch (Exception)
                    {
                        
                        throw;
                    }
                    
                    return View("Index");
                }
                return View("Index");
            }

    Bueno, todo lo publicado es parte del código, es mucha info, por ello tuve que recortar. Sin embargo, al fin me funcionó.

    Finalmente, para lograr los formularios en formato popup, el camino es difícil, ya que bootstrap posee complicaciones con actionlink's. Sin embargo, después de investigar muchas horas, logré encontrar ejemplos en esta web: http://www.fabro.pl/Download.aspx?S=Bootstrap+modal+MVC+5  en ellos encontré exactamente todo lo que necesitaba.

    Gracias por el apoyo.

    jueves, 15 de enero de 2015 23:48