Sei sulla pagina 1di 25

SERVICIO DE INFORMTICA | UNIVERSIDAD DE ALICANTE

ASP.NET MVC 3 y 4
PERSONALIZACIN
Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es/

LTIMA ACTUALIZACIN: 13 DE OCTUBRE DE 2012

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

3 DA PERSONALIZACIN
ENTITY FRAMEWORK BSICO
Vamos a estudiar lo bsico para hacer consultas con Entity Framework. Nos creamos en la aplicacin de libros con Oracle, en el controlador Home, el mtodo BD. Los pasos para hacer la consulta son los siguientes: 1. Preparar una variable con el listado de datos que vamos a pasar al modelo. Si queremos un listado de libros, usaremos IEnumerable<Tabla> para que desde la vista podamos recorrer los datos con las plantillas bsicas que nos ofrece MVC. 2. Abrir la conexin a la Entidad. Depender del nombre que se le haya puesto a la Entidad cuando hayamos importado el modelo. Lo ms cmodo es usar using([declaracin conexin]) {} porque se elimina automticamente al salir del using. 3. Hacer la consulta y almacenar los resultados en la variable del punto 1. Lo ms sencillo es obtener todos los registros de una tabla [conexin].[nombretabla].ToList(). Las tablas pasan a ser unos objetos ms con los que podemos trabajar. 4. Cerrar o liberar la conexin con la entidad. Si hemos usado using no ser necesario, pero en cualquier otro caso habr que usar bd.Dispose() 5. Llamar a la vista con el modelo de datos que hemos almacenado en el punto 1 y 3. Igual que hemos hecho en otras ocasiones View([Variable]). Podra ser algo as.
public ActionResult BD() { IEnumerable<CSI_LIBRO> libros; using (var bd = new EntitiesBiblioteca()) { libros = bd.CSI_LIBRO.ToList(); } return View(libros); }

La nomenclatura usada para esta consulta es lambda, que para es la ms sencilla, pero la tradicional de consultas (Linq) sera:
libros = (from l in bd.CSI_LIBRO select l).ToList();

Como son muy sencilla ambas, que cada uno seleccione la que le sea ms sencilla. Ahora creamos una vista para este mtodo y le indicamos el modelo CSI_LIBRO y la plantilla List.

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Si lo ejecutamos vemos el listado de libros. Tambin incluye la creacin de nuevos libros, edicin, borrado. Toda esta parte la podemos eliminar.

FILTRADO
Cuando hacemos consulta lo normal es mostrar aquellos que cumplen una condicin. La ms bsica podra ser la consulta por id
libros = bd.CSI_LIBRO.Where(l => l.ID == 1 ).ToList(); libros = (from l in bd.CSI_LIBRO where l.ID == 1 select l).ToList();

O que est en un intervalo


libros = bd.CSI_LIBRO.Where(l => l.ID >= 1 && l.ID < 3).ToList(); libros = (from l in bd.CSI_LIBRO where l.ID >= 1 && l.ID <= 3 select l).ToList();

Si queremos consultar aquello libros que tienen en el ttulo El Principito


libros = bd.CSI_LIBRO.Where(l => l.TITULO == "El Principito").ToList(); libros = (from l in bd.CSI_LIBRO where l.TITULO == "El Principito" select l).ToList();

O que contienen la palabra Principito


libros = bd.CSI_LIBRO.Where(l => l.TITULO.Contains("Principito") ).ToList(); libros = (from l in bd.CSI_LIBRO where l.TITULO.Contains("Principito") select l).ToList(); Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Podemos hacer conversiones de maysculas o minsculas de cualquier campo en la propia consulta


libros = bd.CSI_LIBRO.Where(l => l.TITULO.ToUpper().Contains("PRINCIPITO") ).ToList(); libros = (from l in bd.CSI_LIBRO where l.TITULO.ToUpper().Contains("PRINCIPITO") select l).ToList();

ORDENACIN
Disponemos de dos funciones en lambda OrderBy y OrderByDescending al que debemos indicar el campo de ordenacin
libros = bd.CSI_LIBRO.OrderBy(l => l.TITULO).ToList(); libros = (from l in bd.CSI_LIBRO orderby l.TITULO select l).ToList(); libros = bd.CSI_LIBRO.OrderByDescending(l => l.TITULO).ToList(); libros = (from l in bd.CSI_LIBRO orderby l.TITULO descending select l).ToList();

Si queremos ordenar por ms de un campo, en lambda debemos usar ThenBy o ThenByDescending, mientras que en las consultas tradicionales lo hacemos separando los campos por comas.
libros = bd.CSI_LIBRO.OrderBy(l => l.TITULO).ThenBy(l => l.ISBN).ToList(); libros = (from l in bd.CSI_LIBRO orderby l.TITULO, l.ISBN select l).ToList();

