[Reseña] Curso de CampusMVP para la certificación 70-515

Muy buenas! Los chicos de CampusMVP me han dado la ocasión de revisar uno de sus cursos, en concreto el que tienen para preparar la certificación 70-515 (desarrollo de aplicaciones web). Y el resultado es este post 😉

Antes que nada comentaros que yo ya tengo esta certificación, así que me ha sido muy fácil a posteriori ver si el curso cubría lo que entra en el exámen.

El sistema de aprendizaje

Estamos hablando de un curso on-line, por lo tanto tiene las ventajas y desventajas de todo curso on-line. La ventaja es que puedes dedicarte al cuando mejor te vaya: no hay horario fijo. Y esta resulta ser también su mayor desventaja. No malinterpretéis, me refiero a que se requiere cierta disciplina y fuerza de voluntad para sacar el curso adelante. A veces, todo aquello que no tiene un horario fijo tendemos a dejarlo para más adelante, y la verdad es que para aprovechar el curso se requiere invertir un montón de horas. En concreto la duración de este curso está estimada en unos 4 meses (16 semanas), dedicando de 8 a 10 horas cada semana. No se si os parece mucho o poco, pero si os parece mucho dejadme que os diga, que el esfuerzo vale la pena.

El sistema de aprendizaje es muy simple: primero hay una lección escrita y finalmente un soporte en vídeo. Me ha sorprendido muy gratamente el detalle de esos vídeos (y reconozco que con el tiempo que le he dedicado me ha sido imposible verlos todos!). Y además hay soporte del tutor del curso a través de foros y un sistema de mensajería instantanea. De hecho creo que éste es un punto diferencial con otros cursos.

Ah sí! Y también regalan acceso a tests de MeasureUp, para probar nuestros conocimientos con algo que se parezca al exámen real (mi experiencia con los tests de MeasureUp es que suelen ser más difíciles que el exámen real).

En las instrucciones del curso envían la metodología de uso, que no por simple deja de ser efectiva: leer, ver el vídeo, practicar y finalmente reflexionar e intentar ir más allá. Lo que comentaba al principio: es un curso que requiere esfuerzo, pero honestamente creo que vale la pena.

El temario

El curso está dividido en módulos, pero estos módulos no se corresponden a los módulos funcionales del 70-515, sinó que simplemente son módulos tecnológicos. Es decir se engloban las cuatro grandes tecnologías que conforman el ecosistema de desarrollo de aplicaciones web en .NET. Que son:

  1. Webforms ASP.NET 4
  2. ASP.NET Ajax
  3. ASP.NET MVC
  4. jQuery

Si os sorprende la presencia de jQuery, os digo que tiene mucho sentido, primero porque se ha convertido en un estándard de facto y segundo porque jQuery entra como temario en el 70-515.

Las versiones de los productos están adecuados a lo que se pide en el examen, así p.ej. no esperéis encontrar nada de MVC3 en el módulo de ASP.NET MVC, ya que el 70-515 está basado en MVC2. De este modo se evita confundir al alumno y evitar que responda incorrectamente preguntas (de una manera que podría ser correcta en MVC3 pero incorrecta en MVC2 p.ej.).

La relación con el 70-515

MMmmm… en el fondo creo que el 70-515 es una mera excusa que han aprovechado en CampusMVP para realizar un fabuloso curso sobre el desarrollo de aplicaciones web en tecnologías Microsoft. A ver, lo que se cuenta en el curso va mucho más allá de lo que se pide para aprobar el 70-515. Y esa decisión de CampusMVP me parece fenomenal, porque precisamente el 70-515 es un exámen que considero muy mal enfocado y muy sesgado en sus preguntas (opinión personal, por supuesto).

Todos los módulos (cada módulo es un mini-curso que empieza con lo básico y termina con técnicas avanzadas), tienen mucha, mucha información y abarcan mucho más de lo que el 70-515 demanda.

