<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:gr="http://www.google.com/schemas/reader/atom/" xmlns:idx="urn:atom-extension:indexing" idx:index="no" gr:dir="ltr"><!--
Content-type: Preventing XSRF in IE.

--><generator uri="http://www.google.com/reader">Google Reader</generator><id>tag:google.com,2005:reader/user/09819328367926521350/label/aspnetmvc</id><title>"aspnetmvc" via Marc Climent in Google Reader</title><gr:continuation>CLfCsdizt6QC</gr:continuation><author><name>Marc Climent</name></author><updated>2011-02-11T10:22:17Z</updated><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/climens_aspnetmvc" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="climens_aspnetmvc" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gr:crawl-timestamp-msec="1297419737606"><id gr:original-id="tag:blogger.com,1999:blog-27752126.post-6670495499129919078">tag:google.com,2005:reader/item/0704b1b3de8d9601</id><category term="desarrollo" scheme="http://www.blogger.com/atom/ns#" /><category term="asp.net" scheme="http://www.blogger.com/atom/ns#" /><category term="aspnetmvc" scheme="http://www.blogger.com/atom/ns#" /><title type="html">WebGrid en MVC 3, paso a paso (y II)</title><published>2011-02-07T10:59:00Z</published><updated>2011-02-10T08:13:54Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/vnf/~3/8ANhhXhlMjA/webgrid-en-mvc-3-paso-paso-y-ii.html" type="text/html" /><link rel="replies" href="http://www.variablenotfound.com/feeds/6670495499129919078/comments/default" title="Enviar comentarios" type="application/atom+xml" /><link rel="replies" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=6670495499129919078" title="5 comentarios" type="text/html" /><link rel="canonical" href="http://www.variablenotfound.com/2011/02/webgrid-en-mvc-3-paso-paso-y-ii.html" /><content xml:base="http://www.variablenotfound.com/" type="html">&lt;img align="right" alt="ASP.NET MVC" border="0" height="77" src="http://lh5.ggpht.com/_O9D62hXq-ng/TU_KhVcc7CI/AAAAAAAABc0/LIXIPXJrs9M/ASPNETMVC2.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;float:right;margin:0px 0px 10px 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="ASP.NET MVC" width="142"&gt;Días atrás comentábamos por aquí &lt;a href="http://www.variablenotfound.com/2011/02/webgrid-en-mvc-3-paso-paso.html" title="WebGrid en MVC 3, paso a paso"&gt;cómo utilizar el helper WebGrid de MVC 3&lt;/a&gt; para crear rejillas de datos, partiendo de un ejemplo muy sencillo, apenas un par de líneas de código, e introduciendo sucesivas mejoras hasta llegar a un interfaz bastante aceptable para manejar conjuntos de datos con paginación, ordenación, y columnas personalizadas.&lt;br&gt;
&lt;br&gt;
&lt;img alt="WebGrid, con algo de estilo" border="0" height="542" src="http://lh5.ggpht.com/_O9D62hXq-ng/TTxuS7gBi_I/AAAAAAAABcM/3QupqoTzC9E/image3.png?imgmax=800" title="WebGrid, con algo de estilo" width="670"&gt;&lt;br&gt;
&lt;br&gt;
Sin embargo, también comentábamos que la pasmosa simplicidad con la que podíamos poner en marcha un grid completo tenía su coste: por defecto, &lt;strong&gt;WebGrid necesita disponer de una copia en memoria del conjunto completo de datos sobre el que actúa&lt;/strong&gt;. Sí, completo :-O.&lt;br&gt;
&lt;br&gt;
Es decir, si tenemos un millón de filas de nuestra base de datos y queremos mostrarlas en un orden concreto y por páginas, debemos suministrar a WebGrid una colección con el millón de entidades materializadas en memoria; el helper las ordenará según el criterio activo en ese momento, contará el total de elementos, calculará las páginas necesarias para mostrarlos en función del número de elementos por página definidos, y obtendrá el subconjunto de instancias correspondientes a la página actual. Tras ello, generará el grid y el mecanismo de paginación que podemos ver en su pie.&lt;br&gt;
&lt;br&gt;
Obviamente, el impacto en el rendimiento de nuestro sistema puede ser terrible. La materialización de entidades no es un proceso rápido, como tampoco lo es la ordenación en memoria cuando el número de elementos es importante. Y lo peor es que el procedimiento completo se repite para cada petición y usuario conectado, lo que hace que utilizar los mecanismos de paginación y ordenación por defecto no sea una buena idea la mayoría de las veces.&lt;br&gt;
&lt;br&gt;
Sin duda es bastante mejor delegar al motor de base de datos las tareas de ordenación y selección de filas, y materializar en memoria sólo las entidades que sean necesarias en la vista actual, es decir, la página de datos visible. ¿Lo hacemos?&lt;br&gt;
&lt;h3&gt;
1. El Modelo, revisitado&lt;/h3&gt;
Recordemos que en el &lt;a href="http://www.variablenotfound.com/2011/02/webgrid-en-mvc-3-paso-paso.html" title="WebGrid en MVC 3, paso a paso"&gt;post anterior&lt;/a&gt; teníamos una clase de servicios del Modelo simplísima, con un único método llamado &lt;code&gt;ObtenerPersonas()&lt;/code&gt;, que utilizaba un contexto de objetos de Entity Framework para obtener todas las instancias de la clase Persona almacenadas en la base de datos:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; &lt;span style="color:blue"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ModelServices&lt;/span&gt;: &lt;span style="color:#2b91af"&gt;IDisposable&lt;/span&gt;
{
    &lt;span style="color:blue"&gt;private&lt;/span&gt; &lt;span style="color:blue"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af"&gt;DatosEntities&lt;/span&gt; _datos = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;DatosEntities&lt;/span&gt;();
 
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt; ObtenerPersonas()
    {
        &lt;span style="color:blue"&gt;return&lt;/span&gt; _datos.Personas.ToList();
    }
 
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;void&lt;/span&gt; Dispose()
    {
        _datos.Dispose();
    }
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
En este caso, dado que pretendemos delegar al Modelo la responsabilidad de paginar y ordenar adecuadamente los datos antes de enviarlos a WebGrid, necesitamos añadirle dos nuevos métodos: &lt;code&gt;ContarPersonas()&lt;/code&gt;, y &lt;code&gt;ObtenerPaginaDePersonas()&lt;/code&gt;.&lt;br&gt;
&lt;br&gt;
El primero de ellos, &lt;code&gt;ContarPersonas()&lt;/code&gt;, que retornará el número de elementos totales existentes en la base de datos. Ya hemos comentado antes que WebGrid podía obtener este dato simplemente contando el total de elementos presentes en el origen de datos, pero como ahora pretendemos pasarle sólo los datos de la página actual, esta información debemos indicársela expresamente para que pueda construir el mecanismo de paginación correctamente.&lt;br&gt;
&lt;br&gt;
El código de este método es bastante simple:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:10pt"&gt;&lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;int&lt;/span&gt; ContarPersonas()
{
        &lt;span style="color:blue"&gt;return&lt;/span&gt; _datos.Personas.Count();
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Vamos ahora a implementar &lt;code&gt;ObtenerPaginaDePersonas()&lt;/code&gt;. Como seguro podréis intuir, su objetivo es retornar el conjunto de instancias de Persona que deben aparecer en una página concreta de datos, teniendo en cuenta el número de elementos por página empleado y el criterio de ordenación actual. &lt;br&gt;
&lt;br&gt;
Asumiendo que estamos utilizando LINQ, la obtención de una página concreta de datos es trivial utilizando los operadores &lt;code&gt;Skip()&lt;/code&gt; y &lt;code&gt;Take()&lt;/code&gt;. La única dificultad con la que podemos encontrarnos es la forma de pasar al Modelo el criterio de ordenación actual, pero, como podemos comprobar a continuación hay muchas formas de conseguirlo, casi tantas como desarrolladores que se enfrenten a ella. Para que os hagáis una idea, veremos dos posibilidades: utilizando expresiones de cadena, y basada en expresiones lambda.&lt;br&gt;
&lt;h4&gt;
1.1. ObtenerPaginaDePersonas(), &lt;em&gt;magic string edition&lt;/em&gt;&lt;/h4&gt;
Una posibilidad bastante sencilla de implementar consiste en que el Modelo reciba directamente una cadena de caracteres en la que se encuentre la expresión de ordenación utilizada. Si podemos asegurar, además, que esta cadena venga ya escrita en Entity SQL, simplemente tendríamos que insertar la cláusula de ordenación apropiada:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt; 
  ObtenerPaginaDePersonas(&lt;span style="color:blue"&gt;int&lt;/span&gt; paginaActual, &lt;span style="color:blue"&gt;int&lt;/span&gt; personasPorPagina, &lt;span style="color:blue"&gt;string&lt;/span&gt; criterioOrdenacion)
  {
     &lt;span style="color:blue"&gt;if&lt;/span&gt; (paginaActual&amp;lt;1) paginaActual = 1;
      &lt;span style="color:blue"&gt;return&lt;/span&gt; _datos.Personas
        .OrderBy(criterioOrdenacion)
        .Skip((paginaActual - 1) * personasPorPagina)
        .Take(personasPorPagina)
        .ToList();
  }&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
De esta forma, podemos invocar al Modelo pasándole directamente expresiones como “&lt;code&gt;it.Apellidos DESC&lt;/code&gt;”,  “&lt;code&gt;it.FechaNacimiento ASC&lt;/code&gt;”, o incluso combinaciones como “&lt;code&gt;it.Apellidos DESC, it.Nombre DESC&lt;/code&gt;”, que funcionarán perfectamente. Observad que la sintaxis debe ser eSQL (de ahí el prefijo “&lt;code&gt;it.&lt;/code&gt;” que llevan delante las propiedades del objeto actual).&lt;br&gt;
&lt;br&gt;
Este enfoque, aunque bastante sencillo y rápido de implementar tiene algunas contraindicaciones. El hecho de escribir estas expresiones en el interior de cadenas de texto hace que éstas sean inmunes a refactorizaciones o comprobaciones en tiempo de compilación, lo que aumenta la probabilidad de aparición de errores difíciles de detectar. Asimismo, estamos confiando ciegamente en que la expresión es eSQL sintáctica y semánticamente correcto, por lo que o bien nos arriesgamos a que reviente en tiempo de ejecución si no introducimos las comprobaciones oportunas, o bien debemos delegar a otro componente (por ejemplo, al Controlador) la responsabilidad de construir siempre expresiones válidas.&lt;br&gt;
&lt;h4&gt;
1.2. ObtenerPaginaDePersonas(), &lt;em&gt;lambda edition&lt;/em&gt;&lt;/h4&gt;
Si queremos evitar el envío de información en cadenas de texto, podemos seguir el enfoque propuesto por LINQ y utilizar árboles de expresión para trasladar los criterios de ordenación al Modelo.&lt;br&gt;
&lt;br&gt;
En este caso, el método del Modelo recibirá, además de la página actual y el número de filas por página, un árbol de expresión que contiene la expresión de ordenación, y un elemento de la enumeración &lt;code&gt;Direccion&lt;/code&gt; indicando si debe ordenarse ascendente o descendentemente. El código podría ser como el siguiente:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt; ObtenerPaginaDePersonas&amp;lt;T&amp;gt;(
           &lt;span style="color:blue"&gt;int&lt;/span&gt; paginaActual, &lt;span style="color:blue"&gt;int&lt;/span&gt; personasPorPagina, 
           &lt;span style="color:#2b91af"&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;,T&amp;gt;&amp;gt; ordenacion, 
           &lt;span style="color:#2b91af"&gt;Direccion&lt;/span&gt; direccion)
{
    &lt;span style="color:blue"&gt;if&lt;/span&gt; (paginaActual&amp;lt;1) paginaActual = 1;
    &lt;span style="color:#2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt; query = _datos.Personas; 
    &lt;span style="color:blue"&gt;if&lt;/span&gt; (direccion == &lt;span style="color:#2b91af"&gt;Direccion&lt;/span&gt;.Ascendente)
        query = query.OrderBy(ordenacion);
    &lt;span style="color:blue"&gt;else&lt;/span&gt;
        query = query.OrderByDescending(ordenacion);
    &lt;span style="color:blue"&gt;return&lt;/span&gt; query.Skip((paginaActual - 1) * personasPorPagina)
                .Take(personasPorPagina)
                .ToList();
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Como se puede observar, se trata de un &lt;a href="http://www.variablenotfound.com/2008/11/mtodos-genricos-en-c.html"&gt;método genérico&lt;/a&gt; para dar cobertura a los distintos tipos de propiedad por los que es posible ordenar, que es el tipo de retorno del árbol de expresión &lt;code&gt;ordenacion&lt;/code&gt;.&lt;br&gt;
&lt;br&gt;
También se puede ver que se aprovecha de la ejecución diferida de LINQ to SQL para ir especificando de forma sucesiva las distintas cláusulas de la consulta. Ésta no será ejecutada hasta el final, en la llamada al método &lt;code&gt;ToList()&lt;/code&gt;, que es cuando realmente se materializarán las instancias de Persona presentes en la página de datos actual.&lt;br&gt;
&lt;br&gt;
De esta forma, conseguimos que desde el Controlador podamos obtener la página de datos, por ejemplo, así:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:10pt"&gt;&lt;span style="color:blue"&gt;var&lt;/span&gt; personas = _services.ObtenerPaginaDePersonas(
                      page, 
                      personasPorPagina, 
                      p=&amp;gt;p.NumeroDeHijos,     &lt;span style="color:green"&gt;// Expresión ordenación&lt;/span&gt;
                      &lt;span style="color:#2b91af"&gt;Direccion&lt;/span&gt;.Descendente   &lt;span style="color:green"&gt;// Ascendente&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Observad que, a diferencia de la técnica que vimos anteriormente, aquí sí que usamos tipado fuerte para indicar la ordenación. Un cambio de nombre de la propiedad &lt;code&gt;NumeroDeHijos&lt;/code&gt;, por ejemplo, sería refactorizada correctamente o, cuanto menos, generaría un error en compilación.&lt;br&gt;
&lt;br&gt;
Como principal inconveniente, decir que no es tan potente y flexible como la anterior. Por ejemplo, en este caso no podemos indicar de forma inmediata más de una propiedad de ordenación, cosa que antes sí era muy sencillo. Eso sí, en nuestro escenario, dado que vamos a ordenar según columnas independientes del grid, tampoco este aspecto es demasiado importante.&lt;br&gt;
&lt;br&gt;
En definitiva, existen gran cantidad de posibilidades para implementar el método del Modelo que retorna las instancias pertenecientes a una página concreta de datos atendiendo a los criterios de ordenación especificados. Aquí hemos visto un par de ellas, pero basta con pararse a pensarlo un rato y fácilmente podremos idear un buen puñado más de soluciones. &lt;br&gt;
&lt;br&gt;
Vamos a pasar a estudiar ahora qué cambios debemos realizar en el Controlador para realizar la paginación correcta.&lt;br&gt;
&lt;h3&gt;
2. El Controlador&lt;/h3&gt;
Si habéis descargado el ejemplo del &lt;a href="http://www.variablenotfound.com/2011/02/webgrid-en-mvc-3-paso-paso.html" title="WebGrid en MVC 3, paso a paso"&gt;post anterior&lt;/a&gt; u os habéis peleado un poco con WebGrid, habréis notado que el mantenimiento del estado de la rejilla se realiza propagando entre llamadas una serie de parámetros en el &lt;em&gt;query string&lt;/em&gt; que, por defecto, son los siguientes:&lt;br&gt;
&lt;br&gt;
&lt;img align="right" alt="Querystring en peticiones generadas por WebGrid" border="0" height="109" src="http://lh6.ggpht.com/_O9D62hXq-ng/TU_KiHFGusI/AAAAAAAABc4/rI3uC3dapHA/image4.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;float:right;margin:0px 0px 10px 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="Querystring en peticiones generadas por WebGrid" width="462"&gt;&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;page&lt;/em&gt;, que indica el número de página actual, &lt;/li&gt;
&lt;li&gt;&lt;em&gt;sort&lt;/em&gt;, la columna por la que estamos ordenando, &lt;/li&gt;
&lt;li&gt;&lt;em&gt;sortDir&lt;/em&gt;, la dirección de ordenación actual, indicada con las constantes “ASC” o “DESC”. &lt;/li&gt;
&lt;/ul&gt;
Básicamente se trata de la misma información que debemos suministrar al Modelo, previamente adaptada, para obtener la relación de personas de la página actual, por lo que el primer paso será utilizar la magia del binder para poder obtener estos valores directamente desde nuestra acción del controlador. De hecho, el siguiente podría ser un buen esqueleto de partida:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; &lt;span style="color:#2b91af"&gt;ActionResult&lt;/span&gt; Index(&lt;span style="color:blue"&gt;int&lt;/span&gt; page = 1, &lt;span style="color:blue"&gt;string&lt;/span&gt; sort = &lt;span style="color:#a31515"&gt;"Apellidos"&lt;/span&gt;, &lt;span style="color:blue"&gt;string&lt;/span&gt; sortDir = &lt;span style="color:#a31515"&gt;"ASC"&lt;/span&gt;)
{
    &lt;span style="color:green"&gt;// Obtener el número total de personas&lt;/span&gt;
    &lt;span style="color:green"&gt;// Obtener la colección de personas de la página actual&lt;/span&gt;
    &lt;span style="color:green"&gt;// Retornar la vista suministrándole esos datos&lt;/span&gt;
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Observad el uso de parámetros opcionales para la acción, en los que especificamos un valor por defecto para cuando no estén indicados de forma explícita en la petición.&lt;br&gt;
&lt;br&gt;
Ya en el cuerpo del método, la obtención del número de personas es inmediata gracias al método &lt;code&gt;ContarPersonas()&lt;/code&gt; que hemos creado anteriormente en el Modelo. La obtención de las personas para poblar la rejilla depende del enfoque utilizado en la implementación del método &lt;code&gt;ObtenerPaginaDePersonas()&lt;/code&gt;. A continuación veremos algunas posibilidades, aunque antes vamos a pararnos en otro detalle.&lt;br&gt;
&lt;br&gt;
A diferencia del ejemplo del &lt;a href="http://www.variablenotfound.com/2011/02/webgrid-en-mvc-3-paso-paso.html" title="WebGrid en MVC 3, paso a paso"&gt;post anterior&lt;/a&gt;, en el que la Vista sólo necesitaba una lista de personas para maquetarse, en esta ocasión debemos suministrarle alguna información más:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;el número de personas por página, &lt;/li&gt;
&lt;li&gt;la colección de personas, aunque sólo las presentes en la página actual, &lt;/li&gt;
&lt;li&gt;el número total de personas, para que WebGrid pueda crear la herramienta de navegación por páginas. &lt;/li&gt;
&lt;/ul&gt;
Por tanto, nos encontramos ante un escenario “de manual” para el uso de una entidad View Model, que contendrá toda esta información. Su definición podría ser la siguiente:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; &lt;span style="color:blue"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;PaginaDePersonasViewModel&lt;/span&gt;
{
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;int&lt;/span&gt; NumeroDePersonas { &lt;span style="color:blue"&gt;get&lt;/span&gt;; &lt;span style="color:blue"&gt;set&lt;/span&gt;; }
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt; Personas { &lt;span style="color:blue"&gt;get&lt;/span&gt;; &lt;span style="color:blue"&gt;set&lt;/span&gt;; }
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;int&lt;/span&gt; PersonasPorPagina { &lt;span style="color:blue"&gt;get&lt;/span&gt;; &lt;span style="color:blue"&gt;set&lt;/span&gt;; }
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
De esta forma, podemos ir ya dando forma al cuerpo de la acción, que quedaría de la siguiente manera:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; &lt;span style="color:#2b91af"&gt;ActionResult&lt;/span&gt; Index(&lt;span style="color:blue"&gt;int&lt;/span&gt; page = 1, &lt;span style="color:blue"&gt;string&lt;/span&gt; sort = &lt;span style="color:#a31515"&gt;"Apellidos"&lt;/span&gt;, &lt;span style="color:blue"&gt;string&lt;/span&gt; sortDir = &lt;span style="color:#a31515"&gt;"ASC"&lt;/span&gt;)
{
    &lt;span style="color:blue"&gt;&lt;span style="color:blue"&gt;const&lt;/span&gt; &lt;span style="color:blue"&gt;int&lt;/span&gt; &lt;span style="color:black"&gt;personasPorPagina = 10;&lt;/span&gt;
    var &lt;span style="color:black"&gt;numPersonas&lt;/span&gt; = &lt;span style="color:black"&gt;_services.ContarPersonas();&lt;/span&gt;    var&lt;/span&gt; personas = ... &lt;span style="color:green"&gt;// Obtener la colección de personas&lt;/span&gt;
    
    &lt;span style="color:blue"&gt;var&lt;/span&gt; datos = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;PaginaDePersonasViewModel&lt;/span&gt;()
                    {
                        NumeroDePersonas = numPersonas,
                        PersonasPorPagina = filasPorPagina,
                        Personas = personas
                    };
    &lt;span style="color:blue"&gt;return&lt;/span&gt; View(datos);
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Como comentábamos anteriormente, la obtención de las personas a mostrar en la página actual dependerá de la implementación del Modelo. Veremos algunas posibilidades.&lt;br&gt;
&lt;br&gt;
Una solución muy simple aunque bastante cándida e inocentona, basada en la primera de las implementaciones del Modelo que hemos visto anteriormente, podría ser la siguiente:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; personas = _services.ObtenerPaginaDePersonas(
                     page, 
                     personasPorPagina, 
                     &lt;span style="color:#a31515"&gt;"it."&lt;/span&gt; + sort + &lt;span style="color:#a31515"&gt;" "&lt;/span&gt; + sortDir
               );&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Como podemos observar, construimos directamente la expresión de ordenación en Entity SQL basándonos en los parámetros recibidos en el &lt;em&gt;query string&lt;/em&gt;. Obviamente, y dado que estos parámetros son fácilmente manipulables, un nombre de columna incorrecta o una dirección distinta de “ASC” o “DESC” provocarían una excepción en tiempo de ejecución:&lt;br&gt;
&lt;br&gt;
&lt;img alt="Error al ordenar por una columna inexistente" border="0" height="417" src="http://lh5.ggpht.com/_O9D62hXq-ng/TU_KjSFg1FI/AAAAAAAABc8/cRvnTIZhMX4/image12.png?imgmax=800" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:block;float:none;margin:0px auto 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="Error al ordenar por una columna inexistente" width="650"&gt;&lt;br&gt;
Este error es fácil de evitar simplemente introduciendo código que compruebe estos parámetros y establezca valores por defecto en caso de existir algún problema, como el mostrado a continuación, donde comprobamos que la columna de ordenación se encuentra en una “lista blanca” de columnas permitidas, y que la ordenación es ascendente o descendente:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:10pt"&gt;...
sortDir = sortDir.Equals(&lt;span style="color:#a31515"&gt;"desc"&lt;/span&gt;, &lt;span style="color:#2b91af"&gt;StringComparison&lt;/span&gt;.CurrentCultureIgnoreCase) ? sortDir : &lt;span style="color:#a31515"&gt;"asc"&lt;/span&gt;;
&lt;span style="color:blue"&gt;var&lt;/span&gt; validColumns = &lt;span style="color:blue"&gt;new&lt;/span&gt;[] { &lt;span style="color:#a31515"&gt;"apellidos"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"fechanacimiento"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"email"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"numerodehijos"&lt;/span&gt; };
&lt;span style="color:blue"&gt;if&lt;/span&gt; (!validColumns.Any(c =&amp;gt; c.Equals(sort, &lt;span style="color:#2b91af"&gt;StringComparison&lt;/span&gt;.CurrentCultureIgnoreCase)))
    sort = &lt;span style="color:#a31515"&gt;"apellidos"&lt;/span&gt;;
&lt;span style="color:blue"&gt;var&lt;/span&gt; personas = _services.ObtenerPaginaDePersonas(
                    page, 
                    personasPorPagina, 
                    &lt;span style="color:#a31515"&gt;"it."&lt;/span&gt; + sort + &lt;span style="color:#a31515"&gt;" "&lt;/span&gt; + sortDir
              );
...&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Si en cambio preferimos utilizar en el Modelo la opción que vimos anteriormente basada en el uso de árboles de expresión, también podemos crear un código que suministre los criterios de ordenación en función de la columna y dirección actual:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:#2b91af"&gt;&lt;span style="font-size:10pt"&gt;IEnumerable&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt; personas;
&lt;span style="color:#2b91af"&gt;Direccion&lt;/span&gt; dir = sortDir.Equals(&lt;span style="color:#a31515"&gt;"ASC"&lt;/span&gt;, &lt;span style="color:#2b91af"&gt;StringComparison&lt;/span&gt;.CurrentCultureIgnoreCase) ? 
                        &lt;span style="color:#2b91af"&gt;Direccion&lt;/span&gt;.Ascendente:
                        &lt;span style="color:#2b91af"&gt;Direccion&lt;/span&gt;.Descendente;
 
&lt;span style="color:blue"&gt;switch&lt;/span&gt;(sort.ToLower())
{
  &lt;span style="color:blue"&gt;case&lt;/span&gt; &lt;span style="color:#a31515"&gt;"fechanacimiento"&lt;/span&gt;:
    personas = _services.ObtenerPaginaDePersonas(page, personasPorPagina, p =&amp;gt; p.FechaNacimiento, dir);
    &lt;span style="color:blue"&gt;break&lt;/span&gt;;
  c&lt;span style="color:blue"&gt;ase&lt;/span&gt; &lt;span style="color:#a31515"&gt;"numerodehijos"&lt;/span&gt;:
    personas = _services.ObtenerPaginaDePersonas(page, personasPorPagina, p =&amp;gt; p.NumeroDeHijos, dir);
    &lt;span style="color:blue"&gt;break&lt;/span&gt;;
  &lt;span style="color:blue"&gt;case&lt;/span&gt; &lt;span style="color:#a31515"&gt;"email"&lt;/span&gt;:
    personas = _services.ObtenerPaginaDePersonas(page, personasPorPagina, p =&amp;gt; p.EMail, dir);
    &lt;span style="color:blue"&gt;break&lt;/span&gt;;
  &lt;span style="color:blue"&gt;case&lt;/span&gt; &lt;span style="color:#a31515"&gt;"apellidos"&lt;/span&gt;:
    personas = _services.ObtenerPaginaDePersonas(page, personasPorPagina, p =&amp;gt; p.Apellidos, dir);
    &lt;span style="color:blue"&gt;break&lt;/span&gt;;
  &lt;span style="color:blue"&gt;default&lt;/span&gt;:
    personas = _services.ObtenerPaginaDePersonas(page, personasPorPagina, p =&amp;gt; p.Apellidos, dir);
    &lt;span style="color:blue"&gt;break&lt;/span&gt;;
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
En el proyecto que podréis descargar desde el enlace disponible al final del post, encontraréis ambas implementaciones completas.&lt;br&gt;
&lt;br&gt;
Antes de pasar a la Vista, veamos el código completo del controlador pasando los criterios de ordenación al Modelo mediante cadenas. Exceptuando las líneas introducidas para mejorar la legibilidad del código, apenas llegamos a la docena de líneas para completar la acción:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="color:blue"&gt;&lt;span style="font-size:10pt"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt; &lt;span style="color:blue"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Demo2Controller&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;Controller&lt;/span&gt;
{
    &lt;span style="color:blue"&gt;private&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ModelServices&lt;/span&gt; _services = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ModelServices&lt;/span&gt;();
 
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ActionResult&lt;/span&gt; Index(&lt;span style="color:blue"&gt;int&lt;/span&gt; page = 1, &lt;span style="color:blue"&gt;string&lt;/span&gt; sort = &lt;span style="color:#a31515"&gt;"Apellidos"&lt;/span&gt;, &lt;span style="color:blue"&gt;string&lt;/span&gt; sortDir = &lt;span style="color:#a31515"&gt;"ASC"&lt;/span&gt;)
    {
        &lt;span style="color:blue"&gt;const&lt;/span&gt; &lt;span style="color:blue"&gt;int&lt;/span&gt; personasPorPagina = 10;
        &lt;span style="color:blue"&gt;var&lt;/span&gt; numPersonas = _services.ContarPersonas();
 
        sortDir = sortDir.Equals(&lt;span style="color:#a31515"&gt;"desc"&lt;/span&gt;, &lt;span style="color:#2b91af"&gt;StringComparison&lt;/span&gt;.CurrentCultureIgnoreCase) ? sortDir : &lt;span style="color:#a31515"&gt;"asc"&lt;/span&gt;;
        
        &lt;span style="color:blue"&gt;var&lt;/span&gt; validColumns = &lt;span style="color:blue"&gt;new&lt;/span&gt;[] { &lt;span style="color:#a31515"&gt;"apellidos"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"fechanacimiento"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"email"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"numerodehijos"&lt;/span&gt; };
        &lt;span style="color:blue"&gt;if&lt;/span&gt; (!validColumns.Any(c =&amp;gt; c.Equals(sort, &lt;span style="color:#2b91af"&gt;StringComparison&lt;/span&gt;.CurrentCultureIgnoreCase)))
            sort = &lt;span style="color:#a31515"&gt;"apellidos"&lt;/span&gt;;
        
        &lt;span style="color:blue"&gt;var&lt;/span&gt; personas = _services.ObtenerPaginaDePersonas(
                 page, 
                 personasPorPagina, 
                 &lt;span style="color:#a31515"&gt;"it."&lt;/span&gt; + sort + &lt;span style="color:#a31515"&gt;" "&lt;/span&gt; + sortDir
        );
 
        &lt;span style="color:blue"&gt;var&lt;/span&gt; datos = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;PaginaDePersonasViewModel&lt;/span&gt;()
        {
            NumeroDePersonas = numPersonas,
            PersonasPorPagina = personasPorPagina,
            Personas = personas
        };
        &lt;span style="color:blue"&gt;return&lt;/span&gt; View(datos);
    }
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;h3&gt;
3. La Vista&lt;/h3&gt;
La mayor parte de la Vista que implementamos en el &lt;a href="http://www.variablenotfound.com/2011/02/webgrid-en-mvc-3-paso-paso.html" title="WebGrid en MVC 3, paso a paso"&gt;post anterior&lt;/a&gt; sigue siendo válida, sólo tendremos que retocarle un par de detalles que encontramos en las primeras cuatro líneas.&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;&lt;span style="font-size:10pt"&gt;@model &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:10pt"&gt;WebGridDemo.ViewModels.&lt;span style="color:#2b91af"&gt;PaginaDePersonasViewModel&lt;/span&gt;
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@{&lt;/span&gt;&lt;/span&gt;
    ViewBag.Title = &lt;span style="color:#a31515"&gt;"Personas"&lt;/span&gt;;
    &lt;span style="color:#2b91af"&gt;WebGrid&lt;/span&gt; grid = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;WebGrid&lt;/span&gt;(rowsPerPage: Model.PersonasPorPagina);
    grid.Bind(Model.Personas, autoSortAndPage: &lt;span style="color:blue"&gt;false&lt;/span&gt;, rowCount: Model.NumeroDePersonas);   &lt;/span&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow;font-size:12pt"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
En la primera línea, en la directiva &lt;span style="background-color:yellow"&gt;@model&lt;/span&gt; debemos definir el tipo de datos recibidos desde el Controlador, que como ya hemos visto, en este caso se trata de una instancia de &lt;code&gt;PaginaDePersonasViewModel&lt;/code&gt; que contiene toda la información que necesita la Vista para maquetarse apropiadamente.&lt;br&gt;
&lt;br&gt;
A continuación, tras establecer el título de la página, instanciamos el WebGrid suministrándole a su constructor el valor del parámetro &lt;code&gt;rowsPerPage&lt;/code&gt;, el número de filas por página que estamos utilizando, que es el mismo usado por el Controlador a la hora de solicitar los datos al Modelo.&lt;br&gt;
&lt;br&gt;
Finalmente, invocamos a su método &lt;code&gt;Bind()&lt;/code&gt;, donde podemos indicamos:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;el conjunto de Personas a mostrar en la página actual, &lt;/li&gt;
&lt;li&gt;que no deseamos utilizar la ordenación y paginación automática, estableciendo &lt;code&gt;autoSortAndPage&lt;/code&gt; a &lt;code&gt;false&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;mediante el parámetro &lt;code&gt;rowCount&lt;/code&gt;, el número total de personas almacenadas en la base de datos. &lt;/li&gt;
&lt;/ul&gt;
Y afortunadamente, esto es todo lo que necesitamos hacer en la Vista. Por supuesto, no es necesario tocar nada en lo relativo a la definición de columnas, formatos, etc.&lt;br&gt;
&lt;h3&gt;
4. Y recapitulando…&lt;/h3&gt;
A lo largo de este post hemos vuelto a recorrer el Modelo, Controlador y Vista que ya implementamos hace unos días, comentando los cambios que tenemos que hacer para conseguir una paginación de datos más eficiente.&lt;br&gt;
&lt;br&gt;
Hemos visto distintas alternativas para implementar el Modelo, basadas en Entity Framework. No son las únicas posibilidades ni mucho menos, pero espero al menos que os den ideas para implementar vuestras propias soluciones. También hemos reescrito el Controlador, implementando el consumo de estos servicios del Modelo para obtener justo la información que necesitamos para mostrar una página de datos, y la hemos pasado a la Vista, a la que hemos tenido que hacer sólo ligeras modificaciones.&lt;br&gt;
&lt;br&gt;
Finalmente, como el post ha quedado algo extenso, repasamos rápidamente qué es necesario hacer para implementar un WebGrid con una paginación eficiente:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;En el Modelo:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Necesitamos un mecanismo para obtener el número total de elementos.&lt;/li&gt;
&lt;li&gt;Asimismo, tendremos que crear un método para obtener los elementos pertenecientes a una página concreta, atendiendo a los criterios de ordenación suministrados.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;En el Controlador:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Debemos capturar los parámetros &lt;code&gt;page&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt; y &lt;code&gt;sortDir&lt;/code&gt; de la petición, a través de los cuales podremos conocer la página a mostrar, la columna y dirección de ordenación, respectivamente.&lt;/li&gt;
&lt;li&gt;Obtener desde el Modelo el número total de elementos, así como el conjunto de instancias pertenecientes a la página actual de datos, según los criterios de ordenación actuales.&lt;/li&gt;
&lt;li&gt;Retornar la vista, suministrándole:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Los datos a mostrar.&lt;/li&gt;
&lt;li&gt;El total de elementos.&lt;/li&gt;
&lt;li&gt;El número de elementos por página que estamos usando&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;li&gt;En la Vista: &lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Indicar, al instanciar el WebGrid, el número de elementos por página (dato enviado desde el Controlador).&lt;/li&gt;
&lt;li&gt;Enlazar en WebGrid a la colección suministrada por el Controlador, desactivando la paginación y ordenación automática, e indicándole el total de elementos disponibles.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
Y eso es todo. En total, aunque depende de la solución empleada, introducir una paginación eficiente a nuestros WebGrids no debe suponer mucho más de una veintena de líneas, que seguro vale la pena introducir dados los beneficios aportados al rendimiento de nuestras aplicaciones  :-) &lt;br&gt;
&lt;br&gt;
&lt;img align="left" alt="image" border="0" height="57" src="http://lh3.ggpht.com/_O9D62hXq-ng/TU_Kj7SYBLI/AAAAAAAABdA/4vRFQR2Y0yM/image16.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;float:left;margin:0px 0px 10px 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="image" width="55"&gt;&lt;br&gt;
Como en otras ocasiones, podéis &lt;a href="http://cid-c3a43a99b617d787.office.live.com/self.aspx/P%c3%bablico/variablenotfound.com/ASP.NET%20MVC/ASP.NET%20MVC%203/WebGrid/WebGridPaginadoDemo.zip"&gt;descargar el proyecto desde SkyDrive&lt;/a&gt; (requiere VS2010, SQL Express y ASP.NET MVC 3). ¡Que aproveche! ;-)&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;div&gt;&lt;img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/27752126-6670495499129919078?l=www.variablenotfound.com" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/iveid3oitg2k07u8r44sagtpvs/468/60#http%3A%2F%2Fwww.variablenotfound.com%2F2011%2F02%2Fwebgrid-en-mvc-3-paso-paso-y-ii.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=8ANhhXhlMjA:ULpqdhc2Vg0:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=8ANhhXhlMjA:ULpqdhc2Vg0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=8ANhhXhlMjA:ULpqdhc2Vg0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=8ANhhXhlMjA:ULpqdhc2Vg0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=8ANhhXhlMjA:ULpqdhc2Vg0:4cEx4HpKnUU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=8ANhhXhlMjA:ULpqdhc2Vg0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=8ANhhXhlMjA:ULpqdhc2Vg0:F7zBnMyn0Lo" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=8ANhhXhlMjA:ULpqdhc2Vg0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=8ANhhXhlMjA:ULpqdhc2Vg0:gIN9vFwOqvQ" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=8ANhhXhlMjA:ULpqdhc2Vg0:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=I9og5sOYxJI" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/8ANhhXhlMjA" height="1" width="1"&gt;</content><author><name>José M. Aguilar</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/vnf"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/vnf</id><title type="html">Variable not found</title><link rel="alternate" href="http://www.variablenotfound.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1297419729975"><id gr:original-id="http://davidhayden.com/blog/dave/archive/2011/02/09/SessionLessControllersMvc3.aspx">tag:google.com,2005:reader/item/d4bae4666cce5798</id><title type="html">SessionLess Controllers in ASP.NET MVC 3 - SessionState Attribute</title><published>2011-02-09T12:07:00Z</published><updated>2011-02-09T12:07:00Z</updated><link rel="alternate" href="http://davidhayden.com/blog/dave/archive/2011/02/09/SessionLessControllersMvc3.aspx" type="text/html" /><summary xml:base="http://davidhayden.com:80/blog" type="html">A look at the ability to disable, enable, and make session state read-only in ASP.NET MVC 3.&lt;img src="http://davidhayden.com/blog/dave/aggbug/4204.aspx" width="1" height="1"&gt;</summary><author><name>Dave Hayden</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/DavidHayden"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/DavidHayden</id><title type="html">Blog</title><link rel="alternate" href="http://davidhayden.com:80/blog" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1296643508162"><id gr:original-id="tag:blogger.com,1999:blog-27752126.post-6287464583570307465">tag:google.com,2005:reader/item/d5c2df99bc7fe2b5</id><category term="desarrollo" scheme="http://www.blogger.com/atom/ns#" /><category term="asp.net" scheme="http://www.blogger.com/atom/ns#" /><category term="aspnetmvc" scheme="http://www.blogger.com/atom/ns#" /><title type="html">WebGrid en MVC 3, paso a paso</title><published>2011-02-01T09:07:00Z</published><updated>2011-02-01T09:07:33Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/vnf/~3/GE3gZXVmeiA/webgrid-en-mvc-3-paso-paso.html" type="text/html" /><link rel="replies" href="http://www.variablenotfound.com/feeds/6287464583570307465/comments/default" title="Enviar comentarios" type="application/atom+xml" /><link rel="replies" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=6287464583570307465" title="5 comentarios" type="text/html" /><link rel="canonical" href="http://www.variablenotfound.com/2011/02/webgrid-en-mvc-3-paso-paso.html" /><content xml:base="http://www.variablenotfound.com/" type="html">&lt;img alt="ASP.NET MVC" border="0" src="http://3.bp.blogspot.com/_O9D62hXq-ng/TTxz4HPTMFI/AAAAAAAABcY/E9oDlcD3ss0/s1600/ASPNETMVC.png" style="float:right;margin:0px 0px 10px 10px"&gt; Una de las preguntas que recibo con más frecuencia vía &lt;a href="http://kontactr.com/user/jmaguilar" rel="Contactar" title="Contactar"&gt;formulario de contacto&lt;/a&gt; en el blog, en sus comentarios, y en los cursos de MVC es cómo implementar grids, las habituales rejillas de datos que se suelen utilizar en interfaces de gestión de datos, con capacidades de paginación y ordenación. &lt;br&gt;
&lt;br&gt;
Dado que hasta MVC 3 no había un soporte oficial para implementar esta funcionalidad desde la propia plataforma, nos veíamos obligados a buscarnos un poco la vida, y o bien usar el andamiaje generado por Visual Studio y desarrollar a mano las paginaciones y ordenaciones (¡uf!), o utilizar componentes externos (como el de &lt;a href="http://mvccontrib.codeplex.com/wikipage?title=Grid" title="Grid en MVCContrib"&gt;MVCContrib&lt;/a&gt;, &lt;a href="http://www.telerik.com/products/aspnet-mvc/grid.aspx" title="Grid for ASP.NET MVC"&gt;Telerik&lt;/a&gt;, &lt;a href="http://www.variablenotfound.com/2009/10/jqgrid-grids-espectaculares-para-aspnet.html" title="jqGrid, grids espectaculares para ASP.NET MVC"&gt;jqGrid&lt;/a&gt; u otros).&lt;br&gt;
&lt;br&gt;
La última versión de ASP.NET MVC, de la mano de la tecnología WebPages, nos trae un nuevo conjunto de helpers de productividad bastante interesantes en el espacio de nombres &lt;em&gt;System.Web.Helpers&lt;/em&gt;, entre los cuales encontramos &lt;strong&gt;WebGrid&lt;/strong&gt;, que por fin ofrece una solución “de serie” potente y flexible para ayudarnos a implementar esta funcionalidad de uso tan frecuente en nuestras aplicaciones. &lt;br&gt;
&lt;br&gt;
Vamos a ver, paso a paso y de forma totalmente práctica, cómo utilizar WebGrid. Al final de post, además, encontraréis un enlace para descargar el proyecto completo para VS2010+SQL Express.&lt;br&gt;
&lt;h3&gt;
1. Lo primero: el Modelo&lt;/h3&gt;
&lt;img alt="Estructura de la tabla en la base de datos" border="0" height="148" src="http://1.bp.blogspot.com/_O9D62hXq-ng/TTxzrt1jm-I/AAAAAAAABcU/gisYuHA5OYU/s320/bdd.png" style="float:right;margin:0px 0px 10px 10px" width="320"&gt;Lo primero que necesitamos antes de empezar a profundizar en el helper WebGrid es un Modelo, las entidades de datos de nuestra aplicación, así como los mecanismos que nos permitan hacer persistente y recuperar la información desde el sistema de almacenamiento que estemos utilizando.&lt;br&gt;
&lt;br&gt;
En este caso, vamos a utilizar como almacén una base de datos SQL Express con una única tabla, en la que hemos creado una tabla para guardar datos de personas; esta colección es la que pretendemos mostrar en forma de rejilla de datos, por lo que necesitamos poblarla con algunos datos para probar más adelante.&lt;br&gt;
&lt;br&gt;
&lt;img alt="Entity Data Model" border="0" src="http://4.bp.blogspot.com/_O9D62hXq-ng/TTx0Ssxyh5I/AAAAAAAABcc/gumhs7YXIso/s1600/edm.png" style="float:right;margin:0px 0px 10px 10px"&gt; Para acceder a la base de datos vamos a utilizar Entity Framework, por lo que  necesitaremos también un Entity Data Model, un modelo conceptual de entidades, que podemos agregar a la carpeta Models del proyecto utilizando la opción “Agregar nuevo elemento” del menú contextual. En el asistente que aparece, sólo debemos indicarle que vamos a generar el modelo desde una base de datos existente, seleccionamos la tabla Personas, y listo.&lt;br&gt;
&lt;br&gt;
Con esto tenemos ya la infraestructura básica de datos de nuestra aplicación. El siguiente paso será crear una clase de servicios, que será la que provea la lógica de negocio y acceso a datos para nuestro sistema.&lt;br&gt;
&lt;br&gt;
Obviamente esto no tiene por qué ser siempre así, depende de nuestras necesidades y de la arquitectura del software, y en nuestro ejemplo van a ser ambos aspectos bastante simples.&lt;br&gt;
&lt;br&gt;
El código inicial de nuestra clase de servicios es el siguiente:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:small"&gt;&lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ModelServices&lt;/span&gt;: &lt;span style="color:#2b91af"&gt;IDisposable&lt;/span&gt;
{
    &lt;span style="color:blue"&gt;private&lt;/span&gt; &lt;span style="color:blue"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af"&gt;DatosEntities&lt;/span&gt; _datos = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;DatosEntities&lt;/span&gt;();
 
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt; ObtenerPersonas()
    {
        &lt;span style="color:blue"&gt;return&lt;/span&gt; _datos.Personas.ToList();
    }
 
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;void&lt;/span&gt; Dispose()
    {
        _datos.Dispose();
    }
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Como se puede observar en el código anterior, tenemos un único método, llamado &lt;code&gt;ObtenerPersonas()&lt;/code&gt;, que retorna el conjunto completo de personas almacenadas en la base de datos.&lt;br&gt;
&lt;br&gt;
Y de momento, he aquí todo el Modelo que necesitamos de momento.&lt;br&gt;
&lt;h3&gt;
2. El controlador&lt;/h3&gt;
Nuestra clase del controlador, que llamaremos &lt;code&gt;PersonasController&lt;/code&gt;, en este primer acercamiento va a ser realmente sencilla. Una única acción, &lt;code&gt;Index()&lt;/code&gt;, que retornará una vista a la que suministraremos la colección de datos obtenida desde el Modelo:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:small"&gt;&lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;PersonasController&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;Controller&lt;/span&gt;
{
    &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ActionResult&lt;/span&gt; Index()
    {
        &lt;span style="color:blue"&gt;var&lt;/span&gt; datos = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ModelServices&lt;/span&gt;().ObtenerPersonas();
        &lt;span style="color:blue"&gt;return&lt;/span&gt; View(datos);
    }
}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Y esto es todo: una acción con dos líneas. Vale, podría haber sido una única línea, pero así el código me parecía más legible ;-)&lt;br&gt;
&lt;h3&gt;
3. La vista, toma primera: WebGrid entra en escena&lt;/h3&gt;
Ahora es cuando vamos a empezar a notar las ventajas de utilizar WebGrid respecto a las opciones disponibles hasta MVC y que ya hemos citado al principio del post.&lt;br&gt;
&lt;br&gt;
Observad el siguiente código, una vista Razor que recibe una enumeración de objetos &lt;code&gt;Persona&lt;/code&gt; desde el controlador y genera un grid completo:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-size:small"&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@model &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;WebGridDemo.Models.&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt;
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@{&lt;/span&gt;&lt;/span&gt;
    ViewBag.Title = &lt;span style="color:#a31515"&gt;"Personas"&lt;/span&gt;;
    &lt;span style="color:#2b91af"&gt;WebGrid&lt;/span&gt; grid = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;WebGrid&lt;/span&gt;(Model);
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span style="color:blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon"&gt;h2&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;Personas&lt;span style="color:blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon"&gt;h2&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;grid.GetHtml()&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Impresionante, ¿eh? Aunque pueda parecer increíble, el código anterior es todo lo que necesitamos para montar un grid funcionalmente completo, con paginación y ordenación por columnas: ¡dos líneas! En la primera de ellas instanciamos el WebGrid suministrándole la colección de datos sobre la que debe iterar, y en la segunda (ya al final) generamos el marcado HTML que enviaremos al cliente.&lt;br&gt;
&lt;br&gt;
El resultado en ejecución lo podemos ver en la siguiente captura de pantalla:&lt;br&gt;
&lt;br&gt;
&lt;img alt="WebGrid en ejecución" border="0" height="546" src="http://lh3.ggpht.com/_O9D62hXq-ng/TTxuLhuUVlI/AAAAAAAABb8/qUX4--lhDt0/image18.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;padding-left:0px;padding-right:0px;padding-top:0px" title="WebGrid en ejecución" width="677"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Aunque todavía queda algo lejos de la perfección, el resultado es espectacular. &lt;br&gt;
&lt;br&gt;
El helper, en su comportamiento por defecto, muestra una columna por cada propiedad que encuentra en la clase sobre la que itera, eso sí, ordenándolas alfabéticamente. Además, ha utilizado el nombre de las propiedades como encabezado de columna, y las muestra como enlaces para forzar la ordenación por cada una de ellas, e incluso ha introducido en el pie un sistema completo de navegación por las páginas de datos. &lt;br&gt;
&lt;br&gt;
Y lo mejor que todo esto funciona directamente, sin necesidad de añadir una línea de código más :-)&lt;br&gt;
&lt;br&gt;
Sin embargo, como siempre, estos automatismos tienen su precio. Por un lado, no estamos controlando las columnas a mostrar, ni el formato en que sus valores son presentados (observad, por ejemplo, la fecha de nacimiento), ni sus encabezados… Normalmente, necesitaremos esforzarnos algo más (aunque no demasiado) para dejarlo todo perfecto.&lt;br&gt;
&lt;br&gt;
Además, &lt;strong&gt;existe un serio problema de rendimiento&lt;/strong&gt; cuando el número de elementos del grid sea importante: tanto la ordenación como la paginación se realizan en memoria con el número total de elementos. Exagerando, si tenemos un millón de filas en la base de datos, se materializarán en memoria un millón de objetos, serán ordenados según el criterio actual y, finalmente, sólo serán mostrados al cliente los diez objetos que contiene una página de datos. Veremos más adelante que hay fórmulas para gestionar de forma eficiente estos escenarios.&lt;br&gt;
&lt;h3&gt;
4. La vista, toma segunda: las columnas que yo quiera, por favor&lt;/h3&gt;
Existen distintas fórmulas para especificar las columnas a mostrar en un WebGrid. La primera de ellas, es mediante exclusión sobre el conjunto total de propiedades. Entre muchos otros aspectos, en el método &lt;code&gt;GetHtml()&lt;/code&gt; podemos especificar un array de nombres de propiedad que no deben mostrarse como columnas. Por ejemplo, sobre el ejemplo anterior, si no nos interesa mostrar la propiedad &lt;code&gt;IdPersona&lt;/code&gt;, podríamos haber sustituido la última línea de la vista por:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-size:small"&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;grid.GetHtml(exclusions: &lt;span style="color:blue"&gt;new&lt;/span&gt;[] {&lt;span style="color:#a31515"&gt;"IdPersona"&lt;/span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Sin embargo, el enfoque anterior no es demasiado útil, puesto que normalmente querremos indicar el orden de aparición de las columnas, especificar sus encabezados, determinar si las columnas pueden ser utilizadas como criterios de ordenación, etc. Toda esta información se define en objetos &lt;code&gt;WebGridColumn&lt;/code&gt;.&lt;br&gt;
&lt;br&gt;
Aunque hay otras formas de hacerlo, habitualmente encontraremos en el parámetro &lt;code&gt;columns&lt;/code&gt; de la llamada a &lt;code&gt;GetHtml()&lt;/code&gt; un array con el detalle de las columnas del grid, como en el siguiente ejemplo:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:small"&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;grid.GetHtml(columns: &lt;span style="color:blue"&gt;new&lt;/span&gt; [] {
    grid.Column(&lt;span style="color:#a31515"&gt;"Nombre"&lt;/span&gt;),
    grid.Column(&lt;span style="color:#a31515"&gt;"Apellidos"&lt;/span&gt;),
    grid.Column(&lt;span style="color:#a31515"&gt;"EMail"&lt;/span&gt;),
    grid.Column(&lt;span style="color:#a31515"&gt;"FechaNacimiento"&lt;/span&gt;),
    grid.Column(&lt;span style="color:#a31515"&gt;"NumeroDeHijos"&lt;/span&gt;),
})&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Como se puede observar, estamos pasando en el parámetro &lt;code&gt;columns&lt;/code&gt; un array en el que cada elemento lo estamos generando mediante una llamada al método &lt;code&gt;Column()&lt;/code&gt; de WebGrid, en cuyo primer parámetro indicamos el nombre de la propiedad a la que corresponde la columna.&lt;br&gt;
&lt;br&gt;
El resultado de la ejecución del código utilizando este último código sería:&lt;br&gt;
&lt;br&gt;
&lt;img alt="Web grid en ejecución, con mis columnas" border="0" height="588" src="http://lh3.ggpht.com/_O9D62hXq-ng/TTxuNLmadoI/AAAAAAAABcA/oc7SdXnVmaY/image22.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;margin:0px 0px 0px 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="Web grid en ejecución, con mis columnas" width="677"&gt;&lt;br&gt;
&lt;br&gt;
Algo ha mejorado la cosa, aunque todavía tenemos que afinar algo más en cuanto a la presentación.&lt;br&gt;
&lt;h3&gt;
5. La vista, toma tercera: las columnas como yo quiero, por favor&lt;/h3&gt;
Todavía nos quedan varios detalles por apuntalar para que el grid, al menos a efectos visuales, cumpla un mínimo razonable. Para personalizar cada columna, podemos utilizar los parámetros del método generador de columnas &lt;code&gt;Column()&lt;/code&gt; que ya hemos visto anteriormente:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;header&lt;/code&gt;, que permite indicar el texto mostrado en el encabezado, &lt;/li&gt;
&lt;li&gt;&lt;code&gt;canSort&lt;/code&gt;, que indica si la columna puede ser utilizada como criterio de ordenación, &lt;/li&gt;
&lt;li&gt;&lt;code&gt;format&lt;/code&gt;, que permite indicar un formato personalizado para el contenido de la columna, &lt;/li&gt;
&lt;li&gt;&lt;code&gt;style&lt;/code&gt;, que indica la clase CSS que se aplicará a todas las celdas de la columna. &lt;/li&gt;
&lt;/ul&gt;
De todas ellas, sólo merece una especial mención la propiedad format. En ella podemos indicar, bien mediante un bloque de marcado Razor, bien mediante una función lambda, cómo debe formatearse el contenido de la propiedad vinculada a la columna. &lt;br&gt;
&lt;br&gt;
En el primer caso, debemos comenzar el bloque de marcado con el carácter de escape de Razor (&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:small"&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) y seguirlo del código que queremos enviar al cliente. Desde su interior podemos hacer referencia al objeto que está siendo evaluado utilizando &lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;item&lt;/span&gt;, como en el siguiente ejemplo, donde se muestra cómo formatear la columna &lt;code&gt;EMail &lt;/code&gt;para que sea mostrada como un hiperenlace de tipo &lt;em&gt;mailto:&lt;/em&gt;&lt;br&gt;
&lt;pre&gt;&lt;span style="font-size:small"&gt;&lt;span style="font-family:Consolas"&gt;    grid.Column(&lt;span style="color:#a31515"&gt;"EMail"&lt;/span&gt;, 
                 format: &lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon"&gt;a&lt;/span&gt; &lt;span style="color:red"&gt;href&lt;/span&gt;&lt;span style="color:blue"&gt;="mailto:&lt;/span&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;item.Email&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;item.Email&lt;span style="color:blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon"&gt;a&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;
    )&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
Para profundizar en la "magia" que hace posible la utilización de bloques de marcado donde debería haber código, &lt;a href="http://geeks.ms/blogs/etomas/archive/2011/01/25/asp-net-mvc3-razor-templates.aspx"&gt;no os perdáis este magnífico post de Eduard Tomás sobre Razor Templates&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
También podemos utilizar una función lambda, que recibe como parámetro el objeto actual y retorna una cadena (o un &lt;code&gt;IHtmlString&lt;/code&gt; si no debe ser codificada). Por ejemplo, a continuación vemos cómo utilizar esta posibilidad para dar formato a la columna &lt;code&gt;FechaNacimiento&lt;/code&gt;:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-size:small"&gt;&lt;span style="font-family:Consolas"&gt;    grid.Column(&lt;span style="color:#a31515"&gt;"FechaNacimiento"&lt;/span&gt;, 
                format: p=&amp;gt;p.FechaNacimiento.ToShortDateString()
    )&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
Por tanto, teniendo en cuenta todo lo anterior, podemos &lt;em&gt;tunear&lt;/em&gt; un poco el grid utilizando el siguiente código. Como recordatorio, mostraré de nuevo el código completo de la vista, para que podáis observar en su conjunto cómo va quedando:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:small"&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@model &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;WebGridDemo.Models.&lt;span style="color:#2b91af"&gt;Persona&lt;/span&gt;&amp;gt;
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@{&lt;/span&gt;&lt;/span&gt;
    ViewBag.Title = &lt;span style="color:#a31515"&gt;"Personas"&lt;/span&gt;;
    &lt;span style="color:#2b91af"&gt;WebGrid&lt;/span&gt; grid = &lt;span style="color:blue"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;WebGrid&lt;/span&gt;(Model);
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span style="color:blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon"&gt;h2&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;Personas&lt;span style="color:blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon"&gt;h2&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;grid.GetHtml(columns: &lt;span style="color:blue"&gt;new&lt;/span&gt; [] {
    grid.Column(&lt;span style="color:#a31515"&gt;"Nombre"&lt;/span&gt;, canSort: &lt;span style="color:blue"&gt;false&lt;/span&gt;),
    grid.Column(&lt;span style="color:#a31515"&gt;"Apellidos"&lt;/span&gt;),
    grid.Column(&lt;span style="color:#a31515"&gt;"EMail"&lt;/span&gt;, 
                 format: &lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon"&gt;a&lt;/span&gt; &lt;span style="color:red"&gt;href&lt;/span&gt;&lt;span style="color:blue"&gt;="mailto:&lt;/span&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;item.Email&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;item.Email&lt;span style="color:blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon"&gt;a&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;
    ),
    grid.Column(&lt;span style="color:#a31515"&gt;"FechaNacimiento"&lt;/span&gt;, 
                header: &lt;span style="color:#a31515"&gt;"Fecha de nacimiento"&lt;/span&gt;,
                format: p=&amp;gt;p.FechaNacimiento.ToShortDateString()
    ),
    grid.Column(&lt;span style="color:#a31515"&gt;"NumeroDeHijos"&lt;/span&gt;, 
                header: &lt;span style="color:#a31515"&gt;"Número de hijos"&lt;/span&gt;,
                style: &lt;span style="color:#a31515"&gt;"a-la-derecha"&lt;/span&gt;
    )
})&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
En ejecución ya sí que podemos ver algo más terminado:&lt;br&gt;
&lt;br&gt;
&lt;img alt="WebGrid, con las columnas con formato" border="0" height="574" src="http://lh6.ggpht.com/_O9D62hXq-ng/TTxuO5Uq3qI/AAAAAAAABcE/w5OVQHXiwpw/image26.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:block;float:none;margin:0px auto 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="WebGrid, con las columnas con formato" width="676"&gt;&lt;br&gt;
&lt;h3&gt;
6. La vista, toma cuarta: ¿y no puedo añadir columnas personalizadas?&lt;/h3&gt;
¡Pues claro!&lt;br&gt;
&lt;br&gt;
De hecho, basta con añadir columnas exactamente igual que las anteriores, excepto en que no las vincularemos a ninguna propiedad de la clase del Modelo. Esto, combinado con la flexibilidad del formateo personalizado (parámetro &lt;code&gt;format&lt;/code&gt;), nos ofrece ya todo lo que necesitamos para crear columnas totalmente a nuestro antojo.&lt;br&gt;
&lt;br&gt;
El siguiente código muestra cómo añadir una columna adicional con enlaces hacia las acciones que permitirían, por ejemplo, editar o eliminar una Persona:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:small"&gt;&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;grid.GetHtml(columns: &lt;span style="color:blue"&gt;new&lt;/span&gt; [] {

    ... &lt;span style="color:#8fb08c"&gt;// Resto de columnas del grid, vistas anteriormente&lt;/span&gt;
    grid.Column(
          &lt;span style="color:#a31515"&gt;""&lt;/span&gt;, 
          header: &lt;span style="color:#a31515"&gt;"Acciones"&lt;/span&gt;,
          format: &lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&amp;lt;text&amp;gt;&lt;/span&gt;&lt;/span&gt;
                    &lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;Html.ActionLink(&lt;span style="color:#a31515"&gt;"Editar"&lt;/span&gt;,   &lt;span style="color:#a31515"&gt;"Edit"&lt;/span&gt;,   &lt;span style="color:blue"&gt;new&lt;/span&gt; { id=item.IdPersona} )
                    |
                    &lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;Html.ActionLink(&lt;span style="color:#a31515"&gt;"Eliminar"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"Delete"&lt;/span&gt;, &lt;span style="color:blue"&gt;new&lt;/span&gt; { id=item.IdPersona} )
                  &lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;&lt;/span&gt;
    )
})&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
Observad que esta vez, para incrementar la legibilidad del código, estamos utilizando el &lt;em&gt;tag&lt;/em&gt; especial &lt;span style="background-color:yellow"&gt;&amp;lt;text&amp;gt;&lt;/span&gt; de Razor, que nos permite crear bloques de marcado de varias líneas.&lt;br&gt;
&lt;br&gt;
Y el resultado, como el siguiente:&lt;br&gt;
&lt;br&gt;
&lt;img alt="WebGrid, con columnas personalizadas" border="0" height="523" src="http://lh5.ggpht.com/_O9D62hXq-ng/TTxuRI38VNI/AAAAAAAABcI/ZAnw9M4MOV0/image31.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:block;float:none;margin:0px auto 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="WebGrid, con columnas personalizadas" width="675"&gt;&lt;br&gt;
&lt;h3&gt;
7. La vista, toma quinta: mejor casi que lo quiero todo a mi gusto&lt;/h3&gt;
El helper WebGrid ofrece multitud de opciones de personalización adicionales que podemos establecer tanto al llamar a sus distintos métodos como de forma directa. Por ejemplo, &lt;code&gt;GetHtml()&lt;/code&gt; permite indicar los siguientes parámetros, además de los ya vistos:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;headerStyle&lt;/code&gt;, &lt;code&gt;footerStyle&lt;/code&gt;, &lt;code&gt;rowStyle&lt;/code&gt;, &lt;code&gt;alternatingRowStyle&lt;/code&gt;, y selectedRowStyle permite indicar las clases CSS a aplicar a las filas de encabezado, pie, filas de datos alternativas, y fila seleccionada, respectivamente. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;caption&lt;/code&gt;, para especificar un título para la tabla, que será incluido en una etiqueta &lt;code&gt;&amp;lt;caption&amp;gt;&lt;/code&gt; en el encabezado. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;fillEmptyRows&lt;/code&gt;, establecido a &lt;code&gt;true &lt;/code&gt;hace que cada página tenga siempre el mismo número de filas, creando filas en blanco si fuera necesario. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;emptyRowCellValue &lt;/code&gt;indica el valor a mostrar en las celdas de filas vacías. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;mode&lt;/code&gt;, permite especificar el tipo de paginador a generar, eligiéndolo mediante una combinación de elementos de la enumeración &lt;code&gt;WebGridPagerModes&lt;/code&gt;: &lt;br&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WebGridPagerModes.Numeric&lt;/code&gt;: el paginador mostrará enlaces directos a páginas cercanas a la actual. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;WebGridPagerModes.FirsLast&lt;/code&gt;: se mostrarán enlaces para ir a la primera y última página de datos. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;WebGridPagerModes.NextPrevious&lt;/code&gt;: aparecerán enlaces para desplazarse a la página anterior y siguiente. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;WebGridPagerModes.All&lt;/code&gt;: todos los anteriores al mismo tiempo. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;numericLinksCount&lt;/code&gt;: indica el número de páginas que aparecerán, siempre que &lt;code&gt;mode &lt;/code&gt;contenga el valor &lt;code&gt;WebGridPagerModes.Numeric&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;firstText&lt;/code&gt;, &lt;code&gt;previousText&lt;/code&gt;, &lt;code&gt;nextText&lt;/code&gt;, &lt;code&gt;lastText&lt;/code&gt;, permite sustituir los textos que aparecen por defecto en los enlaces de ir a la primera, anterior, siguiente y última página respectivamente. Inicialmente son los habituales “&amp;lt;&amp;lt;”, “&amp;lt;”, “&amp;gt;”, y “&amp;gt;&amp;gt;”. &lt;/li&gt;
&lt;/ul&gt;
Por ejemplo, observad el siguiente código, y su resultado en ejecución una vez hemos creado un par de reglas en la hoja de estilos del sitio web:&lt;br&gt;
&lt;pre&gt;&lt;span style="font-family:Consolas"&gt;&lt;span style="font-size:small"&gt;&lt;span style="color:blue"&gt;...
&amp;lt;&lt;/span&gt;&lt;span style="color:maroon"&gt;h2&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;Personas&lt;span style="color:blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon"&gt;h2&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="background-image:none;background-repeat:repeat"&gt;&lt;span style="background-color:yellow"&gt;@&lt;/span&gt;&lt;/span&gt;grid.GetHtml(
    fillEmptyRows: &lt;span style="color:blue"&gt;true&lt;/span&gt;,
    alternatingRowStyle: &lt;span style="color:#a31515"&gt;"fila-alternativa"&lt;/span&gt;,
    headerStyle: &lt;span style="color:#a31515"&gt;"encabezado-grid"&lt;/span&gt;,
    footerStyle: &lt;span style="color:#a31515"&gt;"pie-grid"&lt;/span&gt;,
    mode: WebGridPagerModes.All,
    firstText: &lt;span style="color:#a31515"&gt;&amp;quot;&amp;lt;&amp;lt; Primera&amp;quot;&lt;/span&gt;,
    previousText: &lt;span style="color:#a31515"&gt;&amp;quot;&amp;lt; Anterior&amp;quot;&lt;/span&gt;,
    nextText: &lt;span style="color:#a31515"&gt;&amp;quot;Siguiente &amp;gt;&amp;quot;&lt;/span&gt;,
    lastText: &lt;span style="color:#a31515"&gt;&amp;quot;Última &amp;gt;&amp;gt;&amp;quot;&lt;/span&gt;,
    columns: &lt;span style="color:blue"&gt;new&lt;/span&gt; [] {
     ... &lt;span style="color:green"&gt;// Definición de columnas vista anteriormente&lt;/span&gt;
})&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img alt="WebGrid, con algo de estilo" border="0" height="542" src="http://lh5.ggpht.com/_O9D62hXq-ng/TTxuS7gBi_I/AAAAAAAABcM/3QupqoTzC9E/image3.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:block;float:none;margin:0px auto 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="WebGrid, con algo de estilo" width="670"&gt;&lt;br&gt;
&lt;br&gt;
Asimismo, el propio constructor de WebGrid permite modificar también numerosos aspectos funcionales del grid mediante los siguientes parámetros:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;defaultSort&lt;/code&gt;, que indica la columna que actuará como ordenación por defecto mientras no se especifique otra. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;rowsPerPage&lt;/code&gt; (por defecto, 10), define el número de filas que aparecerán en cada página. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;canPage&lt;/code&gt;, &lt;code&gt;canSort&lt;/code&gt;, indican respectivamente si el grid va a permitir paginación y ordenación. Por defecto, true en ambos casos. &lt;br&gt;&lt;code&gt;fieldNamePrefix&lt;/code&gt;, que permite indicar el prefijo que será utilizado en los parámetros del query string utilizados por el grid. Esto, por ejemplo, permitiría mostrar varios grids simultáneamente sobre la misma página, sin interferir en su funcionamiento. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;selectionFieldName&lt;/code&gt;, &lt;code&gt;sortFieldName&lt;/code&gt;, &lt;code&gt;sortDirectionFieldName&lt;/code&gt; permiten indicar el nombre de los parámetros usados para mantener el estado de, respectivamente, la fila seleccionada, el campo de ordenación y el sentido de la ordenación. &lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
WebGrid permite incluso el funcionamiento en modo Ajax, es decir, es capaz de mostrar las distintas páginas de datos sin necesidad de recargar la página completa. En este caso, podemos utilizar los parámetros &lt;code&gt;ajaxUpdateContainerId&lt;/code&gt; y &lt;code&gt;ajaxUpdateCallback&lt;/code&gt;, que permiten indicar respectivamente el elemento de la página donde serán mostrados los datos y una función &lt;em&gt;callback&lt;/em&gt; que será llamada tras actualizar el elemento. Esto, si no se me olvida, lo veremos en otro post más adelante.&lt;br&gt;
&lt;h3&gt;
Y recapitulando…&lt;/h3&gt;
A lo largo de este artículo hemos ido profundizando en el uso de WebGrid de forma progresiva, partiendo de un ejemplo realmente simple hasta abordar escenarios de personalización más avanzados. Espero que sirva para mostrar el uso y principales características de este útil y potente helper, que con toda seguridad nos ahorrará bastante trabajo en los proyectos MVC 3.&lt;br&gt;
&lt;br&gt;
Sin embargo, ya he comentado anteriormente que no es oro todo lo que reluce… la paginación implementada por defecto por WebGrid es bastante ineficiente, puesto que necesita tener en memoria el conjunto de datos completo para ordenarlo y extraer únicamente la página solicitada. No es nada complicado implementar de forma correcta esta paginación, pero dado que este post ya ha quedado lo suficientemente extenso, dejaremos su explicación para un artículo posterior.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img align="left" alt="Descargar proyecto" border="0" height="57" src="http://lh4.ggpht.com/_O9D62hXq-ng/TTxuTZRiQPI/AAAAAAAABcQ/vQGgXmsL6_A/image%5B4%5D.png?imgmax=800" style="background-image:none;border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;float:left;margin:0px 0px 10px 10px;padding-left:0px;padding-right:0px;padding-top:0px" title="Descargar proyecto" width="55"&gt;Ah, podéis &lt;a href="http://cid-c3a43a99b617d787.office.live.com/self.aspx/P%c3%bablico/variablenotfound.com/ASP.NET%20MVC/ASP.NET%20MVC%203/WebGrid/WebGridDemo.zip" title="Descargar proyecto desde Skydrive"&gt;descargar el proyecto de demostración desde mi Skydrive&lt;/a&gt; (requiere VS2010, MVC 3 y SQL Express).&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;div&gt;&lt;img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/27752126-6287464583570307465?l=www.variablenotfound.com" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/iveid3oitg2k07u8r44sagtpvs/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fwww.variablenotfound.com%2F2011%2F02%2Fwebgrid-en-mvc-3-paso-paso.html" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=GE3gZXVmeiA:48ytORVWPoQ:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=GE3gZXVmeiA:48ytORVWPoQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=GE3gZXVmeiA:48ytORVWPoQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=GE3gZXVmeiA:48ytORVWPoQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=GE3gZXVmeiA:48ytORVWPoQ:4cEx4HpKnUU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=GE3gZXVmeiA:48ytORVWPoQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=GE3gZXVmeiA:48ytORVWPoQ:F7zBnMyn0Lo" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=GE3gZXVmeiA:48ytORVWPoQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=GE3gZXVmeiA:48ytORVWPoQ:gIN9vFwOqvQ" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=GE3gZXVmeiA:48ytORVWPoQ:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=I9og5sOYxJI" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/GE3gZXVmeiA" height="1" width="1"&gt;</content><author><name>José M. Aguilar</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/vnf"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/vnf</id><title type="html">Variable not found</title><link rel="alternate" href="http://www.variablenotfound.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1296643502408"><id gr:original-id="http://davidhayden.com/blog/dave/archive/2011/02/01/IDependencyResolverAspNetMvc3.aspx">tag:google.com,2005:reader/item/af241dcb6107ac56</id><title type="html">IDependencyResolver in ASP.NET MVC 3</title><published>2011-02-01T14:44:00Z</published><updated>2011-02-01T14:44:00Z</updated><link rel="alternate" href="http://davidhayden.com/blog/dave/archive/2011/02/01/IDependencyResolverAspNetMvc3.aspx" type="text/html" /><summary xml:base="http://davidhayden.com:80/blog" type="html">A fundamental look at IDependencyResolver in ASP.NET MVC 3.&lt;img src="http://davidhayden.com/blog/dave/aggbug/4201.aspx" width="1" height="1"&gt;</summary><author><name>Dave Hayden</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/DavidHayden"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/DavidHayden</id><title type="html">Blog</title><link rel="alternate" href="http://davidhayden.com:80/blog" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1296050736889"><id gr:original-id="http://odetocode.com/Blogs/scott/archive/2011/01/15/configurable-global-action-filters-for-asp-net-mvc.aspx">tag:google.com,2005:reader/item/81939cffae3b4441</id><title type="html">Configurable Global Action Filters for ASP.NET MVC</title><published>2011-01-18T14:12:00Z</published><updated>2011-01-18T14:12:00Z</updated><link rel="alternate" href="http://odetocode.com/Blogs/scott/archive/2011/01/15/configurable-global-action-filters-for-asp-net-mvc.aspx" type="text/html" /><summary xml:base="http://odetocode.com/Blogs/scott/Default.aspx" type="html">&lt;p&gt;ASP.NET MVC 3.0 introduces global action filters - an easy way to apply an action filter to every action in an MVC application. All you need to do is register the filters during application startup: &lt;/p&gt;  &lt;pre&gt;&lt;span style="color:blue"&gt;protected void &lt;/span&gt;Application_Start()
{
    ...&lt;/pre&gt;

&lt;pre&gt;&lt;pre&gt;&lt;span style="color:#2b91af"&gt;    GlobalFilters&lt;/span&gt;.Filters.Add(&lt;span style="color:blue"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;HandleErrorAttribute&lt;/span&gt;());
&lt;span style="color:#2b91af"&gt;    GlobalFilters&lt;/span&gt;.Filters.Add(&lt;span style="color:blue"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FooFilter&lt;/span&gt;());
&lt;span style="color:#2b91af"&gt;    GlobalFilters&lt;/span&gt;.Filters.Add(&lt;span style="color:blue"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;BarFilter&lt;/span&gt;());&lt;/pre&gt;&lt;pre&gt;    ...
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;But what if you wanted to add (or remove) filters through configuration? &lt;/p&gt;

&lt;pre&gt;&lt;span style="color:blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515"&gt;configSections&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515"&gt;section &lt;/span&gt;&lt;span style="color:red"&gt;name&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;filters&lt;/span&gt;" 
           &lt;span style="color:red"&gt;type&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;ConfigurableFilters.FiltersSettings, AssemblyName &lt;/span&gt;"&lt;span style="color:blue"&gt;/&amp;gt; 
&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515"&gt;configSections&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;
...
&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515"&gt;filters&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515"&gt;add &lt;/span&gt;&lt;span style="color:red"&gt;type&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;System.Web.Mvc.HandleErrorAttribute, System.Web.Mvc...&lt;/span&gt;" &lt;span style="color:blue"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515"&gt;add &lt;/span&gt;&lt;span style="color:red"&gt;type&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;ConfigurableFilters.BarFilter, AssemblyName&lt;/span&gt;" &lt;span style="color:blue"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515"&gt;add &lt;/span&gt;&lt;span style="color:red"&gt;type&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;ConfigurableFilters.FooFilter, AssemblyName&lt;/span&gt;" &lt;span style="color:blue"&gt;/&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515"&gt;filters&lt;/span&gt;&lt;span style="color:blue"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;In that case you'll need a ConfigurationElement.&lt;/p&gt;

&lt;pre&gt;&lt;span style="color:blue"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FilterAction &lt;/span&gt;: &lt;span style="color:#2b91af"&gt;ConfigurationElement
&lt;/span&gt;{
    [&lt;span style="color:#2b91af"&gt;ConfigurationProperty&lt;/span&gt;(&lt;span style="color:#a31515"&gt;"type"&lt;/span&gt;, IsRequired = &lt;span style="color:blue"&gt;true&lt;/span&gt;, IsKey = &lt;span style="color:blue"&gt;true&lt;/span&gt;)]
    &lt;span style="color:blue"&gt;public string &lt;/span&gt;Type 
    {
        &lt;span style="color:blue"&gt;get &lt;/span&gt;{ &lt;span style="color:blue"&gt;return base&lt;/span&gt;[&lt;span style="color:#a31515"&gt;"type"&lt;/span&gt;] &lt;span style="color:blue"&gt;as string&lt;/span&gt;; }
        &lt;span style="color:blue"&gt;set &lt;/span&gt;{ &lt;span style="color:blue"&gt;base&lt;/span&gt;[&lt;span style="color:#a31515"&gt;"type"&lt;/span&gt;] = &lt;span style="color:blue"&gt;value&lt;/span&gt;; }
    }
}&lt;/pre&gt;

&lt;p&gt;And a ConfigurationElementCollection.&lt;/p&gt;

&lt;pre&gt;&lt;span style="color:blue"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FilterActionCollection &lt;/span&gt;: &lt;span style="color:#2b91af"&gt;ConfigurationElementCollection
&lt;/span&gt;{       
    &lt;span style="color:blue"&gt;protected override &lt;/span&gt;&lt;span style="color:#2b91af"&gt;ConfigurationElement &lt;/span&gt;CreateNewElement()
    {
        &lt;span style="color:blue"&gt;return new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FilterAction&lt;/span&gt;();
    }

    &lt;span style="color:blue"&gt;protected override object &lt;/span&gt;GetElementKey(&lt;span style="color:#2b91af"&gt;ConfigurationElement &lt;/span&gt;element)
    {            
        &lt;span style="color:blue"&gt;return &lt;/span&gt;((&lt;span style="color:#2b91af"&gt;FilterAction&lt;/span&gt;) element).Type;
    }
}&lt;/pre&gt;

&lt;p&gt;And a ConfigurationSection. &lt;/p&gt;

&lt;pre&gt;&lt;span style="color:blue"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FiltersSettings &lt;/span&gt;: &lt;span style="color:#2b91af"&gt;ConfigurationSection
&lt;/span&gt;{
    &lt;span style="color:blue"&gt;public static &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FiltersSettings &lt;/span&gt;Settings
    {
        &lt;span style="color:blue"&gt;get
        &lt;/span&gt;{
            &lt;span style="color:blue"&gt;var &lt;/span&gt;section = &lt;span style="color:#2b91af"&gt;ConfigurationManager&lt;/span&gt;.GetSection(&lt;span style="color:#a31515"&gt;"filters"&lt;/span&gt;)
                          &lt;span style="color:blue"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FiltersSettings&lt;/span&gt;;
            &lt;span style="color:blue"&gt;return &lt;/span&gt;section ?? &lt;span style="color:blue"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FiltersSettings&lt;/span&gt;();                
        }
    }

    [&lt;span style="color:#2b91af"&gt;ConfigurationProperty&lt;/span&gt;(&lt;span style="color:#a31515"&gt;""&lt;/span&gt;, IsDefaultCollection = &lt;span style="color:blue"&gt;true&lt;/span&gt;)]
    &lt;span style="color:blue"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FilterActionCollection &lt;/span&gt;Filters
    {
        &lt;span style="color:blue"&gt;get
        &lt;/span&gt;{
            &lt;span style="color:blue"&gt;return base&lt;/span&gt;[_filtersProperty] &lt;span style="color:blue"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af"&gt;FilterActionCollection&lt;/span&gt;;
        }
        &lt;span style="color:blue"&gt;set
        &lt;/span&gt;{
            &lt;span style="color:blue"&gt;base&lt;/span&gt;[_filtersProperty] = &lt;span style="color:blue"&gt;value&lt;/span&gt;;
        }
    }

    &lt;span style="color:blue"&gt;private readonly &lt;/span&gt;&lt;span style="color:#2b91af"&gt;ConfigurationProperty &lt;/span&gt;_filtersProperty = 
        &lt;span style="color:blue"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;ConfigurationProperty&lt;/span&gt;(
            &lt;span style="color:blue"&gt;null&lt;/span&gt;, &lt;span style="color:blue"&gt;typeof &lt;/span&gt;(&lt;span style="color:#2b91af"&gt;FilterActionCollection&lt;/span&gt;), &lt;span style="color:blue"&gt;null&lt;/span&gt;, 
            &lt;span style="color:#2b91af"&gt;ConfigurationPropertyOptions&lt;/span&gt;.IsDefaultCollection);
}&lt;/pre&gt;

&lt;p&gt;One way to apply the configured filters is to use the following code during application startup:&lt;/p&gt;

&lt;pre&gt;&lt;span style="color:blue"&gt;var &lt;/span&gt;filters = &lt;span style="color:#2b91af"&gt;FiltersSettings&lt;/span&gt;.Settings.Filters;
&lt;span style="color:blue"&gt;foreach &lt;/span&gt;(&lt;span style="color:blue"&gt;var &lt;/span&gt;filter &lt;span style="color:blue"&gt;in &lt;/span&gt;filters.Cast&amp;lt;&lt;span style="color:#2b91af"&gt;FilterAction&lt;/span&gt;&amp;gt;())
{
    &lt;span style="color:blue"&gt;var &lt;/span&gt;filterType = &lt;span style="color:#2b91af"&gt;Type&lt;/span&gt;.GetType(filter.Type);
    &lt;span style="color:#2b91af"&gt;GlobalFilters&lt;/span&gt;.Filters.Add(&lt;span style="color:#2b91af"&gt;Activator&lt;/span&gt;.CreateInstance(filterType));
}&lt;/pre&gt;

&lt;p&gt;Another approach is to implement a filter provider. We'll take a look at the provider approach tomorrow. &lt;/p&gt;&lt;img src="http://odetocode.com/Blogs/scott/aggbug/1089.aspx" width="1" height="1"&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=HkvTWk-EM_w:-nwPrsGgatg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=HkvTWk-EM_w:-nwPrsGgatg:jWeZv7XsJd0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=jWeZv7XsJd0" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=HkvTWk-EM_w:-nwPrsGgatg:zYSYRoQSaQY"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=zYSYRoQSaQY" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=HkvTWk-EM_w:-nwPrsGgatg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?i=HkvTWk-EM_w:-nwPrsGgatg:V_sGLiPBpWU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=HkvTWk-EM_w:-nwPrsGgatg:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=cGdyc7Q-1BI" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</summary><author><name>K. Scott Allen</name></author><source gr:stream-id="feed/http://odetocode.com/Blogs/scott/atom.aspx"><id>tag:google.com,2005:reader/feed/http://odetocode.com/Blogs/scott/atom.aspx</id><title type="html">K. Scott Allen</title><link rel="alternate" href="http://odetocode.com/Blogs/scott/Default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1296050732063"><id gr:original-id="c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7685905">tag:google.com,2005:reader/item/0a58ef58a7b913c7</id><category term="ASP.NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/ASP.NET/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/.NET/default.aspx" /><category term="MVC" scheme="http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx" /><title type="html">Running an ASP.NET MVC 3 app on a web server that doesn’t have ASP.NET MVC 3 installed</title><published>2011-01-19T06:33:22Z</published><updated>2011-01-19T06:33:22Z</updated><link rel="alternate" href="http://weblogs.asp.net/scottgu/archive/2011/01/18/running-an-asp-net-mvc-3-app-on-a-web-server-that-doesn-t-have-asp-net-mvc-3-installed.aspx" type="text/html" /><summary xml:base="http://weblogs.asp.net/scottgu/default.aspx" type="html">&lt;font size="2" face="arial"&gt;   &lt;p&gt;Last week we released &lt;a href="http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx"&gt;several new web products&lt;/a&gt; – including &lt;a href="http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx"&gt;ASP.NET MVC 3&lt;/a&gt;.  We’ve had a bunch of great feedback and a ton of downloads since then.&lt;/p&gt;    &lt;p&gt;One question a few people have asked me recently is: “My web hosting provider doesn’t yet support ASP.NET MVC 3 - any idea when they will install it?”&lt;/p&gt;    &lt;p&gt;The good news is that you &lt;u&gt;don’t need to wait&lt;/u&gt; for them to install anything on their web-servers.  As long as your web hosting provider supports .NET 4, then you can build and deploy ASP.NET MVC 3 applications on it today – without the hosting provider having to do anything to enable it.  The below post describes how you can enable this.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Some Background&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;We support two ways for you to install and use the assemblies that implement ASP.NET MVC 3 on a machine:&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;Have the ASP.NET MVC 3 assemblies installed in a central place on a machine, and have web projects reference/use the assemblies from there &lt;/li&gt;      &lt;li&gt;Copy the ASP.NET MVC 3 assemblies into the \bin folder of your web project, and have your web project reference/use the assemblies from there &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;The first approach is the default approach we use with Visual Studio, and has the benefit of enabling us to easily service the ASP.NET MVC 3 assemblies using Windows Update (in the event of a bad bug).&lt;/p&gt;    &lt;p&gt;The second approach is also fully supported, and has the benefit of not requiring ASP.NET MVC 3 to be explicitly installed on a machine in order for it to be used.  Instead you can just copy/ftp your web application onto a server (with the ASP.NET MVC assemblies contained within the \bin directory of the application) and it will just work.  You should use this second approach if your web hosting provider hasn’t explicitly installed ASP.NET MVC 3 yet on their servers.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Approach 1: GAC Based Referencing of ASP.NET MVC Assemblies&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;When you install ASP.NET MVC 3 on a machine, a number of assemblies are automatically registered in the &lt;a href="http://en.wikipedia.org/wiki/Global_Assembly_Cache"&gt;GAC&lt;/a&gt; (global assembly cache) as part of the installation process.  The GAC provides a central place that .NET assemblies can be installed and serviced (via Windows Update).  Because it provides an easy way for us to update/service assemblies, ASP.NET MVC projects - &lt;em&gt;by default&lt;/em&gt; - reference the assemblies that implement ASP.NET MVC 3 from it.  &lt;/p&gt;    &lt;p&gt;If you copy a vanilla ASP.NET MVC 3 project – that uses the &lt;em&gt;default approach&lt;/em&gt; of referencing the ASP.NET MVC 3 runtime assemblies using the GAC – onto a machine that has not had ASP.NET MVC 3 installed on it, then you will see an error message like below when you run your application:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_64EB2E92.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2A2385BC.png" width="735" height="301"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;The above error indicates that one of the assemblies required to run ASP.NET MVC 3 from the GAC cannot be found.  Installing ASP.NET MVC 3 on the machine will fix it and allow your application to be run.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Approach 2: \Bin Directory Based Referencing of ASP.NET MVC Assemblies&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;The alternative approach your projects can use is to distribute and reference the ASP.NET MVC 3 runtime assemblies from the \bin directory of your web application.  The benefit of this approach is that you &lt;u&gt;do not&lt;/u&gt; need to explicitly install ASP.NET MVC 3 on a machine in order to run your web application.  Instead, you can just copy/ftp your web application onto an existing .NET 4 server and it will work.  This approach works for both “full trust” and “medium trust” scenarios – which means it will even work with low-cost shared hosting offers.  No addition registration/installation/action is required by the hosting provider in order to enable this.&lt;/p&gt;    &lt;p&gt;Enabling your web project to “bin deploy” the ASP.NET MVC 3 assemblies is easy and only takes about 2 minutes to do.  Here are the steps to follow:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a href="http://drew-prog.blogspot.com/2011/01/how-to-deploy-aspnet-mvc-3-app-to-web.html"&gt;Steps to Deploy an ASP.NET MVC 3 Application to a Web Hosting Provider with \Bin deployment&lt;/a&gt;  &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;Once configured for \bin based deployment, an application you build with ASP.NET MVC 3 will work on any web server that has .NET 4 installed on it.  Just copy/ftp it up to the web-server and it will run.  You don’t need the hosting provider to do anything to enable it – this is true even for low-cost shared hosting accounts.   &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Finding a ASP.NET Web Hosting Provider&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;You can browse the &lt;a href="http://www.microsoft.com/web/hosting/home"&gt;Windows Web Hosting Gallery&lt;/a&gt; to find good ASP.NET based Windows Hosting Providers (all of which support ASP.NET 4):&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.microsoft.com/web/hosting/home"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_6FC80FDA.png" width="743" height="618"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;The &lt;a href="http://www.microsoft.com/web/hosting/home"&gt;Windows Web Hosting Gallery&lt;/a&gt; allows you to filter/browse hosting offers by different countries and service level offerings.  It also allows you to easily filter by “Shared Hosting”, “Virtual Hosting” and “Dedicated Hosting” offers.&lt;/p&gt;    &lt;p&gt;“Shared Hosting” refers to an offer where many customers run on a single web-server and you do not have admin access on the remote server.  “Virtual Hosting” offers provide you with your own Virtual Machine image on a remote-server – typically with OS admin rights and remote terminal server access to manage it.  “Dedicated Hosting” offers provide you an entire physical server, and also typically provide OS admin rights and remote terminal support to it.&lt;/p&gt;    &lt;p&gt;The prices for Windows based web hosting are now very cost effective, and start from as little as $2.75/month for a shared hosting offer and $23/month for a virtual hosting offer.  All of the above offers are capable of running ASP.NET MVC 3 using the \bin deployment approach.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;You can deploy ASP.NET MVC 3 based applications to any web-server that has .NET 4 enabled on it – without having to wait for the hosting provider to explicitly install ASP.NET MVC 3 on it.  Simply &lt;a href="http://drew-prog.blogspot.com/2011/01/how-to-deploy-aspnet-mvc-3-app-to-web.html"&gt;use the steps above&lt;/a&gt; to convert your project to use \bin based deployment of the ASP.NET MVC 3 assemblies, and then you can copy your application onto any ASP.NET 4 based server and it will just work.&lt;/p&gt;    &lt;p&gt;Hope this helps,&lt;/p&gt;    &lt;p&gt;Scott&lt;/p&gt;    &lt;p&gt;&lt;em&gt;P.S.&lt;/em&gt; &lt;em&gt;In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: &lt;/em&gt;&lt;a href="http://www.twitter.com/scottgu"&gt;twitter.com/scottgu&lt;/a&gt;&lt;/p&gt; &lt;/font&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7685905" width="1" height="1"&gt;</summary><author><name>ScottGu</name></author><source gr:stream-id="feed/http://weblogs.asp.net/ScottGu/Rss.aspx"><id>tag:google.com,2005:reader/feed/http://weblogs.asp.net/ScottGu/Rss.aspx</id><title type="html">ScottGu&amp;#39;s Blog</title><link rel="alternate" href="http://weblogs.asp.net/scottgu/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1296050722904"><id gr:original-id="http://odetocode.com/Blogs/scott/archive/2011/01/15/injectable-configurable-action-filters.aspx">tag:google.com,2005:reader/item/df1a06db1a9bda23</id><title type="html">Injectable, Configurable Action Filters</title><published>2011-01-20T14:12:00Z</published><updated>2011-01-20T14:12:00Z</updated><link rel="alternate" href="http://odetocode.com/Blogs/scott/archive/2011/01/15/injectable-configurable-action-filters.aspx" type="text/html" /><summary xml:base="http://odetocode.com/Blogs/scott/Default.aspx" type="html">&lt;p&gt;One of the advantages to using a custom IFilterProvider is how you gain total control over the instantiation of action filters in ASP.NET MVC 3. When you combine an IoC container with a filter provider and a custom IDependencyResolver (&lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt5-idependencyresolver.html"&gt;see Brad's posts for details&lt;/a&gt;),  then all the pieces fall into place. Building on the code &lt;a href="http://odetocode.com/Blogs/scott/archive/2011/01/15/configurable-action-filter-provider.aspx"&gt;from the last post&lt;/a&gt;, we can change our filter provider to utilize Ninject for action filter instantiation. &lt;/p&gt;  &lt;pre&gt;&lt;span style="color:blue"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af"&gt;ConfiguredFilterProvider &lt;/span&gt;: &lt;span style="color:#2b91af"&gt;IFilterProvider
&lt;/span&gt;{
    &lt;span style="color:blue"&gt;private readonly &lt;/span&gt;&lt;span style="color:#2b91af"&gt;IKernel &lt;/span&gt;_kernel;

    &lt;span style="color:blue"&gt;public &lt;/span&gt;ConfiguredFilterProvider(&lt;span style="color:#2b91af"&gt;IKernel  &lt;/span&gt;kernel)
    {
        _kernel = kernel;
    }

    &lt;span style="color:blue"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;Filter&lt;/span&gt;&amp;gt; GetFilters(
        &lt;span style="color:#2b91af"&gt;ControllerContext &lt;/span&gt;controllerContext, 
        &lt;span style="color:#2b91af"&gt;ActionDescriptor &lt;/span&gt;actionDescriptor)
    {
        &lt;span style="color:blue"&gt;var &lt;/span&gt;filters = &lt;span style="color:#2b91af"&gt;FiltersSettings&lt;/span&gt;.Settings.Filters;
        &lt;span style="color:blue"&gt;foreach &lt;/span&gt;(&lt;span style="color:blue"&gt;var &lt;/span&gt;filter &lt;span style="color:blue"&gt;in &lt;/span&gt;filters.Cast&amp;lt;&lt;span style="color:#2b91af"&gt;FilterAction&lt;/span&gt;&amp;gt;())
        {
            &lt;span style="color:blue"&gt;var &lt;/span&gt;filterType = &lt;span style="color:#2b91af"&gt;Type&lt;/span&gt;.GetType(filter.Type);
            &lt;span style="color:blue"&gt;yield return new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;Filter&lt;/span&gt;(
&lt;strong&gt;                    _kernel.Get(filterType),&lt;/strong&gt;
                    &lt;span style="color:#2b91af"&gt;FilterScope&lt;/span&gt;.Global, order:&lt;span style="color:blue"&gt;null          
                &lt;/span&gt;);
        }
    }
}&lt;/pre&gt;

&lt;p&gt;Using Ninject to create the filters makes it trivially easy to inject dependencies into the filter. In case you didn't know, action filters in MVC 3 no longer need to derive from an attribute derived base class. All you need is a class that implements one or more of the action filter interfaces. &lt;/p&gt;

&lt;pre&gt;&lt;span style="color:blue"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af"&gt;LoggingFilter &lt;/span&gt;: &lt;span style="color:#2b91af"&gt;IActionFilter&lt;/span&gt;, 
                             &lt;span style="color:#2b91af"&gt;IExceptionFilter&lt;/span&gt;, 
                             &lt;span style="color:#2b91af"&gt;IResultFilter&lt;/span&gt;, 
                             &lt;span style="color:#2b91af"&gt;IAuthorizationFilter
&lt;/span&gt;{

    &lt;span style="color:blue"&gt;public &lt;/span&gt;LoggingFilter(&lt;span style="color:#2b91af"&gt;ISomeDependency &lt;/span&gt;dependency)
    {
            
    }

    &lt;span style="color:green"&gt;// ...
&lt;/span&gt;}&lt;/pre&gt;

&lt;p&gt;If you are using Ninject, you'll also want to use a custom IDependencyResolver based on Ninject. It's easy to write your own, or you can add one already implemented for you from the &lt;a href="http://nuget.org/"&gt;NuGet gallery&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://odetocode.com/Blogs/images/odetocode_com/Blogs/scott/Windows-Live-Writer/Injectable-Action-Filters_CA59/image_2.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:block;float:none;border-top-width:0px;border-bottom-width:0px;margin-left:auto;border-left-width:0px;margin-right:auto;padding-top:0px" title="image" border="0" alt="image" src="http://odetocode.com/Blogs/images/odetocode_com/Blogs/scott/Windows-Live-Writer/Injectable-Action-Filters_CA59/image_thumb.png" width="379" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the custom dependency resolver in place, you no longer need to register your filter provider in the FilterProvider.Providers collection. Instead, you can just register the provider as another service in the container. &lt;/p&gt;

&lt;pre&gt;&lt;span style="color:blue"&gt;public static class &lt;/span&gt;&lt;span style="color:#2b91af"&gt;AppStart_NinjectMVC3
&lt;/span&gt;{
    &lt;span style="color:blue"&gt;public static void &lt;/span&gt;RegisterServices(&lt;span style="color:#2b91af"&gt;IKernel &lt;/span&gt;kernel)
    {
        kernel.Bind&amp;lt;&lt;span style="color:#2b91af"&gt;IFilterProvider&lt;/span&gt;&amp;gt;()
              .To&amp;lt;&lt;span style="color:#2b91af"&gt;ConfiguredFilterProvider&lt;/span&gt;&amp;gt;();
        kernel.Bind&amp;lt;&lt;span style="color:#2b91af"&gt;ISomeDependency&lt;/span&gt;&amp;gt;()
              .To&amp;lt;&lt;span style="color:#2b91af"&gt;SomeDependency&lt;/span&gt;&amp;gt;();
    }

    &lt;span style="color:blue"&gt;public static void &lt;/span&gt;Start()
    {
        &lt;span style="color:#2b91af"&gt;IKernel &lt;/span&gt;kernel = &lt;span style="color:blue"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;StandardKernel&lt;/span&gt;();
        RegisterServices(kernel);
        &lt;span style="color:#2b91af"&gt;DependencyResolver&lt;/span&gt;.SetResolver(
            &lt;span style="color:blue"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af"&gt;NinjectServiceLocator&lt;/span&gt;(kernel));
    }
}&lt;/pre&gt;

&lt;p&gt;In previous versions of MVC, filters were notoriously difficult for injection, and mostly inflexible. MVC 3 is a great improvement. &lt;/p&gt;&lt;img src="http://odetocode.com/Blogs/scott/aggbug/1091.aspx" width="1" height="1"&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=6q24j0FbaEA:9sHlC6a-7Ro:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=6q24j0FbaEA:9sHlC6a-7Ro:jWeZv7XsJd0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=jWeZv7XsJd0" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=6q24j0FbaEA:9sHlC6a-7Ro:zYSYRoQSaQY"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=zYSYRoQSaQY" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=6q24j0FbaEA:9sHlC6a-7Ro:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?i=6q24j0FbaEA:9sHlC6a-7Ro:V_sGLiPBpWU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=6q24j0FbaEA:9sHlC6a-7Ro:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=cGdyc7Q-1BI" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</summary><author><name>K. Scott Allen</name></author><source gr:stream-id="feed/http://odetocode.com/Blogs/scott/atom.aspx"><id>tag:google.com,2005:reader/feed/http://odetocode.com/Blogs/scott/atom.aspx</id><title type="html">K. Scott Allen</title><link rel="alternate" href="http://odetocode.com/Blogs/scott/Default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1296050700925"><id gr:original-id="http://www.pnpguidance.net/post/FreeAspNetMvc3Training.aspx">tag:google.com,2005:reader/item/1c0bb8ec288f7f2e</id><title type="html">Free ASP.NET MVC 3 Training</title><published>2011-01-22T19:37:50Z</published><updated>2011-01-22T19:37:50Z</updated><link rel="alternate" href="http://www.pnpguidance.net/post/FreeAspNetMvc3Training.aspx" type="text/html" /><summary xml:base="http://www.pnpguidance.net/" type="html">Learn ASP.NET MVC 3 for free.</summary><author><name>PnPGuidance</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/PnPGuidance"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/PnPGuidance</id><title type="html">PnPGuidance</title><link rel="alternate" href="http://www.pnpguidance.net/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1296050687647"><id gr:original-id="ded273ab-9e87-4979-8222-e4e2e46f1b46:95863">tag:google.com,2005:reader/item/2fedff15739bd359</id><category term="Inversion of Control" scheme="http://www.lostechies.com/blogs/johnvpetersen/archive/tags/Inversion+of+Control/default.aspx" /><category term="ASP MVC 3" scheme="http://www.lostechies.com/blogs/johnvpetersen/archive/tags/ASP+MVC+3/default.aspx" /><category term="Dependency Injection" scheme="http://www.lostechies.com/blogs/johnvpetersen/archive/tags/Dependency+Injection/default.aspx" /><title type="html">Dependency Injection with ASP MVC 3–Distilled and Simplified</title><published>2011-01-23T23:46:00Z</published><updated>2011-01-23T23:46:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/LosTechies/~3/JTN00ebTem0/dependency-injection-with-asp-mvc-3-distilled-and-simplified.aspx" type="text/html" /><link rel="canonical" href="http://www.lostechies.com/blogs/johnvpetersen/archive/2011/01/23/dependency-injection-with-asp-mvc-3-distilled-and-simplified.aspx" /><summary xml:base="http://lostechies.com/" type="html">&lt;p&gt;One of the key new features in the ASP MVC 3 framework is how the framework interacts with your Inversion of Control (IoC) Container. Note: the specific behavior of the IoC containers themselves has not changed. The only thing that has changed is how the MVC 3 framework interacts with the IoC Container.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Right off the bat, I want to give a big shout out to fellow MVP and ASPInsider Steve Smith for his very helpful &lt;a href="http://stevesmithblog.com/blog/how-do-i-use-structuremap-with-asp-net-mvc-3/"&gt;post&lt;/a&gt;. I also want to acknowledge Brad Wilson's helpful &lt;a href="http://bradwilson.typepad.com/blog/2010/07/service-location-pt1-introduction.html"&gt;posts&lt;/a&gt;. These posts were very helpful to me and served as an inspiration to this series of posts on my blog. I also want to acknowledge a comment by Jeremy Miller on Steve's blog wherein he chimed in on the semantics of GetInstance. Basically, whomever Steve acknowledged , I acknowledge here!! :)&lt;br&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;In MVC 1 and 2, we had to create our own Custom Controller Factory. In MVC 3, your still free to do so. However, when you see how MVC 3 generically works with IoC containers, when upgrading to MVC 3, you will likely want to re-work your code!&lt;/p&gt;
&lt;h5&gt;Introducing the DependencyResolver Class&lt;/h5&gt;
&lt;p&gt;The DependencyResolver is a member of the System.Web.Mvc NameSpace and its job is quite simple: to provide a central registration point for your chosen IoC Container. Prior to MVC 3, we often dealt with our chosen IoC container directly. In MVC 3, there is an abstraction layer (the DependencyResolver Class) that we will interact with directly. Whether your chosen IoC Container is Windsor, StructureMap or Unity, you can take advantage of this new feature. &lt;/p&gt;
&lt;h4&gt;It’s all about conforming to the IDependencyResolver Interface&lt;/h4&gt;
&lt;p&gt;In order to register a dependency resolver, you must use a class that implements the IDepedencyResolver Interface – which itself, is quite simple:&lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;IDependencyResolver Interface&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;object&lt;/span&gt; GetService(&lt;span style="color:#2b91af"&gt;Type&lt;/span&gt; serviceType)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff"&gt;object&lt;/span&gt;&amp;gt; GetServices(&lt;span style="color:#2b91af"&gt;Type&lt;/span&gt; serviceType)&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The idea is simple – MVC needs interface to interact with. There are many IoC providers available and its not realistic nor desirable to expect that all of the providers would alter their implementations to some common specification. All we need to do to fill the gap is construct custom IDependencyResolver classes for our chosen IoC Containers. &lt;/p&gt;
&lt;h4&gt;Implementing StructureMap and Unity IoC Containers&lt;/h4&gt;
&lt;p&gt;The following classes provide the functionality we need for StructureMap and Unity:&lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;StructureMap Resolver&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;StructureMapDependencyResolver&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;IDependencyResolver&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;       &lt;span style="color:#2b91af"&gt;IContainer&lt;/span&gt; _container;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; StructureMapDependencyResolver(&lt;span style="color:#2b91af"&gt;IContainer&lt;/span&gt; container)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        {&lt;/li&gt;
&lt;li&gt;            _container = container;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        }&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;        &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;object&lt;/span&gt; GetService(&lt;span style="color:#2b91af"&gt;Type&lt;/span&gt; serviceType)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        {&lt;/li&gt;
&lt;li&gt;            &lt;span style="color:#0000ff"&gt;object&lt;/span&gt; instance = _container.TryGetInstance(serviceType);&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;            &lt;span style="color:#0000ff"&gt;if&lt;/span&gt; (instance == &lt;span style="color:#0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; !serviceType.IsAbstract)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            {&lt;/li&gt;
&lt;li&gt;                _container.Configure(c =&amp;gt; c.AddType(serviceType, serviceType));&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;                instance = _container.TryGetInstance(serviceType);&lt;/li&gt;
&lt;li&gt;            }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;            &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; instance;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        }&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff"&gt;object&lt;/span&gt;&amp;gt; GetServices(&lt;span style="color:#2b91af"&gt;Type&lt;/span&gt; serviceType)&lt;/li&gt;
&lt;li&gt;        {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; _container.GetAllInstances(serviceType).Cast&amp;lt;&lt;span style="color:#0000ff"&gt;object&lt;/span&gt;&amp;gt;();&lt;/li&gt;
&lt;li&gt;        }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    }&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;Unity Resolver&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;UnityDependencyResolver&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;IDependencyResolver&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;{&lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#2b91af"&gt;IUnityContainer&lt;/span&gt; _container;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; UnityDependencyResolver(&lt;span style="color:#2b91af"&gt;IUnityContainer&lt;/span&gt; container)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;        _container = container;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    }&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;object&lt;/span&gt; GetService(&lt;span style="color:#2b91af"&gt;Type&lt;/span&gt; serviceType)&lt;/li&gt;
&lt;li&gt;    {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#0000ff"&gt;object&lt;/span&gt; instance;&lt;/li&gt;
&lt;li&gt;        &lt;span style="color:#0000ff"&gt;try&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        {&lt;/li&gt;
&lt;li&gt;            instance = _container.Resolve(serviceType);&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            &lt;span style="color:#0000ff"&gt;if&lt;/span&gt; (serviceType.IsAbstract || serviceType.IsInterface)&lt;/li&gt;
&lt;li&gt;            {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;                &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff"&gt;null&lt;/span&gt;;&lt;/li&gt;
&lt;li&gt;            }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; instance;&lt;/li&gt;
&lt;li&gt;        }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#0000ff"&gt;catch&lt;/span&gt; (&lt;span style="color:#2b91af"&gt;Exception&lt;/span&gt; &lt;span style="color:#c0c0c0"&gt;e&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;        {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff"&gt;null&lt;/span&gt;;&lt;/li&gt;
&lt;li&gt;        }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    }&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff"&gt;object&lt;/span&gt;&amp;gt; GetServices(&lt;span style="color:#2b91af"&gt;Type&lt;/span&gt; serviceType)&lt;/li&gt;
&lt;li&gt;    {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; _container.ResolveAll(serviceType);&lt;/li&gt;
&lt;li&gt;    }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;}&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With our resolver classes in place, we can now set about the task of implementing them. &lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;StructureMap Setup&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;StructureMapContainerSetup&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;{&lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; SetUp()&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#2b91af"&gt;IContainer&lt;/span&gt; container = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Container&lt;/span&gt;(&lt;/li&gt;
&lt;li&gt;                x =&amp;gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;                {&lt;/li&gt;
&lt;li&gt;                    x.For&amp;lt;&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;&amp;gt;().&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;                        Use&amp;lt;&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;&amp;gt;().&lt;/li&gt;
&lt;li&gt;                        WithCtorArg(&lt;span style="color:#a31515"&gt;"stringResponse"&lt;/span&gt;).&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;                        EqualTo(&lt;span style="color:#a31515"&gt;"IoC Container: StructureMap."&lt;/span&gt;);&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;                    x.For&amp;lt;&lt;span style="color:#2b91af"&gt;HomeController&lt;/span&gt;&amp;gt;().Use&amp;lt;&lt;span style="color:#2b91af"&gt;HomeController&lt;/span&gt;&amp;gt;();&lt;/li&gt;
&lt;li&gt;                });&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#2b91af"&gt;DependencyResolver&lt;/span&gt;.SetResolver(&lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;StructureMapDependencyResolver&lt;/span&gt;(container));&lt;/li&gt;
&lt;li&gt;    }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;Unity Setup&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;UnityContainerSetup&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;{&lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; SetUp()&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;        &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; container = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;UnityContainer&lt;/span&gt;();&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;        container&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            .RegisterType&amp;lt;&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;, &lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;&amp;gt;().&lt;/li&gt;
&lt;li&gt;            Configure&amp;lt;&lt;span style="color:#2b91af"&gt;InjectedMembers&lt;/span&gt;&amp;gt;().ConfigureInjectionFor&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            &amp;lt;&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;&amp;gt;(&lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;InjectionConstructor&lt;/span&gt;(&lt;span style="color:#a31515"&gt;"IoC Container: Unity."&lt;/span&gt;));&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        container.RegisterType&amp;lt;&lt;span style="color:#2b91af"&gt;HomeController&lt;/span&gt;, &lt;span style="color:#2b91af"&gt;HomeController&lt;/span&gt;&amp;gt;();&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#2b91af"&gt;DependencyResolver&lt;/span&gt;.SetResolver(&lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;UnityDependencyResolver&lt;/span&gt;(container));&lt;/li&gt;
&lt;li&gt;    }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;}&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you already use these IoC Containers, much of this code should be familiar. The process of setting up the containers. You can see each product’s syntax is slightly different. Regardless, it is clear that both containers are accomplishing the same task. When the Home Controller is requested, the Home Controller is return. When Some Service is requested, Some Service is returned, and in each case, a string is passed as a constructor argument. The following is the class definition for Some Service:&lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;Some Service Class&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;{&lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; _stringResponse;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    &lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; SomeService(&lt;span style="color:#0000ff"&gt;string&lt;/span&gt; stringResponse)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;        _stringResponse = stringResponse;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    }&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; ToString()&lt;/li&gt;
&lt;li&gt;    {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; _stringResponse;&lt;/li&gt;
&lt;li&gt;    }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; SetString(&lt;span style="color:#0000ff"&gt;string&lt;/span&gt; stringResponse)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;        _stringResponse = stringResponse;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Some Service is just a contrived class to demonstrate the these concepts. The following is the Home Controller:&lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;Home Contoller&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;HomeController&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;Controller&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;{&lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;protected&lt;/span&gt; &lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt; _someService;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; HomeController(&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt; someService)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;        _someService = someService;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    }&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ActionResult&lt;/span&gt; Index()&lt;/li&gt;
&lt;li&gt;    {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        ViewBag.Message =  _someService.ToString();&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; View();&lt;/li&gt;
&lt;li&gt;    }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ActionResult&lt;/span&gt; About()&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;        &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; View();&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    }&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is the Home Controller, with a few modifications,  that is generated as part of a default ASP MVC Project. The HomeController takes on a dependency to SomeService which is supplied to the HomeController Constructor. In the Index Action, the ViewBag property is given a Message Property with a default value from SomeService. &lt;/p&gt;
&lt;p&gt;As you would expect with any IoC Container, the SomeService instance will automatically be supplied when the HomeController is invoked. &lt;/p&gt;
&lt;p&gt;All we have to do now is have the application wire-up the IoC Container. For this first example, we’ll use the Unity Container.&lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;Application Start - with Unity&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; Application_Start()&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;{&lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#2b91af"&gt;AreaRegistration&lt;/span&gt;.RegisterAllAreas();&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;    RegisterGlobalFilters(&lt;span style="color:#2b91af"&gt;GlobalFilters&lt;/span&gt;.Filters);&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    RegisterRoutes(&lt;span style="color:#2b91af"&gt;RouteTable&lt;/span&gt;.Routes);&lt;/li&gt;
&lt;li&gt; &lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    &lt;span style="color:#2b91af"&gt;UnityContainerSetup&lt;/span&gt;.SetUp();&lt;/li&gt;
&lt;li&gt;}&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And as we can see, it works!!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/johnvpetersen/image_5F00_4AAFE60D.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px" title="image" alt="image" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/johnvpetersen/image_5F00_thumb_5F00_7E77DC5E.png" border="0" height="334" width="693"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the Application_Start, when we swap out UnityContainerSetup.SetUp() for StructureMapSetup.SetUp(), we get:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/johnvpetersen/image_5F00_0E1A7821.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px" title="image" alt="image" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/johnvpetersen/image_5F00_thumb_5F00_72E4AFD0.png" border="0" height="305" width="626"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Just like that, we can easily swap out one IoC Container for another. &lt;/p&gt;
&lt;p&gt;Using StructureMap as an example, let’s create a subclass of HomeController and have the IoC Container serve that up when an instance of HomeController is requested:&lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;Modified StructureMap Setup&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#2b91af"&gt;IContainer&lt;/span&gt; container = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Container&lt;/span&gt;(&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        x =&amp;gt;&lt;/li&gt;
&lt;li&gt;        {&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;            x.For&amp;lt;&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;&amp;gt;().&lt;/li&gt;
&lt;li&gt;                Use&amp;lt;&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt;&amp;gt;().&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;                WithCtorArg(&lt;span style="color:#a31515"&gt;"stringResponse"&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;                EqualTo(&lt;span style="color:#a31515"&gt;"IoC Container: StructureMap."&lt;/span&gt;);&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;            x.For&amp;lt;&lt;span style="color:#2b91af"&gt;HomeController&lt;/span&gt;&amp;gt;().Use&amp;lt;&lt;span style="color:#2b91af"&gt;HomeController2&lt;/span&gt;&amp;gt;();&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;        });&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Here is the code for HomeController2:&lt;/p&gt;
&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;
&lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;,Courier,Monospace;font-size:10pt"&gt;
&lt;div style="background:#000080;color:#fff;font-family:Verdana,Tahoma,Arial,sans-serif;font-weight:bold;padding:2px 5px"&gt;Home Controller 2&lt;/div&gt;
&lt;div style="background:#ddd;overflow:auto"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px"&gt;
&lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;HomeController2&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;HomeController&lt;/span&gt;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;{&lt;/li&gt;
&lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; HomeController2(&lt;span style="color:#2b91af"&gt;SomeService&lt;/span&gt; someService) : &lt;span style="color:#0000ff"&gt;base&lt;/span&gt;(someService)&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;    {&lt;/li&gt;
&lt;li&gt;        _someService = someService;&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;        _someService.SetString(&lt;span style="color:#0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color:#a31515"&gt;"{0} Using Home Controller 2."&lt;/span&gt;, _someService.&lt;span style="color:#c0c0c0"&gt;ToString&lt;/span&gt;()));&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt; &lt;/li&gt;
&lt;li&gt;    }&lt;/li&gt;
&lt;li style="background:#f3f3f3"&gt;}&lt;/li&gt;
&lt;/ol&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;All were doing here is slightly modifying the string that is returned by SomeService. With the IoC Container wired up, here’s what we get:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/johnvpetersen/image_5F00_06919965.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px" title="image" alt="image" src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/johnvpetersen/image_5F00_thumb_5F00_1D53719F.png" border="0" height="221" width="680"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;  Yes, it’s that easy!! &lt;/p&gt;
&lt;p&gt;We can also use the DependencyResolver Object anywhere in our MVC app. For example, if in some other context, I needed an instance of SomeService:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;var _service = DependencyResolver.Current.GetService&amp;lt;SomeService&amp;gt;();&lt;/b&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The better integration with IoC/DI Containers in ASP MVC 3 is a nice feature. In the event you need to switch to a different container, that task becomes much easier because we  can use a generic interface to reference the container.&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Dependency+Injection+with+ASP+MVC+3%e2%80%93Distilled+and+Simplified&amp;amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjohnvpetersen%2farchive%2f2011%2f01%2f23%2fdependency-injection-with-asp-mvc-3-distilled-and-simplified.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjohnvpetersen%2farchive%2f2011%2f01%2f23%2fdependency-injection-with-asp-mvc-3-distilled-and-simplified.aspx" border="0" alt="Kick It on DotNetKicks.com"&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=95863" width="1" height="1"&gt;&lt;p&gt;&lt;a href="http://theloungenet.com/feeds/redirect/DOTNETRSS/LOSTECHIES/9420D1282E9A464AD3D9819C746D8C4FE397A93F"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/LOSTECHIES/9420D1282E9A464AD3D9819C746D8C4FE397A93F"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=JTN00ebTem0:YEKPLdwBMS0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=JTN00ebTem0:YEKPLdwBMS0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?i=JTN00ebTem0:YEKPLdwBMS0:V_sGLiPBpWU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LosTechies?a=JTN00ebTem0:YEKPLdwBMS0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LosTechies?d=7Q72WNTAKBA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LosTechies/~4/JTN00ebTem0" height="1" width="1"&gt;</summary><author><name>John V. Petersen</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/LosTechies"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/LosTechies</id><title type="html">Los Techies</title><link rel="alternate" href="http://lostechies.com" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1295347789767"><id gr:original-id="http://odetocode.com/Blogs/scott/archive/2011/01/15/http-modules-versus-asp-net-mvc-action-filters.aspx">tag:google.com,2005:reader/item/3fa2646dcd1fa671</id><title type="html">HTTP Modules versus ASP.NET MVC Action Filters</title><published>2011-01-17T14:12:00Z</published><updated>2011-01-17T14:12:00Z</updated><link rel="alternate" href="http://odetocode.com/Blogs/scott/archive/2011/01/15/http-modules-versus-asp-net-mvc-action-filters.aspx" type="text/html" /><summary xml:base="http://odetocode.com/Blogs/scott/Default.aspx" type="html">&lt;p&gt;&lt;a href="http://www.zieak.com/"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;float:right;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px" title="" border="0" alt="Alaskan Pipeline by Ryan McFarland" align="right" src="http://farm3.static.flickr.com/2212/2265541510_8ae8c0269e.jpg" width="360" height="270"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;ASP.NET MVC has &lt;a href="http://msdn.microsoft.com/en-us/magazine/gg232768.aspx"&gt;action filters&lt;/a&gt;, while ASP.NET has &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc301362.aspx"&gt;HTTP modules&lt;/a&gt;. Inside their respective processing pipelines, these abstractions serve similar purposes, and I've heard the following question a few times:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;When should I write an HTTP module and when should I write an action filter?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you are creating an MVC application then I'll almost &lt;em&gt;always&lt;/em&gt; recommend going with an action filter instead of an HTTP module. This is my recommendation even if the functionality you are creating is generic enough to work from inside a module (in other words, it doesn't depend on MVC specific pipeline stages, like the pre and post processing of action invocation). Filters are closely aligned with the MVC infrastructure and vocabulary, and filters are the first thing someone will look for when they want to see how you've implemented cross-cutting functionality in MVC. &lt;/p&gt;  &lt;p&gt;On the other hand, an HTTP module is something you can reuse in any type of ASP.NET application. Witness the flexibility of &lt;a href="http://code.google.com/p/elmah/"&gt;elmah&lt;/a&gt; - just drop an assembly in the bin directory, tweak a config file, and wait for elmah to record errors across an entire application. This configurable flexibility isn't something you can do with filters out of the box, but we’ll see tomorrow how easy it is to add.&lt;/p&gt;&lt;img src="http://odetocode.com/Blogs/scott/aggbug/1088.aspx" width="1" height="1"&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=xMnCYHBI37Q:V_QTZwM2KTw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=xMnCYHBI37Q:V_QTZwM2KTw:jWeZv7XsJd0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=jWeZv7XsJd0" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=xMnCYHBI37Q:V_QTZwM2KTw:zYSYRoQSaQY"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=zYSYRoQSaQY" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=xMnCYHBI37Q:V_QTZwM2KTw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?i=xMnCYHBI37Q:V_QTZwM2KTw:V_sGLiPBpWU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/OdeToCode?a=xMnCYHBI37Q:V_QTZwM2KTw:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/OdeToCode?d=cGdyc7Q-1BI" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</summary><author><name>K. Scott Allen</name></author><source gr:stream-id="feed/http://odetocode.com/Blogs/scott/atom.aspx"><id>tag:google.com,2005:reader/feed/http://odetocode.com/Blogs/scott/atom.aspx</id><title type="html">K. Scott Allen</title><link rel="alternate" href="http://odetocode.com/Blogs/scott/Default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1295347785283"><id gr:original-id="c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7681992">tag:google.com,2005:reader/item/b745ada59c5d358c</id><category term="ASP.NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/ASP.NET/default.aspx" /><category term="Visual Studio" scheme="http://weblogs.asp.net/scottgu/archive/tags/Visual+Studio/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/.NET/default.aspx" /><category term="IIS7" scheme="http://weblogs.asp.net/scottgu/archive/tags/IIS7/default.aspx" /><category term="Community News" scheme="http://weblogs.asp.net/scottgu/archive/tags/Community+News/default.aspx" /><category term="MVC" scheme="http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx" /><category term="jQuery" scheme="http://weblogs.asp.net/scottgu/archive/tags/jQuery/default.aspx" /><title type="html">Announcing release of ASP.NET MVC 3, IIS Express, SQL CE 4, Web Farm Framework, Orchard, WebMatrix</title><published>2011-01-13T18:11:00Z</published><updated>2011-01-13T18:11:00Z</updated><link rel="alternate" href="http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx" type="text/html" /><summary xml:base="http://weblogs.asp.net/scottgu/default.aspx" type="html">&lt;font size="2" face="arial"&gt;   &lt;p&gt;I’m excited to announce the release today of several products:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;ASP.NET MVC 3 &lt;/li&gt;      &lt;li&gt;NuGet &lt;/li&gt;      &lt;li&gt;IIS Express 7.5 &lt;/li&gt;      &lt;li&gt;SQL Server Compact Edition 4 &lt;/li&gt;      &lt;li&gt;Web Deploy and Web Farm Framework 2.0 &lt;/li&gt;      &lt;li&gt;Orchard 1.0 &lt;/li&gt;      &lt;li&gt;WebMatrix 1.0 &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;The above products are all free. They build upon the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/04/12/visual-studio-2010-and-net-4-released.aspx"&gt;.NET 4 and VS 2010&lt;/a&gt; release, and add a ton of additional value to ASP.NET (both Web Forms and MVC) and the Microsoft Web Server stack.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;ASP.NET MVC 3&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today we are shipping the final release of ASP.NET MVC 3.  You can download and install ASP.NET MVC 3 &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=d2928bc1-f48c-4e95-a064-2a455a22c8f6&amp;amp;displaylang=en"&gt;here&lt;/a&gt;.  The ASP.NET MVC 3 source code (released under an OSI-compliant open source license) can also optionally be downloaded &lt;a href="http://download.microsoft.com/download/3/4/A/34A8A203-BD4B-44A2-AF8B-CA2CFCB311CC/mvc3-rtm-mspl.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 is a significant update that brings with it a bunch of great features.  Some of the improvements include:&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Razor&lt;/u&gt;&lt;/strong&gt; &lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 ships with a new view-engine option called “Razor” (in addition to continuing to support/enhance the existing .aspx view engine).  Razor minimizes the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow. &lt;/p&gt;    &lt;p&gt;Unlike most template syntaxes, with Razor you do not need to interrupt your coding to explicitly denote the start and end of server blocks within your HTML. The Razor parser is smart enough to infer this from your code. This enables a compact and expressive syntax which is clean, fast and fun to type.  &lt;/p&gt;    &lt;p&gt;You can learn more about Razor from some of the blog posts I’ve done about it over the last 6 months&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx"&gt;Introducing Razor&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/10/19/asp-net-mvc-3-new-model-directive-support-in-razor.aspx"&gt;New @model keyword in Razor&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/10/22/asp-net-mvc-3-layouts.aspx"&gt;Layouts with Razor&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/11/12/asp-net-mvc-3-server-side-comments-with-razor.aspx"&gt;Server-Side Comments with Razor&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/15/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax.aspx"&gt;Razor’s @: and &amp;lt;text&amp;gt; syntax&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/16/asp-net-mvc-3-implicit-and-explicit-code-nuggets-with-razor.aspx"&gt;Implicit and Explicit code nuggets with Razor&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx"&gt;Layouts and Sections with Razor&lt;/a&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;Today’s release supports full code intellisense support for Razor (both VB and C#) with Visual Studio 2010 and the free Visual Web Developer 2010 Express.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;JavaScript Improvements&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 enables richer JavaScript scenarios and takes advantage of emerging HTML5 capabilities.&lt;/p&gt;    &lt;p&gt;The AJAX and Validation helpers in ASP.NET MVC 3 now use an &lt;a href="http://www.jeremyskinner.co.uk/2010/12/27/unobtrusive-ajax-helpers-in-mvc3/"&gt;Unobtrusive JavaScript&lt;/a&gt; based approach.  Unobtrusive JavaScript avoids injecting inline JavaScript into HTML, and enables cleaner separation of behavior using the new HTML 5 “data-“ attribute convention (which conveniently works on older browsers as well – including IE6). This keeps your HTML tight and clean, and makes it easier to optionally swap out or customize JS libraries.  &lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 now includes built-in support for &lt;a href="http://yobriefcase.posterous.com/aspnet-mvc3s-jsonvalueproviderfactory"&gt;posting JSON-based parameters&lt;/a&gt; from client-side JavaScript to action methods on the server.  This makes it easier to exchange data across the client and server, and build rich JavaScript front-ends.  We think this capability will be particularly useful going forward with scenarios involving &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/05/07/jquery-templates-and-data-linking-and-microsoft-contributing-to-jquery.aspx"&gt;client templates and data binding&lt;/a&gt; (including the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/10/04/jquery-templates-data-link-and-globalization-accepted-as-official-jquery-plugins.aspx"&gt;jQuery plugins the ASP.NET team recently contributed&lt;/a&gt; to the jQuery project).  &lt;/p&gt;    &lt;p&gt;Previous releases of ASP.NET MVC included the core jQuery library.  ASP.NET MVC 3 also now ships the jQuery Validate plugin (which our validation helpers use for client-side validation scenarios).  We are also now shipping and including jQuery UI by default as well (which provides a rich set of client-side JavaScript UI widgets for you to use within projects).&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Improved Validation&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 includes a bunch of validation enhancements that make it even easier to work with data.&lt;/p&gt;    &lt;p&gt;Client-side validation is now enabled by default with ASP.NET MVC 3 (using an onbtrusive javascript implementation).  Today’s release also includes built-in support for &lt;a href="http://davidhayden.com/blog/dave/archive/2011/01/04/ASPNETMVC3RemoteValidationTutorial.aspx"&gt;Remote Validation&lt;/a&gt; - which enables you to annotate a model class with a validation attribute that causes ASP.NET MVC to perform a remote validation call to a server method when validating input on the client.&lt;/p&gt;    &lt;p&gt;The validation features introduced within .NET 4’s System.ComponentModel.DataAnnotations namespace are now supported by ASP.NET MVC 3.  This includes support for the new &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/10/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3.aspx"&gt;IValidatableObject interface&lt;/a&gt; – which enables you to perform model-level validation, and allows you to provide validation error messages specific to the state of the overall model, or between two properties within the model.  &lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 also supports the improvements made to the ValidationAttribute class in .NET 4.  ValidationAttribute now supports a new IsValid overload that provides more information about the current validation context, such as what object is being validated.  This enables richer scenarios where you can validate the current value based on another property of the model.  We’ve shipped a &lt;a href="http://davidhayden.com/blog/dave/archive/2011/01/01/CompareAttributeASPNETMVC3.aspx"&gt;built-in [Compare] validation attribute&lt;/a&gt;  with ASP.NET MVC 3 that uses this support and makes it easy out of the box to compare and validate two property values.&lt;/p&gt;    &lt;p&gt;You can use any data access API or technology with ASP.NET MVC.  This past year, though, we’ve worked closely with the .NET data team to ensure that the new &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx"&gt;EF Code First library&lt;/a&gt; works really well for ASP.NET MVC applications.  These &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/08/announcing-entity-framework-code-first-ctp5-release.aspx"&gt;two&lt;/a&gt; &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/10/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3.aspx"&gt;posts&lt;/a&gt; of mine cover the latest EF Code First preview and demonstrates how to use it with ASP.NET MVC 3 to enable easy editing of data (with end to end client+server validation support).  The final release of EF Code First will ship in the next few weeks.&lt;/p&gt;    &lt;p&gt;Today we are also publishing the first preview of a new MvcScaffolding project.  It enables you to easily scaffold ASP.NET MVC 3 Controllers and Views, and works great with EF Code-First (and is pluggable to support other data providers).  You can learn more about it – and install it via NuGet today - from &lt;a href="http://blog.stevensanderson.com/2011/01/13/scaffold-your-aspnet-mvc-3-project-with-the-mvcscaffolding-package/"&gt;Steve Sanderson’s MvcScaffolding blog post&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Output Caching&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Previous releases of ASP.NET MVC supported output caching content at a URL or action-method level.&lt;/p&gt;    &lt;p&gt;With ASP.NET MVC V3 we are also enabling support for partial page output caching – which allows you to easily output cache regions or fragments of a response as opposed to the entire thing.  This ends up being super useful in a lot of scenarios, and enables you to dramatically reduce the work your application does on the server.  &lt;/p&gt;    &lt;p&gt;The new partial page output caching support in ASP.NET MVC 3 enables you to easily re-use cached sub-regions/fragments of a page across multiple URLs on a site.  It supports the ability to cache the content either on the web-server, or optionally cache it within a distributed cache server like Windows Server AppFabric or memcached.&lt;/p&gt;    &lt;p&gt;I’ll post some tutorials on my blog that show how to take advantage of ASP.NET MVC 3’s new output caching support for partial page scenarios in the future.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Better Dependency Injection&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 provides better support for applying Dependency Injection (DI) and integrating with Dependency Injection/IOC containers.&lt;/p&gt;    &lt;p&gt;With ASP.NET MVC 3 you no longer need to author custom ControllerFactory classes in order to enable DI with Controllers.  You can instead just register a Dependency Injection framework with ASP.NET MVC 3 and it will resolve dependencies not only for Controllers, but also for Views, Action Filters, Model Binders, Value Providers, Validation Providers, and Model Metadata Providers that you use within your application.&lt;/p&gt;    &lt;p&gt;This makes it much easier to cleanly integrate dependency injection within your projects.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Other Goodies&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 includes dozens of other nice improvements that help to both reduce the amount of code you write, and make the code you do write cleaner.  Here are just a few examples: &lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Improved New Project dialog that makes it easy to start new ASP.NET MVC 3 projects from templates. &lt;/li&gt;      &lt;li&gt;Improved Add-&amp;gt;View Scaffolding support that enables the generation of even cleaner view templates. &lt;/li&gt;      &lt;li&gt;New ViewBag property that uses .NET 4’s dynamic support to make it easy to pass late-bound data from Controllers to Views. &lt;/li&gt;      &lt;li&gt;Global Filters support that allows specifying cross-cutting filter attributes (like [HandleError]) across all Controllers within an app. &lt;/li&gt;      &lt;li&gt;New [AllowHtml] attribute that allows for more granular request validation when binding form posted data to models. &lt;/li&gt;      &lt;li&gt;Sessionless controller support that allows fine grained control over whether SessionState is enabled on a Controller. &lt;/li&gt;      &lt;li&gt;New ActionResult types like HttpNotFoundResult and &lt;a href="http://davidhayden.com/blog/dave/archive/2010/12/29/AspNetMvc3RedirectPermanentSEO.aspx"&gt;RedirectPermanent&lt;/a&gt; for common HTTP scenarios. &lt;/li&gt;      &lt;li&gt;New Html.Raw() helper to indicate that output should not be HTML encoded. &lt;/li&gt;      &lt;li&gt;New Crypto helpers for salting and hashing passwords. &lt;/li&gt;      &lt;li&gt;And much, much more… &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;u&gt;&lt;strong&gt;Learn More about ASP.NET MVC 3&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;We will be posting lots of tutorials and samples on the &lt;a href="http://asp.net/mvc"&gt;http://asp.net/mvc&lt;/a&gt; site in the weeks ahead.  Below are two good ASP.NET MVC 3 tutorials available on the site today:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a href="http://www.asp.net/mvc/tutorials/getting-started-with-mvc3-part1-cs"&gt;Build your First ASP.NET MVC 3 Application&lt;/a&gt;: &lt;a href="http://www.asp.net/mvc/tutorials/getting-started-with-mvc3-part1-vb"&gt;VB&lt;/a&gt; and &lt;a href="http://www.asp.net/mvc/tutorials/getting-started-with-mvc3-part1-cs"&gt;C#&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://www.asp.net/mvc/tutorials/mvc-music-store-part-1"&gt;Building the ASP.NET MVC 3 Music Store&lt;/a&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;We’ll post additional ASP.NET MVC 3 tutorials and videos on the &lt;a href="http://asp.net/mvc"&gt;http://asp.net/mvc&lt;/a&gt; site in the future. Visit it regularly to find new tutorials as they are published.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;How to Upgrade Existing Projects&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 is compatible with ASP.NET MVC 2 – which means it should be easy to update existing MVC projects to ASP.NET MVC 3.  &lt;/p&gt;    &lt;p&gt;The new features in ASP.NET MVC 3 build on top of the foundational work we’ve already done with the MVC 1 and MVC 2 releases – which means that the skills, knowledge, libraries, and books you’ve acquired are all directly applicable with the MVC 3 release.  MVC 3 adds new features and capabilities – it doesn’t obsolete existing ones.&lt;/p&gt;    &lt;p&gt;You can upgrade existing ASP.NET MVC 2 projects by following the &lt;a href="http://go.microsoft.com/fwlink/?LinkID=208140"&gt;manual upgrade steps in the release notes&lt;/a&gt;.  Alternatively, you can use this &lt;a href="http://blogs.msdn.com/b/marcinon/archive/2011/01/13/mvc-3-project-upgrade-tool.aspx"&gt;automated ASP.NET MVC 3 upgrade tool&lt;/a&gt; to easily update your  existing projects.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Localized Builds&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Today’s ASP.NET MVC 3 release is available in English.  We will be releasing localized versions of ASP.NET MVC 3 (in 9 languages) in a few days.  I’ll blog pointers to the localized downloads once they are available. &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;NuGet&lt;/u&gt; &lt;/h3&gt;    &lt;p&gt;Today we are also shipping NuGet – a free, open source, package manager that makes it easy for you to find, install, and use open source libraries in your projects. It works with all .NET project types (including ASP.NET Web Forms, ASP.NET MVC, WPF, WinForms, Silverlight, and Class Libraries).  You can download and install it &lt;a href="http://nuget.org/"&gt;here&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;NuGet enables developers who maintain open source projects (for example, .NET projects like Moq, NHibernate, Ninject, StructureMap, NUnit, Windsor, Raven, Elmah, etc) to package up their libraries and register them with an online gallery/catalog that is searchable.  The client-side NuGet tools – which include full Visual Studio integration – make it trivial for any .NET developer who wants to use one of these libraries to easily find and install it within the project they are working on.&lt;/p&gt;    &lt;p&gt;NuGet handles dependency management between libraries (for example: library1 depends on library2). It also makes it easy to update (and optionally remove) libraries from your projects later. It supports updating web.config files (if a package needs configuration settings). It also allows packages to add PowerShell scripts to a project (for example: scaffold commands). Importantly, NuGet is transparent and clean – and does not install anything at the system level. Instead it is focused on making it easy to manage libraries you use with your projects.&lt;/p&gt;    &lt;p&gt;Our goal with NuGet is to make it as simple as possible to integrate open source libraries within .NET projects.  &lt;/p&gt;    &lt;p&gt;&lt;u&gt;&lt;strong&gt;NuGet Gallery&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;This week we also launched a beta version of the &lt;a href="http://nuget.org"&gt;http://nuget.org&lt;/a&gt; web-site – which allows anyone to easily search and browse an online gallery of open source packages available via NuGet.  The site also now allows developers to optionally submit new packages that they wish to share with others.  You can learn more about how to create and share a package &lt;a href="http://haacked.com/archive/2011/01/12/uploading-packages-to-the-nuget-gallery.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;There are hundreds of open-source .NET projects already within the &lt;a href="http://nuget.org/"&gt;NuGet Gallery&lt;/a&gt; today.  We hope to have thousands there in the future.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;IIS Express 7.5&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today we are also shipping IIS Express 7.5.  IIS Express is a free version of IIS 7.5 that is optimized for developer scenarios.  It works for both ASP.NET Web Forms and ASP.NET MVC project types.&lt;/p&gt;    &lt;p&gt;We think IIS Express combines the ease of use of the ASP.NET Web Server (aka Cassini) currently built-into Visual Studio today with the full power of IIS.  Specifically:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;It’s lightweight and easy to install (less than 5Mb download and a quick install) &lt;/li&gt;      &lt;li&gt;It &lt;u&gt;does not&lt;/u&gt; require an administrator account to run/debug applications from Visual Studio &lt;/li&gt;      &lt;li&gt;It enables a &lt;u&gt;full web-server feature set&lt;/u&gt; – including SSL, URL Rewrite, and other IIS 7.x modules &lt;/li&gt;      &lt;li&gt;It supports and enables the same extensibility model and web.config file settings that IIS 7.x support &lt;/li&gt;      &lt;li&gt;It can be installed side-by-side with the full IIS web server as well as the ASP.NET Development Server (they do not conflict at all) &lt;/li&gt;      &lt;li&gt;It works on Windows XP and higher operating systems – giving you a full IIS 7.x developer feature-set on all Windows OS platforms &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;IIS Express (like the ASP.NET Development Server) can be quickly launched to run a site from a directory on disk.  It &lt;u&gt;does not&lt;/u&gt; require any registration/configuration steps. This makes it really easy to launch and run for development scenarios.  You can also optionally redistribute IIS Express with your own applications if you want a lightweight web-server.  The standard IIS Express EULA now includes redistributable rights.&lt;/p&gt;    &lt;p&gt;Visual Studio 2010 SP1 adds support for IIS Express.  Read my &lt;a href="http://weblogs.asp.net/scottgu/archive/2011/01/03/vs-2010-sp1-beta-and-iis-developer-express.aspx"&gt;VS 2010 SP1 and IIS Express blog post&lt;/a&gt; to learn more about what it enables.  &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;SQL Server Compact Edition 4&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today we are also shipping SQL Server Compact Edition 4 (aka SQL CE 4).  SQL CE is a free, embedded, database engine that enables easy database storage.&lt;/p&gt;    &lt;p&gt;&lt;u&gt;No Database Installation Required&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;SQL CE &lt;u&gt;does not&lt;/u&gt; require you to run a setup or install a database server in order to use it.  You can simply copy the SQL CE binaries into the \bin directory of your ASP.NET application, and then your web application can use it as a database engine.  No setup or extra security permissions are required for it to run. You do not need to have an administrator account on the machine. Just copy your web application onto any server and it will work. This is true even of medium-trust applications running in a web hosting environment.&lt;/p&gt;    &lt;p&gt;SQL CE runs in-memory within your ASP.NET application and will start-up when you first access a SQL CE database, and will automatically shutdown when your application is unloaded.  SQL CE databases are stored as files that live within the \App_Data folder of your ASP.NET Applications.&lt;/p&gt;    &lt;p&gt;&lt;u&gt;Works with Existing Data APIs&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;SQL CE 4 works with existing .NET-based data APIs, and supports a SQL Server compatible query syntax.  This means you can use existing data APIs like ADO.NET, as well as use higher-level ORMs like Entity Framework and NHibernate with SQL CE.  This enables you to use the same data programming skills and data APIs you know today.&lt;/p&gt;    &lt;p&gt;&lt;u&gt;Supports Development, Testing and Production Scenarios&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;SQL CE can be used for development scenarios, testing scenarios, and light production usage scenarios.  With the SQL CE 4 release we’ve done the engineering work to ensure that SQL CE won’t crash or deadlock when used in a multi-threaded server scenario (like ASP.NET).  This is a big change from previous releases of SQL CE – which were designed for client-only scenarios and which explicitly blocked running in web-server environments.  Starting with SQL CE 4 you can use it in a web-server as well.&lt;/p&gt;    &lt;p&gt;There are no license restrictions with SQL CE.  It is also totally free.&lt;/p&gt;    &lt;p&gt;&lt;u&gt;Tooling Support with VS 2010 SP1&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;Visual Studio 2010 SP1 adds support for SQL CE 4 and ASP.NET Projects.  Read my &lt;a href="http://weblogs.asp.net/scottgu/archive/2011/01/11/vs-2010-sp1-and-sql-ce.aspx"&gt;VS 2010 SP1 and SQL CE 4 blog post&lt;/a&gt; to learn more about what it enables.  &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Web Deploy and Web Farm Framework 2.0&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today we are also releasing Microsoft Web Deploy V2 and Microsoft Web Farm Framework V2.  These services provide a flexible and powerful way to deploy ASP.NET applications onto either a single server, or across a web farm of machines.&lt;/p&gt;    &lt;p&gt;You can learn more about these capabilities from my previous blog posts on them:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/09/08/introducing-the-microsoft-web-farm-framework.aspx"&gt;Introducing the Microsoft Web Farm Framework&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/09/13/automating-deployment-with-microsoft-web-deploy.aspx"&gt;Automating Deployment with Microsoft Web Deploy&lt;/a&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;Visit the &lt;a href="http://iis.net"&gt;http://iis.net&lt;/a&gt; website to learn more and install them. Both are free.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Orchard 1.0&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today we are also releasing Orchard v1.0.  &lt;/p&gt;    &lt;p&gt;Orchard is a free, open source, community based project.  It provides Content Management System (CMS) and Blogging System support out of the box, and makes it possible to easily create and manage web-sites without having to write code (site owners can customize a site through the browser-based editing tools built-into Orchard).  &lt;a href="http://www.orchardproject.net/docs/"&gt;Read these tutorials&lt;/a&gt; to learn more about how you can setup and manage your own Orchard site.&lt;/p&gt;    &lt;p&gt;Orchard itself is built as an ASP.NET MVC 3 application using Razor view templates (and by default uses SQL CE 4 for data storage).  Developers wishing to extend an Orchard site with custom functionality can open and edit it as a Visual Studio project – and add new ASP.NET MVC Controllers/Views to it.  &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;WebMatrix 1.0&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;WebMatrix is a new, free, web development tool from Microsoft that provides a suite of technologies that make it easier to enable website development.  It enables a developer to start a new site by browsing and downloading an app template from an online gallery of web applications (which includes popular apps like Umbraco, DotNetNuke, Orchard, WordPress, Drupal and Joomla).  Alternatively it also enables developers to create and code web sites from scratch.&lt;/p&gt;    &lt;p&gt;WebMatrix is task focused and helps guide developers as they work on sites.  WebMatrix includes IIS Express, SQL CE 4, and ASP.NET - providing an integrated web-server, database and programming framework combination.  It also includes built-in web publishing support which makes it easy to find and deploy sites to web hosting providers.&lt;/p&gt;    &lt;p&gt;You can learn more about WebMatrix from my &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/06/introducing-webmatrix.aspx"&gt;Introducing WebMatrix blog post&lt;/a&gt; this summer.  Visit &lt;a href="http://microsoft.com/web"&gt;http://microsoft.com/web&lt;/a&gt; to download and install it today.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;I’m really excited about today’s releases – they provide a bunch of additional value that makes web development with ASP.NET, Visual Studio and the Microsoft Web Server a lot better.  &lt;/p&gt;    &lt;p&gt;A lot of folks worked hard to share this with you today. On behalf of my whole team – we hope you enjoy them!&lt;/p&gt;    &lt;p&gt;Scott&lt;/p&gt;    &lt;p&gt;&lt;em&gt;P.S.&lt;/em&gt; &lt;em&gt;In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: &lt;/em&gt;&lt;a href="http://www.twitter.com/scottgu"&gt;twitter.com/scottgu&lt;/a&gt;&lt;/p&gt; &lt;/font&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7681992" width="1" height="1"&gt;</summary><author><name>ScottGu</name></author><source gr:stream-id="feed/http://weblogs.asp.net/ScottGu/Rss.aspx"><id>tag:google.com,2005:reader/feed/http://weblogs.asp.net/ScottGu/Rss.aspx</id><title type="html">ScottGu&amp;#39;s Blog</title><link rel="alternate" href="http://weblogs.asp.net/scottgu/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1295347776689"><id gr:original-id="http://kazimanzurrashid.com/posts/use-razor-for-email-template-outside-asp-dot-net-mvc">tag:google.com,2005:reader/item/a49a32bbd70cfc78</id><category term="ASP.NET MVC" scheme="http://kazimanzurrashid.com/topics/asp-dot-net-mvc/1" label="ASP.NET MVC" /><title type="html">Use Razor for Email Template outside ASP.NET MVC</title><published>2011-01-15T14:04:50Z</published><updated>2011-01-15T14:04:50Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/kazimanzurrashid/~3/gibJidkyX78/use-razor-for-email-template-outside-asp-dot-net-mvc" type="text/html" /><link rel="canonical" href="http://kazimanzurrashid.com/posts/use-razor-for-email-template-outside-asp-dot-net-mvc" /><content xml:base="http://kazimanzurrashid.com/" type="html">&lt;p&gt;So the ASP.NET MVC 3 &lt;a href="http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx" rel="external"&gt;RTM is out&lt;/a&gt; and the real icon of this release is the Razor View Engine. The best thing of Razor is that unlike its predecessor(webforms) it is not tied with the web environment, we can easily host it outside the web and  use it as template engine for various purpose. The project that I am currently working on needs to send bulk emails at various point of the application,  since the numbers can be hundreds or literary thousands I want to host it outside the web application so that it does add unnecessary overheads to the web application. In this post, I will show you you the code that I am using to generate these mails, you can download the complete code with MSpec specs from the bottom of the post.&lt;/p&gt;  &lt;p&gt;Lets say, in your application you want to send a welcome mail to user, whenever s/he registers. To send the mail you can use the following code:&lt;/p&gt;  &lt;div&gt;  &lt;pre&gt;&lt;code&gt;
      public virtual void SendWelcomeMail(string name, string password, string email)
      {
          var model = new
                      {
                          From = Configuration.FromAddress,
                          To = email,
                          Name = name,
                          Password = password,
                          LogOnUrl = Configuration.LogOnUrl()
                      };
      
          var mail = TemplateEngine.Execute(Configuration.SendWelcomeMailTemplateName, model);
      
          Sender.Send(mail);
      }
      &lt;/code&gt;&lt;/pre&gt;
      
      &lt;/div&gt;
      
      &lt;p&gt;And here is the template that it will use to generate the actual mail content:&lt;/p&gt;
      
      &lt;div&gt;
      
      &lt;pre&gt;&lt;code&gt;
      @{
          From = Model.From;
          To.Add(Model.To);
          Subject = &amp;quot;Welcome to my mysite.com&amp;quot;;
      }
      &amp;lt;html&amp;gt;
      &amp;lt;head&amp;gt;
          &amp;lt;title&amp;gt;Welcome to mysite.com&amp;lt;/title&amp;gt;
      &amp;lt;/head&amp;gt;
      &amp;lt;body&amp;gt;
          &amp;lt;p&amp;gt;Dear @Model.Name,&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;An account has been created for you.&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;Your account is FREE and allows you to perform bla bla features.&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;To login and complete your profile, please go to:&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;@Model.LogOnUrl&amp;quot;&amp;gt;@Model.LogOnUrl&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;Your User ID is your email address and password is: @Model.Password&amp;lt;/p&amp;gt;
      &amp;lt;/body&amp;gt;
      &amp;lt;/html&amp;gt;
      &lt;/code&gt;&lt;/pre&gt;
      
      &lt;/div&gt;
      
      &lt;p&gt;The code is very simple, first we are creating an anonymous object as model, you can also use strongly typed as well as the new &lt;code&gt;dynamic&lt;/code&gt; object, next we are using the template engine to generate the output and at last the mail object is passed to the mail sender for dispatching it. In the template the model is that we passed from the method is exposed as the &lt;code&gt;dynamic&lt;/code&gt; object. Behind the scene the template uses a base class which has some of the common properties that we often use for setting the mail:&lt;/p&gt;
      
      &lt;div&gt;
      
      &lt;pre&gt;&lt;code&gt;
      public abstract class EmailTemplate : IEmailTemplate
      {
          private readonly StringBuilder buffer;
      
          [DebuggerStepThrough]
          protected EmailTemplate()
          {
              To = new List&amp;lt;string&amp;gt;();
              ReplyTo = new List&amp;lt;string&amp;gt;();
              CC = new List&amp;lt;string&amp;gt;();
              Bcc = new List&amp;lt;string&amp;gt;();
              Headers = new Dictionary&amp;lt;string, string&amp;gt;(StringComparer.OrdinalIgnoreCase);
      
              buffer = new StringBuilder();
          }
      
          public string From { get; set; }
      
          public string Sender { get; set; }
      
          public ICollection&amp;lt;string&amp;gt; To { get; private set; }
      
          public ICollection&amp;lt;string&amp;gt; ReplyTo { get; private set; }
      
          public ICollection&amp;lt;string&amp;gt; CC { get; private set; }
      
          public ICollection&amp;lt;string&amp;gt; Bcc { get; private set; }
      
          public IDictionary&amp;lt;string, string&amp;gt; Headers { get; private set; }
      
          public string Subject { get; set; }
      
          public string Body
          {
              get { return buffer.ToString(); }
          }
      
          protected dynamic Model { get; private set; }
      
          public void SetModel(dynamic model)
          {
              Model = model;
          }
      
          public abstract void Execute();
      
          public virtual void Write(object value)
          {
              WriteLiteral(value);
          }
      
          public virtual void WriteLiteral(object value)
          {
              buffer.Append(value);
          }
      }
      &lt;/code&gt;&lt;/pre&gt;
      
      &lt;/div&gt;
      
      &lt;p&gt;It is also possible to compose a mail which contains both text and html format, so that the mail client which supports html should use the html version and the unsupported client could use the plain version. To compose a multi formatted mail you will have to use three templates the shared template will contain the common properties like From/To/Subject etc. and the other two will contain the actually body. For example, to use the above mail in multi format we will create the following templates:&lt;/p&gt;
      
      &lt;div&gt;
      
      Shared Template
      &lt;pre&gt;&lt;code&gt;
      @{
          From = Model.From;
          To.Add(Model.To);
          Subject = "Welcome to mysite.com";
      }
      &lt;/code&gt;&lt;/pre&gt;
      
      &lt;/div&gt;
      
      &lt;div&gt;
      
      Html Template
      &lt;pre&gt;&lt;code&gt;
      &amp;lt;html&amp;gt;
      &amp;lt;head&amp;gt;
          &amp;lt;title&amp;gt;Welcome to mysite.com&amp;lt;/title&amp;gt;
      &amp;lt;/head&amp;gt;
      &amp;lt;body&amp;gt;
          &amp;lt;p&amp;gt;Dear @Model.Name,&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;An account has been created for you.&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;Your account is FREE and allows you to perform bla bla features.&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;To login and complete your profile, please go to:&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;@Model.LogOnUrl&amp;quot;&amp;gt;@Model.LogOnUrl&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;Your User ID is your email address and password is: @Model.Password&amp;lt;/p&amp;gt;
      &amp;lt;/body&amp;gt;
      &amp;lt;/html&amp;gt;
      &lt;/code&gt;&lt;/pre&gt;
      
      &lt;/div&gt;
      
      &lt;div&gt;
      
      Text Template
      &lt;pre&gt;&lt;code&gt;
      Dear @Model.Name,
      
      An account has been created for you.
      
      Your account is FREE and allows you to perform bla bla features.
      
      To login and complete your profile, please go to:
      
      @Model.LogOnUrl
      
      Your User ID is your email address and password is: @Model.Password
      &lt;/code&gt;&lt;/pre&gt;
      
      &lt;/div&gt;
      
      &lt;p&gt;Now, when the mail is sent it should look like the following:&lt;/p&gt;
      
      &lt;div&gt;
      
      &lt;pre&gt;&lt;code&gt;
      X-Sender: me@myself.com
      X-Receiver: jon@smith.com
      MIME-Version: 1.0
      From: me@myself.com
      To: jon@smith.com
      Date: 15 Jan 2011 12:42:41 +0600
      Subject: Welcome to mysite.com
      Content-Type: multipart/alternative;
       boundary=--boundary_0_9202367d-977d-49b5-ab86-2bb3ed1bfc76
      
      
      ----boundary_0_9202367d-977d-49b5-ab86-2bb3ed1bfc76
      Content-Type: text/html
      Content-Transfer-Encoding: base64
      
      PGh0bWw+DQo8aGVhZD4NCiAgICA8dGl0bGU+V2VsY29tZSB0byBteXNpdGUuY29t
      PC90aXRsZT4NCjwvaGVhZD4NCjxib2R5Pg0KICAgIDxwPkRlYXIgSm9uIFNtaXRo
      LDwvcD4NCiAgICA8cD5BbiBhY2NvdW50IGhhcyBiZWVuIGNyZWF0ZWQgZm9yIHlv
      dS48L3A+DQogICAgPHA+WW91ciBhY2NvdW50IGlzIEZSRUUgYW5kIGFsbG93cyB5
      b3UgdG8gcGVyZm9ybSBibGEgYmxhIGZlYXR1cmVzLjwvcD4NCiAgICA8cD5UbyBs
      b2dpbiBhbmQgY29tcGxldGUgeW91ciBwcm9maWxlLCBwbGVhc2UgZ28gdG86PC9w
      Pg0KICAgIDxwPjxhIGhyZWY9Imh0dHA6Ly9teWNvbXBhbnkuY29tL2xvZ29uIj5o
      dHRwOi8vbXljb21wYW55LmNvbS9sb2dvbjwvYT48L3A+DQogICAgPHA+WW91ciBV
      c2VyIElEIGlzIHlvdXIgZW1haWwgYWRkcmVzcyBhbmQgcGFzc3dvcmQgaXM6IH4h
      QWdjMmQjNzwvcD4NCjwvYm9keT4NCjwvaHRtbD4=
      ----boundary_0_9202367d-977d-49b5-ab86-2bb3ed1bfc76
      Content-Type: text/plain
      Content-Transfer-Encoding: base64
      
      RGVhciBKb24gU21pdGgsDQoNCkFuIGFjY291bnQgaGFzIGJlZW4gY3JlYXRlZCBm
      b3IgeW91Lg0KDQpZb3VyIGFjY291bnQgaXMgRlJFRSBhbmQgYWxsb3dzIHlvdSB0
      byBwZXJmb3JtIGJsYSBibGEgZmVhdHVyZXMuDQoNClRvIGxvZ2luIGFuZCBjb21w
      bGV0ZSB5b3VyIHByb2ZpbGUsIHBsZWFzZSBnbyB0bzoNCg0KaHR0cDovL215Y29t
      cGFueS5jb20vbG9nb24NCg0KWW91ciBVc2VyIElEIGlzIHlvdXIgZW1haWwgYWRk
      cmVzcyBhbmQgcGFzc3dvcmQgaXM6IH4hQWdjMmQjNw==
      ----boundary_0_9202367d-977d-49b5-ab86-2bb3ed1bfc76--
      &lt;/code&gt;&lt;/pre&gt;
      
      &lt;/div&gt;
      
      &lt;p&gt;Currently it uses templates which are stored in the file system, but it is extensible enough to store the templates in other mediums like database. Like ASP.NET it compiles the templates to .NET types when first time it is requested, but it does not have the cache invalidation support like asp.net, may be I will add it in future.&lt;/p&gt;
      
      &lt;p&gt;That’s it for today.&lt;/p&gt;
      
      &lt;p&gt;&lt;strong&gt;Download:&lt;/strong&gt; &lt;a href="http://media.kazimanzurrashid.s3.amazonaws.com/EmailTemplate.zip"&gt;EmailTemplate.zip&lt;/a&gt;&lt;/p&gt;&lt;div style="margin:0px;padding:0px 0px 0px 0px"&gt;&lt;p&gt;&lt;a rel="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fkazimanzurrashid.com%2fposts%2fuse-razor-for-email-template-outside-asp-dot-net-mvc%26title%3dUse+Razor+for+Email+Template+outside+ASP.NET+MVC"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3a%2f%2fkazimanzurrashid.com%2fposts%2fuse-razor-for-email-template-outside-asp-dot-net-mvc"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kazimanzurrashid?a=gibJidkyX78:J543eTiDqjI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kazimanzurrashid?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kazimanzurrashid?a=gibJidkyX78:J543eTiDqjI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kazimanzurrashid?d=qj6IDK7rITs" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kazimanzurrashid?a=gibJidkyX78:J543eTiDqjI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kazimanzurrashid?i=gibJidkyX78:J543eTiDqjI:F7zBnMyn0Lo" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kazimanzurrashid/~4/gibJidkyX78" height="1" width="1"&gt;</content><author><name>Kazi Manzur Rashid</name></author><source gr:stream-id="feed/http://feeds2.feedburner.com/kazimanzurrashid"><id>tag:google.com,2005:reader/feed/http://feeds2.feedburner.com/kazimanzurrashid</id><title type="html">Kazi Manzur Rashid</title><link rel="alternate" href="http://kazimanzurrashid.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1292063302998"><id gr:original-id="c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7659821">tag:google.com,2005:reader/item/b1cacf3633029285</id><category term="ASP.NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/ASP.NET/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/.NET/default.aspx" /><category term="Community News" scheme="http://weblogs.asp.net/scottgu/archive/tags/Community+News/default.aspx" /><category term="MVC" scheme="http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx" /><title type="html">Announcing ASP.NET MVC 3 (Release Candidate 2)</title><published>2010-12-11T07:47:09Z</published><updated>2010-12-11T07:47:09Z</updated><link rel="alternate" href="http://weblogs.asp.net/scottgu/archive/2010/12/10/announcing-asp-net-mvc-3-release-candidate-2.aspx" type="text/html" /><summary xml:base="http://weblogs.asp.net/scottgu/default.aspx" type="html">&lt;font size="2" face="arial"&gt;   &lt;p&gt;Earlier today the ASP.NET team shipped the final release candidate (RC2) for ASP.NET MVC 3.  You can download and install it &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=955d593e-cbd1-4ed1-88eb-02ff79dd74d8&amp;amp;displaylang=en"&gt;here&lt;/a&gt;.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Almost there…&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today’s RC2 release is the near-final release of ASP.NET MVC 3, and is a true “release candidate” in that we are hoping to not make any more code changes with it.  We are publishing it today so that people can do final testing with it, let us know if they find any last minute “showstoppers”, and start updating their apps to use it.  We will officially ship the final ASP.NET MVC 3 “RTM” build in January.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Works with both VS 2010 and VS 2010 SP1 Beta&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today’s ASP.NET MVC 3 RC2 release works with both the shipping version of Visual Studio 2010 / Visual Web Developer 2010 Express, as well as the newly released &lt;a href="http://www.hanselman.com/blog/VisualStudioExplosionVS2010SP1BETAReleasedAndContext.aspx"&gt;VS 2010 SP1 Beta&lt;/a&gt;.  &lt;/p&gt;    &lt;p&gt;This means that you &lt;u&gt;do not &lt;/u&gt;need to install VS 2010 SP1 (or the SP1 beta) in order to use ASP.NET MVC 3.  It works just fine with the shipping Visual Studio 2010.  I’ll do a blog post next week, though, about some of the nice additional feature goodies that come with VS 2010 SP1 (including IIS Express and SQL CE support within VS) which make the dev experience for both ASP.NET Web Forms and ASP.NET MVC even better.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Bugs and Perf Fixes&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today’s ASP.NET MVC 3 RC2 build contains many bug fixes and performance optimizations.  Our latest performance tests indicate that ASP.NET MVC 3 is now faster than ASP.NET MVC 2, and that existing ASP.NET MVC applications will experience a slight performance increase when updated to run using ASP.NET MVC 3.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Final Tweaks and Fit-N-Finish&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;In addition to bug fixes and performance optimizations, today’s RC2 build contains a number of last-minute feature tweaks and “fit-n-finish” changes for the new ASP.NET MVC 3 features.  The feedback and suggestions we’ve received during the public previews has been invaluable in guiding these final tweaks, and we really appreciate people’s support in sending this feedback our way.  &lt;/p&gt;    &lt;p&gt;Below is a short-list of some of the feature changes/tweaks made between last month’s ASP.NET MVC 3 RC release and today’s ASP.NET MVC 3 RC2 release:&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;jQuery updates and addition of jQuery UI&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;The default ASP.NET MVC 3 project templates have been updated to include jQuery 1.4.4 and jQuery Validation 1.7.  &lt;/p&gt;    &lt;p&gt;We are also excited to announce today that we are including jQuery UI within our default ASP.NET project templates going forward.  jQuery UI provides a powerful set of additional UI widgets and capabilities.  It will be added by default to your project’s \scripts folder when you create new ASP.NET MVC 3 projects.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Improved View Scaffolding&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;The T4 templates used for scaffolding views with the Add-View dialog now generates views that use &lt;em&gt;Html.EditorFor &lt;/em&gt;instead of helpers such as &lt;em&gt;Html.TextBoxFor&lt;/em&gt;. This change enables you to optionally annotate models with metadata (using data annotation attributes) to better customize the output of your UI at runtime. &lt;/p&gt;    &lt;p&gt;The Add View scaffolding also supports improved detection and usage of primary key information on models (including support for naming conventions like ID, ProductID, etc).  For example: the Add View dialog box uses this information to ensure that the primary key value is not scaffold as an editable form field, and that links between views are auto-generated correctly with primary key information.&lt;/p&gt;    &lt;p&gt;The default Edit and Create templates also now include references to the jQuery scripts needed for client validation.  Scaffold form views now support client-side validation by default (no extra steps required).  Client-side validation with ASP.NET MVC 3 is also done using an unobtrusive javascript approach – making pages fast and clean.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;[ControllerSessionState] –&amp;gt; [SessionState]&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 adds support for session-less controllers.  With the initial RC you used a [ControllerSessionState] attribute to specify this.  We shortened this in RC2 to just be [SessionState]:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5DB3F0B7.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_43738793.png" width="376" height="110"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Note that in addition to turning off session state, you can also set it to be read-only (which is useful for webfarm scenarios where you are reading but not updating session state on a particular request).&lt;/p&gt;    &lt;p&gt;&lt;u&gt;&lt;strong&gt;[SkipRequestValidation] –&amp;gt; [AllowHtml]&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC includes built-in support to protect against HTML and Cross-Site Script Injection Attacks, and will throw an error by default if someone tries to post HTML content as input.  Developers need to explicitly indicate that this is allowed (and that they’ve hopefully built their app to securely support it) in order to enable it.&lt;/p&gt;    &lt;p&gt;With ASP.NET MVC 3, we are also now supporting a new attribute that you can apply to properties of models/viewmodels to indicate that HTML input is enabled, which enables much more granular protection in a DRY way.  In last month’s RC release this attribute was named [SkipRequestValidation].  With RC2 we renamed it to [AllowHtml] to make it more intuitive:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_4DC4ABF3.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2CD1394C.png" width="352" height="179"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Setting the above [AllowHtml] attribute on a model/viewmodel will cause ASP.NET MVC 3 to turn off HTML injection protection when model binding just that property.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Html.Raw() helper method&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;The new Razor view engine introduced with ASP.NET MVC 3 automatically HTML encodes output by default.  This helps provide an additional level of protection against HTML and Script injection attacks.&lt;/p&gt;    &lt;p&gt;With RC2 we are adding a Html.Raw() helper method that you can use to explicitly indicate that you do not want to HTML encode your output, and instead want to render the content “as-is”:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_52C6E9A2.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_46C4F96E.png" width="472" height="293"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;&lt;u&gt;&lt;strong&gt;ViewModel/View –&amp;gt; ViewBag&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC has (since V1) supported a ViewData[] dictionary within Controllers and Views that enables developers to pass information from a Controller to a View in a late-bound way.  This approach can be used instead of, or in combination with, a strongly-typed model class.  The below code demonstrates a common use case – where a strongly typed Product model is passed to the view in addition to two late-bound variables via the ViewData[] dictionary:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_45EC9384.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_3022AB27.png" width="611" height="225"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;With ASP.NET MVC 3 we are introducing a new API that takes advantage of the dynamic type support within .NET 4 to set/retrieve these values.  It allows you to use standard “dot” notation to specify any number of additional variables to be passed, and does not require that you create a strongly-typed class to do so.  &lt;/p&gt;    &lt;p&gt;With earlier previews of ASP.NET MVC 3 we exposed this API using a dynamic property called “ViewModel” on the Controller base class, and with a dynamic property called “View” within view templates.  A lot of people found the fact that there were two different names confusing, and several also said that using the name ViewModel was confusing in this context – since often you create strongly-typed ViewModel classes in ASP.NET MVC, and they do not use this API.  &lt;/p&gt;    &lt;p&gt;With RC2 we are exposing a dynamic property that has the same name – ViewBag – within both Controllers and Views.  It is a dynamic collection that allows you to pass additional bits of data from your controller to your view template to help generate a response.  Below is an example of how we could use it to pass a time-stamp message as well as a list of all categories to our view template:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_48461582.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_23485509.png" width="597" height="224"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Below is an example of how our view template (which is strongly-typed to expect a Product class as its model) can use the two extra bits of information we passed in our ViewBag to generate the response.  In particular, notice how we are using the list of categories passed in the dynamic ViewBag collection to generate a dropdownlist of friendly category names to help set the CategoryID property of our Product object.  &lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_226FEF1F.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_0C39D3CD.png" width="763" height="761"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;The above Controller/View combination will then generate an HTML response like below.  &lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_4001CA1E.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_29CBAECC.png" width="618" height="664"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Output Caching Improvements&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3’s output caching system no longer requires you to specify a VaryByParam property when declaring an [OutputCache] attribute on a Controller action method.  MVC3 now automatically varies the output cached entries when you have explicit parameters on your action method – allowing you to cleanly enable output caching on actions using code like below:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_48A222AA.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_7CD64BF0.png" width="362" height="134"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;In addition to supporting full page output caching, ASP.NET MVC 3 also supports partial-page caching – which allows you to cache a region of output and re-use it across multiple requests or controllers.  The [OutputCache] behavior for partial-page caching was updated with RC2 so that sub-content cached entries are varied based on input parameters as opposed to the URL structure of the top-level request – which makes caching scenarios both easier and more powerful than the behavior in the previous RC.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;@model declaration does not add whitespace&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;In earlier previews, the strongly-typed &lt;em&gt;@model&lt;/em&gt; declaration at the top of a Razor view added a blank line to the rendered HTML output. This has been fixed so that the declaration does not introduce whitespace.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Changed &amp;quot;Html.ValidationMessage&amp;quot; Method to Display the First Useful Error Message&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;The behavior of the &lt;em&gt;Html.ValidationMessage()&lt;/em&gt; helper was updated to show the first useful error message instead of simply displaying the first error. &lt;/p&gt;    &lt;p&gt;During model binding, the &lt;em&gt;ModelState&lt;/em&gt; dictionary can be populated from multiple sources with error messages about the property, including from the model itself (if it implements &lt;em&gt;IValidatableObject&lt;/em&gt;), from validation attributes applied to the property, and from exceptions thrown while the property is being accessed. &lt;/p&gt;    &lt;p&gt;When the &lt;em&gt;Html.ValidationMessage()&lt;/em&gt; method displays a validation message, it now skips model-state entries that include an exception, because these are generally not intended for the end user. Instead, the method looks for the first validation message that is not associated with an exception and displays that message. If no such message is found, it defaults to a generic error message that is associated with the first exception.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;RemoteAttribute “Fields” -&amp;gt; “AdditionalFields” &lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 includes built-in remote validation support with its validation infrastructure.  This means that the client-side validation script library used by ASP.NET MVC 3 can automatically call back to controllers you expose on the server to determine whether an input element is indeed valid as the user is editing the form (allowing you to provide real-time validation updates).&lt;/p&gt;    &lt;p&gt;You can accomplish this by decorating a model/viewmodel property with a [Remote] attribute that specifies the controller/action that should be invoked to remotely validate it.  With the RC this attribute had a “Fields” property that could be used to specify additional input elements that should be sent from the client to the server to help with the validation logic.  To improve the clarity of what this property does we have renamed it to “AdditionalFields” with today’s RC2 release. &lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;ViewResult.Model and ViewResult.ViewBag Properties&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;The ViewResult class now exposes both a “Model” and “ViewBag” property off of it.  This makes it easier to unit test Controllers that return views, and avoids you having to access the Model via the ViewResult.ViewData.Model property.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Installation Notes&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;You can download and install the ASP.NET MVC 3 RC2 build &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=955d593e-cbd1-4ed1-88eb-02ff79dd74d8&amp;amp;displaylang=en"&gt;here&lt;/a&gt;.  It can be installed on top of the previous ASP.NET MVC 3 RC release (it should just replace the bits as part of its setup).&lt;/p&gt;    &lt;p&gt;The one component that will not be updated by the above setup (if you already have it installed) is the NuGet Package Manager.  If you already have NuGet installed, please go to the Visual Studio Extensions Manager (via the Tools –&amp;gt; Extensions menu option) and click on the “Updates” tab.  You should see NuGet listed there – please click the “Update” button next to it to have VS update the extension to today’s release.&lt;/p&gt;    &lt;p&gt;If you do not have NuGet installed (and did not install the ASP.NET MVC RC build), then NuGet will be installed as part of your ASP.NET MVC 3 setup, and you do not need to take any additional steps to make it work.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;We are really close to the final ASP.NET MVC 3 release, and will deliver the final “RTM” build of it next month.  It has been only a little over 7 months since ASP.NET MVC 2 shipped, and I’m pretty amazed by the huge number of new features, improvements, and refinements that the team has been able to add with this release (Razor, Unobtrusive JavaScript, NuGet, Dependency Injection, Output Caching, and a lot, lot more).  I’ll be doing a number of blog posts over the next few weeks talking about many of them in more depth.&lt;/p&gt;    &lt;p&gt;Hope this helps,&lt;/p&gt;    &lt;p&gt;Scott&lt;/p&gt;    &lt;p&gt;&lt;i&gt;P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: &lt;/i&gt;&lt;a href="http://www.twitter.com/scottgu"&gt;twitter.com/scottgu&lt;/a&gt;&lt;/p&gt; &lt;/font&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7659821" width="1" height="1"&gt;</summary><author><name>ScottGu</name></author><source gr:stream-id="feed/http://weblogs.asp.net/ScottGu/Rss.aspx"><id>tag:google.com,2005:reader/feed/http://weblogs.asp.net/ScottGu/Rss.aspx</id><title type="html">ScottGu&amp;#39;s Blog</title><link rel="alternate" href="http://weblogs.asp.net/scottgu/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1292063292268"><id gr:original-id="c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7659102">tag:google.com,2005:reader/item/10d7b8a5d1c3aa9f</id><category term="ASP.NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/ASP.NET/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/.NET/default.aspx" /><category term="LINQ" scheme="http://weblogs.asp.net/scottgu/archive/tags/LINQ/default.aspx" /><category term="MVC" scheme="http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx" /><title type="html">Class-Level Model Validation with EF Code First and ASP.NET MVC 3</title><published>2010-12-10T09:05:45Z</published><updated>2010-12-10T09:05:45Z</updated><link rel="alternate" href="http://weblogs.asp.net/scottgu/archive/2010/12/10/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3.aspx" type="text/html" /><summary xml:base="http://weblogs.asp.net/scottgu/default.aspx" type="html">&lt;font size="2" face="arial"&gt;   &lt;p&gt;Earlier this week the data team &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/08/announcing-entity-framework-code-first-ctp5-release.aspx"&gt;released the CTP5 build&lt;/a&gt; of the new Entity Framework Code-First library.  &lt;/p&gt;    &lt;p&gt;In my &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/08/announcing-entity-framework-code-first-ctp5-release.aspx"&gt;blog post&lt;/a&gt; a few days ago I talked about a few of the improvements introduced with the new CTP5 build.  Automatic support for enforcing DataAnnotation validation attributes on models was one of the improvements I discussed.  It provides a pretty easy way to enable property-level validation logic within your model layer.&lt;/p&gt;    &lt;p&gt;You can apply validation attributes like [Required], [Range], and [RegularExpression] – all of which are built-into .NET 4 – to your model classes in order to enforce that the model properties are valid before they are persisted to a database.  You can also create your own custom validation attributes (like this cool &lt;a href="http://benjii.me/2010/11/credit-card-validator-attribute-for-asp-net-mvc-3/"&gt;[CreditCard] validator&lt;/a&gt;) and have them be automatically enforced by EF Code First as well.  This provides a really easy way to validate property values on your models.  I showed some code samples of this in action in my &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/12/08/announcing-entity-framework-code-first-ctp5-release.aspx"&gt;previous post&lt;/a&gt;.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Class-Level Model Validation using IValidatableObject&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;DataAnnotation attributes provides an easy way to validate individual property values on your model classes.  &lt;/p&gt;    &lt;p&gt;Several people have asked - “Does EF Code First also support a way to implement &lt;em&gt;class-level&lt;/em&gt; validation methods on model objects, for validation rules than need to &lt;em&gt;span multiple property values&lt;/em&gt;?”  It does – and one easy way you can enable this is by implementing the IValidatableObject interface on your model classes.&lt;/p&gt;    &lt;p&gt;&lt;u&gt;IValidatableObject.Validate() Method&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;Below is an example of using the IValidatableObject interface (which is built-into .NET 4 within the System.ComponentModel.DataAnnotations namespace) to implement two custom validation rules on a Product model class.  The two rules ensure that:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;New units can’t be ordered if the Product is in a discontinued state &lt;/li&gt;      &lt;li&gt;New units can’t be ordered if there are already more than 100 units in stock &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;We will enforce these business rules by implementing the IValidatableObject interface on our Product class, and by implementing its Validate() method like so:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_3D493906.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_223069F8.png" width="808" height="399"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;The IValidatableObject.Validate() method can apply validation rules that span across multiple properties, and can yield back multiple validation errors. Each ValidationResult returned can supply both an error message as well as an &lt;em&gt;optional&lt;/em&gt; &lt;em&gt;list&lt;/em&gt; of property names that caused the violation (which is useful when displaying error messages within UI).&lt;/p&gt;    &lt;p&gt;&lt;u&gt;Automatic Validation Enforcement&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;EF Code-First (starting with CTP5) now automatically invokes the Validate() method when a model object that implements the IValidatableObject interface is saved.  You &lt;u&gt;do not&lt;/u&gt; need to write any code to cause this to happen – this support is now enabled by default. &lt;/p&gt;    &lt;p&gt;This new support means that the below code – which violates one of our above business rules – will automatically throw an exception (and abort the transaction) when we call the “SaveChanges()” method on our Northwind DbContext:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_0BFA4EA6.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_6A9AA909.png" width="489" height="204"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;In addition to reactively handling validation exceptions, EF Code First also allows you to proactively check for validation errors.  Starting with CTP5, you can call the “GetValidationErrors()” method on the DbContext base class to retrieve a list of validation errors within the model objects you are working with.  GetValidationErrors() will return a list of all validation errors – regardless of whether they are generated via DataAnnotation attributes or by an IValidatableObject.Validate() implementation.  &lt;/p&gt;    &lt;p&gt;Below is an example of proactively using the GetValidationErrors() method to check (and handle) errors before trying to call SaveChanges():&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5E2C85E0.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_764FF03B.png" width="390" height="292"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;ASP.NET MVC 3 and IValidatableObject&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;ASP.NET MVC 2 included support for automatically honoring and enforcing DataAnnotation attributes on model objects that are used with ASP.NET MVC’s model binding infrastructure.  ASP.NET MVC 3 goes further and also honors the IValidatableObject interface.  This combined support for model validation makes it easy to display appropriate error messages within forms when validation errors occur.  &lt;/p&gt;    &lt;p&gt;To see this in action, let’s consider a simple Create form that allows users to create a new Product:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_608607DE.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_7F5C7BBC.png" width="612" height="695"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;We can implement the above Create functionality using a ProductsController class that has two “Create” action methods like below:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_05371F56.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_38FF15A7.png" width="433" height="545"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;The first Create() method implements a version of the /Products/Create URL that handles HTTP-GET requests - and displays the HTML form to fill-out.  The second Create() method implements a version of the /Products/Create URL that handles HTTP-POST requests - and which takes the posted form data, ensures that is is valid, and if it is valid saves it in the database.  If there are validation issues it redisplays the form with the posted values.  &lt;/p&gt;    &lt;p&gt;The razor view template of our “Create” view (which renders the form) looks like below:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_77F09642.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_0FA7CDA9.png" width="583" height="912"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;One of the nice things about the above Controller + View implementation is that &lt;u&gt;we did not write any validation logic within it&lt;/u&gt;.  The validation logic and business rules are instead implemented entirely within our model layer, and the ProductsController simply checks whether it is valid (by calling the ModelState.IsValid helper method) to determine whether to try and save the changes or redisplay the form with errors. The Html.ValidationMessageFor() helper method calls within our view simply display the error messages our Product model’s DataAnnotations and IValidatableObject.Validate() method returned.  &lt;/p&gt;    &lt;p&gt;We can see the above scenario in action by filling out invalid data within the form and attempting to submit it:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_15827142.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2D39A8A8.png" width="647" height="703"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Notice above how when we hit the “Create” button we got an error message.  This was because we ticked the “Discontinued” checkbox while also entering a value for the UnitsOnOrder (and so violated one of our business rules).  &lt;/p&gt;    &lt;p&gt;You might ask – how did ASP.NET MVC know to highlight and display the error message next to the UnitsOnOrder textbox?  It did this because ASP.NET MVC 3 now honors the IValidatableObject interface when performing model binding, and will retrieve the error messages from validation failures with it.&lt;/p&gt;    &lt;p&gt;The business rule within our Product model class indicated that the “UnitsOnOrder” property should be highlighted when the business rule we hit was violated: &lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_4C101C86.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_6AE69064.png" width="814" height="166"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Our Html.ValidationMessageFor() helper method knew to display the business rule error message (next to the UnitsOnOrder edit box) because of the above property name hint we supplied:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_0309FAC0.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_73F31BE5.png" width="490" height="149"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Keeping things DRY&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;ASP.NET MVC and EF Code First enables you to keep your validation and business rules in one place (within your model layer), and avoid having it creep into your Controllers and Views.  &lt;/p&gt;    &lt;p&gt;Keeping the validation logic in the model layer helps ensure that you do not duplicate validation/business logic as you add more Controllers and Views to your application.  It allows you to quickly change your business rules/validation logic in one single place (within your model layer) – and have all controllers/views across your application immediately reflect it.  This help keep your application code clean and easily maintainable, and makes it much easier to evolve and update your application in the future.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;EF Code First (starting with CTP5) now has built-in support for both DataAnnotations and the IValidatableObject interface.  This allows you to easily add validation and business rules to your models, and have EF automatically ensure that they are enforced anytime someone tries to persist changes of them to a database.  &lt;/p&gt;    &lt;p&gt;ASP.NET MVC 3 also now supports both DataAnnotations and IValidatableObject as well, which makes it even easier to use them with your EF Code First model layer – and then have the controllers/views within your web layer automatically honor and support them as well.  This makes it easy to build clean and highly maintainable applications.&lt;/p&gt;    &lt;p&gt;You don’t have to use DataAnnotations or IValidatableObject to perform your validation/business logic.  You can always roll your own custom validation architecture and/or use other more advanced validation frameworks/patterns if you want.  But for a lot of applications this built-in support will probably be sufficient – and provide a highly productive way to build solutions.&lt;/p&gt;    &lt;p&gt;Hope this helps,&lt;/p&gt;    &lt;p&gt;Scott&lt;/p&gt;    &lt;p&gt;&lt;em&gt;P.S.&lt;/em&gt; &lt;em&gt;In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: &lt;a href="http://twitter.com/scottgu"&gt;twitter.com/scottgu&lt;/a&gt;&lt;/em&gt;&lt;/p&gt; &lt;/font&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7659102" width="1" height="1"&gt;</summary><author><name>ScottGu</name></author><source gr:stream-id="feed/http://weblogs.asp.net/ScottGu/Rss.aspx"><id>tag:google.com,2005:reader/feed/http://weblogs.asp.net/ScottGu/Rss.aspx</id><title type="html">ScottGu&amp;#39;s Blog</title><link rel="alternate" href="http://weblogs.asp.net/scottgu/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1289643288058"><id gr:original-id="c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7641686">tag:google.com,2005:reader/item/b07caa794b97a644</id><category term="ASP.NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/ASP.NET/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/.NET/default.aspx" /><category term="Community News" scheme="http://weblogs.asp.net/scottgu/archive/tags/Community+News/default.aspx" /><category term="MVC" scheme="http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx" /><title type="html">ASP.NET MVC 3: Server-Side Comments with Razor</title><published>2010-11-13T01:33:50Z</published><updated>2010-11-13T01:33:50Z</updated><link rel="alternate" href="http://weblogs.asp.net/scottgu/archive/2010/11/12/asp-net-mvc-3-server-side-comments-with-razor.aspx" type="text/html" /><summary xml:base="http://weblogs.asp.net/scottgu/default.aspx" type="html">&lt;font size="2" face="arial"&gt;   &lt;p&gt;Earlier this week we &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/11/09/announcing-the-asp-net-mvc-3-release-candidate.aspx"&gt;shipped the ASP.NET MVC 3 Release Candidate&lt;/a&gt;.  It supports “go live” deployments, and includes a bunch of great improvements/enhancements on top of the features we enabled earlier with the ASP.NET MVC 3 &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/10/06/announcing-nupack-asp-net-mvc-3-beta-and-webmatrix-beta-2.aspx"&gt;beta&lt;/a&gt; and &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx"&gt;first preview&lt;/a&gt; releases.&lt;/p&gt;    &lt;p&gt;This is another in a series of “mini-posts” I’m doing that talk about a few of the new ASP.NET MVC 3 Beta/RC features in more detail:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/10/19/asp-net-mvc-3-new-model-directive-support-in-razor.aspx"&gt;New @model keyword in Razor (Oct 19th)&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/10/22/asp-net-mvc-3-layouts.aspx"&gt;Layouts with Razor (Oct 22nd)&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;Server-Side Comments with Razor (today) &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;In today’s post I’m going to discuss a small, but useful, feature we’ve recently introduced: server-side comment support in Razor.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Why Server Side Comments?&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Scenario: You are working within a view template, and want to temporarily disable some content or view code (potentially to help track down a problem, or to temporarily change the output of your site).&lt;/p&gt;    &lt;p&gt;HTML supports client-side comments (&amp;lt;!-- --&amp;gt;), which you can use to prevent a browser from parsing/running/displaying the HTML content within it.  The problem with using this approach for many scenarios, though, is that the content contained within the comment is still sent down from the server to the client unnecessarily – and the server-side code within the comment will still execute on the server.  &lt;/p&gt;    &lt;p&gt;ASP.NET Web Forms supports a &lt;a href="http://weblogs.asp.net/scottgu/archive/2006/07/09/Tip_2F00_Trick_3A00_-Using-Server-Side-Comments-with-ASP.NET-2.0-.aspx"&gt;server-side comment syntax&lt;/a&gt; (&amp;lt;%-- --%&amp;gt;) that you can use to completely disable content/code/controls within a page.  With server-side comments, the ASP.NET Web Forms compiler completely ignore everything within the &amp;lt;%-- --%&amp;gt; blocks at parse time, and removes the content completely when assembling the page (like the contents wasn’t there at all).  You can learn more about this feature from an older blog post of mine &lt;a href="http://weblogs.asp.net/scottgu/archive/2006/07/09/Tip_2F00_Trick_3A00_-Using-Server-Side-Comments-with-ASP.NET-2.0-.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;    &lt;p&gt;One question someone asked me earlier this week was “is there an equivalent way to do this with Razor?”.  The answer is - yes! &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Server Side Comments with Razor&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Razor now allows you to wrap any code/content/region of a view within a @* comment *@ syntax (which works for both C# and VB templates).  This syntax indicates that the Razor parser should ignore everything within that block and treat it like it isn’t there at all (meaning nothing is ever executed, there is no performance overhead at runtime, and nothing is sent down to the client).&lt;/p&gt;    &lt;p&gt;For example, below I’ve wrapped some HTML content and server-code within a @* *@ block.  This is equivalent to it not being there at all:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_73274D39.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_71E2B45A.png" width="670" height="375"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Notice above how Visual Studio (starting with this week’s ASP.NET MVC 3 RC build) now colorizes comments (by default in green) to make them more visible within the editor.  &lt;/p&gt;    &lt;p&gt;Visual Studio also now enables you to use the comment/uncomment buttons on the text editor toolbar to easily comment/un-comment a block of text/code.  For example, we could select the above @* *@ comment block within the text editor, and then click the “Uncomment” toolbar button (or better yet press Ctrl+K, Ctrl+U) to have VS uncomment the region:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_30D434F6.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_488B6C5C.png" width="670" height="375"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;When we do this the editor will automatically uncomment the block for us (saving us some keystrokes):&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_598F9A3F.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_25E72DE1.png" width="670" height="375"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;We could then highlight another region of text/code within the editor, and then either click the “Comment” toolbar button or press Ctrl+K, Ctrl+C to apply a server-side comment:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_64D8AE7C.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_235DFC23.png" width="670" height="375"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;When we do this the editor will automatically comment the block for us (saving us some keystrokes):&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_4D5DFA4B.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_1302846A.png" width="670" height="375"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Server-side comments are a small, but useful, feature that can come in handy in a variety of circumstances.  Razor now enables server-side comments at runtime, and Visual Studio provides nice tooling support for them at development time.&lt;/p&gt;    &lt;p&gt;Hope this helps,&lt;/p&gt;    &lt;p&gt;Scott&lt;/p&gt;    &lt;p&gt;&lt;i&gt;P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: &lt;/i&gt;&lt;a href="http://www.twitter.com/scottgu"&gt;twitter.com/scottgu&lt;/a&gt;&lt;/p&gt; &lt;/font&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7641686" width="1" height="1"&gt;</summary><author><name>ScottGu</name></author><source gr:stream-id="feed/http://weblogs.asp.net/ScottGu/Rss.aspx"><id>tag:google.com,2005:reader/feed/http://weblogs.asp.net/ScottGu/Rss.aspx</id><title type="html">ScottGu&amp;#39;s Blog</title><link rel="alternate" href="http://weblogs.asp.net/scottgu/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1289337834288"><id gr:original-id="tag:blogger.com,1999:blog-27752126.post-8754954889593511468">tag:google.com,2005:reader/item/2240193a63f623ce</id><category term="desarrollo" scheme="http://www.blogger.com/atom/ns#" /><category term="asp.net" scheme="http://www.blogger.com/atom/ns#" /><category term="aspnetmvc" scheme="http://www.blogger.com/atom/ns#" /><category term="trucos" scheme="http://www.blogger.com/atom/ns#" /><title type="html">Binder para decimales con separador de miles</title><published>2010-11-08T22:58:00Z</published><updated>2010-11-08T22:58:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/vnf/~3/3UIkID1x_qA/binder-para-decimales-con-separador-de.html" type="text/html" /><link rel="replies" href="http://www.variablenotfound.com/feeds/8754954889593511468/comments/default" title="Enviar comentarios" type="application/atom+xml" /><link rel="replies" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=8754954889593511468" title="0 comentarios" type="text/html" /><link rel="canonical" href="http://www.variablenotfound.com/2010/11/binder-para-decimales-con-separador-de.html" /><content xml:base="http://www.variablenotfound.com/" type="html">&lt;img align="right" alt="aspnetmvc" border="0" height="77" src="http://lh4.ggpht.com/_O9D62hXq-ng/TMxeVMqjefI/AAAAAAAABXQ/V1EbambhavU/aspnetmvc%5B3%5D.png?imgmax=800" style="border-bottom:0px;border-left:0px;border-right:0px;border-top:0px;display:inline;margin:0px 0px 10px 10px" title="aspnetmvc" width="142"&gt; Hace poco he estado trabajando en un sistema, desarrollado con ASP.NET MVC, en el que el usuario debía introducir una gran cantidad de datos numéricos dispuestos por filas y columnas, de forma muy similar a una hoja de cálculo:&lt;br&gt;