PAGINACIN
Uno de los problemas que nos encontramos cuando trabajamos con Oracle es la paginacin. Obtener un nmero limitado de registros y saltar hasta un determinado registro es trivial en EF. Para obtener los 2 primeros registos de una consulta
libros = bd.CSI_LIBRO.OrderBy(l => l.TITULO).Take(2).ToList(); libros = (from l in bd.CSI_LIBRO orderby l.TITULO, l.ISBN select l).Take(2).ToList();

Si queremos saltar los primeros 10 registros y obtener los 2 primeros registros


libros = bd.CSI_LIBRO.OrderBy(l => l.TITULO).Skip(10).Take(2).ToList(); libros = (from l in bd.CSI_LIBRO orderby l.TITULO, l.ISBN select l).Skip(10).Take(2).ToList();

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

HELPERS (BSICO)
HTMLHELPERS
Ayer vimos las funciones relacionadas con las direcciones. Hoy nos centramos en las que realmente nos van a ayudar en el trabajo diario, las que nos generan cdigo HTML. Aunque el listado es mucho ms amplio que el de URLHelpers, lo cierto es que todos son muy parecidos. Vamos a comenzar con el elemento bsico que es el formulario que recoge todos los campos con los que trabajamos. Nos creamos una mtodo / accin en nuestro controlador para ir jugando. Le podemos llamar helpers. No le vamos a pasar ningn modelo por el momento. Editamos su vista y lo bsico para un formulario en HTML es <form ></form>. La idea es que no lo escribamos directamente sino que usemos los helpers. BeginForm(s:action, s:controller, o:values) Si escribimos
@using (Html.BeginForm()) { }

Nos generara el siguiente cdigo


<form action="/Home/helpers" method="post"></form>

Por defecto nos genera una accin a nosotros mismos y hace la llamada con mtodo post Con los parmetros podemos indicar que controlador / accin del action y el mtodo
Html.BeginForm("Create", "Libro", FormMethod.Get)

Y generara
<form action="/Libro/Create" method="get"></form>

Todos los HTMLHelpers incluyen un ltimo parmetro abierto a aadir cualquier atributo HTML, por ejemplo id, class, etc. En el caso de que queramos indicar el id
Html.BeginForm("Create", "Libro", FormMethod.Get, new {id="fTest"}))

Si adems quisiramos aadir el estilo con class al ser una palabra reservadas del sistema debemos escribir la propiedad con @class.
Html.BeginForm("Create", "Libro", FormMethod.Get, new {id="fTest", @class="formulario-ua"})

El resultado final sera


<form action="/Libro/Create" class="formulario-ua" id="fTest" method="get"></form>

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

En caso de que no usemos using en la declaracin de beginform deberemos usar endform para indicar donde acaba.
@{ Html.BeginForm("Create", "Libro", FormMethod.Get, new {id = "fTest", @class = "formulario-ua"}); } @{ Html.EndForm();}

Yo usar en todos los ejemplos using porque queda el cdigo ms agrupado. Ahora es el momento de incluir elementos en el formulario Label(s:name, o:text) Un etiqueta con texto que hace referencia a un campo (name). En caso de que no se indique el texto pondr por defecto el nombre del campo que hayamos indicado en el primer parmetro.
@using(Html.BeginForm("Create", "Libro", FormMethod.Get, new {id = "fTest", @class = "formulario-ua"})) { @Html.Label("Nombre", "Nombre:") }

En este ejemplo mostrar una etiqueta Nombre: que hace referencia a un campo Nombre.
<label for="Nombre">Nombre:</label>

TextBox(s:name, o:value) Crea una caja de texto con el nombre que le indiquemos y con un valor por defecto en el segundo parmetro.
@Html.TextBox("Nombre", "Alberto")

genera
<input id="Nombre" name="Nombre" type="text" value="Alberto" />

Todo el contenido que se asigne en el valor por defecto (en cualquier HTMLHelper) se codifica automticamente para evitar que se produzcan ataques XSS injection.

CheckBox(s:name, b:checked) Genera una elemento checkbox.

DropDownList(s:name, list:selectlistitems)
Genera una lista desplegable en la que podemos seleccionar un nico elemento.
@Html.Label("Sexo") @Html.DropDownList("Sexo", new MultiSelectList(new[] {"Hombre", "Mujer"}))

Genera
Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Hidden(s:name, o:value) Genera un campo oculto.