Yo no sé si este curso garantiza el aprobado del 70-515 como dicen en CampusMVP. Lo que sí sé, es que el temario del curso, y el cómo está explicado harán que aprendas de verdad el desarrollo de aplicaciones web en tecnologías Microsoft. Si has seguido bien el curso y has asmiliado bien los conceptos, ya te digo que lo que sabes es mucho más que lo que el 70-515 pide.

En resumen, si lo que quieres es aprender a desarrollar aplicaciones web, con tecnologías modernas (la úñtima versión de webforms y la penúltima de MVC) en .NET, este curso es un candidato que deberías tener en cuenta. Es un todo-en-uno en tecnologías web, sencillamente excelente.

Un saludo a todos!

PD: Edito (18/04/2011) para poner enlaces 😉

  1. Curso de Campus MVP para la preparación del 70-515 (el que he analizado)
  2. Otros cursos de Campus MVP sobre tecnologías MS
  3. Tienda on-line de Campus MVP

[ASP.NET MVC] Pasar parámetros a través del PathInfo

¡Muy buenas! Bueno, el título del post no queda demasiado claro, pero a ver si consigo explicar un poco la idea. 😉

Los que habéis usado ASP.NET MVC estáis muy acostumbradas a las URLs del estilo /controlador/accion/id, es decir algo como:

  • /Home/Index/10
  • /Articles/View/Eiximenis
  • /Blog/View/10293

Sabemos que gracias a la tabla de rutas podemos pasar tantos parámetros como queramos, y así podríamos tener URLs del tipo:

  • /Articles/View/Eiximenis/MVC/2011

Que podría devolverme los articulos de “Eiximenis” con el tag “MVC” y del año 2011.

El único punto a tener presente es que el orden de los parámetros importa, es decir no es lo mismo /Articles/View/Eiximenis/MVC/2011 que /Articles/View/2011/MVC/Eiximenis. En el primer caso buscamos los artículos de Eiximenis sobre MVC en el 2011 y en el segundo caso buscaríamos los artículos del blogger 2011, sobre MVC en el año de Eiximenis. Y sin duda Fra Francesc Eiximenis, fue un gran escritor, pero que yo sepa todavía no se le ha dedicado un año (algo totalmente injusto, por supuesto :p).

En este artículo quiero enseñaros una manera para que podáis gestionar URLs del tipo:

  • /Articles/View/Author/Eiximenis/Tag/MVC/Year/2011
  • /Articles/View/Tag/MVC/Year/2011/Author/Eiximenis

Y que ambas URLs sean tratadas de forma idéntica. En este caso estaríamos pasando tres parámetros: Author, Tag y Year.

Para conseguir este efecto nos bastan dos acciones muy simples: definir un route handler nuevo y una entrada a la tabla de rutas.

El route handler lo único que debe hacer es recoger la información de la URL y parsearla en “tokens” (usando el ‘/’ como separador). Y por cada par de tokens añadir una entrada en los valores de ruta (route values). El código es muy simple:

public class UrlRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var path = requestContext.RouteData.Values["pathInfo"];
if (path != null)
{
var tokens = path.ToString().Split('/');
for (var idx =0; idx<tokens.Length; idx+=2)
{
if (idx+1 < tokens.Length)
{
requestContext.RouteData.Values.Add(tokens[idx], tokens[idx+1]);
}
}
}

return base.GetHttpHandler(requestContext);
}
}

Una pequeña nota es que la cadena que separamos en tokens, no es toda la URL sino “pathInfo” un parámetro de ruta que ya nos vendrá dado. Este parámetro de ruta contendrá todo aquello que no es ni el controlador ni la acción. Es decir en la URL /Articles/View/Author/Eiximenis/Tag/MVC/Year/2011 el valor de pathInfo será Author/Eiximenis/Tag/MVC/Year/2011 (que son justo los parámetros).

Ahora nos queda añadir la entrada a la tabla de rutas. En mi ejemplo yo he eliminado la entrada “Default” que genera VS2010 y la he sustituído por:

