Aplicación web con ASP.NET MVC 2 – parte 5

Img. 1. Resultado final de este avance.

Continuando con el desarrollo de nuestra aplicación ASP.NET MVC 2, seguiremos trabajando con el AdministrarPEController donde agregaremos un poco más de funcionalidad, para ello se plantea lo siguiente:

El Index de AdministrarPEController  muestra la lista de PE’s, donde ahora queremos que al dar clic en un PE (por ahora no tienen link) nos lleve a ver sus cuatrimestres considerando solo mostrar los cuatrimestres del año actual; por ejemplo: estamos en el 2011, cuando entremos a ver los cuatrimestres, solo nos muestre los del 2011, si aún no se han creado, nos permita hacerlo pero evitar que se creen cuatrimestres duplicados (son solo 3 por año y cada uno tiene definido su periodo), además nos permita ver el historial de cuatrimestres del PE, por ejemplo ver la lista de cuatrimestres del año pasado y así poder ingresar al historial (más adelante será el historial de grupos).

Si se hacen pelotas, imaginen como podríamos saber cuantos grupos tiene el PE TIC-SI (TSU) en el cuatrimestre septiembre-diciembre del 2011, cuantos tuvo en el cuatrimestre mayo-agosto 2011, y cuantos tuvo en el cuatrimestre enero-abril2011, para saberlo hay que revisar el historian ¿No?, y si quisiéramos saber ¿cuantos tuvo en los cuatrimestres del año 2010?, solo debemos imaginarlo y pensar en como le daríamos solución.

Entonces a trabajar, de aquí en adelante solo iré agregando las partes del código y una breve explicación, puesto que ya se familiarizaron con el controlador, las acciones, las vistas, los ActionLink, las consultas LINQ y expresiones LAMBDA.

A partir de aquí empezaremos a utilizar CSS y JQuery para realizar consultas AJAX junto con JSON, así que si también no estamos familiarizados (por lo menos tener la idea de que se esta haciendo o de que se trata) entonces es necesario consultar http://jquery.com/ y http://www.json.org/

La acción ProgramaEducativo.

Será la encargada de mostrar los cuatrimestres del año actual de cada PE, permitirá agregar nuevos cuatrimestres y eliminar cuatrimestres siempre y cuando no tengan ningún grupo asociado, la vista permitirá visualizar la lista de cuatrimestres de años anteriores.

// GET: /AdministrarPE/ProgramaEducativo
public ActionResult ProgramaEducativo(int id)
{
    //buscar primero el programa educativo

    var programaeducativo = BD.ProgramaEducativo.Where(p => p.IdPE == id).FirstOrDefault();

    //si existe el PE, cargar sus cuatrimestres
    if (programaeducativo != null)
    {
        //buscar los cuatrimestres del año actual para el ID del PE seleccionado
        var cuatrimestresPE = BD.Cuatrimestre.Where(c => c.IdPE == id && c.Anio == DateTime.Now.Year);

        //pasar a la vista el ID del PE y el nombre  del PE por medio de ViewData
        //ya que solo admite un objeto o colección de objetos (los datos llamados Modelo)
        ViewData["IdPE"] = programaeducativo.IdPE;
        ViewData["NombrePE"] = programaeducativo.Nombre;

        //pasar la lista de cuatrimestres a la vista, si no hay ningúno, la lista aparecerá vacia.
        return View(cuatrimestresPE.ToList());
    }
    else //si no existe, devolver la vista Error.
        return View("Error");
}

Creemos la vista tipada para la clase Cuatrimestre con contenido List.

Img. 2. Crear vista tipada para mostrar la lista de cuatrimestres del PE.

Modifiquemos parte del código de la vista para mostrar los textos deseados, la tabla de cuatrimestres solo debe mostrar el Id del cuatrimestre, un campo Periodo (conformado por Inicio, Fin y Año), eliminaremos el link de Edit y Details.

Al parecer el campo Nombre sale sobrando, así que ve al diseño de la tabla, puedes eliminarlo de la tabla y actualizar el modelo (recuerda hacerlo también en la BD vacía que tenemos de respaldo para que junto con al de prueba sean iguales).