ListBox(s:name, list:selectlistitems) Genera una lista de valores en la que podemos seleccionar ms de un elemento.
@using(Html.BeginForm("Create", "Libro", FormMethod.Get, new {id = "fTest", @class = "formulario-ua"})) { @Html.Label("Unidad") @Html.ListBox("Unidad", new MultiSelectList(new[] {"Servicio de Informtica", "Seleccin y Formacin", "Servicio de Personal"})) }

Genera

RadioButton(s:name, o:value, b:checked) Genera una elemento radiobutton

TextArea(s:name, s:value) Crea una caja de texto de tipo textarea.

INCLUIR BUSCADOR EN NUESTRA APLICACIN


Con lo visto anteriormente preparar una caja de bsqueda totalmente funcional que busque en el listado de libros. Se podr buscar por ttulo o por Isbn. En caso de que se deje en blanco el trmino de bsqueda mostrar todos los libros. Crearemos los modelos que necesitemos, un nuevo mtodo para el controlador Home y una vista con la caja de bsqueda. Luego crearemos una 2 versin que incluiremos el buscador como una seccin dentro de la plantilla _layout.cshtml. De esta manera podremos indicar en las vistas si queremos incluirlo o no.
Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

VISTAS POR DEFECTO


Como ya se coment el primer da las plantillas que usa el Visual Studio son personalizables. Se almacena por defecto en Visual Studio 2010 en la carpeta C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\ CSharp\Web\MVC 3\CodeTemplates\AddView\CSHTML Si accedemos veremos 6 ficheros con la extensin tt. Lo primero que podemos pensar es en modificarlo directamente, pero esto afecta a todos los proyectos. Adems est en una carpeta que es muchas ocasiones, y por medidas de seguridad, nos pide permisos de administrador. Lo mejor es coger la carpeta CodeTemplates y copiarla a la raz de nuestra aplicacin (podemos borrar todo lo que no sea AddView\CSHTML).

El siguiente paso para poder hacer modificaciones a la plantilla es cambiar el parmetro Herramienta personalizada a las 6 plantillas. Por defecto tiene el valor TextTemplatingFileGenerator. Lo dejamos vaco.

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Podemos crear nuevas plantillas y que aparezcan al crear una vista? Por supuesto. Vamos a duplicar la plantilla para a vista de listado (list.tt) para que no incluya ni dar de alta, ni poder gestionar los registros. Aunque el cdigo no es tan legible como en Razor, buscamos los bloques de HTML y vamos eliminando los contenidos que nos interesen. El objetivo es que se vea un listado con este formato. Un problema que nos podemos encontrar es que en los listados personalizados el tipo de libro aparezca como cdigo y no como descripcin. Debemos realizar unos cambios. En el controlador, hacer un include la tabla relacionada.
public ActionResult Buscar(string palabra) { IEnumerable<CSI_LIBRO> libros; using (var bd = new EntitiesBiblioteca()) { libros = bd.CSI_LIBRO.Include("CSI_TIPOLIBRO"); if (!String.IsNullOrEmpty(palabra)) { libros = libros.Where(l => l.TITULO.ToUpper().Contains(palabra.ToUpper())); } libros = libros.ToList(); } return View(libros); }

En la vista cambiar el campo que es clave ajena por la [tabla relacin].[campo descripcin] (slo en el caso que hayamos realizado el include porque si no es inaccesible).
<td> @Html.DisplayFor(modelItem => item.CSI_TIPOLIBRO.DESCRIPCION) </td>

HELPERS
HTMLHELPERS (CONTINUACIN)
ValidationSummary([Exclude property-level error]) Muestra una lista no ordenada de todos los errores que se producen al validar el formulario. Se puede validar todo o excluir los errores a nivel de las propiedades del modelo Los errores se pueden lanzar en tiempo de ejecucin con la propiedad AddModelError(campo, mensaje de error) del objeto ModelState. En caso de que el campo lo dejemos vaco estamos lanzando un error a nivel de modelo
ModelState.AddModelError("", "Prueba de un error general");

y si indicamos el campo lo hacemos a nivel de propiedad.


ModelState.AddModelError("Nombre", "El nombre no cumple con los requisitos");

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Aadimos a la vista un sumario de validacin


@using(Html.BeginForm()) { @Html.ValidationSummary(false) }

El resultado

Por defecto asigna el estilo "validation-summary-errors.

ValidationMessage (s:[Nombre del campo], o:[Mensaje de error]) En caso de que no queramos que sea un sumario el que recoja todos los mensajes, si no que cada mensaje aparezca en el punto que indiquemos (normalmente a la derecha del campo), usaremos este Helper. Si no se especifica el mensaje de error, todos aquellos errores que se produzcan (o provoquemos) se visualizarn en este punto.
@Html.ValidationMessage("Nombre")

Se visualizar de la siguiente manera

Por defecto asigna el estilo field-validation-error.