&lt;br&gt;
&lt;img alt="Captura de imagen de aplicación" border="0" height="180" src="http://lh5.ggpht.com/_O9D62hXq-ng/TMxeV9GtcMI/AAAAAAAABXU/c2GPpEEvENc/image%5B14%5D.png?imgmax=800" style="border-bottom:0px;border-left:0px;border-right:0px;border-top:0px;display:block;float:none;margin:0px auto 10px" title="Captura de imagen de aplicación" width="576"&gt; &lt;br&gt;
&lt;br&gt;
Para conseguir una experiencia de usuario lo mejor posible, introduje en la vista scripting para formatear las celdas, de forma que cuando una de ellas toma el foco, se elimina su formato, mientras que cuando lo pierde, se le aplicaba el formateo numérico correcto. Hasta ahí, sin problema.&lt;br&gt;
&lt;br&gt;
&lt;em&gt;Nota al margen&lt;/em&gt;: para formatear y parsear los valores numéricos en cliente he utilizado por primera vez el nuevo &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/06/10/jquery-globalization-plugin-from-microsoft.aspx"&gt;plugin de globalización para jQuery que ya presentó Scott Guthrie hace algún tiempo&lt;/a&gt;. Me ha parecido magnífico y muy sencillo de utilizar, a ver si un día escribo algo sobre él.&lt;br&gt;
&lt;br&gt;
Bueno, a lo que iba; el único problema de utilizar este enfoque es que, al aceptar el formulario, el valor de los campos es enviado tal y como aparecen en los controles de edición, separador de miles incluido, por lo que el binder para el tipo &lt;code&gt;decimal&lt;/code&gt; no es capaz de identificarlos apropiadamente utilizando su lógica por defecto.&lt;br&gt;
&lt;br&gt;
Sin embargo, dada la facilidad del framework para reemplazar estos comportamientos, es realmente sencillo introducir un binder personalizado capaz de recoger estos valores y retornar el valor &lt;code&gt;decimal&lt;/code&gt; correcto, que es realmente lo que pretendemos que llegue al modelo.&lt;br&gt;
&lt;br&gt;
El código del binder es el siguiente:&lt;br&gt;
&lt;br&gt;
&lt;img alt="Código del binder" border="0" height="249" src="http://lh6.ggpht.com/_O9D62hXq-ng/TMxeW6W2XOI/AAAAAAAABXY/4zV74PhkgNI/image%5B35%5D.png?imgmax=800" style="border-bottom:0px;border-left:0px;border-right:0px;border-top:0px;display:inline;margin:0px 0px 10px" title="Código del binder" width="640"&gt;&lt;br&gt;
Y para que el framework ASP.NET MVC utilice este binder para las propiedades o parámetros de tipo &lt;code&gt;decimal&lt;/code&gt;, basta con registrarlo en el global.asax, como sigue:&lt;br&gt;
&lt;br&gt;
&lt;img alt="Registro del binder en el global.asax" border="0" height="160" src="http://lh3.ggpht.com/_O9D62hXq-ng/TMxeXqycv_I/AAAAAAAABXc/iKIBJWgODx8/image%5B36%5D.png?imgmax=800" style="border-bottom:0px;border-left:0px;border-right:0px;border-top:0px;display:inline;margin:0px 0px 10px" title="Registro del binder en el global.asax" width="463"&gt; &lt;br&gt;
Publicado en: &lt;a href="http://www.variablenotfound.com/" title="Variable Not Found"&gt;Variable not found&lt;/a&gt;.&lt;div&gt;&lt;img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/27752126-8754954889593511468?l=www.variablenotfound.com" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/iveid3oitg2k07u8r44sagtpvs/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fwww.variablenotfound.com%2F2010%2F11%2Fbinder-para-decimales-con-separador-de.html" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=3UIkID1x_qA:zX4bcBmQE4U:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=3UIkID1x_qA:zX4bcBmQE4U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=3UIkID1x_qA:zX4bcBmQE4U:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=3UIkID1x_qA:zX4bcBmQE4U:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=3UIkID1x_qA:zX4bcBmQE4U:4cEx4HpKnUU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=3UIkID1x_qA:zX4bcBmQE4U:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=3UIkID1x_qA:zX4bcBmQE4U:F7zBnMyn0Lo" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=3UIkID1x_qA:zX4bcBmQE4U:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=3UIkID1x_qA:zX4bcBmQE4U:gIN9vFwOqvQ" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=3UIkID1x_qA:zX4bcBmQE4U:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=I9og5sOYxJI" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/3UIkID1x_qA" height="1" width="1"&gt;</content><author><name>José M. Aguilar</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/vnf"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/vnf</id><title type="html">Variable not found</title><link rel="alternate" href="http://www.variablenotfound.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1289337437431"><id gr:original-id="http://haacked.com/archive/2010/11/09/asp-net-mvc-3-release-candidate.aspx">tag:google.com,2005:reader/item/0c886e6b7140fec0</id><category term="ASP.NET" /><category term="ASP.NET MVC" /><category term="Software Development" /><category term="NuGet" /><title type="html">ASP.NET MVC 3 Release Candidate</title><published>2010-11-09T16:05:00Z</published><updated>2010-11-09T16:05:00Z</updated><link rel="alternate" href="http://feeds.haacked.com/~r/haacked/~3/Xjn6-godT1g/asp-net-mvc-3-release-candidate.aspx" type="text/html" /><link rel="canonical" href="http://haacked.com/archive/2010/11/09/asp-net-mvc-3-release-candidate.aspx" /><summary xml:base="http://haacked.com/Default.aspx" type="html">&lt;p&gt;Today we’re releasing the release candidate for ASP.NET MVC 3. We’re in the home stretch now so it’ll mostly be bug fixes and small tweaks from here on out.&lt;/p&gt;  &lt;p&gt;There are two ways to install ASP.NET MVC 3:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="Install MVC 3 via Web PI" href="http://www.microsoft.com/web/gallery/install.aspx?appid=MVC3"&gt;Via the Web Platform Installer (Web PI)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Or by &lt;a title="Download the MVC 3 installer" href="http://go.microsoft.com/fwlink/?LinkID=191797"&gt;downloading the installer directly&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Also, be sure to check out the &lt;a title="ASP.NET MVC 3" href="http://www.asp.net/mvc/mvc3"&gt;ASP.NET MVC 3 web page&lt;/a&gt; for information and content about ASP.NET MVC 3 as well as the &lt;a title="ASP.NET MVC 3 RC Release Notes" href="http://www.asp.net/learn/whitepapers/mvc3-release-notes"&gt;release notes for this release&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Also, don’t miss Scott Guthrie’s &lt;a title="Announcing Release Candidate of ASP.NET MVC 3" href="http://weblogs.asp.net/scottgu/archive/2010/11/09/announcing-the-asp-net-mvc-3-release-candidate.aspx"&gt;blog post on ASP.NET MVC 3&lt;/a&gt; which provides the usual level of detail on the release.&lt;/p&gt;  &lt;h2&gt;Razor Intellisense. Ah Yeah!&lt;/h2&gt;  &lt;p&gt;Probably the most frequently asked question I received when we released the Beta of ASP.NET MVC 3 was “When are we going to get Intellisense for Razor?” Well I’m happy to say the answer to that question is &lt;strong&gt;right now&lt;/strong&gt;!&lt;/p&gt;  &lt;p&gt;Not only Intellisense, but syntax highlighting and colorization also works for Razor views. ScottGu’s blog post I mentioned earlier has some screenshots of the Intellisense in action as well as details on some of the other improvements included in ASP.NET MVC 3 RC.&lt;/p&gt;  &lt;h2&gt;NuGet&lt;/h2&gt;  &lt;p&gt;As &lt;a title="NuGet CTP 2 released" href="http://haacked.com/archive/2010/11/09/nuget-ctp2-released.aspx"&gt;I wrote earlier&lt;/a&gt;, this release of ASP.NET MVC includes an updated version of NuGet, a free and open source Package Manager that integrates nicely into Visual Studio.&lt;/p&gt;  &lt;h2&gt;What’s Next?&lt;/h2&gt;  &lt;p&gt;Well if all goes well, we’ll land this plane nicely with an RTM release, and then it’s time to start thinking about ASP.NET MVC 4. There, I said it. Well, actually, I should probably already be thinking about 4, but seriously, can’t a guy catch a break once in a while to breathe for a moment?&lt;/p&gt;  &lt;p&gt;Well, since I’m lazy, I’ll probably be asking you very soon for your thoughts on what you’d like to see us focus on for the next version of ASP.NET MVC. Then I can present your best ideas as my own in the next executive review. You don’t mind that at all, do you? &lt;img style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none" alt="Winking smile" src="http://haacked.com/images/haacked_com/Windows-Live-Writer/ASP.NET-MVC-3-Release-Candidate_955/wlEmoticon-winkingsmile_2.png"&gt;&lt;/p&gt;  &lt;p&gt;Seriously though, please do provide feedback and I’ll keep you posted on our planning.&lt;/p&gt;  &lt;p&gt;Now that we have Nuget in place, one thing we’ll be focusing on is looking at building packages for features that we would have liked to include in ASP.NET MVC, but maybe didn’t have the time to implement them. Or perhaps simply for experimental features that we’d like feedback on. I think building NuGet packages will be a great way to try out new feature ideas and for the ones we think belong in the product, we can always roll them into ASP.NET MVC core.&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;Tags: &lt;a href="http://haacked.com/tags/aspnetmvc/default.aspx" rel="tag"&gt;aspnetmvc&lt;/a&gt;,&lt;a href="http://haacked.com/tags/asp.net/default.aspx" rel="tag"&gt;asp.net&lt;/a&gt;,&lt;a href="http://haacked.com/tags/nuget/default.aspx" rel="tag"&gt;nuget&lt;/a&gt;&lt;/div&gt;&lt;img src="http://haacked.com/aggbug/18736.aspx" width="1" height="1"&gt;&lt;div&gt;
&lt;a href="http://feeds.haacked.com/~ff/haacked?a=Xjn6-godT1g:93h9EOi_HnU:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/haacked?i=Xjn6-godT1g:93h9EOi_HnU:D7DqB2pKExk" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.haacked.com/~ff/haacked?a=Xjn6-godT1g:93h9EOi_HnU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/haacked?i=Xjn6-godT1g:93h9EOi_HnU:V_sGLiPBpWU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.haacked.com/~ff/haacked?a=Xjn6-godT1g:93h9EOi_HnU:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/haacked?d=G79ilh31hkQ" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/haacked/~4/Xjn6-godT1g" height="1" width="1"&gt;</summary><author><name>Haacked</name></author><source gr:stream-id="feed/http://feeds.haacked.com/haacked/"><id>tag:google.com,2005:reader/feed/http://feeds.haacked.com/haacked/</id><title type="html">you&amp;#39;ve been HAACKED</title><link rel="alternate" href="http://haacked.com/Default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1287003143636"><id gr:original-id="http://www.dotnetkicks.com/aspnet/5_Reasons_to_be_Excited_about_ASP_NET_MVC_3">tag:google.com,2005:reader/item/152204ff07eea02c</id><title type="html">5 Reasons to be Excited about ASP.NET MVC 3</title><published>2010-10-13T13:30:52Z</published><updated>2010-10-13T13:30:52Z</updated><link rel="alternate" href="http://www.dotnetkicks.com/aspnet/5_Reasons_to_be_Excited_about_ASP_NET_MVC_3" type="text/html" /><summary xml:base="http://www.dotnetkicks.com/" type="html">It's already been 6 months since ASP.NET MVC 2 was released and version 3 is already taking shape. I, personally, am thrilled about that because this version seems to put ASP.NET MVC, in terms of maturity and functionality, on the first line along with other MVC frameworks out there like RoR.