routes.Add("Default", new Route(url: "{controller}/{action}/{*pathInfo}",
routeHandler: new UrlRouteHandler(),
defaults: new RouteValueDictionary(new {controller = "Home", action = "Index"})));

La clave aquí está en el {*pathInfo}. Aquí le digo al sistema de rutas que coja todo lo que venga después de /{controller}/{action} y me lo añada a un parámetro de ruta llamado pathInfo. Además de eso, en esta ruta le indico que su routeHandler será una instancia de la clase UrlRouteHandler que hemos creado antes.

Y listos! Una vez los datos están en el route value ya puede entrar en acción el sistema de binding de ASP.NET MVC lo que quiere decir que puedo crear un controlador como el siguiente:

public class ArticlesController : Controller
{
public ActionResult View(string author, string tag, int? year)
{
dynamic data = new ExpandoObject();
data.Author = author ?? "Sin formato";
data.Tag = tag ?? "Sin confirmación";
data.Year = year.HasValue ? year.ToString() : "Sin año";
return View(data);
}
}

Que recibiría los parámetros de las URLs que hemos visto anteriormente.

Un saludo a todos!

[jQuery tmpl] Pasar elemento de template como parámetro a una función del template

Bueno… Vaya título me ha salido, eh? 😛 A ver, realmente este post es para evitar que alguien pierda el mismo tiempo que he pedido yo, para una chorrada…