Action(s: [nombre accin]) Nos permite llamar a un mtodo / accin de un controlador. Puede parecerse mucho a las vistas parciales que vimos ayer y que recordaremos luego, pero lo cierto es que mientras las vistas parciales estn pensadas para escribir bloques de cdigo, action est orientada a ejecutar el proceso completo de la accin de un controlador (que incluye la generacin del cdigo con la Vista). El resultado es una cadena de texto con todo el contenido generado.
@Html.Action("Cabecera")

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

10

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

ActionLink(s: [descripcin], s: [accin], s: [controlador]) Permite generar enlaces a acciones determinadas de un controlador. Por ejemplo si queremos poner un enlace a la accin Index del Home usaramos
@Html.ActionLink("Pgina principal", "Index", "Home")

Se usa en las plantillas para realizar cualquier accin con el modelo del controlador, alta, baja, edicin o borrado. Dispone de muchas sobrecargas este Helper, permitiendo desde indicar protocolor, servidor y ancla, hasta definir los atributos HTML. RouteLink(s: [descripcin], d: [valores ruta]) Es parecido alterior, porque genera un enlace a una ruta o una accin de un controlador. Es algo ms artesanal ya que no dispone de tantas sobrecargas y todos los valores se meten en un campo o se llama a la routa por su nombre (en caso que se haya definido previamente). Si queremos enlazar con la accin Acerca de usaramos
@Html.RouteLink("Acerca de", new { controller = "Home", action="About"})

RenderAction(s: [nombre accin]) Es idntica a Action con la diferencia de que no almacena el contenido en una cadena de texto si no que la escribe directamente al objeto Response, con lo que se visualiza por el navegador. Si deseamos que una accin sea slo llamada desde Action o RenderAction pero no directamente como una direccin ms en el navegador podemos usar la anotacin ChildActionOnly antes de la declaracin [ChildActionOnly] public ActionResult Cabecera() { }

HELPERS CON EL MODELO


Lo normal no ser generar todo el cdigo HTML sino que se genere a partir de un modelo, por lo tanto MVC ofrece tdo lo que hemos visto anteriormente para trabajar con modelos. Analizamos un par, pero ser lo mismo para el resto de compontes. Partimos de que la vista incluye referencia al modelo por ejemplo al Libro que contiene una propiedad ttulo
@model Proyecto.Libro

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

11

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Todos los Helpers se llaman como antes pero postponiendo For al nombre, es decir TextBox pasa a ser TextBoxFor o Label pasa a ser LabelFor. Luego para hacer referencia a una propiedad del modelo se usa un alias por ejemplo m => m.propiedad o l => l.propiedad (lo que os sea ms cmodo) Si necesitamos mostrar la etiqueta, la caja de texto y la validacin
@Html.LabelFor(l => l.Titulo) @Html.TextBoxFor(l => l.Titulo) @Html.ValidationMessageFor(l => l.Titulo)

Si lo ejecutamos lo primero que vemos es que el LabelFor de un modelo no es muy til porque es el nombre del campo. Muchas veces siglas de un campo de la base de datos, o todo en maysculas. MVC incluye data annotations en los campos lo que permite personalizar la informacin que luego se ver con estos Helpers. Por el momento slo vamos a ver el de la descripcin, pero maana nos centraremos en todo el tema de validacin, que es donde realmente se saca el potencial. Las anotaciones se ponen con corchetes antes de la definicin de la propiedad.
[Display(Name = "Ttulo del libro")] public string Titulo { get; set; }

Display permite personalizar aspectos de la visualizacin. Con Name le indicamos el nombre o label que tendr esta propiedad. El resultado es:

PERSONALIZADOS
Como es lgico MVC nos permite crear nuestros propios Helpers para darle mayor potencia a stos. Se comportan como una funcin a la que se pasan parmetros si los necesita, y dentro genera el cdigo que queremos mostrar. El formato es @Helper [Nombre Funcin]( [parmetros] )
@helper BreadCumb(string[] elementos) { <div> for(int i=0; i < elementos.Count(); i++) { <span>@elementos[i]</span> if (i < elementos.Count() - 1) { <text>></text> } } </div> }

Luego para llamarla @NombreFuncin(parmetros)


@BreadCumb(new[] {"Inicio", "Administracin", "Secciones"})

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

12

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

El resultado es el siguiente

Es costumbre a la hora de poner los parmetros, anteponer el nombre de cada parmetro y luego : (dos puntos).
@BreadCumb(elementos: new[] {"Inicio", "Administracin", "Secciones"})