I've put together 5 main reasons why I'm excited about this upcoming version. What about you? &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.ironshay.com%2fpost%2f5-Reasons-to-be-Excited-about-ASPNET-MVC-3.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.ironshay.com%2fpost%2f5-Reasons-to-be-Excited-about-ASPNET-MVC-3.aspx" border="0" alt="kick it on DotNetKicks.com"&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href="http://theloungenet.com/feeds/redirect/DOTNETRSS/DNK/242E243AA1BC73BBABE4A23DB5508DF62CA0687C"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/DNK/242E243AA1BC73BBABE4A23DB5508DF62CA0687C"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/dotnetkicks?a=yN1hW_108bE:k6P1m0wkAzM:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/dotnetkicks?d=G79ilh31hkQ" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dotnetkicks?a=yN1hW_108bE:k6P1m0wkAzM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/dotnetkicks?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</summary><author gr:unknown-author="true"><name>(author unknown)</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/dotnetkicks"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/dotnetkicks</id><title type="html">DotNetKicks.com</title><link rel="alternate" href="http://www.dotnetkicks.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1286391513974"><id gr:original-id="http://haacked.com/archive/2010/10/06/asp-net-mvc-3-beta-released.aspx">tag:google.com,2005:reader/item/6e4d5812666faeb0</id><category term="ASP.NET MVC" /><category term="ASP.NET" /><category term="Software Development" /><title type="html">ASP.NET MVC 3 Beta Released</title><published>2010-10-06T15:00:00Z</published><updated>2010-10-06T15:00:00Z</updated><link rel="alternate" href="http://feeds.haacked.com/~r/haacked/~3/vT-h8dmBdlo/asp-net-mvc-3-beta-released.aspx" type="text/html" /><link rel="canonical" href="http://haacked.com/archive/2010/10/06/asp-net-mvc-3-beta-released.aspx" /><summary xml:base="http://haacked.com/Default.aspx" type="html">&lt;p&gt;UPDATE: This post is a out of date. We recently released the &lt;a href="http://haacked.com/archive/2010/11/09/asp-net-mvc-3-release-candidate.aspx" title="ASP.NET MVC 3 RC Released"&gt;Release Candidate for ASP.NET MVC 3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wow! It’s been a busy two months and change since we released &lt;a title="ASP.NET MVC 3 Preview 1" href="http://haacked.com/archive/2010/07/27/aspnetmvc3-preview1-released.aspx"&gt;Preview 1&lt;/a&gt; of ASP.NET MVC 3. Today I’m happy (and frankly, relieved) to announce &lt;strong&gt;the Beta release of ASP.NET MVC 3&lt;/strong&gt;. Be sure to read &lt;a title="Announcing MVC 3" href="http://weblogs.asp.net/scottgu/archive/2010/10/06/announcing-nupack-asp-net-mvc-3-beta-and-webmatrix-beta-2.aspx"&gt;Scott Guthrie’s announcement as well&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://haacked.com/images/haacked_com/WindowsLiveWriter/ASP.NETMVC3BetaReleased_12A2D/Onward_4.jpg" rel="lightbox"&gt;&lt;img style="border-right-width:0px;display:block;float:none;border-top-width:0px;border-bottom-width:0px;margin-left:auto;border-left-width:0px;margin-right:auto" title="onward" border="0" alt="onward" src="http://haacked.com/images/haacked_com/WindowsLiveWriter/ASP.NETMVC3BetaReleased_12A2D/Onward_thumb_1.jpg" width="504" height="484"&gt;&lt;/a&gt; &lt;em&gt;Credits: Image from ICanHazCheezburger http://icanhascheezburger.com/tag/onward/&lt;/em&gt; &lt;/p&gt;  &lt;p&gt;Yes, you heard me right, we’re jumping straight to Beta with this release! To try it out…&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="Install ASP.NET MVC 3 via Web PI" href="http://www.microsoft.com/web/gallery/install.aspx?appid=MVC3"&gt;Install it immediately&lt;/a&gt; via the Web Platform Installer (Web PI). &lt;/li&gt;    &lt;li&gt;OR, Download the &lt;a title="Download Details for ASP.NET MVC 3 Beta" href="http://go.microsoft.com/fwlink/?LinkID=191795"&gt;Installer files&lt;/a&gt; and install it manually. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;As always, be sure to read the &lt;a title="ASP.NET MVC 3 Release Notes" href="http://www.asp.net/learn/whitepapers/mvc3-release-notes"&gt;release notes&lt;/a&gt; (also available &lt;a title="ASP.NET MVC 3 Release Notes Word Doc" href="http://download.microsoft.com/download/8/8/D/88D72201-4230-4E19-BFDA-5868B350AA09/ASP.NET-MVC-3-Beta-Release-Notes.doc"&gt;as a Word doc&lt;/a&gt; if you prefer that sort of thing) for all the juicy details about what’s new in ASP.NET MVC 3.&lt;/p&gt;  &lt;p&gt;A big part of this release focuses on polishing and improving features started in Preview 1. We’ve made a lot of improvements (and changes) to our support for Dependency Injection allowing you to control how ASP.NET MVC creates your controllers and views as well as services that it needs.&lt;/p&gt;  &lt;p&gt;One big change in this release is that client validation now is built on top of jQuery Validation in an unobtrusive manner. In ASP.NET MVC 3, jQuery Validation is the default client validation script. It’s pretty slick so give it a try and let us know what you think.&lt;/p&gt;  &lt;p&gt;Likewise, our Ajax features such as the Ajax.ActionLink etc. are now built on top of jQuery. There’s a way to switch back to the old behavior if you need to, but moving forward, we’ll be leveraging jQuery for this sort of thing.&lt;/p&gt;  &lt;h3&gt;Where’s the Razor Syntax Highlighting and Intellisense?&lt;/h3&gt;  &lt;p&gt;This is probably a good point to stop and provide a little bit of bad news. One of the most frequently asked questions I hear is when are we going to get syntax highlighting? Unfortunately, it’s not yet ready for this release, but the Razor editor team is hard at work on it and we will see it in a future release.&lt;/p&gt;  &lt;p&gt;I know it’s a bummer (believe me, I’m bummed about it) but I think it’ll make it that much sweeter when the feature arrives and you get to try it out the first time! See, I’m always looking for that silver lining. ;)&lt;/p&gt;  &lt;h3&gt;What’s this NuPack Thing?&lt;/h3&gt;  &lt;p&gt;That’s been the other major project I’ve been working on which has been keeping me very busy. I’ll be posting a follow-up blog post that talks about that.&lt;/p&gt;  &lt;h3&gt;What’s Next?&lt;/h3&gt;  &lt;p&gt;The plan is to have our next release be a Release Candidate. I’ve updated &lt;a href="http://aspnet.codeplex.com/wikipage?title=Road%20Map&amp;amp;referringTitle=MVC" title="ASP.NET MVC Roadmap in CodePlex.com"&gt;the Roadmap&lt;/a&gt; to provide an idea of some of the features that will be coming in the RC. For the most part, we try not to add too many features between Beta and RC preferring to focus on bug fixing and polish.&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px"&gt;Tags: &lt;a href="http://haacked.com/tags/aspnetmvc/default.aspx" rel="tag"&gt;aspnetmvc&lt;/a&gt;, &lt;a href="http://haacked.com/tags/asp.net/default.aspx" rel="tag"&gt;asp.net&lt;/a&gt;&lt;/div&gt;&lt;img src="http://haacked.com/aggbug/18723.aspx" width="1" height="1"&gt;&lt;div&gt;
&lt;a href="http://feeds.haacked.com/~ff/haacked?a=vT-h8dmBdlo:0c2dEAXc-C4:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/haacked?i=vT-h8dmBdlo:0c2dEAXc-C4:D7DqB2pKExk" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.haacked.com/~ff/haacked?a=vT-h8dmBdlo:0c2dEAXc-C4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/haacked?i=vT-h8dmBdlo:0c2dEAXc-C4:V_sGLiPBpWU" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.haacked.com/~ff/haacked?a=vT-h8dmBdlo:0c2dEAXc-C4:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/haacked?d=G79ilh31hkQ" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/haacked/~4/vT-h8dmBdlo" height="1" width="1"&gt;</summary><author><name>Haacked</name></author><source gr:stream-id="feed/http://feeds.haacked.com/haacked/"><id>tag:google.com,2005:reader/feed/http://feeds.haacked.com/haacked/</id><title type="html">you&amp;#39;ve been HAACKED</title><link rel="alternate" href="http://haacked.com/Default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1286391510507"><id gr:original-id="c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7624297">tag:google.com,2005:reader/item/e157ab437205a364</id><category term="ASP.NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/ASP.NET/default.aspx" /><category term="Visual Studio" scheme="http://weblogs.asp.net/scottgu/archive/tags/Visual+Studio/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/scottgu/archive/tags/.NET/default.aspx" /><category term="Community News" scheme="http://weblogs.asp.net/scottgu/archive/tags/Community+News/default.aspx" /><category term="MVC" scheme="http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx" /><title type="html">Announcing NuPack, ASP.NET MVC 3 Beta, and WebMatrix Beta 2</title><published>2010-10-06T15:06:57Z</published><updated>2010-10-06T15:06:57Z</updated><link rel="alternate" href="http://weblogs.asp.net/scottgu/archive/2010/10/06/announcing-nupack-asp-net-mvc-3-beta-and-webmatrix-beta-2.aspx" type="text/html" /><summary xml:base="http://weblogs.asp.net/scottgu/default.aspx" type="html">&lt;font size="2" face="arial"&gt;   &lt;p&gt;I’m excited to announce the beta release of several projects today.&lt;/p&gt;    &lt;p&gt;Two of these releases - ASP.NET MVC 3 Beta and WebMatrix Beta 2 - are evolutions of projects we first previewed this summer.  The third – NuPack - is a new project that I’m particularly excited about.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;NuPack – Open Source Package Manager for .NET&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;NuPack is a free open source package manager that makes it easy for you to find, install, and use .NET libraries in your projects. It works with all .NET project types (including, but not limited to, both ASP.NET Web Forms and ASP.NET MVC).&lt;/p&gt;    &lt;p&gt;NuPack enables developers who maintain open source projects (for example, projects like Moq, NHibernate, Ninject, StructureMap, NUnit, Windsor, RhinoMocks, Elmah, etc) to package up their libraries and register them with an online gallery/catalog that is searchable.  The client-side NuPack tools – which include full Visual Studio integration – make it trivial for any .NET developer who wants to use one of these libraries to easily find and install it within the project they are working on.&lt;/p&gt;    &lt;p&gt;NuPack handles dependency management between libraries (for example: library1 depends on library2). It also makes it easy to update (and optionally remove) libraries from your projects later. It supports updating web.config files (if a package needs configuration settings). It also allows packages to add PowerShell scripts to a project (for example: scaffold commands). Importantly, NuPack is transparent and clean – and does not install anything at the system level. Instead it is focused on making it easy to manage libraries you use with your projects.&lt;/p&gt;    &lt;p&gt;NuPack is itself an open-source project.  The Outercurve Foundation (formerly CodePlex Foundation) today announced the acceptance of the NuPack project to the ASP.NET Open Source Gallery.  Developers - both inside and outside Microsoft – will contribute features, bug fixes and patches to NuPack.&lt;/p&gt;    &lt;p&gt;Our goal with NuPack is to make it as simple as possible to integrate open source libraries within .NET projects.  It will be supported in all versions of Visual Studio.  You can start using the first developer preview of it today.&lt;/p&gt;    &lt;p&gt;&lt;u&gt;A Simple NuPack Scenario – Enabling ELMAH&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;As a simple example to show off what NuPack enables – let’s assume we are working on a brand new ASP.NET application and want to use the popular open-source &lt;a href="http://code.google.com/p/elmah/"&gt;“ELMAH” library&lt;/a&gt; to log and report errors with our site.  To install ELMAH today, you’d need to manually download it, unzip it, add a reference to your project, make sure you have source control bindings for the library setup correctly, and update the web.config file of your application to include the Elmah HttpModule entries.  All doable – but a little tedious.&lt;/p&gt;    &lt;p&gt;With NuPack installed, you can simply open the new “Package Manager Console” that NuPack enables inside VS and type “Add-Package elmah” within it:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_499C9B80.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_0102ACAF.png" width="769" height="520"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;Typing &amp;quot;Add-Package elmah” causes NuPack to check an online feed to locate the Elmah library, download it, add a reference of it to your current project, and automatically add the appropriate Elmah registration entries within your application’s web.config file:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5FA30712.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_6A7FE85A.png" width="758" height="531"&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;And now we have Elmah setup and installed for our project, and error report logging enabled.  No additional manual steps required to make it work.&lt;/p&gt;    &lt;p&gt;&lt;u&gt;Learn More About NuPack&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;Check out the following links to learn more about NuPack and some of the many scenarios it enables:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a href="http://www.hanselman.com/blog/IntroducingNuPackPackageManagementforNETAnotherpieceoftheWebStack.aspx"&gt;Scott Hanselman’s NuPack Tutorial&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;a href="http://haacked.com/archive/2010/10/06/introducing-nupack-package-manager.aspx"&gt;Phil Haack’s NuPack Post&lt;/a&gt;&lt;/li&gt;      &lt;li&gt;&lt;a href="http://weblogs.asp.net/bsimser/archive/2010/10/06/unicorns-triple-rainbows-package-management-and-lasers.aspx"&gt;Bill Simser’s Post on NuPack&lt;/a&gt; (he is a non-Microsoft dev working on it)&lt;/li&gt;      &lt;li&gt;&lt;a href="http://devlicio.us/blogs/rob_reynolds/archive/2010/10/06/the-evolution-of-package-management-for-net.aspx"&gt;Rob Reynold’s “Evolution of Package Management on .NET” Post&lt;/a&gt; (Rob is one of the leaders of the Nu project and is on the NuPack team)&lt;/li&gt;      &lt;li&gt;&lt;a href="http://blogs.msdn.com/b/davidebb/archive/2010/10/05/introducing-nupack-the-smart-way-to-bring-bits-into-your-projects.aspx"&gt;David Ebbo’s NuPack Post&lt;/a&gt;&lt;/li&gt;      &lt;li&gt;Documentation and tutorials on &lt;a href="http://nupack.codeplex.com"&gt;nupack.codeplex.com&lt;/a&gt; &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;u&gt;.NET and Open Source&lt;/u&gt;&lt;/p&gt;    &lt;p&gt;We think NuPack will be a fundamental component of the .NET stack going forward.  It will encourage more .NET developers to use open-source libraries.  Having a standard package manager integrated into millions of copies of Visual Studio will hopefully also encourage the creation of more open source projects with .NET.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;ASP.NET MVC 3 Beta&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today we are also shipping a Beta Release of ASP.NET MVC 3.  This release is a significant update of the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx"&gt;ASP.NET MVC 3 Preview&lt;/a&gt; we shipped two months ago, and includes a bunch of great feature improvements.&lt;/p&gt;    &lt;p&gt;In addition to the ASP.NET MVC 3 features &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx"&gt;introduced with the first preview&lt;/a&gt;, today’s beta includes:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;Razor Enhancements&lt;/strong&gt;: ASP.NET MVC 3 supports the new &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx"&gt;Razor&lt;/a&gt; view-engine option. In addition to the functionality enabled with the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx"&gt;ASP.NET MVC 3 Preview&lt;/a&gt;, today’s Beta adds a bunch of additional capabilities: Cleaner MVC integration – including the ability to use a new @model syntax to more cleanly specify the type being passed to the view.  A new @helper syntax for declaring re-usable HTML helpers (really slick).  A new @* *@ comment syntax.  The ability to specify defaults (like layoutpage) once for the entire site - keeping your views DRY.  Support for using both C# and VB flavors of Razor.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;New View Helpers&lt;/strong&gt;: New view helper methods are now supported.  This includes a new Chart() helper method for dynamically creating charts (same features as the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/02/07/built-in-charting-controls-vs-2010-and-net-4-series.aspx"&gt;&amp;lt;asp:chart&amp;gt; control in ASP.NET 4&lt;/a&gt; – except now using view helper methods), as well as a new WebGrid() helper method that can be used to create data-grid style UI (including paging and sorting).&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;Unobtrusive JavaScript and HTML 5&lt;/strong&gt;: The AJAX and Validation helpers in ASP.NET MVC now both use an &lt;a href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript"&gt;unobtrusive JavaScript&lt;/a&gt; approach by default. Unobtrusive JavaScript avoid injecting inline JavaScript into HTML, and instead enables cleaner separation of behavior using the new HTML 5 data- convention (which conveniently works on older browsers as well). This makes your HTML smaller and cleaner, and makes it easier to optionally swap out or customize JS libraries.  The Validation helpers in ASP.NET MVC 3 also now use the jQueryValidate plugin by default.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;Dependency Injection&lt;/strong&gt;: The initial &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx"&gt;ASP.NET MVC 3 Preview&lt;/a&gt; added better support for Dependency Injection (DI) with Controllers, Views and Action Filters.  Today’s Beta extends this with better dependency injection support for Model Binders, Model Validation Providers, Model Metadata Providers, and Value Providers.  It also supports a new IDependencyResolver interface that makes it easier to integrate Dependency Injection Frameworks.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;NuPack Integration&lt;/strong&gt;: ASP.NET MVC 3 automatically installs and enables NuPack as part of its setup.  This makes it trivial to take advantage of NuPack to find and add lots of MVC extensions and libraries to your projects.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;Other Goodness:&lt;/strong&gt; The initial &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx"&gt;ASP.NET MVC 3 Preview&lt;/a&gt; added lots of additional helpers and classes to make everyday coding better.  Today’s beta includes a bunch of additional improvements: more granular XSS HTML input validation, HTML helper improvements to support HTML 5, Crypto helpers for salting and hashing passwords, easier Email APIs, improved “New Project” dialog, etc.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;The ASP.NET MVC 3 beta supports “go-live” deployments – which means the license does not restrict you from building and deploying production applications with it.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Learn more about ASP.NET MVC 3&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Check out the below links to learn more about the ASP.NET MVC 3 Beta:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;a href="http://haacked.com/archive/2010/10/06/asp-net-mvc-3-beta-released.aspx"&gt;Phil Haack’s Overview Post&lt;/a&gt;&lt;/li&gt;      &lt;li&gt;&lt;a href="http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-ajax.html"&gt;Brad Wilson’s Unobtrusive JavaScript Post&lt;/a&gt;&lt;/li&gt;      &lt;li&gt;&lt;a href="http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html"&gt;Brad Wilson’s Unobtrusive JavaScript Validation Post&lt;/a&gt;&lt;/li&gt;      &lt;li&gt;&lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt5-idependencyresolver.html"&gt;Brad Wilson’s Dependency Injection Series&lt;/a&gt; (&lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt6-model-validation.html"&gt;Model Validation&lt;/a&gt;, &lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt7-model-metadata.html"&gt;Model MetaData&lt;/a&gt;, &lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt8-value-providers.html"&gt;Value Providers&lt;/a&gt;, &lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt9-model-binders.html"&gt;Model Binders&lt;/a&gt;, &lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt10-controller-activator.html"&gt;Controller Activator&lt;/a&gt;, &lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt11-view-page-activator.html"&gt;View Page Activator&lt;/a&gt;) &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Download&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.microsoft.com/web/gallery/install.aspx?appid=MVC3"&gt;Click here&lt;/a&gt; to download and install the ASP.NET MVC 3 Beta using the Microsoft Web Platform Installer. &lt;/p&gt;    &lt;p&gt;Alternatively you can download and install the ASP.NET MVC 3 Beta using a standalone installer &lt;a href="http://go.microsoft.com/fwlink/?LinkID=191795"&gt;here&lt;/a&gt; (note: for today’s beta you need to first install the AspNetWebPages.msi link from that page and then the AspNetMVC3Setup.exe file).&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;WebMatrix Beta 2&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today we are also shipping WebMatrix Beta 2.  This release is an update of the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/06/introducing-webmatrix.aspx"&gt;WebMatrix Beta 1&lt;/a&gt; preview we shipped this summer, and includes a number of great feature improvements.&lt;/p&gt;    &lt;p&gt;In addition to the WebMatrix features &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/06/introducing-webmatrix.aspx"&gt;introduced with the first beta&lt;/a&gt;, today’s Beta 2 release includes:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;Web Page Enhancements&lt;/strong&gt;: WebMatrix supports building standalone ASP.NET Web Pages using the new Razor syntax. It includes the same syntax improvements (@helper, @* comment *@, etc) that I mentioned above with ASP.NET MVC 3.  It also now supports building pages using both VB and C#.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;Improved Templates&lt;/strong&gt;: WebMatrix includes template projects for common scenarios.  The template projects now use HTML 5 and CSS 3 (and also work with downlevel browsers).  A new Wishlist project template has been added with Beta 2.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;NuPack Integration&lt;/strong&gt;: WebMatrix provides NuPack integration and supports a web-based admin experience for installing libraries to an application you are working on.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;Toolkit Support&lt;/strong&gt;: We are delivering a toolkit (that can be installed via NuPack) that provides convenient helpers that can be used within ASP.NET applications.  This includes helpers for Analytics, Facebook, GamerCard, Gravatar, LinkShare, Captcha, Twitter and Video scenarios.&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;strong&gt;&lt;u&gt;Download&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.microsoft.com/web/webmatrix/"&gt;Click here&lt;/a&gt; to download and install WebMatrix Beta 2.&lt;/p&gt;    &lt;h3&gt;&lt;u&gt;Summary&lt;/u&gt;&lt;/h3&gt;    &lt;p&gt;Today’s releases further evolve and enhance the Microsoft Web Stack.  All of the above capabilities work with .NET 4 and VS 2010, and do not modify any existing files that ship with it (they are all additive and safe to install on your machine).  &lt;/p&gt;    &lt;p&gt;I’ll be blogging more details about some of the above improvements in the weeks ahead.&lt;/p&gt;    &lt;p&gt;Hope this helps,&lt;/p&gt;    &lt;p&gt;Scott&lt;/p&gt; &lt;/font&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7624297" width="1" height="1"&gt;</summary><author><name>ScottGu</name></author><source gr:stream-id="feed/http://weblogs.asp.net/ScottGu/Rss.aspx"><id>tag:google.com,2005:reader/feed/http://weblogs.asp.net/ScottGu/Rss.aspx</id><title type="html">ScottGu&amp;#39;s Blog</title><link rel="alternate" href="http://weblogs.asp.net/scottgu/default.aspx" type="text/html" /></source></entry></feed>