Esta vista también ya contiene el form para crear un nuevo cuatrimestre (estará oculto) donde los textbox son de solo lectura, en tiempo de ejecución los llenaremos con JavaScript, incluye también la tabla del historial (también aparcererá oculta).

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	Cuatrimestres del Programa Educativo
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        <script src="../../Scripts/jquery-1.4.1.js" type="text/javascript">
</script>
         <script src="../../Content/Scripts/cuatrimestres.js" 
type="text/javascript"></script>

    <h2>Programa Educativo: <%: ViewData["NombrePE"] %></h2>

    <h4>Cuatrimestres del año <%: DateTime.Now.Year %></h4>

    <% //Mostrar el form para crear un nuevo cuatrimestre 
       (deberá aparecer oculto) %>
        <p>
            <a href="#" id="crearnuevocuatrimestre">Crear nuevo cuatrimestre</a>.
        </p>
        <div id="crearcuatrimestre" class="oculto">
             <fieldset>
            <legend>Crear cuatrimestre</legend>
             <form id="datoscuatrimestre" 
action="/AdministrarPE/NuevoCuatrimestre/<%:
ViewData["IdPE"] %>" method="post">
             <input type="radio" value="1" id="cuatrimestre1" 
name="ncuatrimestre"/><label>Enero - Abril</label><br />
             <input type="radio" value="2" id="cuatrimestre2" 
name="ncuatrimestre"/><label>Mayo - Agosto</label><br />
             <input type="radio" value="3" id="cuatrimestre3" 
name="ncuatrimestre"/><label>Septiembre - Diciembre</label><br />

             <div class="editor-label">
                <label for="PeriodoInicio">Inicio</label>
             </div>
            <div class="editor-field">
                <input id="PeriodoInicio" name="PeriodoInicio" type="text" 
value="" readonly="readonly"/>
            </div>
            <div class="editor-label">
                <label for="PeriodoFin">Fin</label>
             </div>
            <div class="editor-field">
                <input id="PeriodoFin" name="PeriodoFin" type="text" 
value="" readonly="readonly"/>
            </div>
            <div class="editor-label">
                <label for="Anio">Año</label>
             </div>
            <div class="editor-field">
                <input id="Anio" name="Anio" type="text" value="<%: 
DateTime.Now.Year %>" readonly="readonly"/>
            </div>
            <input type="hidden" id="IdPE" name="IdPE" value="<%: 
ViewData["IdPE"] %>" />
            <p>
                <input type="submit" id="EnviarForm" 
value="Registrar cuatrimestre" /> |
                <a href="#" id="cancelarcrearcuatrimestre">Cancelar</a>.
            </p>
            <div id="mensaje"></div>
             </form>
            </fieldset>
        </div>
        <% //FIN Mostrar el form para crear un nuevo cuatrimestre. %>

        <% //Tabla de cuatrimestres del PE, aparece visible %>
    <table>
        <tr>
            <th></th>
            <th>
                Id
            </th>
            <th>
                Periodo
            </th>
            <th>
                Año
            </th>
        </tr>

    <% foreach (var item in Model) { %>

        <tr>
            <td>
                <%: Html.ActionLink("Eliminar", "Delete", new { id=item.Id })%>
            </td>
            <td>
                <%: item.Id %>
            </td>
            <td>
                <%: item.PeriodoInicio + " - " + item.PeriodoFin %>
            </td>
            <td>
            <%: item.Anio %>
            </td>
        </tr>

    <% } %>
    </table>
    <% //FIN Tabla de cuatrimestres del PE. %>

    <% //Aquí irá el historial de cuatrimestres, deberá aparecer oculto %>
    <p>
        <a href="#" id="mostrarh">Historial del programa educativo</a>
    </p>
    <div id="historial" class="oculto">
        <table id="historialtbl">
            <tr>
                <th>
                    Id
                </th>
                <th>
                    Periodo
                </th>
                <th>
                    Año
                </th>
            </tr>
        </table>
    </div>

</asp:Content>

Ejecutando nuestra app, y accediendo nuestra nueva acción http://localhost:2958/AdministrarPE/programaeducativo/1 tenemos el resultado:

Img. 3. Vista previa de la vista ProgramaEducativo/N