Si deseamos que es helper sea reutilizables desde cualquier vista, aadimos la carpeta App_Code a nuestro proyecto (no aparece como opcin en las carpetas de ASP.NET) y creamos el fichero BreadCumbHelpers.cshtml. Copiamos el cdigo del Helper y lo guardamos. Ahora para hacerle referencia desde la vista llamaremos al helper de la siguiente manera @[Nombre fichero (sin extensin)].[Nombre del helper o funcin]( [parmetros])
@BreadcumbHelpers.BreadCumb(elementos: new[] { "Inicio", "Administracin", "Secciones" })

Aunque puede parecer que crear un Helper es lo mismo que llamar a vistas parciales (que vimos ayer) porque ambas se usan para reaprovechar cdigo o dejarlo ms estructurado, si que es cierto que cada uno tiene su uso. Helpers personalizado est pensado para pequeos trozos de cdigo, que generan una programacin sencilla y que se comparte con diferentes vistas de tu proyecto o incluso entre varios. Partial views estn orientadas a secciones de cdigo, con el objetivo de hacer ms clara la estructura. Puede contener una programacin tan complicada como la vista que les llama. Disponemos de dos HTMLHelpers dedicados a trabajar con Partial views (ayer usamos el comando RenderPage). Partial(s: nombrevista) Genera una cadena de texto con la ejecucin de la vista parcial
@Html.Partial("_Cabecera")

RenderPartial(s: nombrevista) Es idntica a Partial con la diferencia de que no almacena el contenido en una cadena de texto si no que la escribe directamente al objeto Response, con lo que se visualiza por el navegador.
@{ Html.RenderPartial("_Cabecera"); }

PERSONALIZADOS CON HTMLHELPER


Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

13

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Hay otra forma de crear Helpers personalizados en el que construimos el contenido que queremos generar. Ser una clase, con mtodos que no generan HTML directamente como una vista parcial, si no que devuelve un objeto de tipo IHtmlString. Las etiquetas se generan con TagBuildery los atributos se aaden con MergeAttribute. Un ejemplo muy til, y que encontramos en muchas pginas, es crear nuestro propio ActionLink para trabajar con imgenes.
using System.Web; using System.Web.Mvc; using System.Web.Mvc.Html; using System.Web.Routing; namespace _3_MVCHelpers.Helpers { public static class HtmlImageActionLinkHelper { public static IHtmlString ImageActionLink( this HtmlHelper helper, string imageUrl, string actionName, object routeValues, object htmlAttributes ) { var builder = new TagBuilder("img"); builder.MergeAttribute("src", imageUrl); builder.MergeAttributes(new RouteValueDictionary(htmlAttributes)); var link = helper.ActionLink("[replaceme]", actionName, routeValues); var html = link.ToHtmlString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)); return new HtmlString(html); } } }

Para referenciarlo en nuestra propia vista, usaremos @Html.[Mtodo] ([Parmetros]). Si queremos aadir una imagen 012.jpg que al pulsar sobre ella vaya a la accin Index usaramos:
@Html.ImageActionLink( Url.Content("~/Fotos/012.jpg"), "Index", new { id = 5 }, new { id = "imgnb", width = "100px", height = "150px", alt = "Foto playa de Alicante" } )

LISTADOS
Uno de las interacciones ms comunes con el usuario es mostrar listados. Puede ser un catlogo de enlaces (por ejemplo en una tienda de libros, de msica), un listado de preguntas (para poder consultar las respuestas), resultado de buscar por algn termino, etc. Por tanto hay que ser verstiles a la hora de mostrar los datos porque si no es operativa el usuario dejar de usar nuestra aplicacin.

PAGINACIN Y ORDENACIN
Los listados que hemos generado con las plantillas de ASP.NET MVC son muy bsicos si lo comparamos con los GridViews de los WebForms.
Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

14

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

El 5 da usaremos componentes externos que nos permite generar listados muy potentes, pero hoy nos centramos en el helper WebGrid que est a medio camino entre uno y otro y que en la mayora de los casos nos sobrar. Explicarlo con detalle es muy complicado, pero aplicarlo en ejemplo es muy sencillo. Vamos a crear una nueva accin Grid que se consulte como el listado de Index
public ViewResult Grid() { return View(db.VCSI_LIBRO.ToList()); }

Ahora creamos la vista (podemos usar la plantilla de listado para ver los campos o vaca) y hacemos una definicin del Grid y luego lo mostramos.
@model IEnumerable<CSI_BibliotecaBDOracle.VCSI_LIBRO> @{ ViewBag.Title = "Grid"; var grid = new WebGrid( source: Model, rowsPerPage: 4); } <h2>Grid</h2> @grid.GetHtml( columns: grid.Columns ( grid.Column("Isbn", "Isbn"), grid.Column("Titulo", "Ttulo"), grid.Column("Descripcion_TipoLibro", "Tipo de libro") ) )