En fin, al tajo. No sé si conocéis jQuery templates. Para los que no, que sepáis que es un plugin de jQuery para convertir objetos json en html. No es la única manera de hacerlo, hace tiempo escribí sobre PURE (http://beebole.com/pure/) otra herramienta para hacer lo mismo, y que os animo a que al menos le echéis un vistazo. Poco después apareció la alfa de jquery-tmpl (y siguiendo con el autobombo escribí una pequeña comparativa, que, todo debe reconocerse, hoy ha quedado un poco desfasada). Poco después se anunció que jQuery-tmpl pasaba a ser considerado plugin oficial de jQuery y se pasó a llamar “jQuery templates”. Actualmente está en beta, pero ya es extremadamente estable. Luis Ruiz Pavón escribió un artículo introductorio a jQuery templates que os recomiendo que le echéis un vistazo (aunque la sintaxis actual sea un poco diferente a la de ese artículo, es lo que tiene escribir sobre versiones alfa y demás).

En jQuery templates se usan básicamente “tres” cosas:

  1. Una definición de template, que se suele incorporar dentro de un tag <script> con un type inválido para que el navegador lo ignore (no lo incorpore al DOM).
  2. Un contenedor donde se incrustará el DOM generado.
  3. Un objeto json inicio de los datos.

La sintaxis para definir el template es el punto fuerte de jQuery templates:

<script type="text/javascript">
$(document).ready(function () {
var data = { nombre: 'edu', twitter: 'eiximenis' };

$("#template").tmpl(data).appendTo("#placeholder");
});
</script>

<script id="template" type="text/x-jquery-tmpl">
<div style="background: green">Usuario ${nombre} - Twitter: <a href="http://twitter.com/${twitter}">${twitter}</a>
</script>

<div id="placeholder"></div>

Este código, en tiempo de ejcución genera el DOM siguiente:

<div style="background: green;">Usuario edu - Twitter: <a href="http://twitter.com/eiximenis">eiximenis</a></div>

Hay varios tags para controlar el template. Para este post vamos a ver uno, que es {{each}} que permite repetir parte del template por cada elemento del array:

<script type="text/javascript">
$(document).ready(function () {
var data = {
titulo: 'Twitters en geeks',
users: [{ nombre: 'edu', twitter: 'eiximenis' },
{ nombre: 'jorge', twitter: 'j0rgeSerran0' },
{ nombre: 'javi', twitter: 'jtorrecilla' },
]
};

$("#template").tmpl(data).appendTo("#placeholder");
});
</script>

<script id="template" type="text/x-jquery-tmpl">

<div style="background: #EEEEEE">
<h4>${titulo}</h4>
{{each users}}
Usuario ${$value.nombre} - Twitter: <a href="http://twitter.com/${twitter}">${$value.twitter}</a><br />
{{/each}}
</div>
</script>

<div id="placeholder"></div>

Con {{each}} iteramos sobre los elementos del array “users”. Dentro del template el valor $value me permite referenciar el valor del array para el que se está renderizando el template (p.ej. ${$value.nombre} me permite acceder al nombre del elemento que se está renderizando). Si el nombre de $value no nos gusta, lo podemos indicar como parámetro de each:

<script id="template" type="text/x-jquery-tmpl">
<div style="background: #EEEEEE">
<h4>${titulo}</h4>
{{each(idx, user) users}}
<strong>${idx}:</strong>Usuario ${user.nombre} - Twitter: <a href="http://twitter.com/${twitter}">${user.twitter}</a><br />
{{/each}}
</div>
</script>

En este código podemos usar ${idx} para acceder al índice del elemento y ${user} para acceder a cada elemento que se está renderizando.

Bien, vayamos ahora al tema del post…

Una cosilla interesante es que a la llamada a tmpl() se le puede pasar un segundo parámetro, con datos adicionales globables que pueden usarse en el template. Esos parámetros pueden ser, entre otras cosas, funciones. Para acceder a los elementos “globales” se usa la variable de template $item. Imaginad que tenemos esto ahora:

<script type="text/javascript">
$(document).ready(function () {
var data = {
titulo: 'Twitters en geeks',
users: [{ nombre: 'edu', twitter: 'eiximenis' },
{ nombre: 'jorge', twitter: 'j0rgeSerran0' },
{ nombre: 'javi', twitter: 'jtorrecilla' },
{ nombre: 'alguien' }
]
};

$("#template").tmpl(data,
{ getUrl: function (name) { return name != undefined ? "http://twitter.com/" + name : '#'; } }).appendTo("#placeholder");
});
</script>

Como segundo parámetro a tmpl() le pasamos un objeto con una función getUrl que dado una cadena me construirá la URL de twitter asociada. Si el la cadena es undefined, me generará una URL que no haga nada (#). Ahora toca llamar a esta función desde el template:

<script id="template" type="text/x-jquery-tmpl">
<div style="background: #EEEEEE">
<h4>${titulo}</h4>
{{each(idx, user) users}}
<strong>${idx}:</strong>Usuario ${user.nombre} -
Twitter: <a href="${$item.getUrl(${user.twitter})}">${user.twitter}</a><br />
{{/each}}
</div>
</script>

Fijaos que llamamos a getUrl usando $item.getUrl() (porque getUrl está definido en el ámbito global del template). Y como parámetro le pasamos el valor de la propiedad twitter del elemento que estamos renderizando. Esto, yo suponía que era ${user.twitter}. Pero eso no funciona. No aparece el template y en su lugar aparece un error de javascript en jquery-tmpl.js. Eso es muy común: errores en el template generan errores de javascript dentro de jquery-tmpl.js.

Después de varios intentos descubrí que pasaba: Cuando se pasan parámetros a una función definida dentro del ámbito global del template esos parámetros de pasan sin ${}. Es decir debemos usar:

<script id="template" type="text/x-jquery-tmpl">
<div style="background: #EEEEEE">
<h4>${titulo}</h4>
{{each(idx, user) users}}
<strong>${idx}:</strong>Usuario ${user.nombre} -
Twitter: <a href="${$item.getUrl(user.twitter)}">${user.twitter}</a><br />
{{/each}}
</div>
</script>

Fijaos en la llamada a getUrl, ahora simplemente la pasamos getUrl(user.twitter). Y eso funciona correctamente!

Así pues:

  • ${$item.getUrl(${user.name})} –> NO FUNCIONA
  • ${item.getUrl(user.name)} –> FUNCIONA CORRECTAMENTE

En fin… cosillas que descubre uno 😉

Saludos!