Creemos nuestro CSS
Abre tu editor de textos favorito, guarda tu nuevo archivo como misestilos.css en la carpeta Content de tu proyecto (busca tu carpeta de proyecto en el explorador de windows), el contenido del archivo es:

.oculto{
	display:none;
	}

Ahora incluyamos nuestro archivo en la plantilla, ve a Views/Shared/ y abre Site.Master, y agrega la linea correspondiente para que se incluya tu nuevo css.

    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="../../Content/misestilos.css" rel="stylesheet" type="text/css" />

Ve al navegador y actualiza la página, veremos que nuestros elementos ocultos yá estan ocultos 😀

Img. 4. Elementos ocultos en la vista.

Creemos nuestros JavaScripts

Ahora utilizaremos JQuery, las aplicaciones ASP.NET MVC 2 ya incluyen la versión 1.4.1, actualmente está disponible la versión 1.6.4, puedes descargarla y actualizar tus JS.

Bien, entonces en tu editor de textos creemos un nuevo archivo y lo guardaremos en la carpeta Content/Scripts de nuestra aplicación, el archivo le llamaremos cuatrimestres.js  ya que si la guardamos en la carpeta Scripts de la app donde estan los jquery y otros js no nos permitirá utilizar nuestro propio js.

En el explorador de soluciones mostremos los archivos ocultos e incluyamos en el proyecto el archivo misestilos.css y la carpeta Scripts.

Donde agregaremos todo lo necesario para mostrar los elementos ocultos, crear el nuevo cuatrimestre y cargar el historial de cuatrimestres del PE.

Entonces el contenido del nuevo archivo de javascript es:

//nueva funcion para resetear elementos de un form
jQuery.fn.reset = function () {
  $(this).each (function() { this.reset(); });
}

//Al hacer clic sobre el link "Crear nuevo cuatrimestre"
//mostrar form
$("#crearnuevocuatrimestre").live("click", function(event){

	//recuperar la lista de cuatrimestres existentes
	//desactivar los radiobutton de los cuatrimestres ya existentes
	var url ="/AdministrarPE/CuatrimestresDelPE/"+$("#IdPE").val();
	//hacer la llamada JSON
	$.getJSON(url,
	    function(data) {
			$.each(data, function(i, item) {
				//verificar cuales cuatrimestres ya existen
				//si existen deshabilitar el radiobutton
 correspondiente
				if(data.c1== true)
			$("#cuatrimestre1").attr("disabled","disabled");
				if(data.c2== true)
			$("#cuatrimestre2").attr("disabled","disabled");
				if(data.c3== true)
			$("#cuatrimestre3").attr("disabled","disabled");
	               });
	    });

	$("#crearcuatrimestre").show("slow");
	//event.preventDefault();
	//ocultar el link
	$("#crearnuevocuatrimestre").hide();
});

//Al hacer clic sobre el Cancelar para "Crear nuevo cuatrimestre"
//resetear y ocultar el form
$("#cancelarcrearcuatrimestre").live("click", function(event){
	//resetear el form
	$("#datoscuatrimestre").reset();
        $("#mensaje").html("");
	$("#crearcuatrimestre").hide("slow");
	//mostrar el link
	$("#crearnuevocuatrimestre").show();
});

//al hacer clic sobre un radiobutton, llenar
//los txt del cuatrimestre con los datos correspondientes
$("#cuatrimestre1").live("click", function(event){
	$("#PeriodoInicio").val("Enero");
	$("#PeriodoFin").val("Abril");
});
$("#cuatrimestre2").live("click", function(event){
		$("#PeriodoInicio").val("Mayo");
		$("#PeriodoFin").val("Agosto");
});
$("#cuatrimestre3").live("click", function(event){
		$("#PeriodoInicio").val("Septiembre");
		$("#PeriodoFin").val("Diciembre");
});