El resultado en pantalla es

Lo primero que haremos ser pulsar en la cabecera para ordenar. No obtendremos el resultado deseado, pero si que veremos que va cambiando la URL Grid?sort=Titulo&sortdir=ASC, sort=Titulo&sortdir=DESC&page=2, dependiendo de si pulsamos ordenar o paginar. Seremos nosotros desde la accin los que gestionemos la ordenacin, porque la paginacin si que la realiza el propio componente. Actualizar la accin para mostrar los resultados es bastante sencill
public ViewResult Grid(string sort, string sortdir) { IEnumerable<VCSI_LIBRO> libros = db.VCSI_LIBRO; if (!String.IsNullOrEmpty(sort)) Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

15

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4


{ switch (sort.ToLower()) { case "titulo": libros = (sortdir == "DESC" ? libros.OrderByDescending(l => l.TITULO) : libros.OrderBy(l => l.TITULO)); break; } } else libros = libros.OrderBy(l => l.TITULO); return View(libros.ToList()); }

Detectamos que nos llegue un campo por el que ordenar. Por cada campo miramos si la ordenacin es ascendente (por defecto) o descendente y actualizamos los libros a mostrar.

PERSONALIZACIN
Para comenzar con listados o grids el formato que nos ofrece es bastante atractivo. Si deseamos modificar la apariencia debemos recurrir a los estilos CSS. Por ejemplo WebGrid permite asignar el estilo a todos los elementos tableStyle, headerStyle, rowStyle y footerStyle. Incluso permite alternar el estilo de cada fila con alternatingRowStyle. Cuando veamos la plantilla de las aplicaciones de la UA, los listados se quedarn con el siguiente formato

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

16

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

GENERACIN DE VERSIONES VALENCIANO E INGLS

IDIOMTICAS,

CASTELLANO,

CONFIGURAR Y DETECTAR EL IDIOMA POR DEFECTO


La forma ms cmoda de gestionar el idioma es definir el mtodo Application_AcquireRequestState en Golbal.asax.cs. Almacenamos en la variable Session[idioma] el idioma por defecto. Luego la asignamos a CurrentCulture del proceso actual. En cada llamada que hagamos se llamar a este mtodo.
protected void Application_AcquireRequestState(object sender, EventArgs e) { const string idiomaDefecto = "es"; if (HttpContext.Current.Session != null) { CultureInfo ci = (CultureInfo)this.Session["idioma"]; if (ci == null) { ci = new CultureInfo(idiomaDefecto); this.Session["idioma"] = ci; } Thread.CurrentThread.CurrentUICulture = ci; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); } else { CultureInfo ci = new CultureInfo(idiomaDefecto); Thread.CurrentThread.CurrentUICulture = ci; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); } }

RECURSOS
El elemento base para gestionar las traducciones son los recursos. Una buena prctica es crearnos una carpeta Resources y meter todos aquellos ficheros que necesitemos. Se pueden crear a nivel de controlador o modelo o a nivel de aplicacin si nuestro proyecto es muy bsico. Sobre el proyectos pulsamos botn derecho Agregar > Nueva carpeta y le ponemos el nombre . Ahora sobre esta nueva carpeta Agregar > Nuevo elemento y seleccionamos (o filtramos) Archivo de recursos. Le llamamos modelos.resx

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

17

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Aadimos las descripciones que queremos que estn en varios idiomas

Es importante que marquemos el fichero como pblico para que se pueda acceder desde el resto de los elementos de MVC

Para crear la versin de recursos para otro idioma, copiamos y pegamos el que usemos de base y luego le aadimo .[dos digitos del idioma] antes de la extensin del fichero. Es nuestro caso para crear el fichero de recursos en ingls renombraramos copia de modelos.resx por modelo.en.resx y traduciramos los valores de cada una de las etiquetas.

VISTAS
La manera ms cmoda de pasar textos traducidos a las vistas, en caso de que sean pocos, es usar el controlador y el objeto ViewBag. Para acceder a un recurso escribimos el [nombre carpeta de recursos].[ nombre recurso (sin extensin].etiqueta.
ViewBag.Titulo = Resources.modelos.tituloLabel;

Luego en la propia vista lo referenciamos


Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

18

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4


Texto del fichero de recursos: @ViewBag.Titulo<br />

Si la vista contiene muchos elementos a traducir, lo ms sencillo es crear dos versiones de la vista de la misma manera que lo hemos hecho con el fichero de recursos. Cogemos la vista base index.cshtml la copiamos y la pegamos y renombramos por index.en.cshml. Hacemos los cambios que corresponda

Creamos una clase para gestionar los idiomas CultureHelper. La variable Cultures almacena los idiomas con los que trabajemos. El primero de ellos ser el que se usar por defecto en caso de que detectemos otro que no se corresponda con nuestro listado.
using System; using System.Collections.Generic; using System.Linq; namespace _3_MvcGlobalization.Helpers { public static class CultureHelper { // Include ONLY cultures you are implementing as views private static readonly Dictionary<String, bool> Cultures = new Dictionary<string, bool> { {"es", true}, // first culture is the DEFAULT {"en", true}, {"ca", true} };

/// <summary> /// Returns a valid culture name based on "name" parameter. If "name" is not valid, it returns the default culture "en-US" /// </summary> /// <param name="name">Culture's name (e.g. en-US)</param> public static string GetValidCulture(string name) { if (string.IsNullOrEmpty(name)) return GetDefaultCulture(); // return Default culture if (Cultures.ContainsKey(name)) return name; // Find a close match. For example, if you have "en-US" defined and the user requests "en-GB", // the function will return closes match that is "en-US" because at least the language is the same (ie English) foreach (var c in Cultures.Keys) if (c.StartsWith(name.Substring(0, 2))) return c;

// else return GetDefaultCulture(); // return Default culture as no match found }

/// <summary> /// Returns default culture name which is the first name decalared (e.g. en-US) /// </summary> /// <returns></returns> public static string GetDefaultCulture() { return Cultures.Keys.ElementAt(0); // return Default culture }

/// <summary> /// Returns "true" if view is implemented separatley, and "false" if not. Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

19

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4


/// For example, if "es-CL" is true, then separate views must exist e.g. Index.es-cl.cshtml, About.es-cl.cshtml /// </summary> /// <param name="name">Culture's name</param> /// <returns></returns> public static bool IsViewSeparate(string name) { if (Cultures.ContainsKey(name)) return Cultures[name]; return false; } } }

El siguiente paso es crear nuestro propio controlador que detectar el idioma y personalizar la vista. Requerimos hacer uso de dos mtodos de la clase Controller: ExecuteCore y OnActionExecuted. El primero normaliza el idioma, lo almacena en una variable sesin y establece CurrentCulture. En Session[idioma] vamos a almacenar el idioma que se haya detectado o el que se seleccione (lo veremos luego). De esa manera lo podremos usar en cualquier vista o controlador. El segundo establece la vista que debe abrir el controlador dependiendo del idioma que se haya seleccionado.
using System.Globalization; using System.Threading; using System.Web.Mvc; using _3_MvcGlobalization.Helpers; namespace _3_MvcGlobalization.Controllers { public class UaController : Controller { protected override void OnActionExecuted(ActionExecutedContext filterContext) { // Detectamos si llamamos desde una vista var view = filterContext.Result as ViewResultBase; if (view == null) // En caso de que no sea, salims return; string cultureName = Thread.CurrentThread.CurrentCulture.Name; // Buscamos si if (cultureName == CultureHelper.GetDefaultCulture()) return; // Are views implemented separately for this culture? if not exit bool viewImplemented = CultureHelper.IsViewSeparate(cultureName); if (viewImplemented == false) return; string viewName = view.ViewName; int i; if (string.IsNullOrEmpty(viewName)) viewName = filterContext.RouteData.Values["action"] + "." + cultureName; // Index.en-US else if ((i = viewName.IndexOf('.')) > 0) { // contains . like "Index.cshtml" viewName = viewName.Substring(0, i + 1) + cultureName + viewName.Substring(i); } else viewName += "." + cultureName; // e.g. "Index" ==> "Index.en-Us" view.ViewName = viewName; Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

20

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

filterContext.Controller.ViewBag._culture = "." + cultureName; base.OnActionExecuted(filterContext); }

protected override void ExecuteCore() { var idioma = Session["idioma"]; string cultureName; if (idioma != null) cultureName = idioma.ToString(); else { cultureName = (Request.UserLanguages == null ? CultureHelper.GetDefaultCulture() : Request.UserLanguages[0]); if (cultureName.IndexOf("-") > 0) cultureName = cultureName.Substring(0, cultureName.IndexOf("-")); Session["idioma"] = cultureName; } // Normalizamos var normalizedCultureName = CultureHelper.GetValidCulture(cultureName); if (normalizedCultureName != cultureName) { cultureName = normalizedCultureName; Session["idioma"] = cultureName; } // Actualizamos el idioma Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName); Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName); base.ExecuteCore(); } } }

PLANTILLA
Por defecto la plantilla que se usa es la que se configure en /Views/ _ViewStart.cshtml. Por seguir con este criterio, si modificamos este fichero y usamos la variable Session[idioma] tendremos la plantilla que se debe usar.
@{ Layout = "~/Views/Shared/_Layout." + @Session["idioma"] + ".cshtml"; }

En clase lo optimizaremos para que no se produzcan errores cuando no est definida esta variable.

CAMBIAR DE IDIOMA
Nuestra plantilla permite cambiar el icioma
public ActionResult ChangeLanguage(string language) { Session["idioma"] = language; if (Request.UrlReferrer != null) Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

21

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4


return Redirect(Request.UrlReferrer.ToString()); return Redirect("Index"); } [ @Html.ActionLink("English", "ChangeLanguage", "Home", new { language = "en" }, null) ] [ @Html.ActionLink("Espaol", "ChangeLanguage", "Home", new { language = "es" }, null) ] [ @Html.ActionLink("Valenci", "ChangeLanguage", "Home", new { language = "ca" }, null) ]

En caso de que nos enven un idioma que no se corresponda con el listado admitido, no habr problemas porque en la siguiente llamada a Index (o la pgina desde donde se llam) se detectar que no se corresponde con uno de los admitidos y se asignar el que tengamos por defecto.

MODELO
Siguiendo el ejemplo del libro de antes, si queremos que la descripcin del ttulo salga del fichero de recursos remplazamos
[Display(Name = "Ttulo del libro")] public string Titulo { get; set; }

por
[Display(Name = "tituloLabel", ResourceType = typeof(Resources.modelos))] public string Titulo { get; set; }

En caso de que nos de un error de que no se encuentra un recurso pblico con ese nombre, recordar lo de marcar Public en el fichero de recursos.

POCO
Cuando el modelo de los datos lo gestionamos desde EF se complica la posibilidad de incluir data annotations porque no disponemos de forma sencilla el modelo y los atributos. Lo vamos a hacer de forma manual para comprender el proceso. Creamos una clase partial donde indiquemos los campos y podamos aadir las anotaciones.
public partial class CSI_LIBRO { .... }

Todos los campos se declaran de tipo virtual para no interferir con la declaracin de EF
public partial class CSI_LIBRO { public virtual decimal ID { get; set; } public virtual string ISBN { get; set; }

Ahora ya podemos incluir las anotaciones sin problemas.


Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

22

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Generar cdigo automtico El proceso anterior se puede gestionar cuando tenemos tablas bsicas como con las que estamos trabajando estas semanas, pero es inviable con una aplicacin con varias tablas y con muchos campos cada un de stas. Por eso EF incluye una opcin de generar este cdigo de forma automtica. SI pulsamos el botn derecho sobre una tabla veremos que disponemos de la opcin Agregar elemento de generacin de cdigo.

Nos abre una ventana que tiene seleccionado por defecto la plantilla de Datos. Seleccionamos Cdigo y nos saldr una lista de plantillas. Seleccionamos EF 4.X POCO Entity Generator. Le ponemos un nombre en la parte inferior, ModelBiblioteca.tt y pulsamos Agregar.

Volveremos al EF y aparentemente no veremos nada nuevo. Ha aadido una referencias y nos ha creado el fichero ModelBiblioteca.Context.tt y ModelBiblioteca.tt.

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

23

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

Si pulsamos sobre la flecha que hay a la izquierda de ModelBiblioteca.tt veremos que aparecen las tablas y/o vistas que tengamos en nuestro EF.

Si abrimos una de estas clases veremos que es de tipo parcial y con todos los campos definidos como virtual. Ahora le podemos aadir los atributos que veamos necesarios. Si por ejemplo a los tipos de libros le inclumos:
[Required] [Display(Name = "Descripcin")] public virtual string DESCRIPCION

Veremos los resultados cuando creemos o modifiquemos un tipo de libro. No nos permite dejarlo en blanco y la decripcin del campo pasa de DESCRIPCION a Descripcin.

Aunque hemos visto que el proceso es muy sencillo y que se crea de forma muy rpida, debemos tener mucho cuidado con las actualizaciones en la base de datos y en el modelo EF. Un cambio en el EF implicar un cambio en el cdigo generado con POCO. Lo ms comn y viendo su sencillez es borrarlo y volverlo a crear. Todas nuestras anotaciones se perdern en este proceso.
Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

24

ASP.NET MVC 3 Y 4 | DESARROLLO DE APLICACIONES CON EL FRAMEWORK MVC 3 Y 4

PROYECTO
CREAR TABLAS BSICAS, CONTROLADORES BSICOS Y MASTER PAGE

Andrs Valls Botella | Analista | Desarrollos propios Servicio de Informtica | Universidad de Alicante Campus de Sant Vicent del Raspeig | 03690 | Espaa http://si.ua.es/es

25

Potrebbero piacerti anche