//al hacer clic en el botón Registrar cuatrimestre
$("#EnviarForm").live("click", function(event){
	event.preventDefault();
	$("#mensaje").html("");

	if($("#PeriodoInicio").val() == "" || $("#PeriodoFin").val() == "")
	{
		$("#mensaje").html("No se puede crear el cuatrimestre, 
seleccione el cuatrimestre a crear.<br>Si el cuatrimestre a crear est&aacute; 
deshabilitado, es porque ya existe.");
		return;
	}else
	$("#datoscuatrimestre").submit();
});

La acción que responde con JSON

En el JS al hacer clic sobre el link “Crear nuevo cuatrimestre”, primero obtiene la lista de cuatrimestres actuales, de los cuales si alguno ya existe, deshabilita el radiobutton correspondiente para evitar que vuelva a crearse el mismo cuatrimestre.

Para esto hace una llamada AJAX que como resultado obtiene un conjunto de datos con formato JSON los cuales son el resultado de invocar a una acción en el controlador, la acción es la siguiente:

        //Respuesta a la acción invocada por AJAX-JSON
        //La acción devuelve un resultado JSON
        //que es la lista de cuatrimestres ya registrados para el PE
        [ActionName("CuatrimestresDelPE")]
        public JsonResult CuatrimestresDelPE(int id)
        {
            //buscar los cuatrimestres del año actual para el PE
            var cuatrimestresPE = BD.Cuatrimestre.Where(c => c.IdPE == id 
&& c.Anio == DateTime.Now.Year);

            //variables auxiliares para almacenar nuestros cuatrimestres
            bool c1= false;
            bool c2 = false;
            bool c3 = false;

            //recorrer la lista
            foreach(Cuatrimestre cuatrimestre in cuatrimestresPE)
            {
                if(cuatrimestre.PeriodoInicio.Trim() == "Enero" && 
cuatrimestre.PeriodoFin.Trim() == "Abril")
                    c1=true;
                if(cuatrimestre.PeriodoInicio.Trim() == "Mayo" && 
cuatrimestre.PeriodoFin.Trim() == "Agosto")
                    c2=true;
                if(cuatrimestre.PeriodoInicio.Trim() == "Septiembre" && 
cuatrimestre.PeriodoFin.Trim() == "Diciembre")
                    c3=true;
            }

            //Creamos el resultado JSON
            //donde indicamos los cuatrimestres y si estos existen
            return this.Json(new { c1 = c1, c2 = c2, c3 = c3}, 
JsonRequestBehavior.AllowGet);
        }

La acción que registrará el Cuatrimestre.

        [HttpPost]
        public ActionResult NuevoCuatrimestre(Cuatrimestre cuatrimestre)
        {
            BD.AddToCuatrimestre(cuatrimestre);
            BD.SaveChanges();

            //agregado el registro (objeto), redireccionar los 
cuatrimestres del PE.
            return Redirect("../ProgramaEducativo/"+cuatrimestre.IdPE);
        }

Antes de comprobar que funcione nuestra app, probaremos con agregar algunos Cuatrimestres como historial en nuestra tabla.

Img. 5. Registrar algunos datos históricos.

Comprobando funcionalidad

Ya con los datos, ahora comprobemos que nuestra app puede agregar nuevos cuatrimestres.

Img. 6. Intentando crear registro sin seleccionar cuatrimestre (no lo permite).
Img. 7. Registrar el cuatrimestre seleccionado.
Img. 8. Cuatrimestre creado, verificando que no permita volver a crearlo.

Y bien, hasta aquí ya funciona nuestra app, pero aún falta la parte del historial.

Agregue los link en la vista Index para que al hacer clic sobre el nombre de un PE lo dirija hacia sus cuatrimestres (el trabajo realizado).

Como ya estoy un poco agotado, en la siguiente entrega continuaremos con lo del historial.

Saludos…!

Anuncios

12 comentarios en “Aplicación web con ASP.NET MVC 2 – parte 5

  1. ya esta todo solucionado, no copie bien la funcion de javascript y no habia leido bien 😀
    estan muy buenos los ejemplos, felicitaciones.

  2. Hola, estoy empezando con MVC y es una de mis primeras aplicaciones, ahora tengo una consulta.
    en el script js, cuando se hace click sobre “Crear nuevo cuatrimestre” en la funcion hace mension a esta vista/pantalla var url =”/AdministrarPE/CuatrimestresDelPE/”+$(“#IdPE”).val(); la cual aun no esta definida, por lo menos en lo que voy haciendo del ejemplo “CuatrimestresDelPE” aun no se definio, y es a ese archivo q llama para hacer la consulta, si estoy equivocado por favor corregirme y me saltie una parte, gracias, y espero a su respuesta!

  3. Exacto, por querer avanzar rápido en el tutorial y mientras avanzaba omití el uso de ese campo y parece que también omití mencionar que ese campo no se utilizaría en el ejemplo y más aún al no actualizar la imagen del modelo.
    Pero se que los usuarios metidos en esto no les será complicado hacer los cambios que crean pertinentes.
    PD: never nunca me suena a un usuario que no quiere hacer aportaciones constructivas.

  4. Hola, el Error 2, lo solucioné actualizando el modelo desde la base de datos. Solo me quedan:

    Advertencia 1 No se encontró el archivo ‘../../content/scripts/cuatrimestres.js

    Error 3 ‘System.Web.Mvc.ControllerBase.ViewData’ es ‘propiedad’ pero se utiliza como ‘método’.

    Gracias de antemano

  5. Hola, estoy siguiendo los ejemplos y me han ayudado mucho, muy buen material. Generé el proyecto y me salieron los siguientes errores:

    Advertencia 1 No se encontró el archivo ‘../../content/scripts/cuatrimestres.js’.

    Error 2 Error 3023: Hay un problema con los fragmentos de asignación a partir de la línea 387:Se debe asignar la columna Cuatrimestre.Nombre de la tabla Cuatrimestre: no tiene ningún valor predeterminado y no es NULL.

    2. Error 3 ‘System.Web.Mvc.ControllerBase.ViewData’ es ‘propiedad’ pero se utiliza como ‘método’.

    Podrían ayudarme por favor.

    Gracias de antemano.

  6. Por que mi código no funciona bien en Internet Explorer 9, si funciona bien en Google Crhome y a veces funciona en Mozilla.

    El problema es cuando hago clic en el link: Crear cuatrimestres, este no muestra y expande el formulario oculto, cual será la razón?

    No hay una forma más sencilla, sin tanto código de utilizar formularios en ASP.NET MVC 2?

    1. Habría que verificar el script y comprobar que las funciones de jQuery utilizadas sean compatibles con tu versión de IE (en lo particular, me centré en realizar un poco rápido el tutorial comprobando su funcionalidad en Chrome y FF, funciona bien en Opera, pero en IE no lo comprobé)

      La versión 3 de asp.net mvc incluye como gestor de vistas a Razor que simplifica la implementación de vistas.

  7. ola estoy siguiendo tu ejemplo y me esta ayudando bastante pero tengo un problemilla aca

    if (cuatrimestre.PeriodoInicio.Trim() == “Enero” && cuatrimestre.PeriodoFIn.Trim() == “Abril”)
    c1 = true;
    if (cuatrimestre.PeriodoInicio.Trim() == “Mayo” && cuatrimestre.PeriodoFIn.Trim() == “Agosto”)
    c2 = true;
    if (cuatrimestre.PeriodoInicio.Trim() == “Septiembre” && cuatrimestre.PeriodoFIn.Trim() == “Diciembre”)
    c3 = true;

    Trim : falta una directiva de uso o una referencia de emsamblador ??? que puede ser ?

  8. Estoy siguiendo tu tutorial y te agradezco por tus enseñanzas, tengo un problema en este capitulo al buscar el la base de datos por IdPE y Anio.

    BD.Cuatrimestre.Where(c => c.IdPE == id && c.Anio == DateTime.Now.Year);
    en especifico c.Anio == DateTime.Now.Year

    da Error 4 El operador ‘==’ no se puede aplicar a operandos del tipo ‘string’ y ‘int’

    e probado cambiando el formato de Anio en la base de datos y del valor recibido en DateTime.Now.Year, pero nada.

    Gracias de antemano.

    1. Verifica que Cuatrimestre.Anio en la BD sea Integer, si lo tenias como string y cambiaste a Int debes eliminar el Modelo.edmx y volver a generarlo o si ya cambiaste en la BD verifica la Entidad Cuatrimestre en el Model y verifica que Anio sea Int, posteriormente vuelve a codificar.

      1. Gracias ese era el problema, me faltaba actualizar el modelo.edmx luego de cambiar Cuatrimestre.Anio de varchar a int

Escribe tu comentario:

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s