<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10spanishfull.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:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DEQMQnwyfSp7ImA9WxJUEE4.&quot;"><id>tag:blogger.com,1999:blog-27752126</id><updated>2009-07-08T08:59:43.295+02:00</updated><title>Variable not found</title><subtitle type="html">Artículos, noticias, curiosidades, reflexiones... sobre el mundo del desarrollo de software, internet, u otros temas relacionados con la tecnología.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.variablenotfound.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>246</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/vnf" type="application/atom+xml" /><feedburner:emailServiceId>vnf</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fvnf" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/vnf" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fvnf" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fvnf" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fvnf" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://add.my.yahoo.com/content?lg=es&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fvnf" src="http://eur.i1.yimg.com/eur.yimg.com/i/es/my/addto1.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.feedness.com/alta/http://feeds.feedburner.com/vnf" src="http://www.feedness.com/ayuda/wp-content/square_b_sh_feed.gif">Subscribe with Feedness</feedburner:feedFlare><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;CEUAR3o4eip7ImA9WxJVGUw.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-1583654848852999434</id><published>2009-07-06T23:56:00.000+02:00</published><updated>2009-07-06T22:30:46.432+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-06T22:30:46.432+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="recomendaciones" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="buenas prácticas" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><title>Aspectos a tener en cuenta al crear sitios web públicos</title><content type="html">&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 5px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SlJCQVsjEJI/AAAAAAAABFo/Lx8Zb8uUqGc/image%5B10%5D.png?imgmax=800" width="130" height="118" /&gt; Hace unos meses, un usuario de &lt;a title="Stackoverflow" href="http://stackoverflow.com/" hreflang="en"&gt;StackOverflow&lt;/a&gt;&lt;a title="Stackoverflow" href="http://stackoverflow.com/"&gt;&lt;/a&gt; planteaba una interesante cuestión: &lt;a title="What should a developer know before building a public web site?" href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site"&gt;¿qué debería saber un desarrollador para construir un sitio web público?&lt;/a&gt;&lt;a title="What should a developer know before building a public web site?" href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site"&gt;&lt;/a&gt; Es decir, ¿cuáles son aquellos aspectos importantes que deben tenerse en cuenta a la hora de crear un site de calidad, desde el punto de vista técnico? &lt;/p&gt;  &lt;p&gt;Tras un tiempo de respuestas, ideas y debates, otro usuario ha realizado una recopilación de los aspectos y sugerencias más votadas y los ha publicado en forma de lista categorizada, donde podemos encontrar muy buenas ideas a tener en cuenta en nuestros propios desarrollos, y que me he permitido traducir.&lt;/p&gt;  &lt;p&gt;Muchos de los puntos son obvios y seguro que ya los estáis teniendo en cuenta, quizás otros son demasiado exagerados, y seguro que alguno de ellos ni siquiera os los habíais planteado. En cualquier caso el resultado es una relación interesante y muy a tener en cuenta para mejorar nuestros sitios web.&lt;/p&gt;  &lt;h3&gt;Interfaz y experiencia de usuario &lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Ser consciente de que los navegadores implementan los estándares de forma diferente y asegurarse de que el sitio web funciona razonablemente bien en la mayoría de los principales navegadores. Como mínimo, sería necesario probarlo con un navegador que utilice un motor reciente Gecko (Firefox), Webkit (Safari, Chrome y algunos navegadores móviles), las versiones soportadas de Internet Explorer, y Opera. &lt;/li&gt;    &lt;li&gt;Tener en cuenta que el sitio web puede ser visitado utilizando medios distintos a los navegadores habituales, como por ejemplo teléfonos móviles, lectores de pantalla, o motores de búsqueda. Usar estándares de accesibilidad como &lt;a title="WAI" href="http://www.w3c.es/Traducciones/es/WAI/intro/accessibility"&gt;WAI&lt;/a&gt; o &lt;a title="Section508" href="http://www.section508.gov/" hreflang="en"&gt;Section508&lt;/a&gt;&lt;a title="Section508" href="http://www.section508.gov/"&gt;&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Considerar los mecanismos de actualización del sitio web para que estos procesos no afecten a los usuarios una vez que el sistema está en marcha y puedan producirse de forma suave y transparente. Por ejemplo, puede ayudar el mantener entornos de prueba paralelos, el uso de herramientas de control del código fuente, o mecanismos de builds automatizados. &lt;/li&gt;    &lt;li&gt;No mostrar errores directamente al usuario. &lt;/li&gt;    &lt;li&gt;No incluir en las páginas direcciones de correo de usuarios en texto plano, para evitar que sean bombardeados por los spammers. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codinghorror.com/blog/archives/001228.html" hreflang="en"&gt;Incluir límites razonables de utilización&lt;/a&gt; del sitio para evitar malos usos por parte de usuarios o procesos automáticos (como puede ser los virus). Por ejemplo, es razonable que un sistema de correo electrónico gratuito limite el número de mensajes diarios que puede enviar un usuario, aunque el número máximo sea muy alto; otro ejemplo podemos verlo en Google, que muestra un mensaje de error cuando detecta demasiado tráfico hacia sus servidores desde una única dirección IP. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;Seguridad&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Conocer la amplia guía de desarrollo &lt;a href="http://www.owasp.org/index.php/Category:OWASP_Guide_Project" hreflang="en"&gt;OWASP&lt;/a&gt;, que&amp;#160; cubre la seguridad de sitios web de forma muy completa. &lt;/li&gt;    &lt;li&gt;Conocer el fundamento de los ataques de &lt;a href="http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL"&gt;inyección SQL&lt;/a&gt; y cómo prevenirlos. &lt;/li&gt;    &lt;li&gt;Jamás confiar en los datos introducidos por los usuarios. &lt;/li&gt;    &lt;li&gt;Evitar el almacenamiento de contraseñas en texto plano utilizando técnicas criptográficas como &lt;em&gt;hashes&lt;/em&gt; y &lt;em&gt;salts&lt;/em&gt;. &lt;/li&gt;    &lt;li&gt;No intentes utilizar tu magnífico y elaborado sistema de autenticación; es bastante probable que existan fallos impredecibles de los que sólo te darás cuenta después de haber sido hackeado. &lt;/li&gt;    &lt;li&gt;Usar &lt;a href="http://es.wikipedia.org/wiki/Transport_Layer_Security"&gt;SSL&lt;/a&gt;/&lt;a href="http://es.wikipedia.org/wiki/Hypertext_Transfer_Protocol_Secure"&gt;HTTPS&lt;/a&gt; en las páginas de identificación de usuarios y, en general, en todas aquellas páginas donde sea introducida información sensible, como datos personales o bancarios. &lt;/li&gt;    &lt;li&gt;Evitar el secuestro de sesiones (&lt;a href="http://en.wikipedia.org/wiki/Session_hijacking" hreflang="en"&gt;session hijacking&lt;/a&gt;&lt;a href="http://en.wikipedia.org/wiki/Session_hijacking"&gt;&lt;/a&gt;). &lt;/li&gt;    &lt;li&gt;Evitar los ataques &lt;a href="http://es.wikipedia.org/wiki/Cross-site_scripting"&gt;XSS&lt;/a&gt; (Cross Site Scripting). &lt;/li&gt;    &lt;li&gt;Evitar los ataques &lt;a href="http://www.lobosoft.es/2008/09/29/proteccion-ante-xsrf/"&gt;XSRF&lt;/a&gt; (Cross Site Request Forgeries). &lt;/li&gt;    &lt;li&gt;Mantener tus sistemas actualizados con los últimos parches disponibles. &lt;/li&gt;    &lt;li&gt;Asegurarse de que la información de conexión a la base de datos está almacenada en un lugar lo suficientemente seguro. &lt;/li&gt;    &lt;li&gt;Mantener informado sobre las últimas técnicas de ataque y vulnerabilidades que afecten a la plataforma sobre la que trabajas. &lt;/li&gt;    &lt;li&gt;Conocer el manual &lt;a title="The Google Browser Security Handbook" href="http://code.google.com/p/browsersec/wiki/Main"&gt;The Google Browser Security Handbook&lt;/a&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Rendimiento&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Implementar el cacheado de páginas cuando sea necesario. Comprender y usar apropiadamente los mecanismos de cacheo HTTP. &lt;/li&gt;    &lt;li&gt;Optimizar las imágenes. Por ejemplo, no utilizar una imagen de 20 Kb. como mosaico de fondo. &lt;/li&gt;    &lt;li&gt;Conocer cómo comprimir el contenido de las páginas con gzip. &lt;/li&gt;    &lt;li&gt;Echar un vistazo al sitio &lt;a title="Yahoo Exceptional Performance" href="http://developer.yahoo.com/performance/"&gt;Yahoo Exceptional Performance&lt;/a&gt;, donde se muestran directrices y buenas prácticas para mejorar el rendimiento de sitios web. Utilizar herramientas como &lt;a title="YSlow" href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Utilizar la técnica de &lt;a href="http://alistapart.com/articles/sprites"&gt;CSS Sprites&lt;/a&gt;&lt;a href="http://alistapart.com/articles/sprites"&gt;&lt;/a&gt; para las pequeñas imágenes (como las que encontramos en las barras de herramientas), con objeto de minimizar el número de peticiones HTTP. &lt;/li&gt;    &lt;li&gt;Los sitios web de alto tráfico deberían considerar el despliegue de componentes en &lt;a href="http://developer.yahoo.com/performance/rules.html#split" hreflang="en"&gt;distintos dominios&lt;/a&gt; para optimizar la descarga en paralelo de los mismos. &lt;/li&gt;    &lt;li&gt;En general, minimizar el número total de peticiones HTTP necesarias para que el navegador muestre las páginas. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;SEO&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Utilizar direcciones URL amigables para los buscadores. Por ejemplo, utilizar direcciones del tipo &amp;quot;ejemplo.com/paginas/titulo-del-articulo&amp;quot; en lugar de &amp;quot;ejemplo.com/index.php?page=45&amp;quot;. &lt;/li&gt;    &lt;li&gt;No utilizar enlaces que digan &amp;quot;pulse aquí&amp;quot;. Estarías creando sitio web poco optimizado para buscadores, a la vez que complicando las cosas para los usuarios que utilizan lectores de pantalla. &lt;/li&gt;    &lt;li&gt;Crear un mapa del sitio en XML (sitemap). &lt;/li&gt;    &lt;li&gt;Utilizar &lt;a href="http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html"&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;canonical&amp;quot; ... /&amp;gt;&lt;/code&gt;&lt;/a&gt; Cuando tengas múltiples URLs que apunten a un mismo contenido. &lt;/li&gt;    &lt;li&gt;Utilizar las herramientas disponibles en &lt;a href="http://www.google.com/webmasters"&gt;www.google.com/webmasters&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Instalar Google Analytics desde el principio. &lt;/li&gt;    &lt;li&gt;Conocer cómo funcionan los rastreadores de los buscadores y el archivo robots.txt. &lt;/li&gt;    &lt;li&gt;No maquetar con tablas; Google generalmente valorará positivamente el marcado HTML semántico y la maquetación con CSS. &lt;/li&gt;    &lt;li&gt;Si tienes contenido no textual en la página, utiliza en el &lt;em&gt;sitemap&lt;/em&gt; las extensiones de Google para audio, video, etc. Hay alguna información sobre ello en la respuesta de &lt;a href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site#167608" hreflang="en"&gt;Tim Farley&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site#167608"&gt;&lt;/a&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Tecnología&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Entender el protocolo &lt;a href="http://es.wikipedia.org/wiki/Hypertext_Transfer_Protocol"&gt;HTTP&lt;/a&gt;; conocer cosas como GET, POST, sesiones, cookies, y saber lo que significa e implica su naturaleza &amp;quot;sin estado&amp;quot; (&lt;em&gt;stateless&lt;/em&gt;). &lt;/li&gt;    &lt;li&gt;Escribir el código (X)HTML y CSS conformes a las especificaciones de la W3C, y asegurarse de que validan. El objetivo es evitar las particularidades de los navegadores, a la vez que se facilita enormemente la navegación utilizando browsers no estándar como lectores de pantalla o dispositivos móviles. &lt;/li&gt;    &lt;li&gt;Comprender cómo se procesa el código javascript en los navegadores. &lt;a href="http://www.anieto2k.com/2009/06/30/baja-tus-scripts-al-final-del-fichero/"&gt;Mover los scripts al final de las páginas&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Comprender cómo funciona el &lt;em&gt;sandbox&lt;/em&gt; de javascript, especialmente si pretendes utilizar &lt;em&gt;iframes&lt;/em&gt;. &lt;/li&gt;    &lt;li&gt;Asegurarse de que javascript puede ser deshabilitado sin que la página deje de funcionar. AJAX debe ser una extensión, y no la base sobre la que se construya un sitio. Aunque la mayoría de usuarios lo tengan activado, recordar que existen muchos y muy populares dispositivos en los que no funcionará correctamente. &lt;/li&gt;    &lt;li&gt;Entender la diferencia entre las reflexiones 301 y 302 (esto también es un aspecto SEO). &lt;/li&gt;    &lt;li&gt;Aprender tanto como sea posible sobre la plataforma en la que será desplegado el sitio web en producción. &lt;/li&gt;    &lt;li&gt;Considerar el uso de un &lt;a href="http://www.anieto2k.com/2007/08/07/reseteando-estilos-css/"&gt;reseteador de CSS&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Considerar herramientas como &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;, que oculta muchas de las particularidades de los distintos navegadores utilizando javascript para la manipulación del DOM. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Corrección de errores&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Entender que pasarás el 20% del tiempo codificando y el 80% restante manteniéndolo, por tanto codifica apropiadamente. &lt;/li&gt;    &lt;li&gt;Configurar un buen sistema de notificación y gestión de errores. &lt;/li&gt;    &lt;li&gt;Habilitar sistemas para que los usuarios puedan contactar contigo y trasladarte críticas y sugerencias. &lt;/li&gt;    &lt;li&gt;Documentar cómo funciona la aplicación para facilitar el futuro soporte y mantenimiento del sistema. &lt;/li&gt;    &lt;li&gt;Poner a funcionar el sistema primero en Firefox y después en Internet Explorer. &lt;/li&gt;    &lt;li&gt;Hacer copias de seguridad frecuentes. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-1583654848852999434?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/D9-IvJm2Qgx6tZGcmbIU1Rh3SPs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D9-IvJm2Qgx6tZGcmbIU1Rh3SPs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/D9-IvJm2Qgx6tZGcmbIU1Rh3SPs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D9-IvJm2Qgx6tZGcmbIU1Rh3SPs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=eRo2kLw3BvA:OiA7rZGbIMM:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=eRo2kLw3BvA:OiA7rZGbIMM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=eRo2kLw3BvA:OiA7rZGbIMM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=eRo2kLw3BvA:OiA7rZGbIMM:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=eRo2kLw3BvA:OiA7rZGbIMM:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=eRo2kLw3BvA:OiA7rZGbIMM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=eRo2kLw3BvA:OiA7rZGbIMM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=eRo2kLw3BvA:OiA7rZGbIMM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=eRo2kLw3BvA:OiA7rZGbIMM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/eRo2kLw3BvA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/1583654848852999434/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=1583654848852999434" title="4 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1583654848852999434?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1583654848852999434?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/eRo2kLw3BvA/aspectos-tener-en-cuenta-al-crear.html" title="Aspectos a tener en cuenta al crear sitios web públicos" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/07/aspectos-tener-en-cuenta-al-crear.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYBSXY6fip7ImA9WxJVFEo.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-6243941910545417005</id><published>2009-07-01T21:33:00.003+02:00</published><updated>2009-07-01T21:39:18.816+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-01T21:39:18.816+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><title>Cómo crear un ControllerFactory personalizado para ASP.NET MVC</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Piezas de Lego" border="0" alt="Piezas de Lego" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/ShBSHufcsQI/AAAAAAAABDs/WkMHqt356PQ/image4.png?imgmax=800" width="199" height="100" /&gt; Hace unas semanas, en el post &lt;a title="Cambiar la ubicación de las vistas en ASP.NET MVC" href="http://www.variablenotfound.com/2009/06/cambiar-la-ubicacion-de-las-vistas-en.html"&gt;Cambiar la ubicación de las vistas en ASP.NET MVC&lt;/a&gt; estuvimos viendo cómo era posible aprovechar la flexibilidad del framework para saltarse las convenciones respecto a la ubicación de los archivos de vistas (.aspx, .ascx y .master).&lt;/p&gt;  &lt;p&gt;En esta ocasión vamos a seguir profundizando en los puntos de extensión del framework, centrándonos en la facilidad con la que podemos modificar el &lt;code&gt;ControllerFactory&lt;/code&gt;, que es el componente encargado de localizar y crear las instancias de los controladores que deben procesar las peticiones.&lt;/p&gt;  &lt;p&gt;Y vamos a ilustrarlo con un ejemplo, en el que desmontaremos otra de las convenciones del framework MVC: el nombre de los controladores. Como sabemos, cuando se recibe una petición que según su ruta debe ser procesada por un controlador llamado XYZ, el motor por defecto intentará instanciar una clase denominada &lt;code&gt;XYZController&lt;/code&gt;.&amp;#160; Lo que vamos a hacer es retocar este comportamiento para que nuestros controladores puedan denominarse “&lt;code&gt;ControladorDeXYZ&lt;/code&gt;”, un nombre mucho más acertado en nuestro idioma. &lt;/p&gt;  &lt;p&gt;En este post veremos cómo podemos modificar la forma en que este componente localiza las clases de controladores y adaptarla a nuestras preferencias. &lt;/p&gt;  &lt;p&gt;Pero antes, recuerda:&lt;/p&gt;  &lt;blockquote&gt;&lt;strong&gt;     &lt;p style="border-bottom: #c0c0c0 1px dotted; border-left: #c0c0c0 1px dotted; padding-bottom: 3px; margin-top: 3px; padding-left: 3px; padding-right: 3px; border-top: #c0c0c0 1px dotted; border-right: #c0c0c0 1px dotted; padding-top: 3px"&gt;Saltarse las convenciones = malo &lt;/p&gt;   &lt;/strong&gt;    &lt;p&gt;Hazlo sólo cuando realmente esté justificado... o por diversión, como es el caso ;-)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Lo que vamos a hacer en el post no es una implementación eficiente, y por supuesto &lt;strong&gt;no es válida para un entorno de producción&lt;/strong&gt;; se trata simplemente de un experimento que demuestra la facilidad para sustituir ciertos componentes del framework, y la flexibilidad que nos aporta. Los conceptos que vamos a tratar pueden ser utilizados con otros fines, como facilitar la inyección de dependencias en controladores, que probablemente veamos en un futuro post.&lt;/p&gt;  &lt;p&gt;Y ahora, al tema…&lt;/p&gt;  &lt;h3&gt;1. El proceso básico de la petición&lt;/h3&gt;  &lt;p&gt;Antes de empezar la faena, es conveniente estudiar un poco el funcionamiento del framework; así podremos entender mejor qué estamos tocando.&lt;/p&gt;  &lt;p&gt;Cuando se recibe una petición, su tratamiento pasa a través de una serie de componentes que se encargan de procesarla a distintos niveles siguiendo el &lt;a title="La serpiente ASP.NET MVC" href="http://www.variablenotfound.com/2008/06/la-serpiente-aspnet-mvc.html"&gt;ciclo de vida definido para el framework&lt;/a&gt;. Así, una vez que el sistema de enrutamiento ha terminado su tarea detectando la información presente en la URL y determinando, por tanto, su destino, utilizará un manejador &lt;code&gt;MvcHandler&lt;/code&gt; para continuar procesando la petición desde el método &lt;code&gt;ProcessRequest()&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;La porción de código de ASP.NET MVC framework donde se define este método es la siguiente (en el archivo &lt;code&gt;MvcHandler.cs&lt;/code&gt;, recordad que el código fuente está disponible en &lt;a title="Codeplex" href="http://www.codeplex.com/"&gt;Codeplex&lt;/a&gt;):&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ProcessRequest(HttpContextBase httpContext) &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     [...]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Get the controller type&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; controllerName = &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         RequestContext.RouteData.GetRequiredString(&lt;span style="color: #006080"&gt;&amp;quot;controller&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Instantiate the controller and call Execute&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     IControllerFactory factory = &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         ControllerBuilder.GetControllerFactory();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     IController controller = &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         factory.CreateController(RequestContext, controllerName);&lt;/pre&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (controller == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; InvalidOperationException(...); &lt;span style="color: #008000"&gt;// Simplificado&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         controller.Execute(RequestContext);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;finally&lt;/span&gt; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;         factory.ReleaseController(controller);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Resumidamente, podríamos decir que el sistema procesa las peticiones siguiendo estos pasos: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;en primer lugar, obtiene el nombre del controlador desde el contexto de la petición (normalmente desde la ruta). En el código anterior, se guarda en la variable &lt;code&gt;controllerName&lt;/code&gt;. &lt;/li&gt;&lt;li&gt;a continuación obtiene una instancia de la factoría de controladores desde la clase &lt;code&gt;ControllerBuilder&lt;/code&gt;. &lt;/li&gt;&lt;li&gt;&lt;code&gt;&lt;/code&gt;una vez obtenida la factoría según el paso anterior, se le pide mediante una llamada a su método &lt;code&gt;CreateController()&lt;/code&gt; que cree el controlador que procesará la petición, enviándole como parámetro el nombre obtenido anteriormente. &lt;/li&gt;&lt;li&gt;y por último, se invoca al método &lt;code&gt;Execute&lt;/code&gt; del controlador para que realice las acciones oportunas, liberando al final los recursos utilizados mediante una llamada a &lt;code&gt;ReleaseController&lt;/code&gt;. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Como en otras muchas partes del framework, se puede observar en el código anterior la utilización de interfaces en lugar de clases para los elementos que intervienen en el proceso, lo que da pistas sobre la flexibilidad de ASP.NET MVC: casi cualquier elemento puede ser sustituido por otro siempre que se cumpla el contrato definido.&lt;/p&gt;&lt;h3&gt;2. La factoría de controladores, a corazón abierto&lt;/h3&gt;&lt;p&gt;Visto el procedimiento anteriormente descrito, está claro que la lógica de localización e instanciación del controlador es responsabilidad de las factorías de controladores, y más exactamente del método &lt;code&gt;&lt;code&gt;&lt;code&gt;CreateController()&lt;/code&gt;&lt;/code&gt;&lt;/code&gt; que éstas deben implementar.&lt;/p&gt;&lt;p&gt;ASP.NET MVC utiliza como factoría la clase &lt;code&gt;DefaultControllerFactory&lt;/code&gt;&amp;#160; de forma predeterminada, sin embargo, nada en el código anterior obliga a que esto sea así. Si logramos crear una nueva factoría que implemente el interfaz &lt;code&gt;IControllerFactory&lt;/code&gt; e indicamos al framework que la utilice, ya casi tendremos el trabajo hecho.&lt;/p&gt;&lt;p&gt;En el código de la clase &lt;code&gt;DefaultControllerFactory&lt;/code&gt; (la factoría predeterminada), se puede observar que el proceso de creación está compuesto por dos pasos; en el primero de ellos se obtiene el tipo de controlador mediante una llamada a &lt;code&gt;GetControllerType()&lt;/code&gt;, mientras que en el segundo se obtiene una instancia de dicho tipo llamando a &lt;code&gt;GetControllerInstance()&lt;/code&gt;, que es la que retorna el método:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; IController &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     CreateController(RequestContext requestContext, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; controllerName) &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     [...] &lt;span style="color: #008000"&gt;// Simplificado&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     Type controllerType = GetControllerType(controllerName);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     IController controller = GetControllerInstance(controllerType);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; controller;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Dado que lo único que queremos sustituir es el mecanismo de localización, lo más sencillo es crear nuestra nueva factoría, a la que llamaremos &lt;code&gt;AcmeControllerFactory&lt;/code&gt;, heredando de &lt;code&gt;DefaultControllerFactory&lt;/code&gt; y sobrescribir el método &lt;code&gt;GetControllerType&lt;/code&gt;, que afortunadamente es virtual.&lt;/p&gt;&lt;p&gt;El código completo para esta nueva clase es el siguiente:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AcmeControllerFactory: DefaultControllerFactory&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; Type GetControllerType(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; controllerName)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;   {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;       Type r = &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.GetControllerType(controllerName);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;       &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (r == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;       {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;           Assembly current = Assembly.GetExecutingAssembly();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;           r = (from t &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; current.GetTypes()&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;                &lt;span style="color: #0000ff"&gt;where&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;                (&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;                        t.Name.Equals(&lt;span style="color: #006080"&gt;&amp;quot;ControladorDe&amp;quot;&lt;/span&gt; + controllerName,&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;                                       StringComparison.InvariantCultureIgnoreCase)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;                   &amp;amp;&amp;amp; t.IsPublic&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;                   &amp;amp;&amp;amp; !t.IsAbstract &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;                   &amp;amp;&amp;amp; &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IController).IsAssignableFrom(t)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;                )&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;                select t).FirstOrDefault();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;       }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;       &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; r;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;   }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Como podemos observar, lo primero que hacemos es intentar localizar el controlador con el nombre que nos llega en el parámetro, pero utilizando el método propuesto por la factoría por defecto, es decir, llamando al método &lt;code&gt;GetControllerType()&lt;/code&gt; original. Es decir, vamos a ser al menos algo respetuosos con las convenciones de nombrado existentes ;-) … primero intentaremos localizar el controlador ciñéndonos a ellas, y sólo si no tenemos éxito aplicaremos nuestro propio criterio de nombrado.&lt;/p&gt;&lt;p&gt;Así, ante una petición rutada hacia el controlador &lt;code&gt;Cliente,&lt;/code&gt; primero buscaremos la clase &lt;code&gt;ClienteController &lt;/code&gt;(según la convención), y si no existe es cuando intentaremos localizar un tipo llamado &lt;code&gt;ControladorDeCliente&lt;/code&gt;. Obviamente, podríamos hacerlo al revés, es decir, buscar primero según nuestro criterio de nombrado y si no tenemos éxito buscar utilizando el estándar, o bien ni siquiera intentar esta última opción.&lt;/p&gt;&lt;p&gt;Por tanto, si el método por defecto no es capaz de encontrar un controlador correspondiente a dicha denominación es cuando ejecutamos nuestra lógica adicional, que consiste en buscar en el ensamblado actual, mediante una consulta LINQ, aquellas clases cuyo nombre corresponda con el patrón que pretendemos emplear (&lt;code&gt;“ControladorDe”+controllerName&lt;/code&gt;), y que sean públicas, instanciables, e implementen el interfaz &lt;code&gt;IController&lt;/code&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;No se han implementado optimizaciones, como la inclusión de un caché, que permitan mejorar el rendimiento en esta consulta. Cada petición deberá recorrer, en el peor de los casos, todo el ensamblado en busca de un controlador apropiado.&lt;/p&gt;&lt;p&gt;Tampoco se ha implementado ningún tipo de resolución de conflictos; si existe más de un controlador con el mismo nombre en distintos namespaces, se retornará el primero que se encuentre.&lt;/p&gt;&lt;p&gt;Eso os lo dejo de deberes ;-)&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;3. Sustituir la factoría de controladores&lt;/h3&gt;&lt;p&gt;Ya tenemos creada la clase &lt;code&gt;AcmeControllerFactory,&lt;/code&gt; nuestra propia factoría de controladores, y está lista para entrar en acción. Pero, ¿cómo le decimos al framework que queremos utilizar una factoría de controladores distinta a la predeterminada? &lt;/p&gt;&lt;p&gt;Volvamos a estudiar el código de procesado de las peticiones que vimos anteriormente. Como se puede observar, el &lt;code&gt;IControllerFactory&lt;/code&gt; a utilizar es obtenido desde la clase &lt;code&gt;ControllerBuilder&lt;/code&gt;:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ProcessRequest(HttpContextBase httpContext) &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;   [...]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;   &lt;span style="color: #008000"&gt;// Instantiate the controller and call Execute&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;   IControllerFactory factory = &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;             ControllerBuilder.GetControllerFactory();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;   IController controller = &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;             factory.CreateController(RequestContext, controllerName);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     [...]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Y aquí de nuevo entra en juego la flexibilidad del diseño de ASP.NET MVC: &lt;code&gt;ControllerBuilder&lt;/code&gt; viene preparada para que podamos sustituir muy fácilmente la factoría a instanciar, por lo que podemos indicarle el tipo concreto que queremos que utilice.&lt;/p&gt;&lt;p&gt;En el siguiente código estamos indicando al &lt;code&gt;ControllerBuilder&lt;/code&gt; que nuestra factoría por defecto, es decir, la clase encargada de buscar e instanciar los controladores, será &lt;code&gt;AcmeControllerFactory. &lt;/code&gt;Como&amp;#160; se define en la inicialización de la aplicación &lt;code&gt;(Application_Start&lt;/code&gt; del &lt;code&gt;global.asax&lt;/code&gt;), todas las peticiones utilizarán esta factoría para crear los controladores:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Application_Start()&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     RegisterRoutes(RouteTable.Routes);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     ControllerBuilder&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         .Current&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         .SetControllerFactory(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(AcmeControllerFactory));&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;4. Probar que realmente funciona&lt;/h3&gt;&lt;p&gt;Podemos comprobar el funcionamiento de todo este invento de forma muy sencilla. Una vez seguidos los pasos anteriores, basta con crear un nuevo controlador que ya atienda a nuestra propia convención de nombrado, como el siguiente:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;br /&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [HandleError]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ControladorDeCliente : Controller&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Listar()&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;   {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;       &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;   }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Editar()&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;   {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;       &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;   }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Creamos, asimismo, una vista “Listar.aspx” y otra “Editar.aspx” en la carpeta “Views\Cliente” para que el motor pueda localizarlas y podamos ver algún resultado en pantalla. A partir de este momento, ejecutando el proyecto, podremos comprobar cómo si introducimos la URL&amp;#160; &lt;code&gt;&lt;a href="http://localhost:tupuerto/Cliente/Listar"&gt;http://localhost:tupuerto/Cliente/Listar&lt;/a&gt;&lt;/code&gt; el flujo de ejecución pasará por el método &lt;code&gt;Listar()&lt;/code&gt; visto anteriormente. También podemos invocar a la acción &lt;code&gt;Editar()&lt;/code&gt;, y el resultado será el esperado.&lt;/p&gt;&lt;p&gt;Y para los perezosos, ahí va el código fuente del proyecto (requiere Visual Studio 2008 o Web Developer Express con SP1 y ASP.NET MVC 1.0):&lt;/p&gt;&lt;br /&gt;&lt;iframe style="border-bottom: #dde5e9 1px solid; border-left: #dde5e9 1px solid; padding-bottom: 0px; background-color: #ffffff; margin: 3px; padding-left: 0px; width: 240px; padding-right: 0px; height: 66px; border-top: #dde5e9 1px solid; border-right: #dde5e9 1px solid; padding-top: 0px" marginheight="0" src="http://cid-c3a43a99b617d787.skydrive.live.com/embedrowdetail.aspx/P%c3%bablico/variablenotfound.com/ASP.NET%20MVC/ASP.NET%20MVC%201.0/ControllerConventionKiller.zip" frameborder="0" marginwidth="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-6243941910545417005?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4Evrm5kgGEL_lZcxNOpYAPyfzsw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4Evrm5kgGEL_lZcxNOpYAPyfzsw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4Evrm5kgGEL_lZcxNOpYAPyfzsw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4Evrm5kgGEL_lZcxNOpYAPyfzsw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=RaEbNxh5xNg:lVfa593W9pg:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=RaEbNxh5xNg:lVfa593W9pg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=RaEbNxh5xNg:lVfa593W9pg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=RaEbNxh5xNg:lVfa593W9pg:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=RaEbNxh5xNg:lVfa593W9pg:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=RaEbNxh5xNg:lVfa593W9pg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=RaEbNxh5xNg:lVfa593W9pg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=RaEbNxh5xNg:lVfa593W9pg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=RaEbNxh5xNg:lVfa593W9pg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/RaEbNxh5xNg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/6243941910545417005/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=6243941910545417005" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/6243941910545417005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/6243941910545417005?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/RaEbNxh5xNg/como-crear-un-controllerfactory.html" title="Cómo crear un ControllerFactory personalizado para ASP.NET MVC" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/07/como-crear-un-controllerfactory.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQGQXs-cSp7ImA9WxJVE0Q.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-5710099093048700967</id><published>2009-06-30T23:12:00.001+02:00</published><updated>2009-06-30T23:12:00.559+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-30T23:12:00.559+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="nivel básico" /><category scheme="http://www.blogger.com/atom/ns#" term="office" /><category scheme="http://www.blogger.com/atom/ns#" term="trucos" /><title>Desactivar el inicio en modo diseño de lectura de Word 2003</title><content type="html">&lt;p&gt;Lo sé. Estoy desactualizado... pero me sigue gustando Office 2003, como supongo que ocurre a mucha gente todavía. Y de hecho, continúo creando mis documentos con Microsoft Word 2003. &lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 10px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/ShwKlZm1nhI/AAAAAAAABEw/ocvi2I9D6Fk/image%5B3%5D.png?imgmax=800" width="269" height="215" /&gt; Sin embargo, a pesar del largo camino que hemos recorrido juntos, aún no he sido capaz de verle sentido al modo diseño de lectura, esa extraña forma de presentar los documentos por defecto al abrirlos,&amp;#160; o que podemos activar voluntariamente desde el menú “edición”. ¿A quién se le ocurrió esa idea? ¿Alguien la ha visto útil alguna vez? ¿Tiene, quizás, alguna utilidad oculta que no he sido capaz de intuir en todos estos años?&lt;/p&gt;  &lt;p&gt;Bueno, en cualquier caso, podemos conseguir muy fácilmente que no utilice el diseño de lectura en el momento de abrir los documentos, accediendo al cuadro de diálogo de configuración (&lt;em&gt;Herramientas &amp;gt;&amp;gt; Opciones&lt;/em&gt;) y &lt;strong&gt;desmarcando&lt;/strong&gt; el check “&lt;em&gt;Permitir el inicio en diseño Lectura&lt;/em&gt;”:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px auto 5px; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_O9D62hXq-ng/ShwKmxwceiI/AAAAAAAABE0/vNdWlK_wIOI/image%5B8%5D.png?imgmax=800" width="525" height="174" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Sencillo, ¿eh? Desde luego, no tengo excusa para haber aguantado este odioso comportamiento durante más de un lustro…&lt;/p&gt;  &lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-5710099093048700967?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/67WwyMaitaiwBcmkIIAQONsuoDM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/67WwyMaitaiwBcmkIIAQONsuoDM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/67WwyMaitaiwBcmkIIAQONsuoDM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/67WwyMaitaiwBcmkIIAQONsuoDM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=dS2MVGmxTyg:ogUHKSWbkH4:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=dS2MVGmxTyg:ogUHKSWbkH4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=dS2MVGmxTyg:ogUHKSWbkH4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=dS2MVGmxTyg:ogUHKSWbkH4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=dS2MVGmxTyg:ogUHKSWbkH4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=dS2MVGmxTyg:ogUHKSWbkH4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=dS2MVGmxTyg:ogUHKSWbkH4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=dS2MVGmxTyg:ogUHKSWbkH4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=dS2MVGmxTyg:ogUHKSWbkH4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/dS2MVGmxTyg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/5710099093048700967/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=5710099093048700967" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/5710099093048700967?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/5710099093048700967?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/dS2MVGmxTyg/desactivar-el-inicio-en-modo-diseno-de.html" title="Desactivar el inicio en modo diseño de lectura de Word 2003" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/06/desactivar-el-inicio-en-modo-diseno-de.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYNRHs5cSp7ImA9WxJVEk8.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-8569052771451826728</id><published>2009-06-29T00:00:00.006+02:00</published><updated>2009-06-29T00:13:15.529+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-29T00:13:15.529+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="libros" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><category scheme="http://www.blogger.com/atom/ns#" term="servicios on-line" /><title>Recopilación de capítulos gratuitos de libros sobre ASP.NET MVC</title><content type="html">&lt;p&gt;He recibido algunos mensajes de lectores de &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt; que quieren iniciarse en ASP.NET MVC, pero no saben por dónde empezar, y me sugieren que escriba algunos posts que expliquen desde cero este nuevo framework. Posiblemente lo haga algún día, pero mientras tanto, les he recordado que existen recursos gratuitos que pueden ser de mucha utilidad para dar los primeros pasos (e incluso profundizar un poco) en esta tecnología.&lt;/p&gt;  &lt;p&gt;Por ejemplo, recientemente han aparecido una gran cantidad de libros sobre ASP.NET MVC, y de la mayoría de ellos se pueden descargar capítulos gratuitos que, además de ayudarnos a decidir cuál de ellos puede ser de nuestro interés, tienen valor por la información que nos pueden aportar. Como siempre, el problema es la dispersión de esta información, por lo que he decidido hacer esta recopilación para tenerlos todos a mano. Conforme vaya descubriendo nuevos ejemplares iré ampliando la lista; y por supuesto, si conocéis alguno que no esté aquí, me lo comentáis y lo añadimos.&lt;/p&gt;&lt;p&gt;Eso sí, todos en inglés, aunque al ser muy técnicos creo que son fáciles de comprender.&lt;/p&gt;&lt;p&gt;&lt;table cellspacing="5" cellpadding="5"&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.com/gp/product/1430210079?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1430210079"&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Pro ASP.NET MVC Framework" border="0" alt="Pro ASP.NET MVC Framework" align="left" src="http://lh4.ggpht.com/_O9D62hXq-ng/SkURy3_XjkI/AAAAAAAABFI/79vqJSwHo2w/image3.png?imgmax=800" width="93" height="122" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.com/gp/product/1430210079?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1430210079"&gt;Pro ASP.NET MVC Framework&lt;/a&gt;&amp;#160; &lt;br /&gt;Autor: &lt;strong&gt;Steve Sanderson&lt;/strong&gt;     &lt;br /&gt;Post de presentación: &lt;a title="Now Published Pro ASP.NET MVC Framework (Apress) « Steve Sanderson’s blog" href="http://blog.codeville.net/2009/04/29/now-published-pro-aspnet-mvc-framework-apress/"&gt;Now Published Pro ASP.NET MVC Framework (Apress) « Steve Sanderson’s blog&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Capítulo gratuito:&amp;#160; &lt;/strong&gt;&lt;a title="Your first ASP.NET MVC Application" href="http://blog.codeville.net/blogfiles/2009/April/Pro_ASP_NET_MVC_Framework-4358.pdf"&gt;&lt;strong&gt;Chapter 2: Your First ASP.NET MVC Application (23 páginas)&lt;/strong&gt;&lt;/a&gt;En este capítulo, el autor muestra muy detalladamente, prácticamente paso a paso, cómo crear nuestra primera aplicación simple con ASP.NET MVC. En primer lugar, crea un proyecto muy básico mediante el cual explica los fundamentos básicos de la programación siguiendo este modelo, y a continuación entra en la creación de una mini-aplicación con entrada de datos, validaciones y lógica simple.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.com/gp/product/0470384611?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0470384611"&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Professional ASP.NET MVC 1.0" border="0" alt="Professional ASP.NET MVC 1.0" align="left" src="http://lh3.ggpht.com/_O9D62hXq-ng/SkURzY_gUgI/AAAAAAAABFM/wrqKo-CU12g/image1%5B2%5D.png?imgmax=800" width="93" height="122" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.com/gp/product/0470384611?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0470384611"&gt;Professional ASP.NET MVC 1.0&lt;/a&gt;     &lt;br /&gt;Autores: &lt;strong&gt;Scott Hanselman, Rob Conery, Phil Haack y Scott Guthrie&lt;/strong&gt;     &lt;br /&gt;    &lt;br /&gt;&lt;strong&gt;Capítulo gratuito: &lt;/strong&gt;&lt;a title="Chapter 1: Nerdinner" href="http://aspnetmvcbook.s3.amazonaws.com/aspnetmvc-nerdinner_v1.pdf"&gt;&lt;strong&gt;Chapter 1: Nerdinner (192 páginas)&lt;/strong&gt;&lt;/a&gt;&amp;#160; &lt;br /&gt;Este extenso capítulo describe la creación de un sitio web medianamente complejo, &lt;a href="http://www.nerddinner.com"&gt;www.nerddinner.com&lt;/a&gt;, utilizando gran cantidad de tecnologías relacionadas con el framework MVC como filtros, Ajax, LinqToSql, pruebas unitarias, etc. Muy recomendable, imprescindible.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a title="ASP.NET MVC 1.0 Quickly" href="http://www.amazon.com/gp/product/184719754X?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=184719754X"&gt;&lt;img style="border-right-width: 0px; margin: 0px 5px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://lh3.ggpht.com/_O9D62hXq-ng/SkUR0Ge5A_I/AAAAAAAABFQ/a2JFOU4PL_Q/image4.png?imgmax=800" width="98" height="122" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;a title="ASP.NET MVC 1.0 Quickly" href="http://www.amazon.com/gp/product/184719754X?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=184719754X"&gt;ASP.NET MVC 1.0 Quickly&lt;/a&gt;     &lt;br /&gt;Autor: &lt;strong&gt;Maarten Balliauw      &lt;br /&gt;&lt;/strong&gt;Post de presentación: &lt;a title="Announcing my book- ASP.NET MVC 1.0 Quickly" href="http://blog.maartenballiauw.be/post/2009/02/17/Announcing-my-book-ASPNET-MVC-10-Quickly.aspx"&gt;Announcing my book- ASP.NET MVC 1.0 Quickly&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Capítulo gratuito: &lt;/strong&gt;&lt;a title="Chapter 2: Your first ASP.NET MVC application" href="http://www.packtpub.com/files/asp-net-mvc-1-0-quickly-sample-chapter-2-your-first-asp-net-mvc-application.pdf"&gt;&lt;strong&gt;Chapter 2: Your first ASP.NET MVC application (20 páginas)&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;#160; &lt;br /&gt;&lt;/strong&gt;Breve recorrido por el proceso de creación de una aplicación MVC, el sistema de rutas, controladores, vistas y realización de pruebas unitarias. Bastante básico, quizás demasiado “quickly”, pero válido en cualquier caso.&lt;/td&gt;&lt;/tr&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.com/gp/product/1933988622?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1933988622"&gt;&lt;img style="border-right-width: 0px; margin: 0px 5px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://lh6.ggpht.com/_O9D62hXq-ng/SkUR0jrORDI/AAAAAAAABFU/b4kQb3I22do/image%5B4%5D.png?imgmax=800" width="97" height="122" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;a title="ASP.NET MVC in Action" href="http://www.amazon.com/gp/product/1933988622?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=1933988622"&gt;ASP.NET MVC in Action&lt;/a&gt;     &lt;br /&gt;Autores: &lt;strong&gt;Jeffrey Palermo, Ben Scheirman, Jimmy Bogard      &lt;br /&gt;&lt;/strong&gt;Post de presentación: &lt;a title="Announcing ASP.NET MVC in Action (from Manning) - Jeffrey Palermo (.com) - CodeBetter.Com - Stuf" href="http://codebetter.com/blogs/jeffrey.palermo/archive/2008/02/23/announcing-asp-net-mvc-in-action-from-manning.aspx"&gt;Announcing ASP.NET MVC in Action (from Manning) - Jeffrey Palermo (.com) - CodeBetter.Com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Recurso gratuito: &lt;/strong&gt;&lt;a title="Getting Started with the ASP.NET MVC Framework (Green Paper - PDF)" href="http://www.manning.com/free/green_palermo.html"&gt;&lt;strong&gt;Getting Started with the ASP.NET MVC Framework (Green Paper – PDF) (18 páginas)&lt;/strong&gt;&lt;/a&gt; (El enlace a este documento te lo envían por correo electrónico tras facilitar tu dirección). Se trata de otra introducción al framework, el sistema de rutas, controladores y vistas partiendo desde cero.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Capítulo gratuito: &lt;/strong&gt;&lt;a title="AJAX in ASP.NET MVC" href="http://www.manning.com/palermo/palermo_meapch9_sample.pdf"&gt;&lt;strong&gt;Chapter 9: AJAX in ASP.NET MVC (21 páginas)&lt;/strong&gt;&lt;/a&gt;     &lt;br /&gt;Interesante capítulo de introducción al uso de la tecnología Ajax sobre ASP.NET MVC utilizando jQuery y los Ajax helpers para intercambiar datos con el servidor.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;img style="border-right-width: 0px; margin: 0px 5px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://lh3.ggpht.com/_O9D62hXq-ng/SkUR1Hz1qcI/AAAAAAAABFY/YxmcAqrd18I/image%5B8%5D.png?imgmax=800" width="94" height="122" /&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.com/gp/product/0672329980?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0672329980"&gt;ASP.NET MVC Framework Unleashed&lt;/a&gt;     &lt;br /&gt;Autor: &lt;strong&gt;Stephen Walther&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Capítulos gratuitos:&lt;/strong&gt; el autor ha publicado varios capítulos en su blog, y los retirará en cuanto el libro esté disponible en Amazon, así que daos prisa que los contenidos son excelentes.    &lt;br /&gt;&lt;a title="Chapter 1 - An Introduction to ASP.NET MVC" href="http://stephenwalther.com/blog/archive/2009/02/05/chapter-1-an-introduction-to-asp.net-mvc.aspx"&gt;Chapter 1 - An Introduction to ASP.NET MVC&lt;/a&gt;     &lt;br /&gt;&lt;a title="Chapter 2 - Building a Simple ASP.NET MVC Application" href="http://stephenwalther.com/blog/archive/2009/02/07/chapter-2-building-a-simple-asp.net-mvc-application.aspx"&gt;Chapter 2 - Building a Simple ASP.NET MVC Application&lt;/a&gt;     &lt;br /&gt;&lt;a title="Chapter 3 - Understanding Controllers" href="http://stephenwalther.com/blog/archive/2009/02/13/chapter-3-understanding-controllers.aspx"&gt;Chapter 3 - Understanding Controllers&lt;/a&gt;     &lt;br /&gt;&lt;a title="Chapter 4 - Understanding Views" href="http://stephenwalther.com/blog/archive/2009/02/21/chapter-4-understanding-views.aspx"&gt;Chapter 4 - Understanding Views&lt;/a&gt;     &lt;br /&gt;&lt;a title="Chapter 5 -- Understanding Models" href="http://stephenwalther.com/blog/archive/2009/02/27/chapter-5-understanding-models.aspx"&gt;Chapter 5 - Understanding Models&lt;/a&gt;     &lt;br /&gt;&lt;a title="Chapter 6 - Understanding HTML Helpers" href="http://stephenwalther.com/blog/archive/2009/03/03/chapter-6-understanding-html-helpers.aspx"&gt;Chapter 6 - Understanding HTML Helpers&lt;/a&gt;     &lt;br /&gt;&lt;a title="Chapter 9 - Understanding Routing" href="http://stephenwalther.com/blog/archive/2009/02/06/chapter-2-understanding-routing.aspx"&gt;Chapter 9 - Understanding Routing&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;a title="Beginning ASP.NET MVC 1.0" href="http://www.amazon.com/gp/product/047043399X?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=047043399X"&gt;&lt;img style="border-right-width: 0px; margin: 0px 5px 100px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/_O9D62hXq-ng/SkUR1zugM6I/AAAAAAAABFc/wDqM9Z-ZOE8/image%5B13%5D.png?imgmax=800" width="97" height="122" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;a href="http://www.amazon.com/gp/product/047043399X?ie=UTF8&amp;amp;tag=variabnotfoun-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=047043399X"&gt;Beginning ASP.NET MVC 1.0&lt;/a&gt;     &lt;br /&gt;Autores: &lt;strong&gt;Simone Chiaretta, Keyvan Nayyeri      &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Capítulo gratuito: &lt;/strong&gt;&lt;a title="Chapter 9: Testing ASP.NET MVC Applications" href="http://p2p.wrox.com/attachment.php?attachmentid=40&amp;amp;d=1241018031"&gt;&lt;strong&gt;Chapter 9: Testing ASP.NET MVC Applications (38 páginas)&lt;/strong&gt;&lt;/a&gt;     &lt;br /&gt;Interesantísimo capítulo que describe distintas técnicas para la realización de pruebas unitarias de aplicaciones creadas con este framework, incluyendo la creación de mocks, inyección de dependencias en controladores, testeo de rutas y de refilón, algo de TDD.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-8569052771451826728?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xbN_KKmInrMpQtSg11rMG7YqyIo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xbN_KKmInrMpQtSg11rMG7YqyIo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xbN_KKmInrMpQtSg11rMG7YqyIo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xbN_KKmInrMpQtSg11rMG7YqyIo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=KSM9TZ0iio4:2H7PFLE1FqI:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=KSM9TZ0iio4:2H7PFLE1FqI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=KSM9TZ0iio4:2H7PFLE1FqI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=KSM9TZ0iio4:2H7PFLE1FqI:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=KSM9TZ0iio4:2H7PFLE1FqI:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=KSM9TZ0iio4:2H7PFLE1FqI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=KSM9TZ0iio4:2H7PFLE1FqI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=KSM9TZ0iio4:2H7PFLE1FqI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=KSM9TZ0iio4:2H7PFLE1FqI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/KSM9TZ0iio4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/8569052771451826728/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=8569052771451826728" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/8569052771451826728?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/8569052771451826728?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/KSM9TZ0iio4/recopilacion-de-capitulos-gratuitos-de.html" title="Recopilación de capítulos gratuitos de libros sobre ASP.NET MVC" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/06/recopilacion-de-capitulos-gratuitos-de.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAAQX08eip7ImA9WxJWEEw.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-3242992232300470870</id><published>2009-06-14T23:59:00.000+02:00</published><updated>2009-06-14T23:59:00.372+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-14T23:59:00.372+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><category scheme="http://www.blogger.com/atom/ns#" term="programación" /><title>Control de errores en acciones ASP.NET MVC</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Sorpresa" border="0" alt="Sorpresa" align="right" src="http://lh5.ggpht.com/_O9D62hXq-ng/SesILhbzQTI/AAAAAAAABBM/DBm8RM37P60/image5.png?imgmax=800" width="103" height="156" /&gt; El control de errores en aplicaciones web es fundamental si queremos ofrecer un interfaz robusto y amigable para los usuarios en cualquier situación. No hay nada más frustrante para un usuario que una pantalla de error con contenidos indescifrables y que no le aportan alternativas de salida.&lt;/p&gt;  &lt;p&gt;El framework ASP.NET MVC nos ofrece mecanismos de control de errores muy potentes basada en la utilización del atributo &lt;code&gt;HandleError, &lt;/code&gt;el cual definirá la vista que será mostrada al usuario cuando se produzca alguna excepción no controlada en el código de los controladores, siempre que en el &lt;code&gt;web.config&lt;/code&gt; se haya activado el uso de errores personalizados mediante la propiedad &lt;code&gt;CustomErrors&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;En este post vamos a profundizar en el uso del atributo &lt;code&gt;HandleError, &lt;/code&gt;comentando cómo se implementa en el controlador, su ámbito de actuación, los parámetros que ofrece y la forma de crear las vistas para mostrar los errores de forma amigable.&lt;/p&gt;  &lt;h3&gt;El controlador&lt;/h3&gt;  &lt;p&gt;&lt;code&gt;HandleError&lt;/code&gt; puede ser declarado tanto a nivel de clase (controlador) como a nivel de acción. En el primer caso, se establecerá el comportamiento general para todas las acciones del controlador, mientras que en el segundo será aplicable sólo a la acción a la que se asocie el atributo:&lt;/p&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" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:11d6b29b-3bfa-4278-85d3-9b9e2929df4f" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Control de errores a nivel de clase de controlador, &lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; que será aplicado a todas las acciones del mismo.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;[HandleError()]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; HomeController : Controller&lt;br /&gt;{&lt;br /&gt;    ...&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:6d6fca21-9272-48f4-902d-3b8e3307c8e2" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Control de errores a nivel de acción concreta...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;[HandleError(ExceptionType&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(ArgumentException), View&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ArgumentError&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ActionResult Calculate(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; a, &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; b)&lt;br /&gt;{&lt;br /&gt;  ViewData[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;results&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; calculateSomething();&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; View();&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;En realidad, el comportamiento definido en el atributo &lt;code&gt;HandleError&lt;/code&gt; a nivel de clase también se aplicará a los errores generados por las vistas u otros resultados (&lt;code&gt;ActionResult&lt;/code&gt;) retornados por los controladores. Es decir, sobre el segundo de los ejemplos anteriores, la vista “ArgumentError” (que existirá en un archivo llamado ArgumentError.aspx) será invocada cuando la excepción &lt;code&gt;ArgumentException&lt;/code&gt; sea lanzada bien por el propio controlador, o bien por la vista “Calculate” que retorna por defecto. &lt;/p&gt;&lt;p&gt;Un último detalle sobre esto: el atributo &lt;code&gt;HandleError&lt;/code&gt; puede ser especificado tantas veces como necesitemos sobre la misma acción o controlador, indicando comportamientos para distintos tipos de excepción. El atributo que se tendrá en cuenta cuando se produzca un error será el primero que se encuentre cuyo tipo de excepción (parámetro ExceptionType) sea compatible con la excepción lanzada. &lt;/p&gt;&lt;p&gt;El manejador de errores que se empleará en una acción será el primero que corresponda al tipo de excepción producida, teniendo en cuenta tanto los atributos que adornan la acción como los que acompañan a su controlador, y siempre según un orden preestablecido.&lt;/p&gt;&lt;p&gt;Veamos con más detenimiento los parámetros que admite la declaración del atributo.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Parámetros de HandleError&lt;/h3&gt;&lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:de227142-859a-47d6-80e5-ef4625944c9d" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;        [HandleError(&lt;br /&gt;            ExceptionType&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(DivisionByZero), &lt;br /&gt;            View&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ErrorPersonalizado&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br /&gt;            Master&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;MaestraErrores&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;            Order &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;        ]&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ActionResult Index()&lt;br /&gt;        ...&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ExceptionType&lt;/strong&gt; permite indicar el tipo de excepción que se pretende controlar. Por defecto, el sistema entenderá que la regla se refiere al tipo base &lt;code&gt;Exception&lt;/code&gt;, por lo que se aplicará a todos los errores que se generen, pues todas las excepciones heredan de esta clase. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;View&lt;/strong&gt;, el nombre de la vista que será mostrada al usuario. Por defecto se tomará el valor “Error”, por eso en la plantilla de proyectos ASP.NET MVC ya existe una vista con este nombre. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Master&lt;/strong&gt;, la página maestra con la que será renderizada la vista, independientemente de lo que tenga declarado ésta. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Order,&lt;/strong&gt; un valor numérico (por defecto –1, el más prioritario) que indica la prioridad de aplicación de esta regla cuando el sistema encuentre varios atributos &lt;code&gt;HandleError&lt;/code&gt; aplicables al mismo elemento y que puedan presentar conflictos. Los valores más pequeños, Por ejemplo, si no se indicara este parámetro en el siguiente caso, el resultado dependería del orden de declaración, lo cual no es demasiado recomendable: &lt;br /&gt;    &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:fb807aa2-2498-4610-92cf-9cce1c2c692e" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;[HandleError(Order&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800080;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt;, View&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ErrorGenerico&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; HomeController : Controller&lt;br /&gt;{&lt;br /&gt;  ...&lt;br /&gt;  [HandleError (ExceptionType&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(DivisionByZero),&lt;br /&gt;                View&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OperacionIncorrecta&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, Order&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ActionResult Calculate()&lt;br /&gt;  ...&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;Como puede intuirse, esto hará que en caso de producirse una división por cero, se muestre la vista “OperacionIncorrecta” y no la “ErrorGenerico”. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Cada vez que utilicemos &lt;code&gt;HandleError&lt;/code&gt; es conveniente tener muy en cuenta la prioridad (definida en la propiedad &lt;code&gt;Order&lt;/code&gt;), el alcance (las excepciones a tratar, definidas en la propiedad &lt;code&gt;ExceptionType&lt;/code&gt;), así como los valores por defecto en cada caso. Esto evitará comportamientos misteriosos del sistema una vez se produzcan errores en tiempo de ejecución.&lt;/p&gt;&lt;h3&gt;Acceso desde la vista a la información del error&lt;/h3&gt;&lt;p&gt;Ya hemos comentado anteriormente que la vista que será mostrada a los usuarios cuando se produzca un error será la indicada en el parámetro &lt;code&gt;View&lt;/code&gt; del atributo &lt;code&gt;HandleError&lt;/code&gt;, o la vista &amp;quot;Error&amp;quot;, si este parámetro no es informado. Sea cual sea, el archivo &lt;em&gt;nombredevista&lt;/em&gt;.aspx deberá estar localizable por el motor de vistas en el momento de su lanzamiento (por cierto, si no te gustan las ubicaciones por defecto, puedes ver &lt;a href="http://www.variablenotfound.com/2009/06/cambiar-la-ubicacion-de-las-vistas-en.html" title="Cambiar la ubicación de las vistas en ASP.NET MVC"&gt;cómo modificar la forma en la que se buscan las vistas&lt;/a&gt; en este post).&lt;/p&gt;&lt;p&gt;La vista de un error es una página .aspx normal, como una vista más de la web, pero con la particularidad de que puede recibir información sobre el error que ha provocado su presentación. De hecho, se trata de una vista tipada que hereda de &lt;code&gt;ViewPage&amp;lt;System.Web.Mvc.HandleErrorInfo&amp;gt;&lt;/code&gt;, de forma que&amp;#160; la propiedad &lt;code&gt;Model&lt;/code&gt; será del tipo &lt;code&gt;HandleErrorInfo&lt;/code&gt;, clase que nos ofrece completa información sobre el origen del problema:&lt;/p&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:b431cced-0c91-4eb1-888d-d3bbd07683f3" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;@ Page Language&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;C#&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; MasterPageFile&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;~/Views/Shared/Site.Master&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; &lt;br /&gt;    Inherits&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;System.Web.Mvc.ViewPage&amp;lt;System.Web.Mvc.HandleErrorInfo&amp;gt;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;asp:Content &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="errorTitle"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; ContentPlaceHolderID&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="TitleContent"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; runat&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    Error en el sistema&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;asp:Content&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;asp:Content &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="errorContent"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; ContentPlaceHolderID&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="MainContent"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; runat&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        Ups, se ha producido un ligero inconveniente...&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        La acción &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; Model.ActionName &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;  &lt;br /&gt;        del controlador &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; Model.ControllerName &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        ha lanzado la excepción &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; Model.Exception.GetType().Name &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;br /&gt;        el mensaje "&lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; Model.Exception.Message &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;".&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;asp:Content&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;A pesar de no ser un buen ejemplo como pantalla del error amigable para el usuario ;-), el código anterior ilustra cómo es posible acceder desde la vista a los datos del contexto del error proporcionados por el entorno, y cómo la clase &lt;code&gt;HandleErrorInfo&lt;/code&gt; nos ofrece una información sobre la acción en la que se ha lanzado la excepción, el controlador en el que se encuentra la misma, y lo más interesante, nos ofrece en la propiedad &lt;code&gt;Exception&lt;/code&gt; la excepción producida, por lo que tendremos acceso a su tipo, descripción e incluso al estado de la pila de llamadas en el momento de producirse el error.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-3242992232300470870?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ECfIVeCk8mS0jP4QJzoTXFtAwp0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ECfIVeCk8mS0jP4QJzoTXFtAwp0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ECfIVeCk8mS0jP4QJzoTXFtAwp0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ECfIVeCk8mS0jP4QJzoTXFtAwp0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=AKTEt91mok4:a7S7wVgH2QU:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=AKTEt91mok4:a7S7wVgH2QU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=AKTEt91mok4:a7S7wVgH2QU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=AKTEt91mok4:a7S7wVgH2QU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=AKTEt91mok4:a7S7wVgH2QU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=AKTEt91mok4:a7S7wVgH2QU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=AKTEt91mok4:a7S7wVgH2QU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=AKTEt91mok4:a7S7wVgH2QU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=AKTEt91mok4:a7S7wVgH2QU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/AKTEt91mok4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/3242992232300470870/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=3242992232300470870" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3242992232300470870?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3242992232300470870?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/AKTEt91mok4/control-de-errores-en-acciones-aspnet.html" title="Control de errores en acciones ASP.NET MVC" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/06/control-de-errores-en-acciones-aspnet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IGQXg_eyp7ImA9WxJXFEw.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-1226820273611158423</id><published>2009-06-07T23:52:00.014+02:00</published><updated>2009-06-07T23:52:00.643+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-07T23:52:00.643+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="utilidades" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="software" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="blogging" /><title>Cómo crear un plugin sencillo para Live Writer, paso a paso</title><content type="html">&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Code Tag" border="0" alt="Code Tag" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SgViKAnmC_I/AAAAAAAABC8/1URQKBft8s0/image25.png?imgmax=800" width="168" height="60" /&gt;Hace unos días publiqué &lt;a title="CodeTag" href="http://www.variablenotfound.com/2009/05/plugin-para-insertar-etiquetas-en-live.html"&gt;CodeTag&lt;/a&gt;, un sencillo plugin para Windows Live Writer que permite insertar pequeñas porciones de código fuente en línea en los contenidos de los posts. Resumidamente, lo único que hace esta utilidad es envolver entre etiquetas &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; y &lt;code&gt;&amp;lt;/code&amp;gt;&lt;/code&gt; el texto que tengamos seleccionado en el momento de su utilización, pero evita tener que entrar al modo de edición HTML para hacer estos ajustes.   &lt;br /&gt;  &lt;br /&gt;Basándome en el código fuente de CodeTag (que podéis descargar al final de este post), voy a describir, paso a paso, cómo podemos crear complementos para Writer que nos faciliten un poco las tareas cotidianas de edición.   &lt;br /&gt;  &lt;br /&gt;  &lt;h3&gt;0. Antes de empezar…&lt;/h3&gt; Para poder desarrollar el plugin necesitáis básicamente dos cosas:   &lt;br /&gt;  &lt;br /&gt;  &lt;ul&gt;   &lt;li&gt;en primer lugar, el propio software &lt;a title="Descargar Live Writer" href="http://download.live.com/writer"&gt;Live Writer&lt;/a&gt;, más que nada porque necesitamos referenciar algunos de sus ensamblados, y por ir probando el complemento durante el desarrollo. &lt;/li&gt;    &lt;li&gt;en segundo lugar, Visual Studio 2005 o 2008, aunque sea una &lt;a title="Visual Studio 2008 Express" href="http://www.microsoft.com/express/download/"&gt;edición express&lt;/a&gt;&lt;a title="Visual Studio 2008 Express" href="http://www.microsoft.com/express/download/"&gt;&lt;/a&gt;. Este desarrollo vamos a realizarlo en C#, pero la traducción a Visual Basic .NET sería trivial. &lt;/li&gt; &lt;/ul&gt; En este post voy a incluir capturas de pantalla correspondientes a Microsoft Visual C# 2008 Express, que es el único que tengo a mano.   &lt;br /&gt;  &lt;br /&gt;  &lt;h3&gt;1. Preparación del proyecto&lt;/h3&gt; Los plugins para Live Writer son archivos .dll, es decir, ensamblados .NET, que se colocan en el directorio &amp;quot;plugins&amp;quot; de la carpeta de instalación del programa. En mi caso, están en la carpeta &lt;code&gt;C:\Archivos de programa\Windows Live\Writer\Plugins, &lt;/code&gt;y si no habéis cambiado las rutas de instalación por defecto, será allí donde los podéis encontrar también. Durante el proceso de arranque, Writer examinará dicha carpeta y cargará los complementos que encuentre en ella.   &lt;br /&gt;  &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_O9D62hXq-ng/SgViLP7h6VI/AAAAAAAABDA/SpFmdK38NI0/s1600-h/image11.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Crear librería de clases" border="0" alt="Crear librería de clases" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SgViLx27-vI/AAAAAAAABDE/fUqnvGIZGLU/image_thumb3.png?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;Lo que vamos a hacer es crear desde Visual Studio un proyecto de librería de clases. Cada vez que compilemos, copiaremos el ensamblado resultante en dicho directorio (veremos cómo podemos automatizar esta tarea) y podremos lanzar Live Writer para comprobar el funcionamiento.   &lt;br /&gt;  &lt;br /&gt;Por tanto, en primer lugar creamos un proyecto de librería de clases como siempre, al que le damos el nombre CodeTag. Obviamente, podéis dar al proyecto el nombre que estiméis conveniente.   &lt;br /&gt;  &lt;br /&gt;Una vez que el IDE crea la estructura, debemos añadir dos referencias al proyecto, que serán necesarias para poder continuar:   &lt;br /&gt;  &lt;br /&gt;  &lt;ul&gt;   &lt;li&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Añadir referencias" border="0" alt="Añadir referencias" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SgViMmq0BfI/AAAAAAAABDI/PYADVmhVgxM/image12.png?imgmax=800" width="244" height="190" /&gt; La primera referencia es al ensamblado que contiene el API de Live Writer, que podéis encontrar en el directorio de instalación de la herramienta. El&amp;#160; archivo a incluir es &lt;code&gt;WindowsLive.Writer.Api.dll&lt;/code&gt; . &lt;/li&gt;    &lt;li&gt;La segunda es a &lt;code&gt;System.Windows.Forms&lt;/code&gt;. Hay que tener en cuenta que Live Writer es una herramienta de escritorio, y esta referencia es importante para poder interactuar con el mismo. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Otro detalle más que nos va a facilitar las cosas: vamos a indicar a Visual Studio que el resultado de la compilación lo copie en el directorio de plugins de Live Writer. Para ello, lo único que tenemos que hacer es acudir a las propiedades del proyecto, pestaña “eventos de generación” e incluir la siguiente orden en el cuadro “línea de comandos del evento posterior a la generación” (obviamente, modificando la ruta si es necesario):    &lt;br /&gt;    &lt;br /&gt;&lt;code&gt;XCOPY /D /Y /R &amp;quot;$(TargetPath)&amp;quot; &amp;quot;C:\Archivos de Programa\Windows Live\Writer\Plugins\&amp;quot;&lt;/code&gt;&lt;/p&gt; &lt;img style="border-right-width: 0px; margin: 0px auto 5px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Evento posterior a la generación" border="0" alt="Evento posterior a la generación" src="http://lh4.ggpht.com/_O9D62hXq-ng/SgViNuYwAMI/AAAAAAAABDM/NM0Tr9eBGE4/image26.png?imgmax=800" width="390" height="268" /&gt;   &lt;br /&gt;  &lt;br /&gt;Ojo, es importante tener en cuenta algo más cuando vayamos a compilar: si Live Writer está abierto, no podremos sobrescribir nuestro plugin con una nueva versión, pues éste se encontrará en uso. En estos casos debemos cerrar el programa antes de copiar el archivo, o antes de compilar.   &lt;br /&gt;  &lt;br /&gt;Con estas operaciones ya tenemos el proyecto listo para empezar a codificar el plugin.   &lt;br /&gt;  &lt;br /&gt;  &lt;h3&gt;2. Escribimos la clase principal&lt;/h3&gt; Un plugin sencillo como este no requiere demasiada programación, pero sí hay que cumplir una serie de requisitos para que se integre correctamente en Live Writer.   &lt;br /&gt;  &lt;br /&gt;En primer lugar, creamos una clase, a la que llamaremos &lt;code&gt;CodeTag&lt;/code&gt;, e insertamos el siguiente código:   &lt;br /&gt;  &lt;br /&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:138dc3ac-6609-4cc0-9532-2a0a5a754c29" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Courier New;font-size:6,75"&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; CodeTag: ContentSource&lt;br /&gt;  {&lt;br /&gt;     &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; DialogResult CreateContent(IWin32Window dialogOwner, &lt;br /&gt;                                               &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;ref&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; content)&lt;br /&gt;    {&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.IsNullOrEmpty(content))&lt;br /&gt;          content &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;YourCodeHere&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;      &lt;br /&gt;      content &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;lt;code&amp;gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; content &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;lt;/code&amp;gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; DialogResult.OK;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;Como se puede observar, la clase hereda de &lt;code&gt;ContentSource, &lt;/code&gt;un tipo definido en &lt;code&gt;WindowsLive.Writer.Api&lt;/code&gt;, que sirve como base para la creación de complementos sencillos como el que nos ocupa. Para casos más complejos, que permitieran por ejemplo edición de contenidos bidireccional entre el contenido de la página y un editor personalizado podríamos heredar de &lt;code&gt;SmartContentSource&lt;/code&gt;, pero no profundizaremos en ello ahora. &lt;br /&gt;&lt;br /&gt;La codificación de la lógica del plugin puede realizarse en varios puntos, dependiendo de la forma en que Writer lo active; en nuestro caso, el complemento se lanzará cuando el usuario presione un botón en la barra lateral o seleccione la opción correspondiente en el menú &amp;quot;insertar&amp;quot;, por lo que simplemente deberemos sobrescribir el método &lt;code&gt;CreateContent&lt;/code&gt;. &lt;br /&gt;&lt;br /&gt;Dicho método recibe dos parámetros. El primero de ellos hace referencia a la ventana activa, que podemos utilizar como &amp;quot;padre&amp;quot; si quisiéramos crear un cuadro de diálogo desde nuestro código. El segundo parámetro contendrá una referencia al texto seleccionado en el momento de lanzar el plugin, pudiendo darse los dos casos que se contemplan en la codificación: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Si la variable &lt;code&gt;content&lt;/code&gt; viene vacía o con valor nulo, es que el complemento ha sido lanzado en modo inserción, es decir, no existía ningún texto seleccionado y por lo tanto lo que se pretende es añadir las etiquetas de código para introducir posteriormente contenido. Como puede observarse en el código, lo que se hace en este caso es insertar las etiquetas &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; con un texto arbitrario para que el usuario lo modifique a su antojo más adelante. &lt;/li&gt;&lt;li&gt;En caso contrario, si la variable &lt;code&gt;content&lt;/code&gt; trae algún contenido, lo que se hace es rodear éste por la apertura y cierre de la etiqueta &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;En ambos casos se retorna un valor &lt;code&gt;DialogResult.OK&lt;/code&gt;, que indica a Live Writer que debe insertar el texto contenido en content en la ubicación donde se encuentre el cursor, o bien sustituir el texto seleccionado por el nuevo valor. &lt;br /&gt;&lt;h3&gt;3. Añadimos metadatos&lt;/h3&gt;Heredar de la clase &lt;code&gt;ContentSource&lt;/code&gt; no es el único requisito para que esta sea considerada como un componente de Writer, es necesario adornarla con un conjunto de atributos como los mostrados en el siguiente código: &lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:88b5158e-55e9-4344-ade0-9bbddb36e66a" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;[WriterPlugin(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;98497c2b-bbfd-4bd1-b343-226f3c9e766b&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Code Tag&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;    Description &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Crea etiquetas &amp;lt;code&amp;gt;&amp;lt;/code&amp;gt; en el contenido&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;    PublisherUrl &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://www.variablenotfound.com&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;[InsertableContentSource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Etiqueta &amp;lt;code&amp;gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; CodeTag: ContentSource&lt;br /&gt;{&lt;br /&gt;  [...]&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;El atributo [&lt;code&gt;WriterPlugin]&lt;/code&gt; es el que realmente identifica la clase como plugin de Live Writer. Los parámetros que se le están enviando son los siguientes: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;El primer parámetro es un GUID, es decir, un identificador único que debemos generar para el plugin, utilizando &lt;a title="Generador de GUIDs on-line" href="http://www.guidgenerator.com/online-guid-generator.aspx"&gt;este servicio on-line&lt;/a&gt; u otras herramientas como la incluida en Visual Studio. &lt;/li&gt;&lt;li&gt;El segundo parámetro es el nombre del plugin. Es la identificación que aparece en el cuadro de diálogo de configuración de complementos de Live Writer. &lt;/li&gt;&lt;li&gt;&lt;code&gt;Description&lt;/code&gt; permite añadir una descripción textual ampliada del plugin. &lt;/li&gt;&lt;li&gt;&lt;code&gt;PublisherUrl&lt;/code&gt; es una dirección web de referencia al autor. Pura propaganda ;-) &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;El atributo &lt;code&gt;[InsertableContentsource]&lt;/code&gt; indica que el complemento debe aparecer en el menú &amp;quot;insertar&amp;quot; de las barra de tareas de Writer y en el menú principal. El parámetro que le estamos enviando es simplemente el texto que aparecerá en estos menús. &lt;br /&gt;&lt;h3&gt;4. Compilamos el proyecto&lt;/h3&gt;Con lo hecho hasta el momento ya podemos compilar e intentar probar nuestro complemento. Este procedimiento lo repetiremos varias veces durante el desarrollo, por lo que es posible que nos encontremos a menudo con un error como el siguiente: &lt;br /&gt;&lt;br /&gt;&lt;img style="border-right-width: 0px; margin: 15px auto 5px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="The command &amp;quot;XCOPY /D /Y /R &amp;quot;CodeTag.dll&amp;quot; &amp;quot;C:\Archivos de Programa\Windows Live\Writer\Plugins\&amp;quot;&amp;quot; exited with code 4" border="0" alt="The command &amp;quot;XCOPY /D /Y /R &amp;quot;CodeTag.dll&amp;quot; &amp;quot;C:\Archivos de Programa\Windows Live\Writer\Plugins\&amp;quot;&amp;quot; exited with code 4" src="http://lh4.ggpht.com/_O9D62hXq-ng/ShBDlTNq2mI/AAAAAAAABDU/voUFYVsqYtU/image16.png?imgmax=800" width="537" height="125" /&gt; &lt;br /&gt;&lt;br /&gt;Esto simplemente quiere decir que Live Writer está usando CodeTag.dll y no puede ser sobrescrito, por lo que &lt;strong&gt;¡cerrad Live Writer antes de compilar!&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CodeTag en el menú &amp;quot;insertar&amp;quot;, sin icono" border="0" alt="CodeTag en el menú &amp;quot;insertar&amp;quot;, sin icono" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/ShBDmJnD5-I/AAAAAAAABDY/Rx-kWMr8QSU/image4.png?imgmax=800" width="183" height="177" /&gt; Una vez superado este leve impedimento, si aparece, ya podremos comenzar a disfrutar de nuestro plugin. Veremos que aparece en el menú &amp;quot;insertar&amp;quot;, con la descripción apropiada, y funcionando correctamente. &lt;br /&gt;&lt;br /&gt;Pero vaya, es cierto que en el menú aparece, pero destaca sobre el resto de complementos porque es el único que no tiene un icono, así que habrá que mejorarlo un poco… &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;5. Añadirle un icono al plugin&lt;/h3&gt;Incluir un icono a nuestro complemento le dará sin duda un aspecto más profesional, vamos a ello. &lt;br /&gt;&lt;br /&gt;&lt;img style="border-right-width: 0px; margin: 0px 5px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://lh3.ggpht.com/_O9D62hXq-ng/ShBDmUnhBoI/AAAAAAAABDc/Ikc0cb_O93g/image161.png?imgmax=800" width="32" height="32" /&gt; Lo primero que necesitamos es una imagen de 16x16 píxeles, por ejemplo en formato .bmp, que actuará como icono. Como el diseño gráfico decididamente no es lo mío, he creado una imagen muy simple pero creo que bastante ilustrativa de la tarea que realiza el complemento: la propia etiqueta &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; que pretendemos crear. &lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Incrustar la imagen como recurso en el ensamblado" border="0" alt="Incrustar la imagen como recurso en el ensamblado" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/ShBDnMXJZ_I/AAAAAAAABDg/aWXOHL2Rwhs/image20.png?imgmax=800" width="176" height="222" /&gt; &lt;br /&gt;&lt;br /&gt;El archivo debemos incluirlo, para no tener problemas, en el directorio raíz del proyecto, y a continuación, hay que indicar a Visual Studio que dicha imagen será un recurso incrustado (&lt;em&gt;embedded resource&lt;/em&gt;) en el ensamblado. Este paso es importante, pues si no se hace correctamente, la imagen no será incluida en la DLL. &lt;br /&gt;&lt;br /&gt;A continuación es necesario indicar a Live Writer la imagen a utilizar como icono, lo que se consigue añadiendo un parámetro más (&lt;code&gt;ImagePath&lt;/code&gt;) en la definición del atributo &lt;code&gt;[WriterPlugin]&lt;/code&gt; con la ruta hacia el fichero que hemos incrustado. Eso sí, no me refiero a la ruta física del archivo .bmp, sino a la representación como espacio de nombres de la misma (por ejemplo, si la imagen se llama &lt;code&gt;logo.bmp&lt;/code&gt; y está en &lt;code&gt;(raíz)\recursos&lt;/code&gt;, la ruta hacia ella será &lt;code&gt;“recursos.logo.bmp”&lt;/code&gt;). &lt;br /&gt;&lt;br /&gt;Como en este caso hemos depositado la imagen en el directorio raíz, la declaración de atributos quedará como sigue: &lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:ef15dc02-a749-41f6-a25d-2d008e802a67" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;    [WriterPlugin(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;98497c2b-bbfd-4bd1-b343-226f3c9e766b&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Code Tag&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;        Description &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Crea etiquetas &amp;lt;code&amp;gt;&amp;lt;/code&amp;gt; en el contenido&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;        ImagePath &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;CodeTag.bmp&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;        PublisherUrl &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://www.variablenotfound.com&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;    [InsertableContentSource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Etiqueta &amp;lt;code&amp;gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; CodeTag : ContentSource&lt;br /&gt;    {&lt;br /&gt;      [...]&lt;br /&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;Un último apunte relativo a este tema: si al iniciar Live Writer éste es incapaz de localizar el recurso indicado en el parámetro &lt;code&gt;ImagePath&lt;/code&gt;, el plugin funcionará, pero aparecerá el siguiente mensaje en el arranque de la aplicación: &lt;br /&gt;&lt;br /&gt;&lt;img style="border-right-width: 0px; margin: 5px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Advertencia: no se ha podido cargar el mapa de bits para el complemento CodeTag desde la ruta especificada (CodeTag.bmp)" border="0" alt="Advertencia: no se ha podido cargar el mapa de bits para el complemento CodeTag desde la ruta especificada (CodeTag.bmp)" src="http://lh4.ggpht.com/_O9D62hXq-ng/ShBDn6IIJoI/AAAAAAAABDk/pueFBrl-B88/image6.png?imgmax=800" width="529" height="99" /&gt; &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;6. O, por si no quieres teclear…&lt;/h3&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CodeTag en el menú &amp;quot;insertar&amp;quot;, con icono" border="0" alt="CodeTag en el menú &amp;quot;insertar&amp;quot;, con icono" align="right" src="http://lh5.ggpht.com/_O9D62hXq-ng/ShBDopPGX2I/AAAAAAAABDo/LCnVeQq2stI/image112.png?imgmax=800" width="197" height="194" /&gt; … he colgado en SkyDrive el código fuente del proyecto, para el que quiera utilizarlo como base de creación de sus propios complementos, o simplemente para trastearlo un poco. &lt;br /&gt;&lt;br /&gt;Requiere, como mínimo, Visual C# 2008 Express, con su correspondiente Service Pack 1.&lt;br /&gt;&lt;iframe style="border-bottom: #dde5e9 1px solid; border-left: #dde5e9 1px solid; padding-bottom: 0px; background-color: white; margin: 3px; padding-left: 0px; width: 240px; padding-right: 0px; height: 66px; border-top: #dde5e9 1px solid; border-right: #dde5e9 1px solid; padding-top: 0px" marginheight="0" src="http://cid-c3a43a99b617d787.skydrive.live.com/embedrowdetail.aspx/P%c3%bablico/variablenotfound.com/Plugins%20Live%20Writer/CodeTag/CodeTag-src.zip" frameborder="0" marginwidth="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-1226820273611158423?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9sYk7hpNwkI81XO82yPqrlbvGQM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9sYk7hpNwkI81XO82yPqrlbvGQM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9sYk7hpNwkI81XO82yPqrlbvGQM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9sYk7hpNwkI81XO82yPqrlbvGQM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=W0uTAcBjdws:-n10g3m6ZEc:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=W0uTAcBjdws:-n10g3m6ZEc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=W0uTAcBjdws:-n10g3m6ZEc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=W0uTAcBjdws:-n10g3m6ZEc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=W0uTAcBjdws:-n10g3m6ZEc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=W0uTAcBjdws:-n10g3m6ZEc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=W0uTAcBjdws:-n10g3m6ZEc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=W0uTAcBjdws:-n10g3m6ZEc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=W0uTAcBjdws:-n10g3m6ZEc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/W0uTAcBjdws" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/1226820273611158423/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=1226820273611158423" title="1 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1226820273611158423?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1226820273611158423?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/W0uTAcBjdws/como-crear-un-plugin-sencillo-para-live.html" title="Cómo crear un plugin sencillo para Live Writer, paso a paso" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/06/como-crear-un-plugin-sencillo-para-live.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08MQXY9fSp7ImA9WxJQGUo.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-4844779139893468663</id><published>2009-06-02T23:58:00.000+02:00</published><updated>2009-06-02T23:58:00.865+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-02T23:58:00.865+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><category scheme="http://www.blogger.com/atom/ns#" term="trucos" /><category scheme="http://www.blogger.com/atom/ns#" term="programación" /><title>Cambiar la ubicación de las vistas en ASP.NET MVC</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="¡Menuda vista!" border="0" alt="¡Menuda vista!" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SfNhHIBnJwI/AAAAAAAABBo/BDstE4gm6Vg/image%5B20%5D.png?imgmax=800" width="228" height="172" /&gt; El framework ASP.NET MVC utiliza en varios puntos la filosofía que suele denominarse &lt;a title="Convención sobre configuración" href="http://es.wikipedia.org/wiki/Convenci%C3%B3n_sobre_Configuraci%C3%B3n"&gt;convención sobre configuración&lt;/a&gt;, ahorrando tiempo y esfuerzos al desarrollador que decida asumir una serie de normas preestablecidas, a la vez que facilita la homogeneidad y coherencia en las soluciones que las implementen.&lt;/p&gt;  &lt;p&gt;Por ejemplo, todos sabemos que las vistas de una aplicación ASP.NET MVC deben encontrarse en la carpeta &lt;code&gt;Views&lt;/code&gt;. Si se trata de una vista compartida como puede ser una página maestra, debemos colocarlas en la subcarpeta &lt;code&gt;Shared&lt;/code&gt;; en caso contrario, deberá existir una subcarpeta con el nombre del controlador en la que se encontrarán las vistas para las distintas acciones, nombradas igual que éstas. Esto, a la postre, evita que sea el desarrollador el que tenga que decidir dónde ubicar dichos archivos y configurar el sistema para que sea capaz de localizarlos cuando&amp;#160; sean necesarios: simplemente deberá seguir la convención preestablecida.&lt;/p&gt;  &lt;p&gt;Pero, ¿qué ocurre cuando estas convenciones no encajan con nuestras necesidades o preferencias?&lt;/p&gt;  &lt;p&gt;En este post voy a describir cómo es posible modificar la ubicación de las vistas en una aplicación ASP.NET MVC 1.0, saltándonos las convenciones establecidas por el framework. Pero sobre todo, ojo:&lt;/p&gt;  &lt;blockquote&gt;&lt;strong&gt;     &lt;p style="border-bottom: #c0c0c0 1px dotted; border-left: #c0c0c0 1px dotted; padding-bottom: 3px; margin-top: 3px; padding-left: 3px; padding-right: 3px; border-top: #c0c0c0 1px dotted; border-right: #c0c0c0 1px dotted; padding-top: 3px"&gt;Saltarse las convenciones = malo &lt;/p&gt;   &lt;/strong&gt;    &lt;p&gt;Hazlo sólo cuando realmente esté justificado... o por diversión, como es el caso ;-)&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;1. Cómo localiza ASP.NET MVC las vistas&lt;/h3&gt;  &lt;p&gt;Cada vez que el framework necesita localizar una vista, por ejemplo después de ejecutar una acción cuyo resultado indica que debe mostrarse al usuario una página,&amp;#160; recorre los directorios donde, por convención, se supone que debe estar. Esta información se encuentra definida a nivel de código en el constructor de la clase &lt;code&gt;&lt;a title="WebFormViewEngine, en MSDN" href="http://msdn.microsoft.com/en-us/library/system.web.mvc.webformviewengine.aspx"&gt;WebFormViewEngine&lt;/a&gt;&lt;/code&gt;, es decir, en el motor de vistas Webforms que se utiliza por defecto en ASP.NET MVC. Su definición es la siguiente (recordad que está &lt;a title="Descargar código fuente de ASP.NET MVC" href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471"&gt;disponible el código fuente&lt;/a&gt; del framework): &lt;/p&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" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:5cea829b-5555-48e5-910b-4fcba75cddfc" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebFormViewEngine : VirtualPathProviderViewEngine&lt;br /&gt;{&lt;br /&gt;  [...]&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebFormViewEngine()&lt;br /&gt;  {&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.MasterLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[]&lt;br /&gt;    { &lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Views/{1}/{0}.master&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Views/Shared/{0}.master&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    };&lt;br /&gt;      &lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.ViewLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] &lt;br /&gt;    { &lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Views/{1}/{0}.aspx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Views/{1}/{0}.ascx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Views/Shared/{0}.aspx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;br /&gt;      &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Views/Shared/{0}.ascx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;br /&gt;    };&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.PartialViewLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.ViewLocationFormats;&lt;br /&gt;  }&lt;br /&gt;  [...]&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;Como se puede observar, existen tres propiedades en el motor del vistas, heredadas de su antecesor, que indican los directorios donde se encuentran los archivos con la definición del interfaz: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;MasterLocationFormats&lt;/strong&gt; es un array con las rutas en las que se buscarán sucesivamente las páginas maestras. En el código puede verse que por defecto el sistema intentará localizar las masters en &lt;code&gt;~/Views &lt;/code&gt;y &lt;code&gt;~/Views/Shared&lt;/code&gt;; los parámetros {0} y {1} corresponden al nombre de la master y del controlador que están siendo buscados, respectivamente.&lt;p&gt;Es importante tener en cuenta que el valor de esta propiedad sólo se aplica cuando se establece desde el código la página maestra con la que debe ser mostrada una vista.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ViewLocationFormats&lt;/strong&gt; contiene las rutas donde se intentarán localizar las vistas. En la implementación por defecto, puede verse cómo el framework intenta localizar primero en &lt;code&gt;~/Views/{1}&lt;/code&gt; (recordad que este parámetro se sustituirá por el nombre del controlador) y luego en &lt;code&gt;~/Views/Shared &lt;/code&gt;una página .aspx o .ascx con el nombre de la vista (parámetro {0}).&amp;#160; &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Por último, &lt;strong&gt;PartialViewLocationFormats&lt;/strong&gt; indica las carpetas donde se deberán buscar las vistas parciales. Por defecto, se buscarán en los mismos directorios que las vistas normales. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;2. Lo que pretendemos&lt;/h3&gt;&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Nueva estructura de carpetas para las vistas" border="0" alt="Nueva estructura de carpetas para las vistas" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/SfNhHqBERTI/AAAAAAAABBs/iyEYzqq-KQA/image%5B16%5D.png?imgmax=800" width="151" height="71" /&gt;Una vez visto en qué se basa el framework para localizar las vistas, vamos al ataque.&amp;#160; Nuestra intención es saltarnos las convenciones creando una nueva estructura de carpetas para las mismas, como la que puede observarse en la imagen lateral. Existirá un directorio raíz, llamado &amp;quot;Interfaz&amp;quot;, en el que podemos encontrar dos subdirectorios: &amp;quot;Vistas&amp;quot; y &amp;quot;Masters&amp;quot;. En ellos almacenaremos, respectivamente, las vistas y las páginas maestras de nuestra aplicación.&lt;/p&gt;&lt;p&gt;La estructura de carpetas del proyecto será, por tanto, diferente a la propuesta por las plantillas de Visual Studio. Además, no tiene demasiado sentido, desde el punto de vista práctico, pero nos valdrá como ejemplo.&lt;/p&gt;&lt;p&gt;En los siguientes apartados vamos a ver dos formas distintas de conseguirlo.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;3. Cómo lograrlo&lt;/h3&gt;&lt;p&gt;La forma más sencilla de conseguir reemplazar las rutas de búsqueda de las vistas es, sin duda, alterar el contenido de las propiedades del motor descritas en el primer punto (&lt;code&gt;MasterLocationFormats&lt;/code&gt;, &lt;code&gt;ViewLocationFormats &lt;/code&gt;y &lt;code&gt;PartialViewLocationFormats&lt;/code&gt;). &lt;/p&gt;&lt;p&gt;Esto puede conseguirse introduciendo el siguiente código en la inicialización de la aplicación, en el archivo global.asax:&lt;/p&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:760b59cd-b2d7-4a20-b44d-b69e9ede82fa" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; MvcApplication : System.Web.HttpApplication&lt;br /&gt;{&lt;br /&gt;  [...]&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Application_Start()&lt;br /&gt;  {&lt;br /&gt;      ReplacePaths();   &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Reemplaza las rutas en el View Engine actual&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;      RegisterRoutes(RouteTable.Routes);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; ReplacePaths()&lt;br /&gt;  {&lt;br /&gt;      WebFormViewEngine eng &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; ViewEngines.Engines[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebFormViewEngine;&lt;br /&gt;      eng.MasterLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] { &lt;br /&gt;              &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Interfaz/Masters/{0}.master&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;          };&lt;br /&gt;       eng.ViewLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] { &lt;br /&gt;              &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Interfaz/Vistas/{0}.aspx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;              &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Interfaz/Vistas/{0}.ascx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;          };&lt;br /&gt;       eng.PartialViewLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; eng.ViewLocationFormats;&lt;br /&gt;  }&lt;br /&gt;  [...]&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;Como se observa en el código anterior, en el método &lt;code&gt;ReplacePaths()&lt;/code&gt; en primer lugar se obtiene una referencia al motor de vistas por defecto, que sabemos que es del tipo &lt;code&gt;WebFormViewEngine&lt;/code&gt;. Después, modificamos las propiedades para introducir las rutas que nos interesan. Tan simple como eso.&lt;/p&gt;&lt;p&gt;Es obvio que de esta forma estamos realizando una actualización &lt;em&gt;destructiva&lt;/em&gt; de las propiedades. Si quisiéramos mantener las localizaciones por defecto del &lt;code&gt;WebFormViewEngine &lt;/code&gt;pero añadir nuevas ubicaciones de búsqueda deberíamos copiar el contenido original del array, añadirle las rutas adicionales, y establecerlo en las propiedades.&lt;/p&gt;&lt;p&gt;Veamos otra forma de conseguir lo mismo. &lt;/p&gt;&lt;h3&gt;4. Cómo lograrlo, toma 2&lt;/h3&gt;&lt;p&gt;ASP.NET MVC framework ha sido diseñado desde sus orígenes con la extensibilidad en mente. Prácticamente cualquiera de sus comportamientos puede ser personalizado sustituyendo componentes como si se trataran de piezas de un &lt;a title="Mecano, en la wikipedia" href="http://es.wikipedia.org/wiki/Meccano"&gt;mecano&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Una de las posibilidades de extensión incluidas en la plataforma es la sustitución del motor de vistas que utiliza para componer los interfaces de usuario. Esto, llevado al extremo, permite la utilización de motores distintos al proporcionado por defecto (WebForms) y utilizar alternativas como &lt;a href="http://code.google.com/p/nhaml/"&gt;NHaml&lt;/a&gt;, &lt;a href="http://dev.dejardin.org/"&gt;Spark&lt;/a&gt;, &lt;a href="http://www.codeplex.com/MVCContrib/Wiki/View.aspx?title=Brail&amp;amp;referringTitle=Documentation"&gt;Brail&lt;/a&gt;, o &lt;a href="http://www.castleproject.org/others/nvelocity/index.html"&gt;NVelocity&lt;/a&gt;, entre otros. &lt;/p&gt;&lt;p&gt;Pero nosotros no iremos tan lejos. Para cumplir con nuestros objetivos simplemente necesitamos crear y registrar en el sistema un nuevo motor de vistas que herede de &lt;code&gt;WebFormViewEngine &lt;/code&gt;y reemplace la inicialización de las propiedades que definen la localización de las vistas.&lt;/p&gt;&lt;p&gt;El nuevo motor, al que llamaremos &lt;strong&gt;AcmeViewEngine&lt;/strong&gt;, será algo como lo siguiente:&lt;/p&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:8cc2254a-34c1-4888-9bc1-fdd4b22bb3a0" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; AcmeViewEngine : WebFormViewEngine&lt;br /&gt; {&lt;br /&gt;     &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; AcmeViewEngine()&lt;br /&gt;     {&lt;br /&gt;         MasterLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;             &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] { &lt;br /&gt;                 &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Interfaz/Masters/{0}.master&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;             };&lt;br /&gt;&lt;br /&gt;         ViewLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;             &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] { &lt;br /&gt;                 &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Interfaz/Vistas/{0}.aspx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;                 &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~/Interfaz/Vistas/{0}.ascx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;             };&lt;br /&gt;&lt;br /&gt;         PartialViewLocationFormats &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.ViewLocationFormats;&lt;br /&gt;     }&lt;br /&gt; }&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;Y ahora sólo nos faltaría registrar el motor de vistas en ASP.NET MVC framework, tarea que podemos realizar en el global.asax, así:&lt;/p&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:6054eae2-6550-4e5c-bf47-419b812205e7" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Application_Start()&lt;br /&gt;{&lt;br /&gt;   ReplaceViewEngine(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Registra el nuevo View Engine&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;   RegisterRoutes(RouteTable.Routes);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; ReplaceViewEngine()&lt;br /&gt;{&lt;br /&gt;   ViewEngines.Engines.Clear();&lt;br /&gt;   ViewEngines.Engines.Add(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; AcmeViewEngine());&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Observad que antes de añadir el nuevo motor de vistas a la colección estamos vaciándola (llamando a su método &lt;code&gt;Clear()&lt;/code&gt;), lo cual asegurará que nuestro &lt;code&gt;AcmeViewEngine &lt;/code&gt;será el utilizado por la plataforma.&lt;/p&gt;&lt;h3&gt;5. Conclusión&lt;/h3&gt;&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="No podremos saltar directamente a la vista desde el controlador" border="0" alt="No podremos saltar directamente a la vista desde el controlador" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SfNhIHmsS-I/AAAAAAAABBw/DAr5jxyyD6U/image%5B6%5D.png?imgmax=800" width="297" height="152" /&gt;Como ya he comentado al principio, saltarnos las convenciones no es buena idea. Por ejemplo, un daño colateral de romper con la convención propuesta por el framework MVC para la localización de las vistas es que Visual Studio no será capaz de proporcionarnos la función que nos&amp;#160; permite abrir la vista asociada con una acción seleccionando la opción “Go to View” del menú contextual, o intentará insistentemente crear las nuevas vistas (con la opción “Add View”) en las carpetas en las que deberían encontrarse según la convención.&lt;/p&gt;&lt;p&gt;Pero en cualquier caso, es un ejercicio interesante para conocer las interioridades de este framework y comprobar de primera mano la flexibilidad con la que ha sido implementado. &lt;/p&gt;&lt;p&gt;Si lo deseas, puedes descargar el código fuente de los ejemplos (requiere Visual Studio 2008 o Web Developer Express con SP1 y ASP.NET MVC 1.0):&lt;/p&gt;&lt;br /&gt;&lt;iframe style="border-bottom: #dde5e9 1px solid; border-left: #dde5e9 1px solid; padding-bottom: 0px; background-color: #ffffff; margin: 3px; padding-left: 0px; width: 240px; padding-right: 0px; height: 66px; border-top: #dde5e9 1px solid; border-right: #dde5e9 1px solid; padding-top: 0px" marginheight="0" src="http://cid-c3a43a99b617d787.skydrive.live.com/embedrowdetail.aspx/P%c3%bablico/variablenotfound.com/ASP.NET%20MVC/ASP.NET%20MVC%201.0/ChangingViewFolders.zip" frameborder="0" marginwidth="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-4844779139893468663?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3EcSDuXd01_PtNu3TfGvKvTgf3M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3EcSDuXd01_PtNu3TfGvKvTgf3M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3EcSDuXd01_PtNu3TfGvKvTgf3M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3EcSDuXd01_PtNu3TfGvKvTgf3M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=20djTU-PZEY:NjrOIQCM9Lc:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=20djTU-PZEY:NjrOIQCM9Lc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=20djTU-PZEY:NjrOIQCM9Lc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=20djTU-PZEY:NjrOIQCM9Lc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=20djTU-PZEY:NjrOIQCM9Lc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=20djTU-PZEY:NjrOIQCM9Lc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=20djTU-PZEY:NjrOIQCM9Lc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=20djTU-PZEY:NjrOIQCM9Lc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=20djTU-PZEY:NjrOIQCM9Lc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/20djTU-PZEY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/4844779139893468663/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=4844779139893468663" title="4 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/4844779139893468663?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/4844779139893468663?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/20djTU-PZEY/cambiar-la-ubicacion-de-las-vistas-en.html" title="Cambiar la ubicación de las vistas en ASP.NET MVC" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/06/cambiar-la-ubicacion-de-las-vistas-en.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MERncycSp7ImA9WxJQF0Q.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-3860530422631475763</id><published>2009-05-31T23:45:00.000+02:00</published><updated>2009-05-31T21:50:07.999+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-31T21:50:07.999+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="novedades" /><category scheme="http://www.blogger.com/atom/ns#" term="noticias" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><category scheme="http://www.blogger.com/atom/ns#" term="servicios on-line" /><title>Sintoniza la onda de Google</title><content type="html">&lt;p&gt;No sé si será un &lt;a title="Google Wave- el día que cambió la comunicación en la web" href="http://feedproxy.google.com/~r/ElBlogDeEnriqueDans/~3/rzXhpyMuGCk/google-wave-el-dia-que-cambio-la-comunicacion-en-la-web.html"&gt;cambio en la forma de comunicarse a través de la red&lt;/a&gt;, pero sin duda es una idea conceptualmente atractiva: unir en una única plataforma todas las conversaciones que mantenemos sobre Internet… pero entendiendo el término &lt;em&gt;conversación&lt;/em&gt; de una forma más amplia de lo habitual. &lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Mensajes tradicionales frente al concepto Google Waves" border="0" alt="Mensajes tradicionales frente al concepto Google Waves" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/SiLdf_tY1cI/AAAAAAAABE4/ri_rffxN78Q/image%5B7%5D.png?imgmax=800" width="119" height="216" /&gt;Mensajes de correo, foros, mensajería instantánea, compartición de imágenes y documentos, posts, comentarios en blogs, sus respuestas, twits, intercambio de mensajes vía redes sociales, documentos colaborativos en tiempo real, wikis, juegos… todo cabe en &lt;strong&gt;Google Wave&lt;/strong&gt;, la criatura en la que los hermanos Lars y Jens Rasmussen (famosos por haber creado Google Maps) llevan trabajando más de dos años, y que fue presentada hace unos días en el Google I/O.&lt;/p&gt;  &lt;p&gt;Básicamente, Google Wave es la respuesta a una serie de preguntas que se formularon al comienzo del proyecto:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;¿cómo sería el correo electrónico si hubiera sido inventado hoy, y no hace más de tres décadas? &lt;/li&gt;    &lt;li&gt;si en el fondo todo es comunicación, ¿por qué tenemos que diferenciar entre emails, chats, conversaciones o documentos? &lt;/li&gt;    &lt;li&gt;¿es posible que un único modelo de comunicaciones sea capaz de unir de forma sencilla los sistemas web que utilizamos hoy? &lt;/li&gt;    &lt;li&gt;dado que las herramientas de comunicación habituales son meros reflejos digitales de los procesos del mundo analógico (email vs. correo tradicional, mensajería instantánea vs. teléfono…), ¿cómo sería un sistema diseñado para beneficiarse de las capacidades de las redes y ordenadores actuales, en lugar de limitarse a emular los medios no electrónicos? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Pero no penséis que &lt;strong&gt;Google Wave&lt;/strong&gt; sólo es una aplicación más, como GMail o Google Reader, capaz de hacer de forma diferente cosas que ya se podían hacer antes. Se trata de un trío compuesto por tres elementos: producto, plataforma y protocolo:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SiLdhQ644LI/AAAAAAAABE8/6hzVndVluvk/image%5B12%5D.png?imgmax=800" width="283" height="186" /&gt; El producto, que es la aplicación cliente que mostraron en el evento, muy al estilo Google, desde la que se pueden iniciar y gestionar nuestras conversaciones. Se trata de una aplicación HTML5 construida sobre &lt;a title="Google Web Toolkit - Google Code" href="http://code.google.com/intl/es/webtoolkit/"&gt;Google Web Toolkit&lt;/a&gt;, que todavía sólo está disponible para un grupo reducido de desarrolladores, y que han confirmado que será &lt;em&gt;open source&lt;/em&gt;. &lt;/li&gt;    &lt;li&gt;La plataforma, el conjunto de APIs y especificaciones que permiten &lt;a title="Embedding Wave" href="http://code.google.com/intl/es/apis/wave/embed/index.html" hreflang="en"&gt;integrar&lt;/a&gt;&lt;a title="Embedding Wave" href="http://code.google.com/intl/es/apis/wave/embed/index.html"&gt;&lt;/a&gt; Wave en cualquier sistema web, o extenderlo mediante la creación de &lt;a title="Robots en Google Wave" href="http://code.google.com/intl/es/apis/wave/extensions/robots/index.html" hreflang="en"&gt;Robots&lt;/a&gt;&lt;a title="Robots en Google Wave" href="http://code.google.com/intl/es/apis/wave/extensions/robots/index.html"&gt;&lt;/a&gt; o &lt;a title="Gadgets en Google Wave" href="http://code.google.com/intl/es/apis/wave/extensions/gadgets/guide.html" hreflang="en"&gt;Gadgets&lt;/a&gt;&lt;a title="Gadgets en Google Wave" href="http://code.google.com/intl/es/apis/wave/extensions/gadgets/guide.html"&gt;&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;El protocolo, &lt;a title="Google Wave Federation Protocol" href="http://www.waveprotocol.org/draft-protocol-spec" hreflang="en"&gt;Google Wave Federation Protocol&lt;/a&gt;&lt;a title="Google Wave Federation Protocol" href="http://www.waveprotocol.org/draft-protocol-spec"&gt;&lt;/a&gt;, aún en borrador, se encuentra definido en una serie de documentos que detallan su arquitectura, el modelo de datos, las comunicaciones entre clientes y servidores y, en general, toda la información necesaria para que &lt;em&gt;puedan existir distintas implementaciones del servicio&lt;/em&gt;. De hecho, el producto de Google será únicamente una implementación de referencia. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Esta nueva forma de colaboración gira en torno a la figura del Wave, que según dicen los entendidos es una mezcla entre una conversación y un documento sobre los que trabajan de forma colaborativa una serie de participantes. Y la verdad, tiene un aire a las conversaciones de GMail, y también a la edición multiusuario de Google Docs, pero va bastante más allá. Un Wave puede contener mensajes, comentarios, anotaciones y elementos más avanzados, como mapas, encuestas, juegos, o tomar datos desde otras aplicaciones y servicios, como blogs, twits, foros, sistemas de seguimiento de errores, y todo integrado dentro de un mismo contexto (la conversación). La cuestión es tener agrupadas todas las comunicaciones relativas a un mismo tema en un único punto.&lt;/p&gt;  &lt;p&gt;Además, los participantes no tienen que ser necesariamente humanos, es decir, por ejemplo es posible que en un Wave intervenga un robot que se encargue de ir traduciendo los mensajes al idioma de cada participante, lo cual abre unas posibilidades inimaginables. En el vídeo al que hago referencia abajo hay una demo de Rosy, un robot traductor muy apañado que realiza estas funciones.&lt;/p&gt;  &lt;p&gt;Otro aspecto interesante es la facilidad para organizar la información, y me ha gustado mucho la capacidad de temporalizar las conversaciones, de forma que sea posible reproducir la secuencia de aportaciones realizadas al Wave por cada uno de los participantes.&lt;/p&gt;  &lt;p&gt;Si tenéis una horita y media libre, y podéis haceros de coca-cola y palomitas, no os perdáis el vídeo de la presentación del producto de mano de sus responsables. Muy divertida y sin duda espectacular. Eso sí, si no domináis el inglés, tendréis que activar vuestro &lt;em&gt;modo de inferencia lingüística&lt;/em&gt;, ese que se encarga de rellenar con la imaginación las expresiones que no llegamos a comprender&lt;em&gt; ;-)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px auto; padding-left: 0px; width: 512px; padding-right: 0px; display: block; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:3b08a57f-f4f1-4636-95dc-7d93f4a89659" class="wlWriterEditableSmartContent"&gt;&lt;div id="ead5f75c-bfd1-4940-8a59-562b7659d3d3" style="margin: 0px; padding: 0px; display: inline;"&gt;&lt;div&gt;&lt;a href="http://www.youtube.com/watch?v=v_UyVmITiYQ&amp;amp;hl=es&amp;amp;fs=1" target="_new"&gt;&lt;img src="http://lh4.ggpht.com/_O9D62hXq-ng/SiLeVD19I9I/AAAAAAAABFE/oHLfQmW3n1E/video581975032326%5B2%5D.jpg?imgmax=800" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('ead5f75c-bfd1-4940-8a59-562b7659d3d3'); downlevelDiv.innerHTML = &amp;quot;&amp;lt;div&amp;gt;&amp;lt;object width=\&amp;quot;512\&amp;quot; height=\&amp;quot;384\&amp;quot;&amp;gt;&amp;lt;param name=\&amp;quot;movie\&amp;quot; value=\&amp;quot;http://www.youtube.com/v/v_UyVmITiYQ&amp;amp;hl=es&amp;amp;fs=1&amp;amp;hl=en\&amp;quot;&amp;gt;&amp;lt;\/param&amp;gt;&amp;lt;embed src=\&amp;quot;http://www.youtube.com/v/v_UyVmITiYQ&amp;amp;hl=es&amp;amp;fs=1&amp;amp;hl=en\&amp;quot; type=\&amp;quot;application/x-shockwave-flash\&amp;quot; width=\&amp;quot;512\&amp;quot; height=\&amp;quot;384\&amp;quot;&amp;gt;&amp;lt;\/embed&amp;gt;&amp;lt;\/object&amp;gt;&amp;lt;\/div&amp;gt;&amp;quot;;" alt=""&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;p&gt;Se dice que Wave estará disponible a finales de año. En este momento, lo más que podéis hacer es &lt;a href="https://services.google.com/fb/forms/wavesignup/"&gt;solicitar que os tengan en consideración&lt;/a&gt; cuando lo abran al público.&lt;/p&gt;  &lt;p&gt;Enlaces interesantes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="Google Wave, todo lo que tienes que saber" href="http://www.cristalab.com/blog/google-wave-todo-lo-que-tienes-que-saber-c73716l/"&gt;Google Wave, todo lo que tienes que saber (Cristalab)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="¿Qué significa Google Wave" href="http://www.maestrosdelweb.com/actualidad/google-wave/"&gt;¿Qué significa Google Wave? (Maestros del Web)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="Google Wave lo nuevo de Google  Jorge Oyhenard" href="http://www.jorgeoyhenard.com/google-wave-lo-nuevo-de-google/1225/"&gt;Google Wave: lo nuevo de Google (Jorge Oyhenard&lt;/a&gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Más enlaces interesantes (en inglés):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Sitio oficial: &lt;a title="Google Wave Preview" href="http://wave.google.com/"&gt;Google Wave&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="Introduction ‎(Google Wave Federation Protocol)‎" href="http://www.waveprotocol.org/"&gt;Google Wave Federation Protocol&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="Official Google Blog Went Walkabout. Brought back Google Wave" href="http://googleblog.blogspot.com/2009/05/went-walkabout-brought-back-google-wave.html"&gt;Official Google Blog Went Walkabout. Brought back Google Wave&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="Google Wave Developer Blog Introducing the Google Wave APIs what can you build" href="http://googlewavedev.blogspot.com/2009/05/introducing-google-wave-apis-what-can.html"&gt;Google Wave Developer Blog: Introducing the Google Wave APIs: what can you build&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a title="Google Wave API - Google Code" href="http://code.google.com/intl/es/apis/wave/"&gt;Google Wave API - Google Code&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-3860530422631475763?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/92VatrnSpBBq-xyEWtBweFevMGY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/92VatrnSpBBq-xyEWtBweFevMGY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/92VatrnSpBBq-xyEWtBweFevMGY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/92VatrnSpBBq-xyEWtBweFevMGY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=h9DQ-fVfM2c:vXmjNdW9r-M:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=h9DQ-fVfM2c:vXmjNdW9r-M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=h9DQ-fVfM2c:vXmjNdW9r-M:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=h9DQ-fVfM2c:vXmjNdW9r-M:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=h9DQ-fVfM2c:vXmjNdW9r-M:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=h9DQ-fVfM2c:vXmjNdW9r-M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=h9DQ-fVfM2c:vXmjNdW9r-M:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=h9DQ-fVfM2c:vXmjNdW9r-M:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=h9DQ-fVfM2c:vXmjNdW9r-M:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/h9DQ-fVfM2c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/3860530422631475763/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=3860530422631475763" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3860530422631475763?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3860530422631475763?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/h9DQ-fVfM2c/sintoniza-la-onda-de-google.html" title="Sintoniza la onda de Google" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/sintoniza-la-onda-de-google.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUACSXcyeip7ImA9WxJQFE0.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-2912735278759021734</id><published>2009-05-26T23:48:00.001+02:00</published><updated>2009-05-27T09:02:48.992+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-27T09:02:48.992+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="proyectos" /><category scheme="http://www.blogger.com/atom/ns#" term="herramientas" /><category scheme="http://www.blogger.com/atom/ns#" term="blogging" /><category scheme="http://www.blogger.com/atom/ns#" term="software libre" /><title>Plugin para insertar etiquetas &lt;code&gt; en Live Writer</title><content type="html">&lt;p&gt;Desde hace unos meses estoy escribiendo las entradas de &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable Not Found&lt;/a&gt; desde &lt;a title="Windows Live Writer" href="http://www.variablenotfound.com/2009/03/windows-live-writer.html"&gt;Windows Live Writer&lt;/a&gt;, y la verdad es que estoy encantado con esta herramienta. Pero como &lt;a title="Nadie es perfecto, Con faldas y a lo loco (1959)" href="http://www.youtube.com/watch?v=NnUNegRiP14"&gt;nadie es perfecto&lt;/a&gt;, me he encontrado con ocasiones en las que tengo que acceder y retocar a mano el código fuente de la página para que el resultado sea el que pretendo.&lt;/p&gt;  &lt;p&gt;Me suele ocurrir, por ejemplo, cuando inserto pequeñas porciones de código fuente en mitad de una frase, pues siempre me ha gustado rodear este tipo de textos por las correspondientes etiquetas &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; y &lt;code&gt;&amp;lt;/code&amp;gt;&lt;/code&gt;. Esto, además de ser un marcado semánticamente más correcto, me permite modificar la forma en que se muestra desde CSS, estableciéndole, por ejemplo, una tipografía de ancho fijo.&lt;/p&gt;  &lt;p&gt;Para no tener que hacerlo más a mano, he creado un pequeño plugin para &lt;a title="Descargar Live Writer" href="http://download.live.com/writer" target="_blank"&gt;Live Writer&lt;/a&gt; que permite seleccionar un texto y envolverlo automáticamente por dichas etiquetas, y he pensado que quizás pueda serle útil a alguien más.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SficoyJLicI/AAAAAAAABCQ/F7XPrDtobsE/image3.png?imgmax=800" width="145" height="179" /&gt; La criatura se llama “&lt;strong&gt;CodeTag&lt;/strong&gt;”, y la podéis descargar desde el enlace de más abajo. Para instalarla en vuestro Live Writer, simplemente debéis descomprimir el archivo y copiar CodeTag.dll a la carpeta &lt;code&gt;Plugins&lt;/code&gt; dentro del directorio donde hayáis instalado la herramienta (en mi caso, la ruta completa es &lt;code&gt;C:\Archivos de programa\Windows Live\Writer\Plugins&lt;/code&gt;). &lt;/p&gt;  &lt;p&gt;Seguidamente, reiniciáis Live Writer y listo, veréis que en la barra lateral y el menú “insertar” ha aparecido la opción “Etiqueta &amp;lt;code&amp;gt;”, que os permitirá realizar el proceso descrito anteriormente.&lt;/p&gt;  &lt;p&gt;En breve publicaré un post describiendo paso a paso cómo se crea un plugin para Live Writer, y veréis lo sencillo que resulta hacer estas pequeñas herramientas de productividad.&lt;/p&gt; &lt;iframe style="border-bottom: #dde5e9 1px solid; border-left: #dde5e9 1px solid; padding-bottom: 0px; background-color: #ffffff; margin: 3px; padding-left: 0px; width: 240px; padding-right: 0px; height: 66px; border-top: #dde5e9 1px solid; border-right: #dde5e9 1px solid; padding-top: 0px" marginheight="0" src="http://cid-c3a43a99b617d787.skydrive.live.com/embedrowdetail.aspx/P%c3%bablico/variablenotfound.com/Plugins%20Live%20Writer/CodeTag/CodeTag-bin.zip" frameborder="0" marginwidth="0" scrolling="no"&gt;&lt;/iframe&gt;  &lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-2912735278759021734?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UDhw9R7wur3fdoOLRslmeZVTfus/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UDhw9R7wur3fdoOLRslmeZVTfus/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UDhw9R7wur3fdoOLRslmeZVTfus/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UDhw9R7wur3fdoOLRslmeZVTfus/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=9Wojzc7ezn0:njyUQgR-spo:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=9Wojzc7ezn0:njyUQgR-spo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=9Wojzc7ezn0:njyUQgR-spo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=9Wojzc7ezn0:njyUQgR-spo:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=9Wojzc7ezn0:njyUQgR-spo:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=9Wojzc7ezn0:njyUQgR-spo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=9Wojzc7ezn0:njyUQgR-spo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=9Wojzc7ezn0:njyUQgR-spo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=9Wojzc7ezn0:njyUQgR-spo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/9Wojzc7ezn0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/2912735278759021734/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=2912735278759021734" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2912735278759021734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2912735278759021734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/9Wojzc7ezn0/plugin-para-insertar-etiquetas-en-live.html" title="Plugin para insertar etiquetas &amp;lt;code&amp;gt; en Live Writer" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/plugin-para-insertar-etiquetas-en-live.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IEQXY_cSp7ImA9WxJQEk0.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-3850340180729181243</id><published>2009-05-24T23:45:00.004+02:00</published><updated>2009-05-24T23:45:00.849+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-24T23:45:00.849+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vs2008" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><category scheme="http://www.blogger.com/atom/ns#" term="trucos" /><category scheme="http://www.blogger.com/atom/ns#" term="programación" /><title>Compilar las vistas en ASP.NET MVC</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Yellow Screen of Death" border="0" alt="Yellow Screen of Death" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SgR1XiQ8TPI/AAAAAAAABC4/plYPyED3xK4/image%5B8%5D.png?imgmax=800" width="232" height="83" /&gt; El código introducido en las vistas ASP.NET MVC pueden ser fuente de problemas en tiempo de ejecución debido a que, por defecto, no se compilan con el proyecto, sino cuando el sistema necesita mostrarlas por primera vez. Es decir, es perfectamente posible que errores de codificación en un archivo .ASPX no sean detectados hasta el momento de su ejecución, provocando un &lt;a title="Yellow Screen of Death" href="http://en.wikipedia.org/wiki/Screens_of_death#ASP.NET" hreflang="en"&gt;YSOD&lt;/a&gt;&lt;a title="Yellow Screen of Death" href="http://en.wikipedia.org/wiki/Screens_of_death#ASP.NET"&gt;&lt;/a&gt; de los de toda la vida.&lt;/p&gt;  &lt;p&gt;Un ejemplo. Imaginemos una vista tipada (en un archivo .ASPX) en la que hemos incluido el siguiente código,&lt;em&gt; perfectamente válido…&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&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" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:5d049fea-50da-48b3-a037-217cd68838f3" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;@ Page Language&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;C#&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; MasterPageFile&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;~/Views/Shared/Site.Master&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; &lt;br /&gt;         Inherits&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;System.Web.Mvc.ViewPage&amp;lt;Persona&amp;gt;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;[...]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Datos personales&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;Nombre: &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt; this.Model.Nombre &lt;/span&gt;&lt;span style="background-color: #FFFF00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;[...]&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;em&gt;… perfectamente válido&lt;/em&gt; mientras la clase &lt;code&gt;Persona&lt;/code&gt; tenga una propiedad que se llame &lt;code&gt;Nombre&lt;/code&gt;. Si eliminamos esta propiedad o simplemente cambiamos su nombre, la refactorización automática del IDE no se realizará sobre el código de la vista, y se generará un error en ejecución en cuanto intentemos acceder a ella, es decir, &lt;strong&gt;estaremos llevando a tiempo de ejecución problemas propios del tiempo de compilación.&lt;/strong&gt;&lt;p&gt;Afortunadamente, ASP.NET MVC framework incluye un mecanismo que nos permite forzar la compilación de las vistas y, así, detectar estos problemas de forma temprana, antes de poner el sitio en producción. &lt;/p&gt;&lt;p&gt;Para activarlo, lo primero que hay que hacer es abrir el archivo del proyecto (.csproj o .vbproj) con cualquier editor de textos, como el block de notas, localizar en las primeras líneas el comienzo de la sección &lt;code&gt;PropertyGroup, &lt;/code&gt;e insertar justo después la declaración que habilita la compilación de las vistas:&lt;/p&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:cf2daa20-08af-40d2-b614-3a9f0df5cbfd" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;MvcBuildViews&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;true&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;MvcBuildViews&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;   [...]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Ojo a un detalle: es posible que en algún punto del archivo del proyecto exista una declaración que anule la anterior así: &lt;code&gt;&amp;lt;MvcBuildViews&amp;gt;false&amp;lt;/MvcBuildViews&amp;gt;&lt;/code&gt;. Debéis eliminar esa línea, pues de lo contrario no se activará esta característica.&lt;/p&gt;&lt;p&gt;Acto seguido, debemos asegurarnos de que exista el siguiente código cerca del final del archivo; en mi caso ya existía, pero si no es así debemos insertarlo, por ejemplo, justo antes del cierre del documento (en la línea anterior a &lt;code&gt;&amp;lt;/Projects&amp;gt;&lt;/code&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" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3d0a91dd-bb7d-4284-8c15-99a8a26c3e8a" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Target &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="AfterBuild"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; Condition&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="'$(MvcBuildViews)'=='true'"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;AspNetCompiler &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;VirtualPath&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="temp"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; &lt;br /&gt;                   PhysicalPath&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="$(ProjectDir)\..\$(ProjectName)"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Target&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;Una vez guardado el archivo, recargamos la solución en Visual Studio, y listo. Eso sí, a partir de este momento tendremos que esperar un poco más durante la generación del proyecto, pero la seguridad que aporta bien vale la pena.&lt;/p&gt;&lt;p&gt;Fuente: &lt;a title="Compile Views in ASP.NET MVC - Stack Overflow" href="http://stackoverflow.com/questions/383192/compile-views-in-asp-net-mvc" hreflang="en"&gt;Compile Views in ASP.NET MVC - Stack Overflow&lt;/a&gt;&lt;a title="Compile Views in ASP.NET MVC - Stack Overflow" href="http://stackoverflow.com/questions/383192/compile-views-in-asp-net-mvc"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-3850340180729181243?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UEkZFOwxfqVU42tGHdcUAspqgSQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UEkZFOwxfqVU42tGHdcUAspqgSQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UEkZFOwxfqVU42tGHdcUAspqgSQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UEkZFOwxfqVU42tGHdcUAspqgSQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cjxlTzhZ0PQ:fWpnh4xgJnk:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cjxlTzhZ0PQ:fWpnh4xgJnk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cjxlTzhZ0PQ:fWpnh4xgJnk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cjxlTzhZ0PQ:fWpnh4xgJnk:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=cjxlTzhZ0PQ:fWpnh4xgJnk:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cjxlTzhZ0PQ:fWpnh4xgJnk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=cjxlTzhZ0PQ:fWpnh4xgJnk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cjxlTzhZ0PQ:fWpnh4xgJnk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=cjxlTzhZ0PQ:fWpnh4xgJnk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/cjxlTzhZ0PQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/3850340180729181243/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=3850340180729181243" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3850340180729181243?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3850340180729181243?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/cjxlTzhZ0PQ/compilar-las-vistas-en-aspnet-mvc.html" title="Compilar las vistas en ASP.NET MVC" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/compilar-las-vistas-en-aspnet-mvc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MMQXs9fip7ImA9WxJRGEg.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-4441232237590637271</id><published>2009-05-20T23:38:00.000+02:00</published><updated>2009-05-20T23:38:00.566+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-20T23:38:00.566+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xhtml" /><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><category scheme="http://www.blogger.com/atom/ns#" term="programación" /><category scheme="http://www.blogger.com/atom/ns#" term="css" /><title>Cómo depurar selectores jQuery</title><content type="html">&lt;p&gt;&lt;a href="http://www.odetocode.com/"&gt;&lt;/a&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="jQuery" border="0" alt="jQuery" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SdpMPp7yG8I/AAAAAAAABA0/OrHi6p0c2Og/image%5B4%5D.png?imgmax=800" width="240" height="75" /&gt;El gran &lt;a href="http://odetocode.com/Blogs/scott/default.aspx" hreflang="en"&gt;K. Scott Allen&lt;/a&gt; comentaba hace unas semanas en &lt;a title="OdeToCode" href="http://www.odetocode.com/" hreflang="en"&gt;OdeToCode&lt;/a&gt; un pequeño truco que puede resultar de utilidad cuando tengamos un código &lt;a title="jQuery" href="http://jquery.org" hreflang="en"&gt;jQuery&lt;/a&gt; que no funcione correctamente.&lt;/p&gt;  &lt;p&gt;Como comenta el autor, la mayoría de los problemas con jQuery se deben a un uso incorrecto de los potentes &lt;a title="Selectores jQuery" href="http://docs.jquery.com/Selectors" hreflang="en"&gt;selectores&lt;/a&gt;, así que lo que propone es el uso de la consola &lt;em&gt;javascript&lt;/em&gt; incluida en algunas herramientas como &lt;a title="Firebug" href="https://addons.mozilla.org/es-ES/firefox/addon/1843"&gt;Firebug&lt;/a&gt; (para Firefox) o las propias herramientas de desarrollo incluidas en Internet Explorer 8 (geniales, por cierto).&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Consola en Firebug" border="0" alt="Consola en Firebug" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/SdpMQvXFNEI/AAAAAAAABA4/iJEgRBFAPME/image%5B20%5D.png?imgmax=800" width="385" height="202" /&gt;Esta consola permite en ambos casos introducir instrucciones javascript de forma directa, que serán ejecutadas en el contexto de la página actual como si formaran parte del código de las mismas. Por tanto, en aquellas páginas en las que se incluido jQuery, será posible ejecutar llamadas y selecciones a lo largo del &lt;a title="Document Object Model, en Wikipedia" href="http://es.wikipedia.org/wiki/DOM"&gt;DOM&lt;/a&gt; y observar el resultado de forma interactiva.&lt;/p&gt;  &lt;p&gt;En la imagen adjunta se ve cómo podemos ir realizando consultas con selectores e ir observando sus resultados con Firebug. Hay que tener en cuenta que la mayoría de operaciones de selección con jQuery retornan una colección con los elementos encontrados, por eso podemos utilizar &lt;code&gt;length &lt;/code&gt;para obtener el número de coincidencias. Pero no sólo eso, podríamos utilizar expresiones como la siguiente para mostrar por consola el texto contenido en las etiquetas que cumplan el criterio: &lt;/p&gt;  &lt;pre&gt;&lt;code&gt;$(&amp;quot;div &amp;gt; a&amp;quot;).each(function() { console.log($(this).text()) })&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Y más aún, si lo que queremos es obtener una representación visual sobre la propia página, podemos alterar los elementos o destacarlos con cualquiera de los métodos de manipulación disponibles en jQuery, por ejemplo:&lt;/p&gt;&lt;pre&gt;&lt;p&gt;&lt;code&gt;$(&amp;quot;a:contains['sex']&amp;quot;).css(&amp;quot;background-color&amp;quot;, &amp;quot;yellow&amp;quot;)&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;La siguiente captura muestra el resultado de una consulta realizada con las herramientas de desarrollo incluidas en Internet Explorer 8: &lt;img style="border-right-width: 0px; margin: 5px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Consola en IE8" border="0" alt="Consola en IE8" src="http://lh4.ggpht.com/_O9D62hXq-ng/SdpMRJJB78I/AAAAAAAABA8/qPz5kRGMsgI/image%5B28%5D.png?imgmax=800" width="622" height="250" /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;En fin, un pequeño truco para facilitarnos un poco la vida.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Fuente: &lt;a title="What I Do When My jQuery Code Doesn’t Work" href="http://odetocode.com/Blogs/scott/archive/2009/03/12/12643.aspx" hreflang="en"&gt;What I Do When My jQuery Code Doesn’t Work&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-4441232237590637271?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/94py0FzAaZoroJ6_LtaH9U5I5Eg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/94py0FzAaZoroJ6_LtaH9U5I5Eg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/94py0FzAaZoroJ6_LtaH9U5I5Eg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/94py0FzAaZoroJ6_LtaH9U5I5Eg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=fXIKwcSfE4g:eOcgwTKB1BU:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=fXIKwcSfE4g:eOcgwTKB1BU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=fXIKwcSfE4g:eOcgwTKB1BU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=fXIKwcSfE4g:eOcgwTKB1BU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=fXIKwcSfE4g:eOcgwTKB1BU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=fXIKwcSfE4g:eOcgwTKB1BU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=fXIKwcSfE4g:eOcgwTKB1BU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=fXIKwcSfE4g:eOcgwTKB1BU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=fXIKwcSfE4g:eOcgwTKB1BU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/fXIKwcSfE4g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/4441232237590637271/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=4441232237590637271" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/4441232237590637271?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/4441232237590637271?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/fXIKwcSfE4g/como-depurar-selectores-jquery.html" title="Cómo depurar selectores jQuery" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/como-depurar-selectores-jquery.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMMQH8zeyp7ImA9WxJRFkw.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-3041552074621912393</id><published>2009-05-18T05:48:00.001+02:00</published><updated>2009-05-18T05:48:01.183+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-18T05:48:01.183+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="curiosidades" /><category scheme="http://www.blogger.com/atom/ns#" term="humor" /><category scheme="http://www.blogger.com/atom/ns#" term="frases célebres" /><title>Y todavía otras 101 citas célebres del mundo de la informática</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Pensador" border="0" alt="Pensador" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SfiFykpIqII/AAAAAAAABCI/YAiwV-5oy3U/image4.png?imgmax=800" width="184" height="244" /&gt;Ha transcurrido un año desde que publiqué mi recopilación de &lt;a title="Otras 101 citas célebres del mundo de la informática" href="http://www.variablenotfound.com/2008/04/otras-101-citas-clebres-del-mundo-de-la.html"&gt;citas célebres del mundo de la informática&lt;/a&gt;, como continuación de la serie iniciada originalmente por el amigo Timm Martin en &lt;a href="http://www.devtopics.com/101-great-computer-programming-quotes/" title="101 great computer programming quotes" hreflang="en"&gt;DevTopics&lt;/a&gt;. Desde entonces he ido anotando todas las citas que me llamaban la atención, hasta que por fin he llegado al número mágico y puedo publicar el tercer post de la serie que tanto me divierte. Que aproveche.&lt;/p&gt;  &lt;h3&gt;Desarrollo de software&lt;/h3&gt;  &lt;p&gt;1. “Cualquier problema en ciencias de la computación puede ser solucionado con otra capa de indirección… pero usualmente creará otro problema”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- David Wheeler &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;2. “Hay únicamente dos problemas realmente duros en informática: el primero es la invalidación de cachés, y el segundo darles nombres apropiados a las cosas”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Phil Karlton &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;3. “Una documentación voluminosa es parte del problema, no de la solución”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Tom DeMarco &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;4. “Compatibilidad significa repetir deliberadamente los errores de otras personas”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- David Wheeler&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;5. “Cuando te enfrentes a la ambigüedad, no caigas la tentación de adivinar”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Guido van Rossum &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Usuarios y usabilidad&lt;/h3&gt;  &lt;p&gt;6. “‘Usuario’ es la palabra que usan los profesionales de la informática cuando quieren decir idiota”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Dave Barry &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;7. “Me siento frente a la condenada pantalla del ordenador todo el día, varios días, semana tras semana, y pienso: tío, si pudieras tan sólo encontrar el interruptor de encendido…”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Zachary Good &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;8. “Un error frecuente que comete la gente cuando intenta diseñar algo a prueba de tontos es que subestiman la ingenuidad de los tontos“    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Douglas Adams &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;9. “Estas máquinas no tienen sentido común; todavía no han aprendido a pensar, sólo hacen exactamente lo que se les ordena, ni más ni menos. Este hecho es el concepto más difícil de entender la primera vez que se utiliza un ordenador”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Donald Knuth &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;10. “Ordenador, mata a Flanders”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Homer Simpson &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;11. “La última prueba que me gustaría proponerle para medir la usabilidad es realmente simple: si el sistema fuera una persona, ¿cuánto tiempo tardarías en golpearle en la nariz?”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Tom Carey &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;12. “La base de usuarios de sistemas criptográficos fuertes se reduce a la mitad por cada pulsación de tecla o click de ratón requerido para hacerlos funcionar“    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Carl Ellison &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Errores&lt;/h3&gt;  &lt;p&gt;13. “Cuidado con los errores en el código anterior; sólo he demostrado que es correcto, no lo he probado”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Donald Knuth &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;14. &amp;quot;No hay en nuestro software un número significativo de errores que un número significativo de usuarios necesite ver resueltos&amp;quot;    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Bill Gates, 1995 &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;15. “Cometer fallos es humano. Y echarle las culpas a un ordenador, aún más”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Robert Orben &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;16. “Si tu proyecto no funciona, busca en la parte que no pensaste que fuera importante“    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Arthur Bloch &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;17. “No me culpes. Solo soy un intérprete. No sabia que el enchufe de energía llegaba a esta terminal de computadora”&amp;#160;&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- C3PO, después de freír a R2D2&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;18. “Cualquier bug lo suficientemente avanzado es indistinguible de una funcionalidad”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Rich Kulawiec&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;19. “A veces vale más la pena quedarse en la cama el lunes que pasar el resto de la semana depurando el código que creaste el lunes”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; -- &lt;cite&gt;Dan Salomon&lt;/cite&gt;&lt;/p&gt;  &lt;p&gt;20. “Una solución elegante a un problema incorrecto no resuelve nada”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- M. Bryce &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;21. “Nunca cometo errores estúpidos. Sólo errores inteligentes, muy inteligentes”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Dr. Who &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;22. “Hay una cosa peor que un programa que no funciona como debe: un programa que funciona como no debe”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Bob Archer &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Trabajo en equipo&lt;/h3&gt;  &lt;p&gt;23. “Siempre he encontrado los planes inútiles, pero la planificación es indispensable”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Dwight Eisenhower &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;24. “Eliminar a un mal desarrollador del equipo de un proyecto es a menudo más productivo que añadir un desarrollador bueno”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Tom DeMarco &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;25. “Incluir trabajadores en un proyecto retrasado hará que éste avance aún más lentamente”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Ley de Brooks &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;26. “Un grupo es un montón de gente en un ascensor. Un equipo es un montón de gente en un ascensor, ¡pero con el ascensor roto!”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Bonnie Edelstein &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;27. “Ninguno de nosotros es tan inteligente como todos nosotros”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Ken Blanchard &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Conocimiento&lt;/h3&gt;  &lt;p&gt;28. “Mi definición de un experto en cualquier campo es una persona que sabe lo suficiente sobre la realidad como para estar asustado”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- P.J. Plauger &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;29. “La inteligencia consiste no sólo en el conocimiento, sino también en la destreza de aplicar los conocimientos en la práctica”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Aristóteles &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;30. “Hay tres maneras de adquirir sabiduría: primero, por la reflexión, que es la más noble; segundo, por imitación, que es la más sencilla; y tercero, por la experiencia, que es la más amarga”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Confucio &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;31. “Los elementos más comunes en el universo son el hidrógeno y la estupidez”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Harlan Ellison &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;32. “Tengo que dejar de hablar. Ya te he contado más de lo que sé”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Wolf Logan &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;33. “Un experto es una persona que ha cometido todos los errores posibles en un determinado terreno”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Niels Bohr &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;34. “No podemos solucionar problemas usando el mismo razonamiento que usamos cuando los creamos”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;--Albert Einstein &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;35. “No hay parche que corrija la estupidez”&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- Kevin Mitnick &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;36. “Solía pensar que el cerebro era el órgano más importante del cuerpo, hasta que me di cuenta de quién era el que me estaba diciendo eso”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Emo Philips &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Inteligencia artificial&lt;/h3&gt;  &lt;p&gt;37. “Dentro de 30 años tendremos los medios tecnológicos para crear una inteligencia superhumana… Algún tiempo después, la era humana habrá terminado”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Vernor Vinge &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;38. “Algunos se preocupan de que la inteligencia artificial pueda hacer que nos sintamos inferiores, pero entonces cualquiera en su sano juicio debería sentir complejo de inferioridad cada vez que mirase a una flor”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Alan Kay &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;39. “No le atribuyas cualidades humanas a los ordenadores. No les gusta”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- anónimo&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;40. “Lo siento, Dave. No puedo hacer eso”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- HAL 9000 &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;41. “La inteligencia artificial nunca podrá competir con la estupidez natural”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- anónimo &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;42. “El esfuerzo de utilizar las máquina para emular el pensamiento humano siempre me ha parecido bastante estúpido. Preferiría usarlas para emular algo mejor”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Edsger Dijkstra &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Creatividad&lt;/h3&gt;  &lt;p&gt;43. &amp;quot;Yo lo inventé, Bill lo hizo famoso&amp;quot;    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- David Bradley, &lt;a title="El hombre que inventó el Control-Alt-Suprimir" href="http://www.variablenotfound.com/2009/04/el-hombre-que-invento-el-control-alt.html"&gt;el hombre que inventó el Control-Alt-Suprimir&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;44. “No te preocupes de que la gente te pueda robar una idea. Si es original, se la harás tragar a la fuerza”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Howard Aiken, creador del Mark I. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;45. “Hacer lo simple complicado es bastante corriente; hacer lo complicado simple, sorprendentemente simple, eso es la creatividad”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Charles Mingus &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Desarrolladores&lt;/h3&gt;  &lt;p&gt;46. “Los hombres de verdad no hacen copias de seguridad. Publican sus cosas en servidores FTP públicos, y dejan que el resto del mundo las copie”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- Linus Torvald, desarrollador del Linux &lt;/em&gt;&lt;/p&gt;&lt;p&gt;47. “Cuídate de los programadores que llevan destornillador”   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- Leonard Brandwein &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;48. “Los programadores hablan sobre desarrollo los fines de semana, vacaciones y en las comidas, no por falta de imaginación, sino porque su imaginación revela mundos que otros no pueden ver”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- &lt;/em&gt;&lt;em&gt;Larry O'Brien&lt;/em&gt;&lt;em&gt; y &lt;/em&gt;&lt;em&gt;Bruce Eckel&lt;/em&gt;&lt;em&gt; en "Thinking in C#"&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;49. “Los programadores de verdad siempre confunden Navidad con Halloween porque saben que Oct 31 == Dec 25”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- &lt;/em&gt;&lt;em&gt;Andrew Rutherford&lt;/em&gt;&lt;em&gt; &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;50. “Un buen programador es aquél que mira a los dos lados antes de cruzar una carretera con un único sentido”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Doug Linder &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;51. &amp;quot;Sólo por diversión.&amp;quot;    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Linus Torvalds, refiriéndose a las razones para haber creado Linux. &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Codificación&lt;/h3&gt;  &lt;p&gt;52. “Ese código es demasiado inteligente como para tener esperanzas de que funcione correctamente”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Tim Peters &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;53. “Las guías de estilo de codificación son como los traseros: todo el mundo tiene uno, y a nadie le gusta el de los demás”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Eric Warmenhoven&lt;/em&gt; &lt;/p&gt;  &lt;p&gt;54. “Reutilizar porciones de código es como tomar frases de textos de otras personas e intentar escribir con ellas un artículo en una revista”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Bob Frankston &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;55. “La programación orientada a objetos ofrece una vía sostenible de escribir código spaghetti”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Paul Graham &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;56. “Cuanto antes comiences a codificar, más tiempo tardarás en finalizar el programa”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Roy Carlson &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Empresa&lt;/h3&gt;  &lt;p&gt;57. “El objetivo es entregar código limpio que funcione… ahora”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Kent Beck &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;58. “No puedes simplemente preguntar a los clientes lo que quieren e intentar dárselo. Algo después, cuando lo hayas construido, ellos querrán otra cosa”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Steve Jobs &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;59. “Si pagas con cacahuetes, sólo puedes aspirar a contratar monos”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Sir James Goldsmith&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;60. “La primera regla de cualquier tecnología utilizada en los negocios es que la automatización aplicada a una operación eficiente magnificará la eficiencia. La segunda es que si la automatización se aplica a una operación ineficiente, magnificará la ineficiencia”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Bill Gates &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;61. “Walt Disney creó su imperio con un ratón. Igual que Steve Jobs”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- San Francisco Chronicle, Febrero de 2004 &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Lenguajes&lt;/h3&gt;  &lt;p&gt;62. “C fue diseñado para ser escrito; Ada para ser leído”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- &lt;/em&gt;&lt;em&gt;Jean Ichbiah&lt;/em&gt;&lt;em&gt; &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;63. “Java es C++, pero sin pistolas, cuchillos ni garrotes”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- James Gosling&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;64. “Perl es otro ejemplo de cómo cubrir una pequeña necesidad a corto plazo, y que se convierte en problema real a la larga”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Alan Kay &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;65. “APL es un lenguaje de sólo escritura. Puedo escribir programas en APL, pero luego no puedo leer ninguno de ellos”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Roy Keir &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;66. “El lenguaje C++ intenta proteger de Murphy, no de Maquiavelo”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Damian Conway &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;67. “Si C++ me ha enseñado algo es que por muy consistente que sea un sistema, no significa que no sea un trabajo de Satanás”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- Andrew Plotkin &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;68. “SQL, Lisp y Haskell son los únicos lenguajes de programación que he visto en los que uno pasa más tiempo pensando que escribiendo”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Philip Greenspun &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Predicciones&lt;/h3&gt;  &lt;p&gt;69. “Hacer predicciones es muy difícil, especialmente sobre el futuro”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Niels Bohr &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;70. ”La inteligencia artificial, ESTÁ AQUÍ”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- Portada del Business Week, July 9, 1984 &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;71. “He viajado a lo largo y ancho de este país, y hablado con la gente más preparada, y puedo asegurar que el proceso de datos es una moda pasajera que pasará antes de fin de año”    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;-- El editor responsable de libros de negocios de Prentice Hall, 1957.&lt;/em&gt; &lt;/p&gt;  &lt;p&gt;72. &lt;img style="border-right-width: 0px; margin: 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Logo de la campaña de la BPI" border="0" alt="Logo de la campaña de la BPI" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SfiFzsyQb8I/AAAAAAAABCM/FDBmwwY7DxA/clip_image0027.jpg?imgmax=800" width="128" height="141" /&gt;“Los Macintosh usan un dispositivo apuntador llamado “ratón”. No hay razón alguna para que la gente quiera usar esas cosas”     &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- John C. Dvorak, 1984 &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;73. “El casette doméstico está acabando con la música”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Campaña de la BPI (Industria Fonográfica Británica), en 1980 &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;74. “Los americanos han necesitado el teléfono, pero nosotros no. Tenemos gran cantidad de mensajeros”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Sir William Preece, Ingeniero jefe de la British Post Office, 1878. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;75. “Las máquinas serán capaces, en los próximos veinte años, de hacer cualquier trabajo que una persona pueda hacer”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Herbert Simon, 1965 &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Internet&lt;/h3&gt;  &lt;p&gt;76. “Navegar en Internet es como el sexo; todo el mundo presume de hacerlo mucho más de lo que realmente lo practican. Pero en el caso de Internet, mucho más todavía”   &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160; -- Tom Fasulo&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;77. “En el ciberespacio todo el mundo es anónimo 15 minutos”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Graham Greenleaf &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;78. “Si imagináis un colegio con niños que saben leer y escribir, pero los profesores no, tendréis una metáfora de la era de la información en la que vivimos”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Peter Cochrane. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;79. “Internet es la primera creación de la humanidad que la propia humanidad no entiende, el más grande experimento de anarquía que jamás hemos conocido”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Eric Schmidt &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;80. “En internet nadie sabe que eres un perro”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Peter Steiner, chiste en The New Yorker, Julio de 1993 &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;81. “El email es algo maravilloso para aquellos cuyo rol en la vida es estar encima de todo. Pero no para mí, que estoy debajo. Lo que hago requiere horas de estudio y concentración ininterrumplible”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Donald Knuth &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;82. “Internet es la biblioteca más grande del mundo. Lo que ocurre es que todos los libros están por el suelo”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- John Allen Paulos&lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Ordenadores&lt;/h3&gt;  &lt;p&gt;83. “La memoria es como un orgasmo: es mucho mejor cuando no tienes que simularla”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Seymoure Cray&lt;/em&gt; &lt;/p&gt;  &lt;p&gt;84. “Imagínate que todos los jueves tus zapatos explotaran cuando te los atas de la forma habitual. Esto es lo que nos ocurre siempre con los ordenadores, pero a nadie se le ocurre quejarse”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Jef Raskin &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;85. “Los ordenadores son imbéciles” &lt;a href="http://www.variablenotfound.com"&gt;&amp;#160;&lt;/a&gt;     &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Peter Drucker &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;86. “Ningún ordenador ha sido jamás diseñado para ser consciente de lo que está haciendo; pero la mayor parte del tiempo, nosotros tampoco lo somos”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Marvin Minsky &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;87. “La mejor forma de acelerar un ordenador es aquella que lo lanza a 9.8 m/s2”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- anónimo &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;88. “La paridad es para los granjeros”&amp;#160; &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Seymoure Cray, por qué no incluyó sistemas de corrección de errores en el CDC 6600.&lt;/em&gt; &lt;/p&gt;  &lt;p&gt;89. “He aprendido que muchos granjeros compran ordenadores”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Seymoure Cray, por qué incluyó sistemas de corrección de errores en el CDC 7600. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;90. “El hombre todavía puede apagar el ordenador. sin embargo, tendremos que esforzarnos mucho para conservar este privilegio”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- J. Weizembaum &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Calidad del software&lt;/h3&gt;  &lt;p&gt;91. “La seguridad, como la corrección, no es una característica adicional”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Andrew S. Tanenbaum &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;92. “La calidad es gratis, pero sólo para aquellos que están dispuestos a pagar mucho por ella”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Tom deMarco &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;93. “Un sistema que se base en la fiabilidad de un ordenador, no es fiable. Si se basa en la fiabilidad del ser humano, tampoco”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Una de las leyes de Troutman &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Complejidad&lt;/h3&gt;  &lt;p&gt;94. “Si piensas que la criptografía es la solución a tu problema, es que realmente no conoces tu problema”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Peter G. Neumann &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;95. “La generación de números aleatorios es demasiado importante como para ser dejada al azar”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Robert R. Covey &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;96. &amp;quot;Cualquiera que considere métodos aritméticos para producir dígitos aleatorios está, por supuesto, en pecado mortal&amp;quot;    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- John von Neumann &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;97. “La simplicidad es un prerequisito para la fiabilidad”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- E. W. Dijkstra &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Videojuegos&lt;/h3&gt;  &lt;p&gt;98. &amp;quot;Como cualquier programador de juegos sabe, los 3 tipos básicos de alimento son Fritos, Cheetos y Doritos&amp;quot;    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Satoru Iwata (presidente de Nintendo) &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;99. “La historia en un juego es como la de una película porno. Se espera que esté ahí, pero no es eso lo que importa”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- John Carmack &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;100. “Siempre me he preguntado si existe una versión Hezbolá del buscaminas en la que obtienes puntos si haces explotar el tablero en el primer movimiento”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; --James Lileks&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;101. “Los videojuegos no tienen ninguna influencia sobre los niños. Es decir, si el Pac-Man hubiese influenciado a nuestra generación, estaríamos todos corriendo en salas oscuras, masticando píldoras mágicas y escuchando músicas electrónicas repetitivas”    &lt;br /&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; -- Atribuida a Kristian Wilson, de Nintendo Inc; reivindicada por Marcus Brigstocke&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Y no te pierdas las entregas anteriores:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="101 citas célebres del mundo de la informática" href="http://www.variablenotfound.com/2008/02/101-citas-clebres-del-mundo-de-la.html"&gt;101 citas célebres del mundo de la informática&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a title="Otras 101 citas célebres del mundo de la informática" href="http://www.variablenotfound.com/2008/04/otras-101-citas-clebres-del-mundo-de-la.html"&gt;Otras 101 citas célebres del mundo de la informática&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-3041552074621912393?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dKzbL08MDTmm5DvqaKzek7pcktg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dKzbL08MDTmm5DvqaKzek7pcktg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dKzbL08MDTmm5DvqaKzek7pcktg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dKzbL08MDTmm5DvqaKzek7pcktg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cY_bTI65Oqo:T_z4tk8nPqY:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cY_bTI65Oqo:T_z4tk8nPqY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cY_bTI65Oqo:T_z4tk8nPqY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cY_bTI65Oqo:T_z4tk8nPqY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=cY_bTI65Oqo:T_z4tk8nPqY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cY_bTI65Oqo:T_z4tk8nPqY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=cY_bTI65Oqo:T_z4tk8nPqY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=cY_bTI65Oqo:T_z4tk8nPqY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=cY_bTI65Oqo:T_z4tk8nPqY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/cY_bTI65Oqo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/3041552074621912393/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=3041552074621912393" title="6 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3041552074621912393?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3041552074621912393?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/cY_bTI65Oqo/y-todavia-otras-101-citas-celebres-del.html" title="Y todavía otras 101 citas célebres del mundo de la informática" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/y-todavia-otras-101-citas-celebres-del.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQEQH08eCp7ImA9WxJREUs.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-1084361797259775423</id><published>2009-05-12T23:05:00.000+02:00</published><updated>2009-05-12T23:05:01.370+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-12T23:05:01.370+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="diseño" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="patrones" /><category scheme="http://www.blogger.com/atom/ns#" term="servicios on-line" /><category scheme="http://www.blogger.com/atom/ns#" term="dsl" /><title>yUML, generación de diagramas UML al vuelo</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="yUML" border="0" alt="yUML" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SfspLMjjCVI/AAAAAAAABCU/ehO_lHMYfbg/image%5B22%5D.png?imgmax=800" width="192" height="168" /&gt; &lt;a title="tobin harris" href="http://www.tobinharris.com/past/2009/4/30/yuml-for-not-sketching-uml-diagrams-online-/" hreflang="en"&gt;Tobin Harris&lt;/a&gt;&lt;a title="tobin harris" href="http://www.tobinharris.com/past/2009/4/30/yuml-for-not-sketching-uml-diagrams-online-/"&gt;&lt;/a&gt; ha puesto en marcha un curioso e interesante servicio, al que ha denominado &lt;a title="yUML" href="http://yuml.me/"&gt;yUML&lt;/a&gt;, cuyo propósito es facilitar la generación al vuelo de diagramas UML a partir de una concisa descripción expresada en un sencillo lenguaje específico.&lt;/p&gt;  &lt;p&gt;Pero además de la generación automática del diagrama UML, que ya tiene mérito de por sí, llama la atención que esto puede realizarse desde una etiqueta (X)HTML &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; a la que se le envía la especificación como parámetro, generándose en tiempo real una imagen con el diagrama correspondiente. Por ello, está especialmente indicado para autores de blogs, wikis o contenidos web que deseen introducir muy fácilmente estos diagramas en sus creaciones.&lt;/p&gt;  &lt;p&gt;En los siguientes ejemplos se muestran la especificación y la imagen generada de un diagrama de clases y uno de casos de uso, respectivamente. Como podréis comprobar, la especificación es bastante legible directamente.&lt;/p&gt;  &lt;h4&gt;Diagrama de clases&lt;/h4&gt;  &lt;p&gt;Especificación: &lt;code&gt;&lt;strong&gt;[Company]&amp;lt;&amp;gt;-1&amp;gt;[Location], [Location]+-&amp;gt;[Point]&lt;/strong&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px auto 5px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_O9D62hXq-ng/SfspLhVzp_I/AAAAAAAABCY/SP7V9LRczCE/image%5B8%5D.png?imgmax=800" width="465" height="58" /&gt;&lt;/p&gt;  &lt;p&gt;Código fuente para su inserción en una página:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3d54bd07-fb3f-49e7-8a4d-b9f5e3dbda4d" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;img &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="http://yuml.me/diagram/class/[Company]&amp;lt;&amp;gt;-1&amp;gt;[Location], [Location]+-&amp;gt;[Point]"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Estilo informal" border="0" alt="Estilo informal" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SgdBm_Q4XmI/AAAAAAAABDQ/dUufERXRNs8/image%5B5%5D.png?imgmax=800" width="221" height="101" /&gt;Una curiosidad es que si en la dirección insertamos la palabra “scruffy”, el sistema generará un diagrama como si hubiese sido dibujado a mano, en un estilo mucho más informal: &lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:46e2acd0-b52b-42da-883b-4c522347668a" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;img &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="http://yuml.me/diagram/scruffy/class/[Company]&amp;lt;&amp;gt;-1&amp;gt;[Location], [Location]+-&amp;gt;[Point]"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;h4&gt;Diagrama de casos de uso&lt;/h4&gt;&lt;p&gt;Especificación: &lt;strong&gt;[User]-(Login), [User]-(Logout), (Login)&amp;lt;(Reminder), (Login)&amp;gt;(Captcha)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px auto 5px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_O9D62hXq-ng/SfspMTtCR1I/AAAAAAAABCc/DxG062f8lgw/image%5B16%5D.png?imgmax=800" width="450" height="167" /&gt; &lt;/p&gt;&lt;p&gt;Código fuente para su inserción en una página:&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" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:358bb2c4-24f5-4e9a-956f-f5d08aa0358a" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;img &lt;/span&gt;&lt;span style="color: #FF0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="http://yuml.me/diagram/usecase/[User]-(Login), [User]-(Logout), (Login)&amp;lt;(Reminder), (Login)&amp;gt;(Captcha)"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Si prefieres simplemente descargar el diagrama para subirlo a tu web, &lt;em&gt;opción bastante prudente hasta que se pueda confiar en la fiabilidad y disponibilidad del servicio&lt;/em&gt;, desde el mismo sitio web del producto podemos &lt;a title="Generar un diagrama de clases" href="http://yuml.me/diagram/class/draw"&gt;generar la imagen introduciendo la especificación textual&lt;/a&gt;; a partir de ahí podremos copiarla y pegarla sobre nuestra herramienta de edición, o salvarla en nuestro equipo para enviarla a su ubicación definitiva.&lt;/p&gt;&lt;p&gt;Si bien todavía &lt;a title="yUML" href="http://yuml.me"&gt;yUML&lt;/a&gt; está en pruebas y es algo limitado (sólo soporta diagramas de clases y de casos de uso), me ha parecido muy interesante tanto la idea como la implementación del servicio.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-1084361797259775423?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HsRbCR8NEQIcC3pqHaQXDR-_4Q4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HsRbCR8NEQIcC3pqHaQXDR-_4Q4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HsRbCR8NEQIcC3pqHaQXDR-_4Q4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HsRbCR8NEQIcC3pqHaQXDR-_4Q4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WE7PEfHRAck:HgybSYGpflc:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WE7PEfHRAck:HgybSYGpflc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WE7PEfHRAck:HgybSYGpflc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WE7PEfHRAck:HgybSYGpflc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WE7PEfHRAck:HgybSYGpflc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WE7PEfHRAck:HgybSYGpflc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WE7PEfHRAck:HgybSYGpflc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WE7PEfHRAck:HgybSYGpflc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WE7PEfHRAck:HgybSYGpflc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/WE7PEfHRAck" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/1084361797259775423/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=1084361797259775423" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1084361797259775423?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1084361797259775423?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/WE7PEfHRAck/yuml-generacion-de-diagramas-uml-al.html" title="yUML, generación de diagramas UML al vuelo" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/yuml-generacion-de-diagramas-uml-al.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQEQHs6cSp7ImA9WxJREEo.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-2707727935695557967</id><published>2009-05-11T23:45:00.000+02:00</published><updated>2009-05-11T23:45:01.519+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-11T23:45:01.519+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vs2008" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="buenas prácticas" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><title>Plantillas de proyectos ASP.NET MVC 1.0 para NUnit</title><content type="html">&lt;p&gt;Joe Cartano, perteneciente al Visual Web Development Team de Microsoft, ha publicado en el blog oficial (&lt;a title="Visual Web Developer Team Blog" href="http://blogs.msdn.com/webdevtools/default.aspx"&gt;Visual Web Developer Team &lt;/a&gt;&lt;a title="Visual Web Developer Team Blog" href="http://blogs.msdn.com/webdevtools/default.aspx" hreflang="en"&gt;Blog&lt;/a&gt;) un post anunciando que ha actualizado la plantilla que permite crear directamente proyectos ASP.NET MVC con tests unitarios &lt;a title="NUnit" href="http://www.nunit.org" hreflang="en"&gt;NUnit&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Así, una vez instalado, al crear un proyecto de tipo ASP.NET MVC nos aparecerá un cuadro de diálogo como el siguiente, en el que se nos brindará la oportunidad de crear en la solución un proyecto de pruebas unitarias utilizando NUnit:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px auto 5px; display: block; float: none; border-top: 0px; border-right: 0px" title="Crear proyecto de pruebas unitarias" border="0" alt="Crear proyecto de pruebas unitarias" src="http://lh5.ggpht.com/_O9D62hXq-ng/SgRnjqs-QUI/AAAAAAAABCw/h0AdXjB8ppM/image%5B14%5D.png?imgmax=800" width="325" height="225" /&gt;&lt;/p&gt;  &lt;p&gt;Para los poseedores de algunas de las versiones profesionales de Visual Studio 2008, esta ventana no es nueva, puesto que por defecto ya se incluyen los proyectos de tests propios de Microsoft, pero sí lo es para la versión express del IDE, que no incluye el framework de pruebas y en el que había que crear el proyecto a mano.&lt;/p&gt;  &lt;p&gt;El proyecto, que se crea automáticamente, realiza 27 tests sobre la plantilla original de proyectos ASP.NET MVC, y pueden servir como base para seguir creando nuestro propio conjunto de pruebas:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px auto 5px; display: block; float: none; border-top: 0px; border-right: 0px" title="¡La plantilla ASP.NET MVC valida!" border="0" alt="¡La plantilla ASP.NET MVC valida!" src="http://lh3.ggpht.com/_O9D62hXq-ng/SgRnk2XzKHI/AAAAAAAABC0/uIA5GhjfcXA/image%5B25%5D.png?imgmax=800" width="367" height="238" /&gt; &lt;/p&gt;  &lt;p&gt;La plantilla se instala descargando el archivo .zip cuyo enlace encontraréis en &lt;a title="Updated NUnit Templates for ASP.Net MVC 1.0 RTM" href="http://blogs.msdn.com/webdevtools/archive/2009/04/28/updated-nunit-templates-for-asp-net-mvc-1-0-rtm.aspx" hreflang="en"&gt;el post original&lt;/a&gt; y ejecutando, si es necesario con un usuario con privilegios de administrador, el script &lt;code&gt;installNUnit.cmd&lt;/code&gt; disponible en el raíz del directorio donde lo hayáis descomprimido.&lt;/p&gt;  &lt;p&gt;Para que todo vaya bien, debéis contar con &lt;a title="NUnit" href="http://www.nunit.org" hreflang="en"&gt;NUnit&lt;/a&gt; previamente instalado en vuestro equipo. Pero ojo, las plantillas están preparadas para la versión 2.4.8.0 y la versión actual es la 2.5.0.9122, por lo que puede que no os funcionen bien si estáis a la última.&lt;/p&gt;  &lt;p&gt;En este caso, es necesario tocar a mano los archivos de plantillas. Podéis seguir estos pasos:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Descargad el archivo de plantillas &lt;a title="Plantillas para NUnit y ASP.NET MVC" href="http://blogs.msdn.com/webdevtools/archive/2009/04/28/updated-nunit-templates-for-asp-net-mvc-1-0-rtm.aspx" hreflang="en"&gt;desde el blog del Visual Web Developer Team&lt;/a&gt;&lt;a title="Plantillas para NUnit y ASP.NET MVC" href="http://blogs.msdn.com/webdevtools/archive/2009/04/28/updated-nunit-templates-for-asp-net-mvc-1-0-rtm.aspx"&gt;&lt;/a&gt;.&lt;/li&gt;    &lt;li&gt;Descomprimidlo sobre cualquier carpeta.&lt;/li&gt;    &lt;li&gt;En los subdirectorios CSharp y Visual Basic encontraréis un archivo llamado &lt;code&gt;MvcApplication.NUnit.Tests.zip&lt;/code&gt;. Son las plantillas para cada uno de esos lenguajes.&lt;/li&gt;    &lt;li&gt;El interior de dicho zip está el archivo de proyecto (&lt;code&gt;MvcApplication.NUnit.Test.vbproj&lt;/code&gt; en el caso de Visual Basic, &lt;code&gt;MvcApplication.NUnit.Test.csproj&lt;/code&gt; en C#). Descomprimid sólo estos archivos y buscar en ambos la cadena “2.4.8.0” y sustituirla por la versión de NUnit que tengáis instalada (en mi caso, “2.5.0.9122”). Al acabar, actualizad de nuevo el .zip con el archivo que acabáis de editar.&lt;/li&gt;    &lt;li&gt;Ejecutad el script de instalación &lt;code&gt;installNUnit.cmd&lt;/code&gt;.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-2707727935695557967?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Dl_HStfqzLc1WlHFJFhTfGxwafk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Dl_HStfqzLc1WlHFJFhTfGxwafk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Dl_HStfqzLc1WlHFJFhTfGxwafk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Dl_HStfqzLc1WlHFJFhTfGxwafk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=JeCRXlnpW3Y:XAM63aMRAgk:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=JeCRXlnpW3Y:XAM63aMRAgk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=JeCRXlnpW3Y:XAM63aMRAgk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=JeCRXlnpW3Y:XAM63aMRAgk:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=JeCRXlnpW3Y:XAM63aMRAgk:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=JeCRXlnpW3Y:XAM63aMRAgk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=JeCRXlnpW3Y:XAM63aMRAgk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=JeCRXlnpW3Y:XAM63aMRAgk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=JeCRXlnpW3Y:XAM63aMRAgk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/JeCRXlnpW3Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/2707727935695557967/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=2707727935695557967" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2707727935695557967?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2707727935695557967?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/JeCRXlnpW3Y/plantillas-de-proyectos-aspnet-mvc-10.html" title="Plantillas de proyectos ASP.NET MVC 1.0 para NUnit" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/plantillas-de-proyectos-aspnet-mvc-10.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04CQH08fip7ImA9WxJSGUQ.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-8205245790872510579</id><published>2009-05-10T23:46:00.002+02:00</published><updated>2009-05-10T23:46:01.376+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-10T23:46:01.376+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="blogging" /><category scheme="http://www.blogger.com/atom/ns#" term="autobombo" /><category scheme="http://www.blogger.com/atom/ns#" term="aniversario" /><title>Ya van tres años sin saber nada de la variable</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="¡Ya van tres años!" border="0" alt="¡Ya van tres años!" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/Sf22su5EnhI/AAAAAAAABCg/ln-PTVneaG0/image%5B9%5D.png?imgmax=800" width="128" height="171" /&gt; El pasado 8 de mayo, además de conmemorarse &lt;a title="Conoce la Coca-Cola" href="http://www.conocecocacola.com/"&gt;el nacimiento de la Coca-Cola&lt;/a&gt;, se cumplían &lt;strong&gt;tres años&lt;/strong&gt; desde que publiqué &lt;a title="¡Paren el tren, que me subo!" href="http://www.variablenotfound.com/2006/05/paren-el-tren-que-me-subo.html"&gt;el primer post&lt;/a&gt; en este blog. Y me sigue pareciendo que fue ayer, cómo pasa el tiempo…&lt;/p&gt;  &lt;p&gt;Como en otras ocasiones, es un bonito momento para recapitular y comentar lo que ha ido ocurriendo por aquí desde entonces.&lt;/p&gt;  &lt;p&gt;Durante la celebración del &lt;a title="Dos años ya, y la variable sigue sin aparecer" href="http://www.variablenotfound.com/2008/05/dos-aos-ya-y-la-variable-sigue-sin.html"&gt;segundo cumpleaños&lt;/a&gt; hice una distinción de dos periodos en la historia de &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;, que os resumo:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Año 1: la travesía del desierto (mayo 2006 - mayo 2007)&lt;/strong&gt;, periodo caracterizado principalmente por la ausencia prácticamente total de visitantes al blog, por aquellos tiempos disponible a través de la dirección &lt;a onclick="alert(&amp;#39;¿Dónde vas?&amp;#39;); return false;" href="#"&gt;jmaguilar.blogspot.com&lt;/a&gt;. Y no exagero, observad el registro de visitas de los primeros meses, y tened en cuenta que yo mismo también visitaba la página:       &lt;br /&gt;      &lt;br /&gt;&lt;img style="border-right-width: 0px; margin: 0px auto 5px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_O9D62hXq-ng/Sf22tJ65yOI/AAAAAAAABCk/kcnHZYI1yIg/image%5B18%5D.png?imgmax=800" width="528" height="122" /&gt;&amp;#160; &lt;br /&gt;Aprovecho para introducir un mensaje de aliento para los que estéis en esta situación ahora, empezando un blog: &lt;em&gt;no os desaniméis, ni aun viendo este desastre. Con un poco de esfuerzo todo puede cambiar. El desierto también tiene su fin.&lt;/em&gt;       &lt;br /&gt;&amp;#160; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Año 2: el despegue (mayo 2007 - mayo 2008)&lt;/strong&gt;, durante el cual se produjeron múltiples novedades, como la adquisición del dominio &lt;a href="http://www.variablenotfound.com"&gt;variablenotfound.com&lt;/a&gt;, la difusión de &lt;em&gt;feeds&lt;/em&gt; a través de&lt;strike&gt;, el por aquél entonces magnífico,&lt;/strike&gt; Feedburner, la creación del diseño actual, y la inclusión en agregadores y comunidades como &lt;a title="Planeta Código" href="http://www.planetacodigo.com/"&gt;Planeta Código&lt;/a&gt;, &lt;a title="Planet WebDev" href="http://planetwebdev.net/"&gt;Planet WebDev&lt;/a&gt; y &lt;a title="Geeks.ms" href="http://geeks.ms/"&gt;Geeks.ms&lt;/a&gt;.       &lt;p&gt;Este segundo año lo acabamos con un incremento del 2.500% en el número de visitas (la verdad, tampoco lo tenía muy difícil partiendo desde cero ;-)), y lo que me parecía más increíble, 380 suscriptores.&lt;/p&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Y siguiendo esta línea, el año que hemos acabamos ahora podríamos describirlo como:&lt;/p&gt;  &lt;h3&gt;&lt;strong&gt;Año 3: la consolidación (mayo 2008 – mayo 2009)&lt;/strong&gt;&lt;/h3&gt;  &lt;p&gt;Aunque ha sido un año sin grandes cambios, &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt; ha seguido creciendo. Obviamente no en las proporciones anteriores, pero sí ha mostrado un aumento considerable tanto de visitantes como de suscriptores.&lt;/p&gt;  &lt;p&gt;Respecto a las visitas a la web, hay que destacar los siguientes datos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;las visitas, en general, han aumentado cerca de un 40%, así como el número de usuarios únicos absolutos. Hay que tener en cuenta que durante este último año no se han producido &lt;em&gt;meneos espectaculares&lt;/em&gt; como el año anterior, no han pasado de meneillos, por lo que la subida de visitas en global tiene bastante mérito. &lt;/li&gt;    &lt;li&gt;También se han incrementado ligeramente el número de páginas vistas por visita, y el tiempo medio en la página. &lt;/li&gt;    &lt;li&gt;El tráfico dirigido desde buscadores se han incrementado en un 75% desde el periodo anterior. Esto podría entenderse como que el blog está logrando un posicionamiento importante en estos motores, probablemente debido a la antigüedad, a las referencias externas y a los propios contenidos. &lt;/li&gt;    &lt;li&gt;Curiosamente, ha disminuido el número de visitantes nuevos en proporción a los que repiten, lo que implica que aumenta el número de usuarios que han visitado el blog más de una vez. &lt;/li&gt;    &lt;li&gt;Los comentarios, como manda la tradición, siguen siendo escasos: la media no llega a dos comentarios por cada post publicado. Nada que objetar en esto, soy el primero al que le cuesta la misma vida comentar algo en blogs ajenos que sigo con asiduidad. Es cierto que me gustaría obtener más feedback y opiniones de los lectores, pero entiendo que no sea así. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 5px 0px 5px 5px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/SgRXQSCEuiI/AAAAAAAABCs/eSufsmuG0DQ/image%5B5%5D.png?imgmax=800" width="308" height="80" /&gt;En cuanto a las suscripciones, siguen siendo uno de los datos que más me están sorprendiendo, y muy gratamente. En estos momentos, &lt;em&gt;a pesar de los cambios de humor de Feedburner&lt;/em&gt;, hemos llegado ya a alcanzar los &lt;strong&gt;650 suscriptores&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Y sinceramente, este es uno de los datos que más valoro. La temática tan específica del blog hace que los destinatarios de los contenidos, principalmente desarrolladores, sean una minoría, y conseguir que un número tan alto de personas decidan &lt;em&gt;voluntariamente&lt;/em&gt; añadirte de alguna forma a sus fuentes favoritas es todo un honor y, sin duda, motivo de orgullo.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 5px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="¿Dormido o durmiendo?" border="0" alt="¿Dormido o durmiendo?" align="left" src="http://lh6.ggpht.com/_O9D62hXq-ng/Sf22t_p9OCI/AAAAAAAABCo/7DcZVZwfz9I/image%5B23%5D.png?imgmax=800" width="118" height="118" /&gt;En el aspecto económico, sigo arrasando con los ingresos por AdSense. El mes pasado, junto con el cheque mensual me enviaron una caja de bombones, con una tarjeta de felicitación firmada por el mismísimo &lt;a title="Sergey Brin - Wikipedia, la enciclopedia libre" href="http://es.wikipedia.org/wiki/Sergey_Brin"&gt;Sergey Brin&lt;/a&gt;…&lt;/p&gt;  &lt;p&gt;… vaya, parece que me había quedado dormido otra vez ;-D. Pues no, de momento sigo recaudando centimillos a un ritmo lamentable, pero bueno, ¿quién dijo que esto de bloguear se hacía por dinero?&lt;/p&gt;  &lt;p&gt;Lo que considero mi recompensa es lo que estoy aprendiendo. Cada tema tratado, ejemplo, referencia, cada comentario, cada mensaje privado recibido, me aportan una nueva oportunidad para ampliar conocimientos. Si esto lo unimos al placer de comunicar y de compartir los descubrimientos, ya tenemos un buen conjunto de motivaciones que animan a seguir trabajando en el blog.&lt;/p&gt;  &lt;p&gt;Pero aún falta algo, sin duda lo más importante: &lt;strong&gt;vosotros&lt;/strong&gt;. Los que estáis ahí leyendo, enviando comentarios o mensajes, añadiendo valor a las entradas, los que le dais sentido a todo esto. Repito lo que ya comenté en el post en el que celebraba el &lt;a title="Un año sin encontrar la variable" href="http://www.variablenotfound.com/2007/05/un-ao-sin-encontrar-la-variable.html"&gt;primer aniversario&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Os puedo asegurar que he disfrutado escribiendo cada post, pero las alegrías han venido con cada comentario, con cada visita, con cada referencia.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Muchas gracias a todos, y espero que sigáis por aquí, &lt;em&gt;ayudándome a buscar la variable&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Publicado en: &lt;a title="Variable Not Found" href="http://www.variablenotfound.com/"&gt;Variable not found&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-8205245790872510579?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/v7g3AoS54jm-d3excIMaDIFbqh8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/v7g3AoS54jm-d3excIMaDIFbqh8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/v7g3AoS54jm-d3excIMaDIFbqh8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/v7g3AoS54jm-d3excIMaDIFbqh8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=CtJklTSz2aA:Tw28rWqBobc:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=CtJklTSz2aA:Tw28rWqBobc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=CtJklTSz2aA:Tw28rWqBobc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=CtJklTSz2aA:Tw28rWqBobc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=CtJklTSz2aA:Tw28rWqBobc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=CtJklTSz2aA:Tw28rWqBobc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=CtJklTSz2aA:Tw28rWqBobc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=CtJklTSz2aA:Tw28rWqBobc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=CtJklTSz2aA:Tw28rWqBobc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/CtJklTSz2aA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/8205245790872510579/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=8205245790872510579" title="11 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/8205245790872510579?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/8205245790872510579?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/CtJklTSz2aA/ya-van-tres-anos-sin-saber-nada-de-la.html" title="Ya van tres años sin saber nada de la variable" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/ya-van-tres-anos-sin-saber-nada-de-la.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8EQH4_eyp7ImA9WxJSE0U.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-5499156950095572458</id><published>2009-05-03T23:40:00.002+02:00</published><updated>2009-05-03T23:40:01.043+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-03T23:40:01.043+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="antipatrones" /><category scheme="http://www.blogger.com/atom/ns#" term="herramientas" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="buenas prácticas" /><category scheme="http://www.blogger.com/atom/ns#" term="calidad" /><category scheme="http://www.blogger.com/atom/ns#" term="patrones" /><title>NDepend, analiza a fondo tu código</title><content type="html">&lt;p&gt;Existen numerosas aplicaciones que permiten analizar nuestros desarrollos con el objetivo final de incrementar la calidad de los mismos. &lt;a title="Mejora la calidad de tus aplicaciones y librerías .Net con FxCop" href="http://www.variablenotfound.com/2008/01/mejora-la-calidad-de-tus-aplicaciones-y.html"&gt;FxCop&lt;/a&gt;, por ejemplo, es capaz de analizar los ensamblados y avisarnos cuando se encuentra con incumplimientos de las pautas de diseño para desarrolladores de librerías para .Net Framework (&lt;a href="http://msdn2.microsoft.com/en-us/library/czefa0ke(vs.71).aspx" hreflang="en"&gt;Design Guidelines for Class Library Developers&lt;/a&gt;). También hace tiempo comenté por aquí la disponibilidad de&amp;#160; &lt;a title="Disponible Microsoft Source Analysis for C#" href="http://www.variablenotfound.com/2008/05/disponible-el-microsoft-source-analysis.html"&gt;Microsoft Source Analysis for C#&lt;/a&gt;, una herramienta que se centra en el código fuente y el cumplimiento de reglas de codificación.&lt;/p&gt;  &lt;p&gt;Ahora, gracias al ofrecimiento de &lt;a title="Blog de Patrick Smacchia" href="http://codebetter.com/blogs/patricksmacchia/" hreflang="en"&gt;Patrick Smacchia&lt;/a&gt;, lead developer del producto, he podido probar &lt;a title="NDepend" href="http://www.ndepend.com/Default.aspx"&gt;NDepend&lt;/a&gt;, una herramienta de análisis de código de la que había oído hablar y que va mucho más allá que las citadas anteriormente.&lt;/p&gt;  &lt;p&gt;La principal misión de &lt;a title="NDepend" href="http://www.ndepend.com/Default.aspx"&gt;NDepend&lt;/a&gt; es ayudarnos a incrementar la calidad de nuestros sistemas desarrollados con .NET mediante el análisis de sus ensamblados y código fuente desde distintas perspectivas, como la complejidad de sus módulos, el tamaño de los mismos, las interdependencias entre ellos, etc. Es decir, a diferencia de otros analizadores, su objetivo no es avisarnos de aspectos como la utilización de convenciones de codificación (aunque también puede hacerlo), o el uso de buenas prácticas de diseño, sino ayudarnos a determinar, por ejemplo, cuándo ponemos en peligro la mantenibilidad y evolución de un sistema debido a la complejidad&amp;#160; o al fuerte acoplamiento de algunos de sus componentes, por citar sólo algunos criterios.&lt;/p&gt;  &lt;h3&gt;El entorno gráfico&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;VisualNDepend&lt;/strong&gt; es el entorno gráfico de la herramienta, y nos ofrece un entorno de trabajo muy potente e intuitivo, aunque durante los primeros minutos pueda resultar algo complejo debido a la cantidad de información mostrada.&lt;/p&gt;  &lt;p&gt;Iniciar el análisis de un sistema es muy sencillo; una vez seleccionado el ensamblado, conjunto de ensamblados o proyecto a estudiar, el sistema realiza el análisis, del cual se obtiene un informe bastante completo, basado en web, sobre el mismo (podéis ver un &lt;a title="Ejemplo de informe en la web de NDepend" href="http://www.ndepend.com/SampleReports/OnNUnit/NDependReport.html"&gt;ejemplo de informe&lt;/a&gt; en la página del producto). En él se recogen:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;em&gt;métricas de la aplicación&lt;/em&gt;, entre las que encontramos el número de líneas de código, comentarios, número de clases, métodos, etc., así como datos estadísticos relativos a la complejidad, extensión y estructura del código. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;métricas por ensamblado&lt;/em&gt;, donde se refleja, por cada uno de los ensamblados que componen la solución, datos sobre su tamaño, grados de cohesión, acoplamiento, y otros aspectos relativos a su complejidad e interdependencia. &lt;/li&gt;    &lt;li&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 5px; display: inline; border-top: 0px; border-right: 0px" title="Vista de estructura" border="0" alt="Vista de estructura" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SfiARJtOUaI/AAAAAAAABB0/0HEqHplAfA8/image%5B4%5D.png?imgmax=800" width="178" height="178" /&gt; &lt;em&gt;vista de estructura&lt;/em&gt; (captura de la derecha) que muestra la distribución de componentes, la granularidad y su complejidad relativa según el tamaño de los bloques visualizados. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;diagrama de abstracción e inestabilidad&lt;/em&gt;, que posiciona cada ensamblado en función del número de clases abstractas e interfaces que presenta y su dependencia del resto de elementos. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;relación entre ensamblados&lt;/em&gt;, que detalla las interdependencias entre ensamblados del proyecto, los posibles ciclos, así como un posible orden de generación. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;consultas y restricciones CQL&lt;/em&gt;, que realiza una serie de consultas predefinidas sobre los ensamblados y el código que nos ayuda a detectar una infinidad de problemas en nuestros desarrollos, desde aspectos relativamente simples como el exceso de métodos en clases o el incumplimiento de ciertas convenciones de nombrado, hasta problemas en la cobertura de los tests generados con &lt;a title="NCover" href="http://www.ncover.com/"&gt;NCover&lt;/a&gt; o Visual Studio Team System. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Pero lo mejor del entorno gráfico no es poder generar un análisis en formato web para poder consultarlo más adelante, de hecho esto puede conseguir también con la aplicación de consola que incluye NDepend. Lo mejor son las fantásticas herramientas interactivas que nos permiten navegar a través de nuestras aplicaciones, cambiar de vista, ampliar información sobre cualquier elemento, y realizar consultas en tiempo real, siempre ofreciendo unos resultados muy claros y visuales, como:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 5px 5px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Diagrama de dependencias" border="0" alt="Diagrama de dependencias" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SfiARrE5UbI/AAAAAAAABB4/kQsADiVukjU/image6.png?imgmax=800" width="347" height="122" /&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;em&gt;diagrama de dependencias&lt;/em&gt; entre todo tipo de elementos, como clases, espacios de nombres, o ensamblados. Resulta muy útil, además, configurar el tamaño de los bloques, el grosor del borde y el de las flechas de unión para que sean proporcionales a la complejidad, tamaño y una larga lista de criterios.&lt;/li&gt;    &lt;li&gt;&lt;img style="border-right-width: 0px; margin: 5px 5px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tabla de dependencias" border="0" alt="Tabla de dependencias" align="right" src="http://lh5.ggpht.com/_O9D62hXq-ng/SfiAS3A9wCI/AAAAAAAABB8/U6SVo_Krd7o/image18.png?imgmax=800" width="245" height="239" /&gt; &lt;em&gt;matriz de dependencias&lt;/em&gt;, que muestra de forma visual las relaciones de utilización entre espacios de nombres, tipos, métodos o propiedades, con posibilidad de ir ampliando información. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;comparación entre ensamblados&lt;/em&gt;, mostrándonos los cambios producidos entre, por ejemplo, dos versiones de una misma librería o aplicación.&lt;/li&gt;    &lt;li&gt;&lt;em&gt;navegación avanzada por el código &lt;/em&gt;a través del uso del menú contextual que facilita la rápida localización de referencias, directas e indirectas, hacia y desde un método, propiedad o tipo existente.&lt;/li&gt;    &lt;li&gt;&lt;em&gt;enlace con &lt;/em&gt;&lt;a title=".NET Reflector" href="http://www.red-gate.com/products/reflector/"&gt;&lt;em&gt;Reflector&lt;/em&gt;&lt;/a&gt;, una herramienta indispensable, con la que se integra perfectamente gracias a su plugin.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;CQL (Code Query Language)&lt;/h3&gt;  &lt;p&gt;Sin duda, una de las características más interesante que tiene NDepend es el soporte del lenguaje de consulta &lt;a title="CQL Language Specification" href="http://www.ndepend.com/CQL.htm"&gt;CQL (Code Query Language)&lt;/a&gt;, que nos ofrece la posibilidad de tratar nuestro código y ensamblados como si fuesen una gigantesca base de datos sobre la que podemos realizar consultas de forma muy natural.&amp;#160; Las posibilidades que esto ofrece son tan amplias que prácticamente todas las funcionalidades de la aplicación están basadas en órdenes CQL prediseñadas que acompañan al producto, aunque podemos crear todas las consultas personalizadas que necesitemos, como por ejemplo:&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" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e488ea34-dcfe-41eb-87f7-17a63719d982" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #008080;"&gt;/*&lt;/span&gt;&lt;span style="color: #008080;"&gt; Obtiene los métodos que escriben una propiedad &lt;/span&gt;&lt;span style="color: #008080;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;SELECT&lt;/span&gt;&lt;span style="color: #000000;"&gt; METHODS &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;WHERE&lt;/span&gt;&lt;span style="color: #000000;"&gt; IsDirectlyWritingField "Model.Cliente.Nombre"&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;/*&lt;/span&gt;&lt;span style="color: #008080;"&gt; Obtiene métodos que acceden incorrectamente a los&lt;br /&gt;   datos desde la capa de interfaz&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;SELECT&lt;/span&gt;&lt;span style="color: #000000;"&gt; METHODS &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;FROM&lt;/span&gt;&lt;span style="color: #000000;"&gt; NAMESPACES "Interfaz" &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;WHERE&lt;/span&gt;&lt;span style="color: #000000;"&gt; IsDirectlyUsing "MySql.Data"&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;/*&lt;/span&gt;&lt;span style="color: #008080;"&gt; Obtiene los 10 métodos con más líneas de código &lt;/span&gt;&lt;span style="color: #008080;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;SELECT&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;TOP&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000; font-weight: bold;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt; METHODS &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;ORDER&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;BY&lt;/span&gt;&lt;span style="color: #000000;"&gt; NbLinesOfCode &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;DESC&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;/*&lt;/span&gt;&lt;span style="color: #008080;"&gt; Obtiene los métodos considerados "peligrosos" según su complejidad ciclomática &lt;/span&gt;&lt;span style="color: #008080;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;SELECT&lt;/span&gt;&lt;span style="color: #000000;"&gt; METHODS &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;WHERE&lt;/span&gt;&lt;span style="color: #000000;"&gt; CyclomaticComplexity &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000; font-weight: bold;"&gt;20&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 5px; display: inline; border-top: 0px; border-right: 0px" title="Editor de CQL con intellisense" border="0" alt="Editor de CQL con intellisense" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SfiATQ-yZeI/AAAAAAAABCA/D4xeGfvl3AI/image%5B3%5D.png?imgmax=800" width="204" height="122" /&gt;Además de consultas CQL cuyo resultado podremos observar de forma directa tanto visualmente como en forma de listado, es posible incluir restricciones (WARN) que hará que el sistema nos alerte durante el análisis de un proyecto que cumpla las condiciones especificadas. Por ejemplo, la siguiente restricción nos avisará cuando exista un &lt;a title="A qué huele tu código" href="http://www.variablenotfound.com/2008/05/qu-huele-tu-cdigo.html"&gt;cierto tufillo&lt;/a&gt; a complejidad excesiva en un método (que haya sido definido con más de 10 parámetros):&lt;/p&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:ec482473-2dec-43d6-8bbc-280e5117c328" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;WARN &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;IF&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #FF00FF;"&gt;Count&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000; font-weight: bold;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;IN&lt;/span&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;SELECT&lt;/span&gt;&lt;span style="color: #000000;"&gt; METHODS &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;WHERE&lt;/span&gt;&lt;span style="color: #000000;"&gt; NbParameters &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000; font-weight: bold;"&gt;10&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;Estas consultas pueden ser añadidas (en la versión Pro) e integradas en los análisis, así como modificar las existentes, de forma que el producto puede ser personalizado a nuestras convenciones o necesidades específicas. &lt;/p&gt;&lt;p&gt;Otra posibilidad es incluir dentro del código de un ensamblado las restricciones que deseamos que se cumplan, expresándolas en lenguaje CQL embebido en un atributo de tipo &lt;code&gt;CQLConstraint&lt;/code&gt; aplicado a sus elementos:&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.ndepend.com/Res/ConstraintInCodeSource4.JPG" width="561" height="225" /&gt;&lt;/p&gt;&lt;p&gt;Afortunadamente existe mucha información disponible en la web sobre el lenguaje CQL, y consultas que nos muestran cómo sacarle el máximo partido.&lt;/p&gt;&lt;h3&gt;Instalación e integraciones&lt;/h3&gt;&lt;p&gt;NDepend se distribuye en formato .zip, y que puede ejecutarse directamente una vez descomprimido el contenido sobre una carpeta. La licencia, una vez obtenida, es un archivo XML firmado digitalmente que debemos colocar en el directorio de la aplicación, y listo.&lt;/p&gt;&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Integración con VS y Reflector" border="0" alt="Integración con VS y Reflector" align="right" src="http://lh5.ggpht.com/_O9D62hXq-ng/SfiAUPrw8zI/AAAAAAAABCE/QkbQF_iim5E/image10.png?imgmax=800" width="277" height="167" /&gt; &lt;/p&gt;&lt;p&gt;Ya en ejecución, desde el menú “options” es posible configurarlo para que se integre con Visual Studio 2005, 2008 y como he comentado anteriormente, con el magnífico &lt;a title=".NET Reflector" href="http://www.red-gate.com/products/reflector/"&gt;Reflector&lt;/a&gt;, con el que hace una excelente pareja.&lt;/p&gt;&lt;p&gt;Asimismo, es posible utilizarlo en sistemas como MSBuild y NAnt, facilitando así su uso en entornos de integración continua y montaje automatizado, para los que ofrece librerías &lt;/p&gt;&lt;p&gt;Finalmente, he de aclarar que NDepend es una aplicación comercial, aunque dispone de una versión limitada gratuita utilizable por universidades, desarrolladores open source e incluso, durante un tiempo determinado, de prueba en proyectos comerciales. &lt;/p&gt;&lt;p&gt;En cualquier caso, no dudéis en probarlo: os dará un control sobre vuestro código difícil de conseguir con otras herramientas.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-5499156950095572458?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/c1aTH5eVjkYIG7IIUIy2aWiiEYk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c1aTH5eVjkYIG7IIUIy2aWiiEYk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/c1aTH5eVjkYIG7IIUIy2aWiiEYk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c1aTH5eVjkYIG7IIUIy2aWiiEYk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZGg99OWNMOI:uNK9kOaS8dE:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZGg99OWNMOI:uNK9kOaS8dE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZGg99OWNMOI:uNK9kOaS8dE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZGg99OWNMOI:uNK9kOaS8dE:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=ZGg99OWNMOI:uNK9kOaS8dE:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZGg99OWNMOI:uNK9kOaS8dE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=ZGg99OWNMOI:uNK9kOaS8dE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZGg99OWNMOI:uNK9kOaS8dE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=ZGg99OWNMOI:uNK9kOaS8dE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/ZGg99OWNMOI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/5499156950095572458/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=5499156950095572458" title="3 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/5499156950095572458?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/5499156950095572458?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/ZGg99OWNMOI/ndepend-analiza-fondo-tu-codigo.html" title="NDepend, analiza a fondo tu código" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/ndepend-analiza-fondo-tu-codigo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EMSHo5cSp7ImA9WxJSEUQ.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-2948163147921011571</id><published>2009-05-01T19:40:00.002+02:00</published><updated>2009-05-01T19:41:29.429+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-01T19:41:29.429+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="paranoias" /><category scheme="http://www.blogger.com/atom/ns#" term="humor" /><category scheme="http://www.blogger.com/atom/ns#" term="frases célebres" /><title>Palabras malditas</title><content type="html">&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SesH1CtYalI/AAAAAAAABBI/MB3V3NmkSKQ/image%5B3%5D.png?imgmax=800" width="134" height="134" /&gt;Huye como del diablo de aquél que utilice demasiadas veces las palabras:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Necesitamos&lt;/li&gt;    &lt;li&gt;Debemos&lt;/li&gt;    &lt;li&gt;No podemos&lt;/li&gt;    &lt;li&gt;Sencillo&lt;/li&gt;    &lt;li&gt;Simplemente&lt;/li&gt;    &lt;li&gt;Sólo&lt;/li&gt;    &lt;li&gt;Rápido&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;… y especialmente si las utiliza en el mismo párrafo.&lt;/p&gt;  &lt;p&gt;(Del clásico &lt;a title="Four Letter Words" href="http://www.37signals.com/svn/posts/439-four-letter-words" hreflang="en"&gt;Four Letter Words&lt;/a&gt; –need, must, can’t, easy, just, only, fast- publicado en &lt;a href="http://www.37signals.com/svn/"&gt;Signals vs Noise&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-2948163147921011571?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QnQBboxR2Du9dJPKfRC_Q_47yy8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QnQBboxR2Du9dJPKfRC_Q_47yy8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QnQBboxR2Du9dJPKfRC_Q_47yy8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QnQBboxR2Du9dJPKfRC_Q_47yy8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=HHKXz-QGJLk:rewfhe9N0q8:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=HHKXz-QGJLk:rewfhe9N0q8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=HHKXz-QGJLk:rewfhe9N0q8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=HHKXz-QGJLk:rewfhe9N0q8:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=HHKXz-QGJLk:rewfhe9N0q8:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=HHKXz-QGJLk:rewfhe9N0q8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=HHKXz-QGJLk:rewfhe9N0q8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=HHKXz-QGJLk:rewfhe9N0q8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=HHKXz-QGJLk:rewfhe9N0q8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/HHKXz-QGJLk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/2948163147921011571/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=2948163147921011571" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2948163147921011571?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2948163147921011571?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/HHKXz-QGJLk/palabras-malditas.html" title="Palabras malditas" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/05/palabras-malditas.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMGQX06fCp7ImA9WxJTF0U.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-178427140670451001</id><published>2009-04-26T23:47:00.000+02:00</published><updated>2009-04-26T23:47:00.314+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-26T23:47:00.314+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="curiosidades" /><category scheme="http://www.blogger.com/atom/ns#" term="frases célebres" /><category scheme="http://www.blogger.com/atom/ns#" term="historias" /><title>El hombre que inventó el Control-Alt-Suprimir</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="David J. Bradley (Fotografía: Charles Harris)" border="0" alt="David J. Bradley (Fotografía: Charles Harris)" align="right" src="http://lh5.ggpht.com/_O9D62hXq-ng/Sd4VHxtvnsI/AAAAAAAABBA/CN0Sr3WC7h4/image2.png?imgmax=800" width="128" height="128" /&gt;&lt;/p&gt;  &lt;p&gt;La combinación de teclas Control-Alt-Suprimir lleva con nosotros prácticamente desde el principio de los tiempos ayudándonos a escapar de callejones sin salida. Y como muchas otras pequeñas cosas de la vida, tiene su curiosa historia por detrás.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;David Bradley&lt;/strong&gt; era uno de los doce ingenieros que trabajaron en el diseño del &lt;a title="IBM PC en la wikipedia" href="http://es.wikipedia.org/wiki/IBM_PC"&gt;IBM PC&lt;/a&gt; original a principios de los años 80, implementando el código de la &lt;a title="BIOS en la wikipedia" href="http://es.wikipedia.org/wiki/BIOS"&gt;ROM BIOS&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;El objetivo inicial era crear una combinación de teclas exclusivamente para que los desarrolladores y escritores técnicos pudieran resetear el ordenador en caliente, de forma rápida, puesto que el apagado manual requería la espera de algunos segundos antes de volver a encenderlo para evitar daños a la fuente de alimentación, y cuando esto había que repetirlo muchas veces al día, como era el caso, la pérdida de tiempo era considerable. &lt;/p&gt;  &lt;p&gt;De hecho, al principio ni siquiera se pensaba en trasladar esta función a los usuarios finales de estos ordenadores, pero finalmente resultó tan útil y ahorraba tanto tiempo que difundió y popularizó rápidamente entre los usuarios.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/Sd4VIbZAYMI/AAAAAAAABBE/f2wvSSDyQJU/image13.png?imgmax=800" width="83" height="123" /&gt; La combinación original de teclas era Control-Alt-Escape, pero pensaron que de esa forma alguien podía pulsarlas accidentalmente al encontrarse todas en el lado izquierdo del teclado. Por ello, finalmente se decantaron por una secuencia que era imposible, en los teclados de entonces, reproducir con una única mano. Había nacido el Control-Alt-Suprimir, y para muchos, un icono cultural de nuestros tiempos.&lt;/p&gt;  &lt;p&gt;David Bradley también es famoso por la frase que tanto hizo reír a casi todos durante la celebración del 20 aniversario del IBM PC:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“Yo lo inventé, pero Bill lo hizo famoso”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p align="center"&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/WdGQsBDSEpk&amp;amp;hl=en&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/WdGQsBDSEpk&amp;amp;hl=en&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;Bradley se retiró en 2004, tras cerca de 29 años trabajando en IBM.&lt;/p&gt;  &lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-178427140670451001?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6qAYPpj_DyMf5knV9ZN36xSTVOo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6qAYPpj_DyMf5knV9ZN36xSTVOo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6qAYPpj_DyMf5knV9ZN36xSTVOo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6qAYPpj_DyMf5knV9ZN36xSTVOo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=wxwdcR7s0Rg:2edra6nW5ik:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=wxwdcR7s0Rg:2edra6nW5ik:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=wxwdcR7s0Rg:2edra6nW5ik:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=wxwdcR7s0Rg:2edra6nW5ik:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=wxwdcR7s0Rg:2edra6nW5ik:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=wxwdcR7s0Rg:2edra6nW5ik:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=wxwdcR7s0Rg:2edra6nW5ik:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=wxwdcR7s0Rg:2edra6nW5ik:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=wxwdcR7s0Rg:2edra6nW5ik:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/wxwdcR7s0Rg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/178427140670451001/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=178427140670451001" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/178427140670451001?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/178427140670451001?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/wxwdcR7s0Rg/el-hombre-que-invento-el-control-alt.html" title="El hombre que inventó el Control-Alt-Suprimir" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/04/el-hombre-que-invento-el-control-alt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8DRHg_eip7ImA9WxJTGE8.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-3359378450436405687</id><published>2009-04-19T22:25:00.002+02:00</published><updated>2009-04-27T12:41:15.642+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-27T12:41:15.642+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><category scheme="http://www.blogger.com/atom/ns#" term="consultas" /><category scheme="http://www.blogger.com/atom/ns#" term="programación" /><title>ASP.NET MVC: trece preguntas básicas</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="10 Preguntas con respuesta ASP.NET MVC" border="0" alt="10 Preguntas con respuesta ASP.NET MVC" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/SetPkqG0LBI/AAAAAAAABBQ/pO2BP-LO6Nk/image9.png?imgmax=800" width="244" height="199" /&gt; En marzo de 2008 publiqué un post en el que se recogían respuestas a diez preguntas básicas sobre el framework ASP.NET MVC, que por aquellos entonces se encontraba todavía en una versión muy preliminar, la Preview 2. &lt;/p&gt;&lt;p&gt;Más de un año después, coincidiendo con el reciente lanzamiento de la versión 1.0, voy a actualizar el contenido y las preguntas conforme a la evolución de los desarrollos y a lo que he podido profundizar en el tema desde entonces.&lt;/p&gt;  &lt;p&gt;Las cuestiones que trataré son las siguientes:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="#p1"&gt;Empecemos desde el principio, ¿qué es MVC?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p2"&gt;¿Qué ventajas tiene el uso del patrón MVC?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p3"&gt;¿Qué es ASP.NET MVC framework?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p4"&gt;¿Es el primer framework MVC creado para .NET?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p5"&gt;Como desarrollador de aplicaciones web con ASP.NET, ¿me afectará la llegada de este framework?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p6"&gt;Entonces, ¿no significa la aparición del framework MVC la muerte próxima de los Webforms de ASP.NET?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p7"&gt;¿Vale la pena pasarse a ASP.NET MVC o sigo usando Webforms?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p8"&gt;¿Puedo convertir mi proyecto ASP.NET Webforms a ASP.NET MVC?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p9"&gt;¿Se puede utilizar ASP.NET Ajax con el framework MVC?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p10"&gt;¿Se puede utilizar VB.NET con ASP.NET MVC?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p11"&gt;¿Puedo usar LINQ desarrollando aplicaciones con ASP.NET MVC framework?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p12"&gt;¿Qué tipo de tecnologías puedo utilizar en las vistas?&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#p13"&gt;¿Es ASP.NET MVC framework software libre?&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;h3 id="p1"&gt;1. Empecemos desde el principio, ¿qué es MVC?&lt;/h3&gt; Aunque de forma algo simplista, podríamos definir MVC como un patrón arquitectural que describe una forma de desarrollar aplicaciones software separando los componentes en tres grupos (o capas):   &lt;ul&gt;   &lt;li&gt;El &lt;strong&gt;Modelo&lt;/strong&gt; que contiene una representación de los datos que maneja el sistema, su lógica de negocio, y sus mecanismos de persistencia. &lt;/li&gt;    &lt;li&gt;La &lt;strong&gt;Vista&lt;/strong&gt;, o interfaz de usuario, que compone la información que se envía al cliente y los mecanismos interacción con éste. &lt;/li&gt;    &lt;li&gt;El &lt;strong&gt;Controlador&lt;/strong&gt;, que actúa como intermediario entre el Modelo y la Vista, gestionando el flujo de información entre ellos y las transformaciones para adaptar los datos a las necesidades de cada uno. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;MVC&lt;/strong&gt; son las siglas de Modelo-Vista-Controlador, y se trata de un modelo muy maduro y que ha demostrado su validez a lo largo de los años en todo tipo de aplicaciones, y sobre multitud de lenguajes y plataformas de desarrollo.&lt;/p&gt;  &lt;p&gt;Puedes encontrar más información en: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://es.wikipedia.org/wiki/Modelo_Vista_Controlador"&gt;Wikipedia, Modelo-Vista-Controlador&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html"&gt;Documentos originales de definición de MVC, de Trygve M. H. Reenskaug, en Xerox (¡año 1978!)&lt;/a&gt;&lt;a href="http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html" hreflang="en"&gt;&amp;#160;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.ulpgc.es/otros/tutoriales/java/Apendice/arq_mvc.html"&gt;Tutorial de Java, Arquitectura MVC&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms978748.aspx" hreflang="en"&gt;Model-View-Controller Web presentation pattern en MSDN&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h3 id="p2"&gt;2. ¿Qué ventajas tiene el uso del patrón MVC?&lt;/h3&gt; Como siempre, esto de enumerar ventajas es algo subjetivo, por lo que puede que pienses que falta o sobra alguna &lt;em&gt;(¡&lt;a title="¿alguna ventaja o inconveniente adicional del patrón MVC?" href="http://kontactr.com/user/jmaguilar" target="_blank"&gt;dímelo&lt;/a&gt;!)&lt;/em&gt;. En un primer asalto podríamos aportar las siguientes:   &lt;ul&gt;   &lt;li&gt;Clara separación entre interfaz, lógica de negocio y de presentación, que además provoca parte de las ventajas siguientes. &lt;/li&gt;    &lt;li&gt;Sencillez para crear distintas representaciones de los mismos datos. &lt;/li&gt;    &lt;li&gt;Facilidad para la realización de pruebas unitarias de los componentes, así como de aplicar &lt;a href="http://es.wikipedia.org/wiki/Tdd"&gt;desarrollo guiado por pruebas (&lt;acronym&gt;TDD&lt;/acronym&gt;)&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Reutilización de los componentes. &lt;/li&gt;    &lt;li&gt;Simplicidad en el mantenimiento de los sistemas. &lt;/li&gt;    &lt;li&gt;Facilidad para desarrollar prototipos rápidos. &lt;/li&gt;    &lt;li&gt;Los desarrollos suelen ser más escalables. &lt;/li&gt; &lt;/ul&gt; Pero bueno, también se pueden citar algunos inconvenientes:   &lt;ul&gt;   &lt;li&gt;Tener que ceñirse a una estructura predefinida, lo que a veces puede incrementar la complejidad del sistema. Hay problemas que son más difíciles de resolver respetando el patrón MVC. &lt;/li&gt;    &lt;li&gt;La curva de aprendizaje para los nuevos desarrolladores se estima mayor que la de modelos más simples como Webforms. &lt;/li&gt;    &lt;li&gt;La distribución de componentes obliga a crear y mantener un mayor número de ficheros. &lt;/li&gt; &lt;/ul&gt;  &lt;h3 id="p3"&gt;3. ¿Qué es ASP.NET MVC Framework?&lt;/h3&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Plantilla de aplicación ASP.NET MVC" border="0" alt="Plantilla de aplicación ASP.NET MVC" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/SetPlffhMJI/AAAAAAAABBU/gO6lUo1AHso/image8.png?imgmax=800" width="244" height="187" /&gt; Es un framework, un entorno de trabajo cuya primera versión acaba de ver la luz, creado por Microsoft con objeto de ayudarnos a desarrollar aplicaciones que sigan la filosofía MVC sobre ASP.NET.&lt;/p&gt;  &lt;p&gt;Además del conjunto de librerías (ensamblados) que proporcionan las nuevas funcionalidades a nivel de API, incluye plantillas y herramientas que se integran en Visual Studio 2008 (tanto en la versión Express de Visual Web Developer como en sus hermanas mayores) para facilitarnos un poco las cosas.&lt;/p&gt;  &lt;p&gt;Una vez instalado el marco de trabajo (&lt;a title="Descargar ASP.NET MVC" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b" target="_blank"&gt;que puedes iniciar desde aquí&lt;/a&gt; o desde el &lt;a title="Web Platform Installer" href="http://www.microsoft.com/Web/downloads/platform.aspx" target="_blank"&gt;Web Platform Installer&lt;/a&gt;), Visual Studio mostrará un nuevo tipo de proyecto (&lt;em&gt;ASP.NET MVC Web Application&lt;/em&gt;) que nos permitirá crear el esqueleto básico de un proyecto de este tipo. Y ya para cuando estemos en faena, el entorno ofrece multitud de utilidades para hacer nuestro trabajo más fácil, como la herramienta de creación de vistas automáticas, el desplazamiento entre controladores y vistas, o plantillas para la definición de controladores, entre otras.&lt;/p&gt;  &lt;h3 id="p4"&gt;4. ¿Es el primer framework MVC creado para .NET?&lt;/h3&gt;  &lt;p&gt;No, ni el único. Existen multitud de frameworks MVC para ASP.Net, como &lt;a href="http://www.castleproject.org/monorail/index.html"&gt;MonoRail&lt;/a&gt;, &lt;a href="http://mavnet.sourceforge.net/"&gt;Maverick.Net&lt;/a&gt;, &lt;a href="http://www.codeplex.com/ProMesh"&gt;ProMesh.Net&lt;/a&gt; y muchos otros.&lt;/p&gt;  &lt;h3 id="p5"&gt;5. Como desarrollador de aplicaciones web con ASP.NET, ¿me afectará la llegada de este framework?&lt;/h3&gt;  &lt;p&gt;No necesariamente. Puedes seguir desarrollando aplicaciones como hasta ahora, con Webforms. Si así lo decides, este nuevo framework no te afectará nada; simplemente, ignóralo.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;De todas formas, ya que has leído hasta aquí, permíteme un consejo: aprende a utilizar ASP.NET MVC framework. Después podrás decidir con conocimiento de causa si te conviene o no.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3 id="p6"&gt;6. Entonces, ¿no significa la aparición del framework MVC la muerte próxima de los Webforms de ASP.NET?&lt;/h3&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Diseñador de Webforms" border="0" alt="Diseñador de Webforms" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SetPmELDrYI/AAAAAAAABBY/pRjZ30TRf3A/image12.png?imgmax=800" width="244" height="190" /&gt; En absoluto. Son simplemente dos filosofías diferentes para conseguir lo mismo, ¡páginas web!&lt;/p&gt;  &lt;p&gt;La tecnología de Webforms es muy útil para asemejar el desarrollo de aplicaciones web a las de escritorio, ocultando la complejidad derivada del entorno desconectado y &lt;em&gt;stateless&lt;/em&gt; (sin conservación de estado) del protocolo HTTP a base de complejos &lt;em&gt;roundtrips&lt;/em&gt;, &lt;em&gt;postbacks&lt;/em&gt; y &lt;em&gt;viewstates&lt;/em&gt;, lo que nos permite crear de forma muy productiva formularios impresionantes y que el funcionamiento de nuestra aplicación esté guiado por eventos, como si estuviéramos programando Winforms.&lt;/p&gt;  &lt;p&gt;Sin embargo, esta misma potencia a veces hace que las páginas sean pesadas y difícilmente mantenibles, además de dificultar enormemente la realización de pruebas automatizadas. Y por no hablar de comportamientos extraños cuando intentamos intervenir en el ciclo de vida de las páginas, por ejemplo para la carga y descarga de controles dinámicos.&lt;/p&gt;  &lt;p&gt;ASP.NET MVC propone una forma distinta de trabajar, más cercana a la realidad del protocolo y, curiosamente, más parecida a cómo se hacía unos años atrás, cuando controlábamos cada byte que se enviaba al cliente o se recibía de éste. No existen, por tanto, conceptos como el mantenimiento del estado en el &lt;em&gt;viewstate&lt;/em&gt;, ni el &lt;em&gt;postback&lt;/em&gt;, ni nos valdrán los controles de servidor basados en estas características, que son la mayoría. Sin embargo, dado que el framework está creado sobre ASP.NET, será posible utilizar páginas maestras, codificar las vistas en un .aspx utilizando C# o VB.NET, usar los mecanismos de seguridad internos, control de caché, gestión de sesiones, localización, etc.&lt;/p&gt;  &lt;h3 id="p7"&gt;7. ¿Vale la pena pasarse a ASP.NET MVC o sigo usando Webforms?&lt;/h3&gt;  &lt;p&gt;En mi opinión, probablemente no se trate de decidirse por una u otra tecnología, sino de conocer ambas y utilizar la más apropiada en cada momento. Hay muchos aspectos a tener en cuenta, por citar algunos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="#xequipo"&gt;los conocimientos y experiencia del equipo de desarrollo&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#xcontroles"&gt;la necesidad de usar controles o sistemas preexistentes&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#xmadurez"&gt;la madurez del framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#xfuturo"&gt;el futuro de la tecnología&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#xbeneficios"&gt;la importancia de ventajas propias de MVC&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#xtipo"&gt;el tipo de sistema que se pretende construir&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Vamos a reflexionar sobre cada uno de estos puntos, y la decisión os la dejo a vosotros. ;-)&lt;/p&gt;  &lt;h4 id="xequipo"&gt;El equipo de desarrollo&lt;/h4&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="right" src="http://lh4.ggpht.com/_O9D62hXq-ng/SetPnvCSgTI/AAAAAAAABBc/tuCTGRIKU8c/image131.png?imgmax=800" width="229" height="154" /&gt;&lt;/p&gt;  &lt;p&gt;La tecnología de formularios web (Webforms) permite el desarrollo rápido de aplicaciones (RAD) a través de diseñadores visuales con los que es posible componer una página compleja y definir el comportamiento del interfaz a golpe de ratón, puesto que el framework se encarga de realizar parte del trabajo duro, como el mantenimiento del estado entre peticiones, convertir propiedades de controles en código HTML y CSS, o incluso generar scripts que realicen determinadas tareas en cliente. De hecho, siguiendo este modelo es posible crear aplicaciones para Internet sin tener apenas idea de las particularidades inherentes al desarrollo web, lo que permite que muchos programadores procedentes del mundo del escritorio puedan ser productivos muy rápidamente, aunque sea a costa de generar páginas mucho más pesadas y con un código de marcado complejo.&lt;/p&gt;  &lt;p&gt;No hay que olvidar que para determinado tipo de aplicaciones, los Webforms son una buena opción, tanto como lo han sido hasta ahora. Por tanto, si el equipo de desarrollo tiene ya experiencia creando aplicaciones con esta tecnología y no poseen grandes conocimientos sobre programación web de más bajo nivel ni experiencia previa trabajando con el patrón MVC, deberíamos pensárnoslo antes de dar el salto a ASP.NET MVC, puesto que la productividad, al menos inicialmente, va a caer.&lt;/p&gt;  &lt;p&gt;ASP.NET MVC requiere un conocimiento más profundo del entorno web y sus tecnologías subyacentes, puesto que a la vez que ofrece un control mucho más riguroso sobre los datos que se envían y reciben desde el cliente, exige una mayor responsabilidad por parte del desarrollador, ya que deberá encargarse él mismo de mantener el estado entre peticiones, maquetar las vistas, crear las hojas de estilo apropiadas, e incluso los scripts. Esto, sin embargo, no difiere mucho de la forma de trabajar unos años atrás, y es posible que en el equipo de trabajo haya desarrolladores experimentados que se sientan incluso más cómodos trabajando a este nivel que utilizando abstracciones como las provistas por ASP.NET Webforms.&lt;/p&gt;  &lt;h4 id="xcontroles"&gt;Controles y módulos reutilizables&lt;/h4&gt;  &lt;p&gt;Otro aspecto a valorar antes de dar el salto a ASP.NET MVC es que existe una altísima probabilidad de que no podamos utilizar sistemas o componentes que hayamos desarrollado previamente, lo cual redundará en los tiempos de desarrollo y productividad del equipo de trabajo. No nos valdrán los controles de servidor, ni las plantillas de proyectos, ni los generadores de código, y en muchos casos ni siquiera la &lt;em&gt;herencia de editor&lt;/em&gt; (que por muy &lt;a title="Ojo a los antipatrones" href="http://www.variablenotfound.com/2008/02/ojo-los-antipatrones.html"&gt;antipatrón&lt;/a&gt; que sea seguro que acostumbramos a utilizar).&lt;/p&gt;  &lt;p&gt;Probablemente en breve dispondremos de componentes para ASP.NET MVC generados por la propia comunidad de desarrolladores, ya sea en forma de &lt;em&gt;helpers (&lt;/em&gt;métodos estáticos de generación de código en cliente), en forma de vistas parciales (por ejemplo en archivos .ASCX) y nos permitan reutilizar código, o incluso como controles de servidor (ya se puede ver algo de eso en el ensamblado &lt;a title="MVC Futures assembly" href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471"&gt;MVC Futures&lt;/a&gt;, disponible en CodePlex). &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Puedes ver un ejemplo de &lt;em&gt;helper&lt;/em&gt; en el post “&lt;a title="Helper para desplegables enlazados con ASP.NET MVC y jQuery" href="http://www.variablenotfound.com/2008/12/helper-para-desplegables-enlazados-con.html"&gt;Helper para desplegables enlazados con ASP.NET MVC y jQuery&lt;/a&gt;”.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h4 id="xmadurez"&gt;Madurez del framework&lt;/h4&gt;  &lt;p&gt;ASP.NET MVC es un framework recién salido del horno, por lo cual su adopción implica ciertos riesgos, ya superados por los veteranos Webforms.&lt;/p&gt;  &lt;p&gt;En primer lugar, es bastante probable que durante un primer periodo de adopción comiencen a surgir bugs, agujeros de seguridad y otros problemas que podrán hacer tambalear los cimientos de los sistemas que utilicen este marco de trabajo. También es cierto que dada la disponibilidad del código fuente del mismo y su relativa simplicidad frente a los formularios web, los inconvenientes que puedan aparecer podrían ser rápidamente subsanados.&lt;/p&gt;  &lt;p&gt;La madurez también se hace patente en la cantidad y calidad de información disponible. ASP.NET MVC, aunque cuenta con una comunidad de desarrolladores bastante entusiasta, son una minoría comparándola con su veterana competencia.&lt;/p&gt;  &lt;p&gt;Y lo mismo ocurre con el número ingente de componentes y controles reutilizables disponibles para Webforms. Dado que no son compatibles con el framework MVC, se parte de una situación de clara desventaja frente a éstos, aunque como comentaba anteriormente seguro que con el tiempo este aspecto irá mejorando.&lt;/p&gt;  &lt;h4 id="xfuturo"&gt;Consideraciones sobre el futuro de la tecnología&lt;/h4&gt;  &lt;p&gt;Si lo que te preocupa es el futuro de los Webforms, has de saber que Microsoft va a seguir dándoles soporte y mejorándolos, como no podía ser de otra forma. Por tanto, de momento no es necesario que bases tu decisión en esto.&lt;/p&gt;  &lt;p&gt;Eso sí, hay quien opina que ASP.NET MVC será el estándar de creación de sistemas web en unos años, por lo que en cualquier caso se trata de una tecnología que no habría que perder de vista…&lt;/p&gt;  &lt;h4 id="xbeneficios"&gt;Beneficios de ASP.NET MVC&lt;/h4&gt;  &lt;p&gt;Las ventajas de la arquitectura MVC, descritas anteriormente, y las bondades del diseño del framework son un buen aliciente para comenzar a trabajar con ASP.NET MVC. De hecho, deberíamos tener muy en cuenta en qué aspectos nuestros desarrollos van a beneficiarse del uso de esta tecnología y valorar si estas ventajas compensan los inconvenientes que su adopción va a suponer:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;la separación de aspectos impuesta por el patrón MVC obligará a tener un código más limpio y estructurado, independizando totalmente la interfaz de la lógica de navegación y, por supuesto, de la de negocio. &lt;/li&gt;    &lt;li&gt;de la misma forma, esta división facilita el trabajo en equipo, pues permite el avance en paralelo en las distintas capas. &lt;/li&gt;    &lt;li&gt;si entre nuestras prioridades está el asegurar el correcto funcionamiento de nuestros componentes a través de pruebas unitarias, o hemos optado por utilizar una metodología de desarrollo guiado por pruebas (&lt;a title="Desarrollo guiado por pruebas (TDD)" href="http://es.wikipedia.org/wiki/Tdd"&gt;TDD&lt;/a&gt;), ASP.NET MVC nos vendrá de perlas. La separación de aspectos citada anteriormente facilita la creación de pruebas específicas para los componentes de cada capa de forma independiente, así como el uso de técnicas avanzadas (&lt;em&gt;&lt;a title="Mock object en Wikipedia" href="http://es.wikipedia.org/wiki/Mock_object"&gt;mocking&lt;/a&gt;&lt;/em&gt;, &lt;a title="Inyección de dependencias" href="http://es.wikipedia.org/wiki/Inyecci%C3%B3n_de_dependencias"&gt;inyección de dependencias&lt;/a&gt;…) para que éstas sean lo más completas posible. &lt;/li&gt;    &lt;li&gt;las friendly URLS, o direcciones amigables, es un beneficio directo del uso del framework de Microsoft. Estrictamente hablando no es mérito de la plataforma MVC, sino del juego de clases presentes en el espacio de nombres &lt;a title="System.Web.Routing (Espacio de nombres) ()" href="http://msdn.microsoft.com/es-es/library/system.web.routing.aspx"&gt;System.Web.Routing&lt;/a&gt;, incluidas en .NET framework 3.5, pero en cualquier caso si optamos por esta tecnología la tendremos “de serie”, con las ventajas que ello conlleva (SEO, REST, claridad en direcciones…). &lt;/li&gt;    &lt;li&gt;al final, el software será mucho más mantenible; el hecho de que los componentes estén separados y bien estructurados simplificará las tareas de mantenimiento. &lt;/li&gt;    &lt;li&gt;el conjunto de convenciones en cuanto a la estructura de proyectos y de nombrado y disposición de elementos facilitará el desarrollo una vez sean asimiladas. &lt;/li&gt; &lt;/ul&gt;  &lt;h4 id="xtipo"&gt;El tipo de sistema&lt;/h4&gt;  &lt;p&gt;A la hora de plantearse un cambio de este tipo es imprescindible tener en cuenta el tipo de proyecto en el que solemos trabajar. No es lo mismo desarrollar un sitio web colaborativo destinado a un gran número de usuarios, como Facebook o Digg, donde el control fino sobre la entrada y salida es crucial para asegurar aspectos como la escalabilidad, cumplimiento de estándares, o accesibilidad, que crear una aplicación de gestión que utilizarán un grupo relativamente reducido de usuarios desde una intranet corporativa.&lt;/p&gt;  &lt;p&gt;Para el primer caso, ASP.NET MVC es una buena opción. La simplicidad de la arquitectura MVC hace que el &lt;a title="La serpiente ASP.NET MVC" href="http://www.variablenotfound.com/2008/06/la-serpiente-aspnet-mvc.html"&gt;ciclo de vida de las páginas&lt;/a&gt; de este framework sea mucho más sencillo que el de los Webforms, y la ausencia de automatismos y persistencia de estado aligera en gran medida el peso y complejidad de las páginas, lo cual redundará muy positivamente en el rendimiento del sistema. Si además el proyecto requiere o resulta beneficiado por el uso de direcciones URL amigables (por razones de SEO, para presentar un interfaz claro de tipo &lt;a title="Representational State Transfer, en la wikipedia" href="http://es.wikipedia.org/wiki/Representational_State_Transfer"&gt;REST&lt;/a&gt;, o cualquier otro motivo), más aún. &lt;/p&gt;  &lt;p&gt;Un ejemplo de aplicación real de este tipo es la famosa comunidad &lt;a title="Stack Overflow" href="http://stackoverflow.com/" hreflang="en"&gt;StackOverflow&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;En cambio, el segundo caso, cuando se trata de crear pesadas aplicaciones de gestión con interfaces de usuario complejos y en las que no es especialmente relevante la calidad del código HTML enviado al cliente, ni el peso de éstas al ser entornos cerrados y controlados, ASP.NET Webforms sigue siendo la opción más razonable. Las facilidades para el desarrollo rápido de aplicaciones (RAD) son mayores utilizando formularios web, aunque sea a cambio de sacrificar aspectos como la separación de código e interfaz, o la facilidad para realización de pruebas unitarias.&lt;/p&gt;  &lt;h3 id="p8"&gt;8. ¿Puedo convertir mi proyecto ASP.NET Webforms a ASP.NET MVC?&lt;/h3&gt;  &lt;p&gt;Sí, pero tardarás un buen rato ;-)&lt;/p&gt;  &lt;p&gt;Al menos que conozca, no existe ninguna herramienta ni siquiera capaz de intentar realizar tal proeza. Hay que tener en cuenta que el cambio de una a otra tecnología no es una mera traducción como podría ser convertir una aplicación VB.NET a C#; se trata de un nuevo marco de trabajo que afecta sobre todo a la presentación y control de flujo del sistema. &lt;/p&gt;  &lt;p&gt;Si tienes unas buenas clases de lógica de negocio, bien aisladas de la tecnología Webforms (como debería ser, por otra parte), probablemente sean los únicos componentes que puedas reutilizar de forma directa, sin grandes cambios. El resto, es decir, todo lo relativo a la interacción con el usuario, habría que convertirlo de forma manual, y por tanto, probablemente habría que pensarse bien si vale la pena hacerlo.&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3 id="p9"&gt;9. ¿Se puede utilizar ASP.NET Ajax con el framework MVC?&lt;/h3&gt;  &lt;p&gt;Si nos estamos refiriendo a la posibilidad de utilizar controles de servidor Ajax, como el célebre &lt;code&gt;UpdatePanel&lt;/code&gt; o los controles del &lt;a title="ASP.NET Ajax Control Toolkit" href="http://www.asp.net/AJAX/AjaxControlToolkit/" hreflang="en"&gt;ASP.NET Ajax Control Toolkit&lt;/a&gt;, la respuesta es rotunda: &lt;strong&gt;no&lt;/strong&gt;. De hecho, el modelo MVC no permite el uso de controles de servidor (&lt;code&gt;runat=&amp;quot;server&amp;quot;&lt;/code&gt;); bueno, o al menos no lo permite de la forma en que veníamos haciéndolo, pues han dejado de existir aspectos tan fundamentales para ellos como el &lt;em&gt;viewstate&lt;/em&gt; o los &lt;em&gt;postbacks&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Ahora bien, si la pregunta la generalizamos como “¿se pueden utilizar librerías Ajax con el framework MVC?” la respuesta es &lt;strong&gt;absolutamente&lt;/strong&gt;. De hecho, ASP.NET MVC se lleva de fábula con librerías de scripting como las incluidas en el framework ASP.NET 3.5, o con la magnífica &lt;a title="jQuery" href="http://jquery.com/" hreflang="en"&gt;jQuery&lt;/a&gt;. La limpieza de la filosofía MVC hace posible que sea realmente sencillo realizar desde cliente llamadas a los controladores mediante scripting con objeto de obtener datos, actualizar porciones de contenido de la página con el marcado de la vista correspondiente, o, en definitiva, interactuar con el servidor.&lt;/p&gt;  &lt;p&gt;En este mismo blog puedes encontrar &lt;a title="ASP.NET MVC en Variable not found" href="http://www.variablenotfound.com/search/label/aspnetmvc"&gt;multitud de ejemplos&lt;/a&gt; de integración de jQuery y ASP.NET MVC, que aunque implementados con las previews del framework (¡a ver si un día tengo un rato y los voy actualizando!), pueden ayudarte a entender cómo hacerlo.&lt;/p&gt;  &lt;p&gt;Otro aspecto interesante respecto a jQuery es que &lt;a title="jQuery, Microsoft y tú" href="http://www.variablenotfound.com/2008/09/jquery-microsoft-y-t.html"&gt;esta librería entró a formar parte de la plataforma de desarrollo de Microsoft&lt;/a&gt; el pasado mes de septiembre, lo que en la práctica aporta varias ventajas: la primera, que jQuery viene incluido de serie en las plantillas de proyectos ASP.NET MVC; la segunda, que Microsoft se ha esforzado por mejorar la &lt;a title="Intellisense completo para jQuery" href="http://www.variablenotfound.com/2008/11/intellisense-completo-para-jquery-en.html"&gt;integración con Visual Studio&lt;/a&gt; de esta librería, facilitando archivos que hacen posible el disfrute de &lt;em&gt;intellisense&lt;/em&gt; mientras la utilizamos.&lt;/p&gt;  &lt;h3 id="10"&gt;10. ¿Se puede utilizar VB.NET con ASP.NET MVC?&lt;/h3&gt;  &lt;p&gt;Por supuesto. Aunque la mayoría de código que se encuentra por la red utiliza C#, probablemente porque es el lenguaje en el que ha sido desarrollado y sobre el que se están exponiendo más ejemplos desde las previews más tempranas, cualquier lenguaje .NET podría ser utilizado sin problema para desarrollar aplicaciones sobre este framework. &lt;/p&gt;  &lt;p&gt;A nivel de entorno de desarrollo, Visual Basic ofrece el mismo nivel de ayudas y plantillas que C#, pero desconozco si esto es así en otros lenguajes.&lt;/p&gt;  &lt;h3 id="p11"&gt;11. ¿Puedo usar LINQ desarrollando aplicaciones con ASP.NET MVC framework?&lt;/h3&gt;  &lt;p&gt;Sí, de hecho se complementan a la perfección.&lt;/p&gt;  &lt;p&gt;Aunque LINQ como tal sólo es un mecanismo de consulta integrado en los lenguajes de programación, las tecnologías &lt;acronym title="Object-Relational Mapping"&gt;ORM&lt;/acronym&gt; que lo rodean, como LINQ2SQL o Entity Framework son ideales para implementar los componentes propios del &lt;strong&gt;M&lt;/strong&gt;odelo (la M de “MVC”). En aplicaciones relativamente simples, estas clases podrían generarse con los diseñadores visuales del entorno de desarrollo, o de forma externa con herramientas como SQLMetal, facilitándonos enormemente el trabajo.&lt;/p&gt;  &lt;p&gt;Este es un buen momento para comentar que una de las grandes críticas que se están haciendo a la implementación del framework ASP.NET MVC es que parece hacer olvidado la “M”. Si bien el marco de trabajo establece con claridad el alcance y responsabilidades de los controladores y las vistas y dota de herramientas y convenciones específicas a cada una de estas capas, no ocurre lo mismo con el Modelo, que queda totalmente al libre albedrío del desarrollador.&lt;/p&gt;&lt;h3 id="p12"&gt;12. ¿Qué tipo de tecnologías puedo utilizar en las vistas?&lt;/h3&gt;  &lt;p&gt;El objetivo de las vistas es componer el interfaz de usuario y los mecanismos de interacción con el usuario. Lo habitual será utilizar XHTML, CSS y Javascript, aderezado con bloques de código de servidor que se ejecutará en el momento de &lt;em&gt;renderizar&lt;/em&gt; la página.&lt;/p&gt;  &lt;p&gt;También puedes utilizar la tecnología Ajax para enviar u obtener información desde el servidor, siempre mediante llamadas a acciones definidas en el controlador, que te permitirán crear interfaces más dinámicos y actuales.&lt;/p&gt;  &lt;p&gt;Pero sobre todo, nada de utilizar controles de servidor (Label, Button, Dropdowns…). Estos deberán ser sustituidos por sus elementos XHTML equivalentes, lo que implica que perderemos los automatismos provistos por Webforms para el mantenimiento del estado de los controles.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px 0px 5px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:dc312513-c5aa-4ac5-abba-94e2ac8f72c8" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt; each&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;var name in names&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;test &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name == 'Jose'&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;p&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Yo mismo&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;p&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;p&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Amigo: ${name}  &lt;br /&gt;  &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;test&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;p&gt;Otra posibilidad interesante que aprovecha y demuestra la flexibilidad de la arquitectura de ASP.NET MVC framework, es la utilización de motores de vistas distintos al estándar. Existen multitud de motores ligeros (&lt;a title="NHaml View Engine" href="http://code.google.com/p/nhaml/"&gt;NHaml&lt;/a&gt;, &lt;a title="Spark View Engine" href="http://dev.dejardin.org/"&gt;Spark&lt;/a&gt;, &lt;a title="Brail View Engine" href="http://www.codeplex.com/MVCContrib/Wiki/View.aspx?title=Brail&amp;amp;referringTitle=Documentation"&gt;Brail&lt;/a&gt;, &lt;a title="NVelocity View Engine" href="http://www.castleproject.org/others/nvelocity/index.html"&gt;NVelocity&lt;/a&gt;…), cada uno con su propio lenguaje de marcas y convenciones, que permiten la definición de vistas a partir de plantillas como la que se muestra en el lateral (ejemplo de Spark).&amp;#160;&lt;/p&gt;&lt;h3 id="p13"&gt;13. ¿Es ASP.NET MVC framework software libre?&lt;/h3&gt;&lt;p&gt;He aquí una de las grandes novedades respecto al post que escribí un año atrás. Por aquellos tiempos era inimaginable que esta pregunta pudiera responderse de forma afirmativa, pero… efectivamente, &lt;strong&gt;ASP.NET MVC Framework es software libre&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;A primeros de abril de 2009 se comenzó a distribuir oficialmente el código fuente de ASP.NET MVC con licencia &lt;a title="Licencia MS-PL" href="http://www.microsoft.com/spain/sharedsource/licensingbasics/publiclicense.mspx"&gt;MS-PL&lt;/a&gt; (Microsoft Public License), un modelo de licencia aprobado por la &lt;a title="Open Source Initiative" href="http://www.opensource.org/" hreflang="en"&gt;OSI&lt;/a&gt; (Open Source Initiative) que permite el uso del software en aplicaciones comerciales y no comerciales.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-3359378450436405687?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wsBLgUWotBy1uq3s6xCb33UsnRA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wsBLgUWotBy1uq3s6xCb33UsnRA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wsBLgUWotBy1uq3s6xCb33UsnRA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wsBLgUWotBy1uq3s6xCb33UsnRA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=bzKyXJGfktM:D1CZMn7oTHY:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=bzKyXJGfktM:D1CZMn7oTHY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=bzKyXJGfktM:D1CZMn7oTHY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=bzKyXJGfktM:D1CZMn7oTHY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=bzKyXJGfktM:D1CZMn7oTHY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=bzKyXJGfktM:D1CZMn7oTHY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=bzKyXJGfktM:D1CZMn7oTHY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=bzKyXJGfktM:D1CZMn7oTHY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=bzKyXJGfktM:D1CZMn7oTHY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/bzKyXJGfktM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/3359378450436405687/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=3359378450436405687" title="6 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3359378450436405687?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3359378450436405687?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/bzKyXJGfktM/aspnet-mvc-trece-preguntas-basicas.html" title="ASP.NET MVC: trece preguntas básicas" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/04/aspnet-mvc-trece-preguntas-basicas.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYDRHo5fyp7ImA9WxJQFE8.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-2152904230891176161</id><published>2009-04-05T23:24:00.002+02:00</published><updated>2009-05-27T14:09:35.427+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-27T14:09:35.427+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jquery" /><category scheme="http://www.blogger.com/atom/ns#" term="desarrollo" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><title>Helper para desplegables enlazados actualizado para ASP.NET MVC 1.0.</title><content type="html">&lt;img style="margin: 0px 0px 5px 5px; display: inline" border="0" alt="Una cascada" align="right" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SGPTmkbv-4I/AAAAAAAAAj8/FYJCFM3v1SY/s320/cascada.png" width="128" height="159" /&gt;   &lt;p&gt;He actualizado a la versión 1.0 de ASP.NET MVC framework el ejemplo de &lt;a title="Helper para crear desplegables enlazados" href="http://www.variablenotfound.com/2008/12/helper-para-desplegables-enlazados-con.html"&gt;Helper para crear desplegables enlazados&lt;/a&gt; (&lt;em&gt;cascading dropdowns&lt;/em&gt;) con jQuery que escribí unos meses atrás. &lt;/p&gt;  &lt;p&gt;El contenido del &lt;a title="Helper para crear desplegables enlazados" href="http://www.variablenotfound.com/2008/12/helper-para-desplegables-enlazados-con.html"&gt;post&lt;/a&gt; sigue siendo válido, sólo ha sido necesario retocar algunos detallitos en el código debido a los cambios introducidos en el framework desde la versión Beta.&lt;/p&gt;  &lt;p&gt;&lt;a title="Helper para desplegables enlazados" href="http://cid-c3a43a99b617d787.skydrive.live.com/self.aspx/P%c3%bablico/variablenotfound.com/ASP.NET%20MVC/ASP.NET%20MVC%201.0/MvcCascadingDropDowns.1.0.zip"&gt;Descargar proyecto (comprimido en .zip)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Requisitos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Visual Studio 2008/&lt;a title="Web Developer Express 2008" href="http://www.microsoft.com/express/vwd/"&gt;Web Developer Express 2008&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Service Pack 1 (VS2008/VWD2008) &lt;/li&gt;    &lt;li&gt;&lt;a title="Descargar ASP.NET MVC framework 1.0" href="http://www.asp.net/mvc/download/"&gt;ASP.NET MVC framework 1.0&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-2152904230891176161?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QZTwLka5EbMemk5-z6mS8QCDIs4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QZTwLka5EbMemk5-z6mS8QCDIs4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QZTwLka5EbMemk5-z6mS8QCDIs4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QZTwLka5EbMemk5-z6mS8QCDIs4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WEjp1J_gdt4:7JhSUU6qsu0:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WEjp1J_gdt4:7JhSUU6qsu0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WEjp1J_gdt4:7JhSUU6qsu0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WEjp1J_gdt4:7JhSUU6qsu0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WEjp1J_gdt4:7JhSUU6qsu0:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WEjp1J_gdt4:7JhSUU6qsu0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WEjp1J_gdt4:7JhSUU6qsu0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WEjp1J_gdt4:7JhSUU6qsu0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WEjp1J_gdt4:7JhSUU6qsu0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/WEjp1J_gdt4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/2152904230891176161/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=2152904230891176161" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2152904230891176161?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/2152904230891176161?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/WEjp1J_gdt4/helper-para-desplegables-enlazados.html" title="Helper para desplegables enlazados actualizado para ASP.NET MVC 1.0." /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_O9D62hXq-ng/SGPTmkbv-4I/AAAAAAAAAj8/FYJCFM3v1SY/s72-c/cascada.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/04/helper-para-desplegables-enlazados.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcGQXozeSp7ImA9WxVbFkU.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-1600026792488953353</id><published>2009-04-02T17:42:00.001+02:00</published><updated>2009-04-02T17:43:40.481+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-02T17:43:40.481+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="noticias" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspnetmvc" /><category scheme="http://www.blogger.com/atom/ns#" term="software libre" /><category scheme="http://www.blogger.com/atom/ns#" term="microsoft" /><title>¡ASP.NET MVC es open source!</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 5px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ASP.NET MVC es open source" border="0" alt="ASP.NET MVC es open source" align="right" src="http://lh3.ggpht.com/_O9D62hXq-ng/SdTcxSYhQ0I/AAAAAAAABAw/xyopYw0FFyg/image%5B8%5D.png?imgmax=800" width="116" height="218" /&gt; Tras esperar un poco por aquello del April’s Fool (el equivalente a nuestro Día de los Inocentes ), ya hoy se puede confirmar que el código fuente del framework &lt;a title="ASP.NET MVC" href="http://www.asp.net/mvc"&gt;ASP.NET MVC 1.0&lt;/a&gt; ha sido publicado con licencia &lt;a title="Microsoft Public License" href="http://www.opensource.org/licenses/ms-pl.html" hreflang="en"&gt;MS-PL&lt;/a&gt;, lo que en la práctica significa que &lt;strong&gt;ha pasado a ser oficialmente software libre&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Aunque el código fuente de la plataforma estaba disponible en &lt;a title="Proyecto ASP.NET en CodePlex" href="http://www.codeplex.com/aspnet" hreflang="en"&gt;CodePlex&lt;/a&gt; prácticamente desde que empezaron a publicarse las primeras previews de la plataforma, es ahora cuando, en palabras de &lt;a title="Microsoft ASP.NET MVC 1.0 is now Open Source MS-PL" href="http://www.hanselman.com/blog/MicrosoftASPNETMVC10IsNowOpenSourceMSPL.aspx" hreflang="en"&gt;Scott Hanselman&lt;/a&gt;, ha pasado de ser “source opened” a “open source”.&lt;/p&gt;  &lt;p&gt;Muchas de las grandes figuras implicadas en el proyecto han publicado ya en sus respectivos blogs el esperado anuncio, felicitándose por el logro conseguido, una nueva demostración del cambio de rumbo de Microsoft respecto al código abierto.&lt;/p&gt;  &lt;p&gt;También &lt;a title="Miguel de Icaza&amp;#39;s web log" href="http://tirania.org/blog/" hreflang="en"&gt;Miguel de Icaza&lt;/a&gt;, quien por cierto recientemente anunciaba la disponibilidad de &lt;a title="Mono 2.4 and MonoDevelop 2.0 released" href="http://tirania.org/blog/archive/2009/Mar-30.html"&gt;Mono 2.4 y &lt;/a&gt;&lt;a title="Mono 2.4 and MonoDevelop 2.0 released" href="http://tirania.org/blog/archive/2009/Mar-30.html" hreflang="en"&gt;MonoDevelop 2.0&lt;/a&gt;, ya ha comentado que se trata de una magnífica noticia no sólo para el equipo del &lt;a title="Proyecto Mono" href="http://www.mono-project.com/" hreflang="en"&gt;Proyecto Mono&lt;/a&gt;, sino para toda la comunidad de desarrolladores ASP.NET.&lt;/p&gt;  &lt;p&gt;Enlaces (en inglés):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a title="ASP.NET MVC 1.0" href="http://weblogs.asp.net/scottgu/archive/2009/04/01/asp-net-mvc-1-0.aspx"&gt;ASP.NET MVC 1.0&lt;/a&gt; (ScottGu) &lt;/li&gt;    &lt;li&gt;&lt;a title="Microsoft ASP.NET MVC 1.0 is now Open Source MS-PL" href="http://feedproxy.google.com/~r/ScottHanselman/~3/-NNmNcdP3GA/MicrosoftASPNETMVC10IsNowOpenSourceMSPL.aspx"&gt;Microsoft ASP.NET MVC 1.0 is now Open Source MS-PL&lt;/a&gt; (Hanselman) &lt;/li&gt;    &lt;li&gt;&lt;a title="Open Source License For System.Web.Mvc" href="http://haacked.com/archive/2009/04/01/aspnetmvc-open-source.aspx"&gt;Open Source License For System.Web.Mvc&lt;/a&gt; (Haack) &lt;/li&gt;    &lt;li&gt;&lt;a title="Rolling a Bubble – ASP.NET MVC is Ms-PL" href="http://feedproxy.google.com/~r/wekeroad/EeKc/~3/YiI7F4mjn_A/"&gt;Rolling a Bubble – ASP.NET MVC is Ms-PL&lt;/a&gt; (Connery) &lt;/li&gt;    &lt;li&gt;&lt;a title="Microsoft releases ASP.NET under the MS-PL License" href="http://tirania.org/blog/archive/2009/Apr-02.html"&gt;Microsoft releases ASP.NET under the MS-PL License&lt;/a&gt; (Miguel de Icaza) &lt;/li&gt;    &lt;li&gt;&lt;a title="Download details ASP.NET MVC 1.0" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b&amp;amp;displaylang=en"&gt;Download ASP.NET MVC 1.0&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Publicado en: &lt;a title="Variable not found" href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-1600026792488953353?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bcaZPHziEuUW0EAu9Lpg5Ts0jQY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bcaZPHziEuUW0EAu9Lpg5Ts0jQY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bcaZPHziEuUW0EAu9Lpg5Ts0jQY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bcaZPHziEuUW0EAu9Lpg5Ts0jQY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WH8_jkQXA1E:r7mkxDCYMtg:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WH8_jkQXA1E:r7mkxDCYMtg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WH8_jkQXA1E:r7mkxDCYMtg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WH8_jkQXA1E:r7mkxDCYMtg:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WH8_jkQXA1E:r7mkxDCYMtg:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WH8_jkQXA1E:r7mkxDCYMtg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WH8_jkQXA1E:r7mkxDCYMtg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=WH8_jkQXA1E:r7mkxDCYMtg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=WH8_jkQXA1E:r7mkxDCYMtg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/WH8_jkQXA1E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/1600026792488953353/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=1600026792488953353" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1600026792488953353?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/1600026792488953353?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/WH8_jkQXA1E/aspnet-mvc-es-open-source.html" title="¡ASP.NET MVC es open source!" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/04/aspnet-mvc-es-open-source.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYMQHo6cCp7ImA9WxVbFUQ.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-3218006969096149097</id><published>2009-04-01T16:40:00.000+02:00</published><updated>2009-04-01T16:46:21.418+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-01T16:46:21.418+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vs2008" /><category scheme="http://www.blogger.com/atom/ns#" term="lambdas" /><category scheme="http://www.blogger.com/atom/ns#" term="linq" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="árboles de expresión" /><title>C#: Desmitificando las expresiones lambda (y III)</title><content type="html">&lt;img style="float:right; margin:0 0 10px 10px;" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s200/lambdas.jpg" border="0" alt="Lambda" id="BLOGGER_PHOTO_ID_5263418794000817106" /&gt;En el &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda.html"&gt;primer post&lt;/a&gt; intentamos describir qué eran las expresiones lambda, resumiendo muy brevemente su utilidad, así como los aspectos sintácticos de este tipo de construcciones del lenguaje. &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_29.html"&gt;El segundo&lt;/a&gt; lo enfocamos a explicar el papel de las lambda como funciones anónimas, su estrecha relación con los delegados, y su forma de utilización.&lt;br /&gt;&lt;br /&gt;En esta tercera y última entrega de la serie, vamos a centrarnos en otra de las grandes utilidades de las expresiones lambda en .NET framework: la definición de árboles de expresión.&lt;br /&gt;&lt;br /&gt;&lt;h3 id="arboles"&gt;Las lambda como árboles de expresión&lt;/h3&gt;&lt;img style="float:right; margin:0 0 10px 10px;" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SPD32TjLheI/AAAAAAAAA5w/9wlOhabJCs8/s400/ExpressionTree.jpg" border="0" alt="Árbol de expresión" id="BLOGGER_PHOTO_ID_5255973277474194914" /&gt;Los compiladores de C# y VB.NET pueden, bajo determinadas circunstancias, utilizar las lambdas para crear un árbol  de expresión, una estructura en memoria que representa en forma de árbol las operaciones a realizar, y en el orden que hay que hacerlo, para lograr un objetivo. Si lo queréis ver más claro, observad el diagrama adjunto, en el que se muestra el árbol de expresión correspondiente a una función lambda que obtiene la media de dos números.&lt;br /&gt;&lt;br /&gt;Esto es muy diferente al caso anterior, donde hablábamos de las lambda como funciones ejecutables que podían ser referenciadas por delegados e invocadas de forma directa. Entonces las expresiones lambda eran transformadas en tiempo de compilación en código ejecutable (de hecho, en métodos estáticos que pueden ser consultados usando &lt;a href="http://www.red-gate.com/products/reflector/index.htm" title=".NET Reflector" hreflang="en"&gt;Reflector&lt;/a&gt; u otros desensambladores), y por ello podíamos utilizarlas de forma directa.&lt;br /&gt;&lt;br /&gt;En el caso de los árboles de expresión, la compilación no genera código ejecutable correspondiente a las instrucciones definidas en la lambda, sino el código para crear y llenar el árbol con dicha expresión. Después, en tiempo de ejecución, será posible recorrer dicho árbol, analizarlo, seriarlo para almacenarlo o moverlo a otras capas, e incluso compilarlo para poder lanzar su ejecución.&lt;br /&gt;&lt;br /&gt;Pero paremos aquí un momento... según lo dicho, cuando el compilador se encuentra con una expresión lambda, por ejemplo &lt;code&gt;x =&amp;gt; x * 2&lt;/code&gt;, puede optar por generar una función anónima o por generar el código de llenado del árbol, ¿cómo sabe lo que debe hacer?&lt;br /&gt;&lt;br /&gt;Pues bien, el compilador elegirá la opción adecuada dependiendo del tipo de la referencia a la expresión lambda. Si se trata de un tipo de delegado como &lt;code&gt;Func&lt;/code&gt; o &lt;code&gt;Action&lt;/code&gt;, generará código ejecutable y las referencias a la función serán tratados como delegados; si se usa el tipo &lt;code&gt;Expression&lt;/code&gt;, que veremos más adelante, se generará el árbol de expresión y las referencias no se considerarán delegados, sino objetos de este tipo. Por este motivo no podemos utilizar para declarar lambdas &lt;a href="http://www.variablenotfound.com/2007/12/variables-locales-implictamente-tipadas.html" title="Variables locales implícitamente tipadas en C#"&gt;variables locales de tipo implícito&lt;/a&gt;: el compilador no sabría qué hacer.&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  &lt;span style="color: red; font-weight: bold;"&gt;var dobla = a =&amp;gt; a * 2;&lt;/span&gt;&lt;span style="color: green"&gt; // Error: no se puede asignar&lt;br /&gt;                          // una expresión lambda a una variable&lt;br /&gt;                          // local de tipo implícito.&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;h3 id="definicionarboles"&gt;Definición de árboles con expresiones lambda&lt;/h3&gt;Para definir un árbol de expresión a partir de una lambda debemos utilizar el tipo genérico &lt;code&gt;Expression&amp;lt;TipoDelegado&amp;gt;&lt;/code&gt;, siendo &lt;code&gt;TipoDelegado&lt;/code&gt; un delegado como &lt;code&gt;Action&lt;/code&gt; o &lt;code&gt;Func&lt;/code&gt; de los descritos en el post anterior. ¿Que esto os parece confuso? Pues esperad a ver el ejemplo... ;-)&lt;pre&gt;&lt;code&gt;  Expression&amp;lt;&lt;span style="background-color: #ffffc0;"&gt;Func&amp;lt;int, int, int&amp;gt;&lt;/span&gt;&amp;gt; media = (a, b) =&gt; (a + b) / 2;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;En realidad, aparte de lo difícil de leer que es una declaración de este tipo, la idea es bastante sencilla. Lo que estamos indicando al compilador es que queremos montar un árbol de una expresión de la que conocemos el tipo de los parámetros de entrada y del valor de retorno, datos que indicamos mediante el delegado que utilizamos como argumento genérico de la clase &lt;code&gt;Expression&lt;/code&gt;, la porción que he marcado de amarillo en el ejemplo anterior. Además, este delegado lo utilizaremos cuando queramos convertir el árbol de expresión en código ejecutable, más adelante veremos cómo.&lt;br /&gt;&lt;br /&gt;Para que quede claro, ahí van algunos ejemplos más:&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green"&gt;// Árbol de expresión de una función que determina&lt;br /&gt;  // si el parámetro que le llega es par&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color: #ffffc0;"&gt;Func&amp;lt;int, bool&amp;gt;&lt;/span&gt;&amp;gt; esPar = a =&amp;gt; a%2==0;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Árbol de expresión de una función &lt;br /&gt;  // que retorna el máximo de dos números.&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color: #ffffc0;"&gt;Func&amp;lt;int, int, int&amp;gt;&lt;/span&gt;&amp;gt; maximo =&lt;br /&gt;              (a, b) =&amp;gt; a &amp;gt; b ? a:b;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Árbol de expresión de una función que&lt;br /&gt;  // retorna un string transformado&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color: #ffffc0;"&gt;Func&amp;lt;string, string&amp;gt;&lt;/span&gt;&amp;gt; TrimMays = &lt;br /&gt;              a =&amp;gt; a.Trim().ToUpper();&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Árbol de expresión de una acción &lt;br /&gt;  // sin parámetros que escribe por consola la fecha y hora.&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color: #ffffc0;"&gt;Action&lt;/span&gt;&amp;gt; accion =&lt;br /&gt;              () =&amp;gt; Console.WriteLine(DateTime.Now); &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Fijaos que el tipo de delegado &lt;code&gt;Action&lt;/code&gt; o &lt;code&gt;Func&lt;/code&gt;, que son los parámetros genéricos de la expresión, son los que definen los tipos de parámetros y retornos de la lambda. En el primer caso, el &lt;code&gt;Func&amp;lt;int, bool&amp;gt;&lt;/code&gt; define que la función recibe un entero y retorna un booleano; en el último caso, ni se envía ni se recibe nada, de ahí que utilicemos un delegado &lt;code&gt;Action&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Un detalle importante, antes de que se me olvide comentarlo. Los árboles de expresión sirven, como su nombre indica, para almacenar expresiones. Esto limita el tipo de construcciones de código que podemos usar en las lambdas que los definen: no está permitido utilizar asignaciones, bloques con llaves { }, ni bucles... debe tratarse de una expresión que pueda representarse en una jerarquía de árbol. Si intentamos saltarnos estas restricciones, el compilador generará un error, aunque el tipo de delegado sea correcto y la función lambda también, como en el siguiente ejemplo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green"&gt;// Suma los n primeros naturales&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color: #ffffc0;"&gt;Func&amp;lt;int, int&amp;gt;&lt;/span&gt;&amp;gt; expr =&lt;br /&gt;&lt;span style="color: red;"&gt;    n =&amp;gt; {&lt;br /&gt;           int t = 0;&lt;br /&gt;           for (int i = 1; i &amp;lt;= n; t += i++) ;&lt;br /&gt;           return t;&lt;br /&gt;         };&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Error CS0834: Una expresión lambda con cuerpo no puede ser &lt;br /&gt;  // convertida a árbol de expresión&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;img style="float:right; margin:0 0 10px 10px;" src="http://2.bp.blogspot.com/_O9D62hXq-ng/SQ2ntSUN7eI/AAAAAAAAA7M/ZZ60FYYNyR8/s400/expression-tree-2.jpg" border="0" alt="Árbol de expresión" id="BLOGGER_PHOTO_ID_5264047935918566882" /&gt;Volvemos un poco atrás ahora para recordar cuando comentaba que la compilación de una lambda no genera código ejecutable correspondiente a las instrucciones definidas en la expresión, sino el código para llenar el árbol de expresión que la representa. &lt;br /&gt;&lt;br /&gt;¿Y cómo hace eso? Muy sencillo. El compilador analiza la expresión, genera la secuencia de instrucciones que compone el árbol, las compila, e introduce el resultado en el ensamblado. El siguiente ejemplo muestra cómo crear un árbol de expresión usando una lambda, y una aproximación al código equivalente que genera el compilador, para que nos podamos hacer una idea del trabajo que nos ahorra esta característica del lenguaje:&lt;br /&gt;&lt;pre style='clear: both;'&gt;&lt;code&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Árbol definido con una lambda:&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;int, bool&amp;gt;&amp;gt; esPar = a =&amp;gt; a % 2 == 0;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Y el mismo árbol definido a mano, &lt;/span&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// lo que genera el compilador automáticamente:&lt;/span&gt;&lt;br /&gt;  ParameterExpression param = Expression.Parameter(typeof(int), "a");&lt;br /&gt;  ConstantExpression dos = Expression.Constant(2, typeof(int));&lt;br /&gt;  ConstantExpression cero = Expression.Constant(0, typeof(int));&lt;br /&gt;  BinaryExpression modulo = Expression.Modulo(param, dos);&lt;br /&gt;  BinaryExpression comparacion = Expression.Equal(modulo, cero);&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;int, bool&amp;gt;&amp;gt; esPar2 =&lt;br /&gt;       Expression.Lambda&amp;lt;Func&amp;lt;int, bool&amp;gt;&amp;gt;(comparacion, param);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;h3 id="usoarboles"&gt;Uso de los árboles de expresión&lt;/h3&gt;Ya sabemos qué son los árboles de expresión y cómo podemos definirlos, pero aún no le hemos visto sentido a su existencia. Pero lo tiene, vaya si lo tiene ;-)&lt;br /&gt;&lt;br /&gt;En primer lugar, el hecho de poder definir el árbol partiendo de una expresión lambda, además de comodidad a la hora de codificar, nos permite aprovechar el tipado fuerte y la potencia del intellisense para evitar errores. En el ejemplo anterior, las probabilidades de que nos equivoquemos creando el árbol de forma manual son muy superiores a que ocurra si utilizamos la sintaxis lambda.&lt;br /&gt;&lt;br /&gt;Segundo, fijaos que en ningún momento se está generando código IL o compilando la expresión representada por la lambda. Estamos creando una estructura en memoria. Esto quiere decir que después podemos procesar esta información como estimemos conveniente; podemos, por ejemplo, analizar su contenido, recorrerlo, seriarlo, o transformarlo, en función de nuestras necesidades. Es ideal, por tanto, cuando tengamos interés en interpretar una expresión para realizar alguna acción con ella.&lt;br /&gt;&lt;br /&gt;Vamos a ver ahora varios ejemplos para ilustrar el uso de las lambdas y árboles de expresión en el mundo real.&lt;br /&gt;&lt;h4&gt;Linq&lt;/h4&gt;En el caso de &lt;acronym title="Language INtegrated Query"&gt;Linq&lt;/acronym&gt; aplicado a un proveedor externo de datos relacional (por ejemplo, las tecnologías Linq to SQL, o Entity Framework), no tiene interés alguno el código ejecutable asociado a una expresión, sino su estructura, pues al final va a ser traducida al lenguaje o tecnología del almacén de información. Supongamos la siguiente consulta para obtener los productos que comienzan por "S":&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green;"&gt;// Usando una consulta Linq:&lt;/span&gt;&lt;br /&gt;  var datos = from p in productos &lt;br /&gt;                 where p.Nombre.StartsWith("S")&lt;br /&gt;                 select p;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green;"&gt;// O su equivalente usando &lt;br /&gt;  // &lt;a href="http://www.variablenotfound.com/2008/04/chuleta-de-operadores-estndar-de.html" title="Operadores de consulta"&gt;operadores de consulta&lt;/a&gt;:&lt;/span&gt;&lt;br /&gt;  var datos = productos.Where(&lt;span style="background-color: #ffffc0;"&gt;p=&gt;p.Nombre.StartsWith("S")&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;La lambda resaltada servirá para crear un árbol de expresión con las condiciones indicadas, pues el &lt;a href="http://www.variablenotfound.com/2008/02/mtodos-de-extensin-en-c.html" title="¿Qué son los métodos de extensión?"&gt;método de extensión&lt;/a&gt; &lt;code&gt;Where&lt;/code&gt; aplicado acepta un predicado de tipo &lt;code&gt;Expression&lt;/code&gt;. No se genera ningún método anónimo para la expresión lambda, ni se traduce a IL su contenido: sólo interesa para definir la expresión que será introducida en el árbol. Más adelante, en el momento de extraer realmente la información desde el almacén correspondiente, el componente proveedor de datos recorrerá y analizará la estructura en memoria, generando su equivalente en SQL, que es lo que lanzará al &lt;acronym title="Sistema Gestor de Bases de Datos"&gt;SGBD&lt;/acronym&gt; para obtener los datos.&lt;br /&gt;&lt;br /&gt;Por cierto, existen en la actualidad una gran cantidad de &lt;a href="http://blogs.msdn.com/charlie/archive/2008/02/28/link-to-everything-a-list-of-linq-providers.aspx" title="Lista de proveedores Linq" hreflang="en"&gt;proveedores de Linq&lt;/a&gt;, capaces de transformar los árboles de expresión en consultas a casi cualquier tipo de almacén. Fijaos que la posibilidad de separar la codificación lambda de la interpretación de la expresión hace posible su utilización en una gran variedad de ámbitos.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Cálculo simbólico&lt;/h4&gt;Otro ejemplo que ilustra muy bien las posibilidades de los árboles de expresión, de mano del maestro &lt;a href="http://geeks.ms/blogs/ohernandez" title="Octavio Hernández, en Geeks.ms"&gt;Octavio Hernández&lt;/a&gt;. Se trata del artículo &lt;a href="http://www.elguille.info/NET/futuro/firmas_octavio_calculo_simbolico.htm" title="Cálculo simbólico en C# 3.0"&gt;Cálculo simbólico en C# 3.0&lt;/a&gt;, publicado en la web de &lt;a href="http://www.elguille.info/" title="El Guille"&gt;El Guille&lt;/a&gt; a principios de 2007.&lt;br /&gt;&lt;br /&gt;A lo largo del artículo se realiza la implementación básica de un sistema de cálculo de derivadas de funciones matemáticas partiendo de un árbol de expresiones. El proceso, que el autor va explicando paso a paso, consiste en analizar el árbol, e ir generando otro árbol con el resultado de la derivación de cada expresión encontrada. A continuación se muestra la porción de código donde se realiza la derivación de una operación de suma, utilizando recursividad para derivar además cada uno de los sumandos:&lt;pre&gt;&lt;code&gt;  private static Expression Derive(this Expression e, string paramName)&lt;br /&gt;  {&lt;br /&gt;      switch (e.NodeType)&lt;br /&gt;      {&lt;br /&gt;          [...]&lt;br /&gt;          &lt;span style="color: green"&gt;// sum rule&lt;/span&gt;&lt;br /&gt;          case ExpressionType.Add:&lt;br /&gt;              {&lt;br /&gt;                  Expression dleft = &lt;br /&gt;                     ((BinaryExpression) e).Left.Derive(paramName);&lt;br /&gt;                  Expression dright = &lt;br /&gt;                     ((BinaryExpression) e).Right.Derive(paramName);&lt;br /&gt;                  return Expression.Add(dleft, dright);&lt;br /&gt;              }&lt;br /&gt;          [...]&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Al final, fijaos que de nuevo no nos interesa en absoluto la lambda como función anónima ni delegado, sino la estructura de la propia expresión, de forma que podamos recorrerla y transformarla en otra expresión, en este caso la función derivada de la original. El siguiente ejemplo muestra el uso de esta clase:&lt;pre&gt;&lt;code&gt;   Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                funcion = x =&amp;gt; x*x;          &lt;span style="color: green"&gt;// f(x)=x^2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                derivada = funcion.Derive(); &lt;span style="color: green"&gt;// f'(x)=2*x&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Console.WriteLine(derivada); &lt;span style="color: green"&gt;// Muestra la función derivada:&lt;br /&gt;                               //    x =&gt; ((x * 1) + (1 * x))&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Creedme, vale la pena &lt;a href="http://www.elguille.info/NET/futuro/firmas_octavio_calculo_simbolico.htm" title="Cálculo simbólico en C# 3.0"&gt;echarle un vistazo&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;ASP.NET MVC&lt;/h4&gt;Un último ejemplo, que demuestra la versatilidad del uso de lambdas y árboles de expresión en multitud de escenarios. En el &lt;a href="http://www.asp.net/mvc" title="Sitio oficial de ASP.NET MVC" hreflan="en"&gt;framework ASP.NET MVC&lt;/a&gt;, es posible crear enlaces hacia acciones desde dentro de las vistas (páginas .ASPX), que no son sino métodos dentro de unas clases concretas llamadas "controladores". El caso es que para hacer referencia a un método del controlador, pueden utilizarse estas dos vías, de resultado idéntico:&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green"&gt;// Obtiene un enlace al método "ChangePassword"&lt;br /&gt;  // de la clase "AccountController":&lt;/span&gt;&lt;br /&gt;  Html.ActionLink("Cambiar clave", "ChangePassword", "Account")&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Lo mismo, pero usando un árbol de expresión:&lt;/span&gt;&lt;br /&gt;  Html.ActionLink&amp;lt;AccountController&amp;gt;&lt;br /&gt;              (acc=&amp;gt;acc.ChangePassword(), "Cambiar clave")&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Aunque el resultado es el mismo, la segunda usa un árbol de expresión para realizar la referencia al método &lt;code&gt;ChangePassword&lt;/code&gt; de la clase &lt;code&gt;AccountController&lt;/code&gt;. La implementación del método &lt;code&gt;ActionLink&lt;/code&gt; recorre el árbol generado desde la expresión lambda para obtener el nombre del controlador y del método, por lo que es equivalente a primera fórmula, pero beneficiándose de las ventajas del tipado fuerte y del &lt;em&gt;intellisense&lt;/em&gt; en la edición.&lt;br /&gt;&lt;h3&gt;Los árboles de expresión como código ejecutable&lt;/h3&gt;Hasta ahora siempre me he referido a los árboles de expresión como entidades de almacenamiento. De alguna u otra forma, estaba equiparando su utilidad a la cualquier estructura de datos que permitiera guardar y procesar información, lo cual es cierto pero sólo parcialmente.&lt;br /&gt;&lt;br /&gt;Los árboles de expresión aportan una característica adicional: se pueden convertir en código ejecutable. Es decir, &lt;strong&gt;es posible compilar un árbol de expresión&lt;/strong&gt; en tiempo de ejecución, dando lugar a una función anónima a la que podemos tener acceso, es decir, invocarla, a través de sus delegados.&lt;br /&gt;&lt;br /&gt;Veámoslo con un caso concreto. Retomando el ejemplo de obtención de derivadas, sería perfectamente posible obtener el valor de la función derivada en un punto ampliando ligeramente el código visto anteriormente:&lt;pre&gt;&lt;code&gt;  Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                funcion = x =&amp;gt; x*x;          &lt;span style="color: green"&gt;// f(x)=x^2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                derivada = funcion.Derive(); &lt;span style="color: green"&gt;// f'(x)=2*x&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Compilamos la función derivada&lt;br /&gt;  // y obtenemos un delegado a la misma:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;double, double&amp;gt; funcDerivada = derivada.Compile();&lt;br /&gt;&lt;br /&gt;  double result = funcDerivada(6); &lt;span style="color: green"&gt;// Obtenemos el valor de la función &lt;br /&gt;                                   // invocando al delegado con x=6&lt;/span&gt;&lt;br /&gt;  Console.WriteLine(result);       &lt;span style="color: green"&gt;// Muestra "12"&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Como se puede observar en el código, la llamada al método &lt;code&gt;Compile()&lt;/code&gt; devuelve un delegado del tipo &lt;code&gt;Func&lt;/code&gt; indicado en el parámetro genérico de la expresión, que apunta hacia la función anónima creada "al vuelo" a partir de las expresiones contenidas en el árbol. Es decir, desde la definición simbólica contenida en el árbol ¡obtenemos código ejecutable!&lt;br /&gt;&lt;br /&gt;Aunque espectacular, en realidad no hay nada mágico en esta característica: se trata de ir recorriendo el árbol y emitiendo el código IL correspondiente a cada expresión, que está perfectamente tipificada y definida. En el namespace &lt;code&gt;System.Linq.Expressions&lt;/code&gt; existe una bonita clase interna llamada &lt;code&gt;ExpressionCompiler&lt;/code&gt; que se dedica exclusivamente a ello, utilizando herramientas suministradas por &lt;code&gt;System.Reflection.Emit&lt;/code&gt;, como los generadores de lenguaje intermedio &lt;code&gt;ILGenerator&lt;/code&gt;.&lt;br /&gt;&lt;h3&gt;¡Y hasta aquí hemos llegado!&lt;/h3&gt;A lo largo de estos tres posts hemos recorrido las principales características y utilidades de las expresiones lambda. Obviamente, han quedado cosas por detrás; no era objetivo de esta serie profundizar demasiado, sino ofrecer una visión suficiente para animar a los desarrolladores a utilizar esta potente característica que nos ofrece C# (y VB.NET).&lt;br /&gt;&lt;br /&gt;Espero que os haya sido una lectura útil, al menos tanto como me ha resultado a mí su escritura. Ah, y para consultas, sugerencias o puntualizaciones, por aquí me tenéis.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-3218006969096149097?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RktV2hbyEXV7GbcqW7GBIrIZLxg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RktV2hbyEXV7GbcqW7GBIrIZLxg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RktV2hbyEXV7GbcqW7GBIrIZLxg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RktV2hbyEXV7GbcqW7GBIrIZLxg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=39JNdwsKiv8:rex6r_V-rMs:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=39JNdwsKiv8:rex6r_V-rMs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=39JNdwsKiv8:rex6r_V-rMs:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=39JNdwsKiv8:rex6r_V-rMs:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=39JNdwsKiv8:rex6r_V-rMs:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=39JNdwsKiv8:rex6r_V-rMs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=39JNdwsKiv8:rex6r_V-rMs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=39JNdwsKiv8:rex6r_V-rMs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=39JNdwsKiv8:rex6r_V-rMs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/39JNdwsKiv8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/3218006969096149097/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=3218006969096149097" title="3 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3218006969096149097?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3218006969096149097?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/39JNdwsKiv8/c-desmitificando-las-expresiones-lambda_2829.html" title="C#: Desmitificando las expresiones lambda (y III)" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s72-c/lambdas.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_2829.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYCQn8ycCp7ImA9WxVbFUQ.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-3946535709363445451</id><published>2009-04-01T16:32:00.000+02:00</published><updated>2009-04-01T16:46:03.198+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-01T16:46:03.198+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vs2008" /><category scheme="http://www.blogger.com/atom/ns#" term="lambdas" /><category scheme="http://www.blogger.com/atom/ns#" term="linq" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="métodos anónimos" /><category scheme="http://www.blogger.com/atom/ns#" term="delegados" /><title>C#: Desmitificando las expresiones lambda (II)</title><content type="html">&lt;img style="float:right; margin:0 0 10px 10px;" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s200/lambdas.jpg" border="0" alt="Lambda" id="BLOGGER_PHOTO_ID_5263418794000817106" /&gt;En el &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda.html"&gt;post anterior&lt;/a&gt; intentamos realizar una primera aproximación a las expresiones lambda, centrándonos en obtener una definición lo suficientemente cercana, que nos permitiera conocer a grandes rasgos qué son, así como en describir su forma general y sus particularidades sintácticas.&lt;br /&gt;&lt;br /&gt;En esta segunda entrega vamos a profundizar un poco en el papel de las expresiones lambda como vía para definir muy rápidamente funciones anónimas y los tipos de delegados con los que podemos referenciarlas, y por tanto, invocarlas.&lt;br /&gt;&lt;br /&gt;Ya en el tercer post describiremos el papel de las &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_2829.html"&gt;expresiones lambda como herramienta de generación de árboles de expresión&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3 id="funciones"&gt;Las lambdas como funciones anónimas&lt;/h3&gt;Como habíamos insinuado anteriormente, uno de los usos de las expresiones lambda es permitir la definición "en línea" de funciones anónimas. De hecho, en tiempo de compilación las expresiones lambda son convertidas en métodos a los que el compilador establece un nombre único autogenerado, como los ejemplos mostrados a continuación:&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;" src="http://1.bp.blogspot.com/_O9D62hXq-ng/SQww-8_vZJI/AAAAAAAAA68/qPY91CUBI8s/s400/lambda-anonimas.jpg" border="0" alt="Transformación de lamdas en métodos" id="BLOGGER_PHOTO_ID_5263635922572764306" /&gt;&lt;br /&gt;Las referencias a estas funciones anónimas son transformadas en delegados (punteros) a las mismas, lo que nos permitirá, por ejemplo, invocarlas desde el código. En la práctica esto  quiere decir que podemos asignar una lambda a una variable y ejecutarla como muestra el siguiente pseudocódigo:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  delegado &lt;strong&gt;duplica&lt;/strong&gt; = &lt;span style="background-color: #ffffc0;"&gt;x =&amp;gt; x * 2&lt;/span&gt;; &lt;br /&gt;  escribe &lt;strong&gt;duplica(2)&lt;/strong&gt;; &lt;span style="color: green"&gt;// Escribe un 4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;En este primer acercamiento, fijaos que &lt;code&gt;duplica&lt;/code&gt; es el nombre del delegado, la función definida en forma de expresión lambda no tiene nombre, será el compilador el que se asigne uno. &lt;br /&gt;&lt;br /&gt;Veamos cómo se concreta esta idea en C#. En el siguiente código, la variable &lt;code&gt;duplica&lt;/code&gt; &lt;em&gt;apunta&lt;/em&gt; hacia una función anónima definida a través de la expresión lambda en cuya implementación lo único que se hace es retornar el doble del valor que le llega como parámetro. Vemos también cómo podemos utilizarla de forma directa:&lt;pre&gt;&lt;code&gt;  Func&amp;lt;int, int&amp;gt; &lt;strong&gt;duplica &lt;/strong&gt;= &lt;span style="background-color: #ffffc0;"&gt;x =&gt; x * 2&lt;/span&gt;;&lt;br /&gt;  int result = &lt;strong&gt;duplica&lt;/strong&gt;(7); &lt;span style="color: green"&gt;// result vale 14&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Sólo con objeto de que podáis entender el código anterior, os adelantaré que la porción &lt;code&gt;Func&amp;lt;int, int&amp;gt;&lt;/code&gt; es una forma rápida de tipificar el delegado, indicando que &lt;code&gt;duplica&lt;/code&gt; apunta a una función que espera un entero como parámetro de entrada, y que su valor de retorno será otro entero. Esto lo veremos dentro de un momento.&lt;br /&gt;&lt;br /&gt;De la misma forma que asignamos la expresión lambda a una variable, podemos hacerlo también para indicar el valor de un parámetro a un método que acepte un delegado concreto. Por ejemplo, el siguiente código muestra un método llamado &lt;code&gt;calcula&lt;/code&gt; que recibe un valor entero y una referencia a una función, retornando el resultado de efectuar dicha operación sobre el entero proporcionado:&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green"&gt;// Es método ejecuta la función indicada por&lt;br /&gt;  // el parámetro &lt;em&gt;operacion&lt;/em&gt;, enviándole el &lt;em&gt;valor&lt;/em&gt; especificado, &lt;br /&gt;  // y retorna el resultado obtenido de la misma.&lt;/span&gt;&lt;br /&gt;  public int calcula(int valor, Func&amp;lt;int, int&amp;gt; operacion)&lt;br /&gt;  {&lt;br /&gt;    return operacion(valor); &lt;span style="color: green"&gt;// retorna el resultado de aplicar la &lt;br /&gt;                             // expresión indicada al valor.&lt;/span&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Usos posibles:&lt;/span&gt;&lt;br /&gt;  int i = calcula(4, &lt;span style="background-color: #ffffc0"&gt;x =&amp;gt; x / 2&lt;/span&gt;); &lt;span style="color: green"&gt;// Le pasamos una referencia a la &lt;br /&gt;                                  // función que estamos definiendo sobre&lt;br /&gt;                                  // la marcha. El resultado es que i=2.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  int j = calcula(4, &lt;strong&gt;duplica&lt;/strong&gt;);    &lt;span style="color: green"&gt;// Le pasamos la variable "duplica", &lt;br /&gt;                                  // que es una referencia a la lambda&lt;br /&gt;                                  // definida anteriormente. J valdrá 8.&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;div style="margin-left: 4em; padding: 5px; border: 1px dotted #c0c0c0; background-color: #fffff0;"&gt;&amp;lt;HistoriaDelAbuelete&amp;gt;&lt;br /&gt;Seguro que a los más viejos del lugar esto le recuerda a los &lt;a href="http://www.leylan.com/app.asp?pg=blocks" hreflang="en" title="They're Mysterious... They're Code Blocks"&gt;Codeblocks&lt;/a&gt; que utilizábamos en &lt;a href="http://es.wikipedia.org/wiki/Clipper_(lenguaje_de_programaci%C3%B3n)" title="El Lenguaje Clipper"&gt;Clipper&lt;/a&gt; a principios de los 90 (uuf, cómo pasa el tiempo...). ¿Todavía reconocéis el siguiente código?&lt;pre&gt;&lt;code&gt;  bDuplica := { |n| n*2 }&lt;br /&gt;  ? EVAL(bDuplica, 7)     // Muestra un 14&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&amp;lt;/HistoriaDelAbuelete&amp;gt;&lt;/div&gt;&lt;br /&gt;Una consecuencia directa de que las expresiones lambdas sean referenciadas a través de delegados es que &lt;strong&gt;podemos utilizarlas en cualquier sitio donde se acepte un delegado&lt;/strong&gt;, con la única precaución de escribirla teniendo en cuenta el tipo de su retorno y los parámetros que recibe. Un ejemplo claro lo tenemos en la suscripción a eventos, donde la técnica habitual consiste en utilizar un delegado a un método en el que se implementa la lógica del tratamiento de los mismos, algo como:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green;"&gt;// Nos suscribimos al evento MouseMove:&lt;/span&gt;&lt;br /&gt;  this.MouseMove += &lt;span style="background-color: #ffffc0"&gt;new MouseEventHandler(this.Form1_MouseMove);&lt;/span&gt;&lt;br /&gt;  [...]&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green;"&gt;// Tratamiento del evento MouseMove:&lt;/span&gt;&lt;br /&gt;  private void Form1_MouseMove(object sender, MouseEventArgs e)&lt;br /&gt;  {&lt;br /&gt;    this.Text = e.X + "," + e.Y;&lt;br /&gt;  }&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Como sabemos, podemos suscribirnos al evento &lt;code&gt;MouseMove&lt;/code&gt; añadiéndole delegados del tipo &lt;code&gt;MouseEventHandler&lt;/code&gt;, definido en &lt;code&gt;System.Windows.Forms&lt;/code&gt;, cuya firma indica que recibe un parámetro de tipo &lt;code&gt;object&lt;/code&gt;, otro de tipo &lt;code&gt;MouseEventArgs&lt;/code&gt; y no retorna ningún valor, exactamente igual que sería un delegado anónimo (C# 2.0) escrito así:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  this.MouseMove += delegate(object sender, MouseEventArgs args)&lt;br /&gt;  {&lt;br /&gt;    this.Text = args.X + "," + args.Y;&lt;br /&gt;  };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Y dado que las lambdas pueden sustituir de forma directa a cualquier delegado, podemos utilizarlas para conseguir un código más compacto:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  this.MouseMove += &lt;span style="background-color: #ffffc0;"&gt;(sender, args) =&amp;gt; {&lt;/span&gt;&lt;br /&gt;                    &lt;span style="background-color: #ffffc0;"&gt;   this.Text = args.X + "," + args.Y;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="background-color: #ffffc0;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Llegados a este punto es conveniente aclarar que las expresiones lambda son características introducidas en los lenguajes, y por tanto en sus compiladores, pero no en la plataforma de ejecución (CLR) en sí. Por tanto, todo lo descrito hasta el momento era posible realizarlo antes que las lambda aparecieran por el horizonte, aunque de forma un poco más tediosa, utilizando mecanismos que la versión 2.0 del framework ponía a nuestra disposición, como los delegados y métodos anónimos. En este sentido, el uso de expresiones lambda aportan mucha simplicidad, elegancia y legibilidad al código.&lt;br /&gt;&lt;br /&gt;Esto explica, además, que Visual Studio 2008 sea capaz de generar código para .NET 2.0 a partir de código fuente C# 3.0.&lt;br /&gt;&lt;br /&gt;&lt;h3 id="tiposdelegados"&gt;Tipos de delegados de expresiones lambda&lt;/h3&gt;Antes ya había adelantado que la definición &lt;code&gt;Func&amp;lt;int, int&amp;gt;&lt;/code&gt; era simplemente una forma de indicar el tipo del parámetro que recibía la función lambda, así como el tipo del valor de retorno. En realidad, lo único que estábamos haciendo era definir, de forma muy sencilla y rápida, el delegado hacia la función. &lt;br /&gt;&lt;br /&gt;Vamos a concretar esto un poco más, pero antes de continuar, una cosa: si para tí un genérico es un &lt;a href="http://es.wikipedia.org/wiki/Medicamento_gen%C3%A9rico" title="Medicamentos genéricos en la Wikipedia"&gt;tipo de medicamento&lt;/a&gt;, mejor que leas algo sobre el tema antes de continuar, pues en caso contrario es posible que te pierdas un poco ;-). Pues probar leyendo una &lt;a href="http://www.variablenotfound.com/2007/03/generics-en-c.html" title="Introducción a los generics"&gt;introducción a los generics en c#&lt;/a&gt;, o la &lt;a href="http://msdn.microsoft.com/es-es/library/512aeb7t(VS.80).aspx" title="Tipos genéricos"&gt;Guía de programación de C#&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;.NET Framework ofrece en el espacio de nombres &lt;code&gt;System&lt;/code&gt; un conjunto de definiciones de genéricas de delegados para que podamos utilizarlos para "apuntar" hacia las funciones definidas mediante expresiones lambda, llamados &lt;code&gt;Action&lt;/code&gt; y &lt;code&gt;Func&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Utilizaremos los tipos &lt;code&gt;Func&lt;/code&gt; para definir referencias a expresiones lambda que retornen un valor, o sea, funciones. De ahí su nombre. Los tipos &lt;code&gt;Action&lt;/code&gt;, en cambio, están destinados a referenciar a lambdas que realicen acciones y que no retornen ningún valor. De ahí su nombre también. ;-)&lt;br /&gt;&lt;br /&gt;Una de estas definiciones es la que habíamos usado en un ejemplo anterior:&lt;pre&gt;&lt;code&gt;  &lt;span style="background-color: #ffffc0;"&gt;&lt;strong&gt;Func&amp;lt;int, int&amp;gt;&lt;/strong&gt;&lt;/span&gt; duplica = x =&amp;gt; x * 2;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Como se puede observar, al tratarse de una referencia a una función que retorna un valor, hemos utilizado un tipo &lt;code&gt;Func&lt;/code&gt; con dos parámetros genéricos, que corresponde con la siguiente declaración existente en el espacio de nombres &lt;code&gt;System&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  public delegate TResult Func&amp;lt;T, TResult&amp;gt;(T arg);&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Por ello, cuando declarábamos que la variable &lt;code&gt;duplica&lt;/code&gt; era del tipo &lt;code&gt;Func&amp;lt;int, int&amp;gt;&lt;/code&gt;, lo que indicábamos era, en primer lugar que el parámetro que necesitaba la lambda era un &lt;code&gt;int&lt;/code&gt;, y que ésta nos devolvería también un &lt;code&gt;int&lt;/code&gt;, es decir, lo mismo que si hubiéramos definido &lt;code&gt;duplica&lt;/code&gt; así, utilizando métodos anónimos de C# 2.0:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green"&gt;// En el área de declaraciones:&lt;/span&gt;&lt;br /&gt;  public delegate int Duplicador(int arg);&lt;br /&gt;  &lt;span style="color: blue"&gt;...&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// En el código:&lt;/span&gt;&lt;br /&gt;  Duplicador duplica = delegate(int k) { return k*2 };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Obviamente, la sintaxis lambda es mucho más compacta y expresiva.&lt;br /&gt;&lt;br /&gt;En la práctica, lo único que tenemos que tener claro a la hora de referenciar una función lambda es el tipo de cada uno de los parámetros que usa, y el tipo de retorno. Estos se introducen, en ese orden, en los parámetros genéricos de la clase &lt;code&gt;Func&lt;/code&gt; y listo. Como esto debe quedar claro, ahí van unos ejemplos de definición y uso:&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green;"&gt;// Recibe un entero y retorna un booleano:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;int, bool&amp;gt; esPar = x =&amp;gt; x%2==0;     &lt;br /&gt;  Console.WriteLine(esPar(2)); &lt;span style="color: green;"&gt;// Muestra "True"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green;"&gt;// Recibe dos enteros, retorna otro entero:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;int, int, int&amp;gt; suma = (a,b) =&amp;gt; a+b;&lt;br /&gt;  Console.WriteLine(suma(2,3)); &lt;span style="color: green;"&gt;// Muestra "5"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green;"&gt;// No recibe nada, retorna un texto:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;string&amp;gt; hora = () =&amp;gt; "Son las "&lt;br /&gt;                             + DateTime.Now.ToShortTimeString();&lt;br /&gt;  Console.WriteLine(hora()); &lt;span style="color: green;"&gt;// Muestra "Son las 14:21:10"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Es importante saber que en el framework están definidos los delegados &lt;code&gt;Func&amp;lt;tipo1, tipo2..., tipoResult&amp;gt;&lt;/code&gt; para funciones de hasta cuatro parámetros. Si necesitamos más deberemos definir los delegados a mano, aunque esto es realmente sencillo utilizando una de las declaraciones existentes y añadiéndole el número de parámetros que deseemos. Por ejemplo, para seis parámetros la definición del genérico sería algo así como:&lt;pre&gt;&lt;code&gt;  public delegate &lt;br /&gt;         TResult Func&amp;lt;T1, T2, T3, T4, T5, T6, TResult&amp;gt;&lt;br /&gt;                 (T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6);&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Pero ahora aparece un pequeño problema: las funciones sin retorno no pueden referenciarse con delegados de tipo &lt;code&gt;Func&lt;/code&gt;, puesto que el framework .NET no soporta la instanciación de tipos genéricos utilizando parámetros &lt;code&gt;void&lt;/code&gt; (&lt;a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf" hreflang="en" title="Common Language Infrastructure (CLI)"&gt;ECMA 335&lt;/a&gt;, sección 9.4, pág. 153). Por tanto, no podríamos declarar un delegado como &lt;code&gt;Func&amp;lt;int, void&amp;gt;&lt;/code&gt; para apuntar hacia una función que recibe un entero y no devuelve nada. Si lo pensáis un poco, este es el motivo de que no exista ninguna sobrecarga de la clase &lt;code&gt;Func&lt;/code&gt; sin parámetros genéricos, pues como mínimo debemos indicar el tipo del valor de retorno.&lt;br /&gt;&lt;br /&gt;La clave para cubrir estos casos se encuentra en el tipo &lt;code&gt;Action&lt;/code&gt;. Como comentaba unas líneas más arriba, el objeto de estos tipos de delegados es apuntar a expresiones lambda que realicen acciones y que no retornen ningún valor, por lo que sus parámetros genéricos describirán exclusivamente los tipos de los parámetros de la función. En este caso, como es obvio, sí existe una clase no parametrizada &lt;code&gt;Action&lt;/code&gt; para apuntar a funciones sin parámetros, además de disponer de genéricos que cubren las acciones de hasta cuatro parámetros. Veamos unos ejemplos:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="color: green;"&gt;// Acción sin parámetros (no genérica):&lt;/span&gt;&lt;br /&gt;  Action saluda = () =&amp;gt; Console.WriteLine("hola");&lt;br /&gt;  saluda();  &lt;span style="color: green;"&gt;// Muestra "hola";&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green;"&gt;// Acción que recibe un string&lt;/span&gt;&lt;br /&gt;  Action&amp;lt;string&amp;gt; apaga = motivo =&amp;gt; { &lt;br /&gt;                                      log(motivo);&lt;br /&gt;                                      shutdown();&lt;br /&gt;                                   };&lt;br /&gt;  apaga("mantenimiento"); &lt;span style="color: green;"&gt;// Apaga el sistema&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Por último, me parece interesante recordar algo que había comentado en el post anterior, que en las expresiones lambda no era necesario indicar el tipo de los parámetros ni del retorno porque el compilador los infería del contexto. Como podemos ver, lo tiene bastante fácil, puesto que simplemente debe tomar la definición del delegado para conocerlos; por eso no es necesario introducir redundancias como las siguientes:&lt;pre&gt;&lt;code&gt;  Func&amp;lt;&lt;span style="background-color: #ffc0ff"&gt;int&lt;/span&gt;, &lt;span style="background-color: #ffffc0"&gt;int&lt;/span&gt;&amp;gt; duplica = (&lt;span style="background-color: #ffc0ff"&gt;int&lt;/span&gt; a) =&amp;gt; (&lt;span style="background-color: #ffffc0"&gt;int&lt;/span&gt;)(a * 2); &lt;span style="color: green"&gt;// ¡Redundante!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: green"&gt;// Forma más cómoda:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Func&amp;lt;&lt;span style="background-color: #ffc0ff"&gt;int&lt;/span&gt;, &lt;span style="background-color: #ffffc0"&gt;int&lt;/span&gt;&amp;gt; duplica =  a =&amp;gt; a * 2; &lt;span style="color: green"&gt;// Ok!&lt;/span&gt;&lt;/pre&gt;&lt;/code&gt;&amp;nbsp;&lt;br /&gt;En cualquier caso, si por algún motivo es necesario utilizar la forma explícita, sabed que no se permite hacerlo de forma parcial, es decir, o le ponéis los tipos a todo, o no se los ponéis a nada.&lt;br /&gt;&lt;br /&gt;Y hasta aquí esta segunda entrega. En el siguiente post, el último de la serie, estudiaremos el uso de las &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_2829.html"&gt;lambda como herramientas de definición de árboles de expresión&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Por supuesto, para cualquier duda o sugerencia, ya sabéis dónde encontrarme. :-)&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-3946535709363445451?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/DUhQBA6Bjp7BZfIgAdm_oCkOVFo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DUhQBA6Bjp7BZfIgAdm_oCkOVFo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/DUhQBA6Bjp7BZfIgAdm_oCkOVFo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DUhQBA6Bjp7BZfIgAdm_oCkOVFo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZSNo4oA0h5A:T8C7bVfcXHY:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZSNo4oA0h5A:T8C7bVfcXHY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZSNo4oA0h5A:T8C7bVfcXHY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZSNo4oA0h5A:T8C7bVfcXHY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=ZSNo4oA0h5A:T8C7bVfcXHY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZSNo4oA0h5A:T8C7bVfcXHY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=ZSNo4oA0h5A:T8C7bVfcXHY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=ZSNo4oA0h5A:T8C7bVfcXHY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=ZSNo4oA0h5A:T8C7bVfcXHY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/ZSNo4oA0h5A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/3946535709363445451/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=3946535709363445451" title="5 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3946535709363445451?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/3946535709363445451?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/ZSNo4oA0h5A/c-desmitificando-las-expresiones-lambda_29.html" title="C#: Desmitificando las expresiones lambda (II)" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s72-c/lambdas.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_29.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08FQH47eCp7ImA9WxVaFk0.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-5659861920250304880</id><published>2009-04-01T16:30:00.001+02:00</published><updated>2009-04-13T10:03:31.000+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-13T10:03:31.000+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vs2008" /><category scheme="http://www.blogger.com/atom/ns#" term="lambdas" /><category scheme="http://www.blogger.com/atom/ns#" term="linq" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="árboles de expresión" /><category scheme="http://www.blogger.com/atom/ns#" term="delegados" /><title>C#: Desmitificando las expresiones lambda (I)</title><content type="html">&lt;img style="float:right; margin:0 0 10px 10px;" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s200/lambdas.jpg" border="0" alt="Lambda" id="BLOGGER_PHOTO_ID_5263418794000817106" /&gt;Entre las múltiples novedades aparecidas con C# 3.0 y VB.NET 9.0, las &lt;em&gt;expresiones lambda&lt;/em&gt; son sin duda una de las que en principio pueden parecer más complejas, probablemente por su relación con conceptos no demasiado asimilables como los delegados, inferencia de tipado, métodos anónimos, o tipos genéricos, entre otros.&lt;br /&gt;&lt;br /&gt;Sin embargo, esa aparente dificultad desaparece en cuanto se les presta un poco de atención, y una vez comprendidas aportan a los desarrolladores una potencia y agilidad difíciles de lograr con las herramientas disponibles hasta el momento. Sólo hay que ver su amplia utilización dentro del propio .NET framework, LINQ, y nuevas plataformas como ASP.NET MVC, para darse cuenta de su importancia. Y por si fuera poco, según cuentan los expertos, &lt;a href="http://blog.wekeroad.com/blog/my-personal-lambda-crusade/" title="Rob Conery, My Personal Lambda Crusade" hreflang="en"&gt;su uso "engancha"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A lo largo de esta serie de tres posts intentaré describir las expresiones lambda desde un punto de vista práctico, con la única pretensión de aportar algo de luz a los que todavía no han sucumbido a su poder. ;-)&lt;br /&gt;&lt;br /&gt;El objetivo de este primer post es puramente introductorio, y trataré conceptos y nociones básicas para poder abordar los siguientes. En el segundo post de la serie trataremos las expresiones lambda como funciones anónimas, dejando para el tercero los &lt;em&gt;misteriosos&lt;/em&gt; árboles de expresión.&lt;br /&gt;&lt;br /&gt;&lt;h3 id="intro"&gt;Introducción a las lambda&lt;/h3&gt;Según la definición en la &lt;a href="http://msdn.microsoft.com/es-es/library/bb397687.aspx" title="Expresiones lambda, Referencia del lenguaje C#"&gt;Referencia del lenguaje C# de MSDN&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;"Una expresión lambda es una función anónima que puede contener expresiones e instrucciones y se puede utilizar para crear delegados o tipos de árboles de expresión"&lt;/blockquote&gt;En la &lt;a href="http://msdn.microsoft.com/es-es/library/bb531253.aspx" title="Expresiones lambda, en la Guía de Programación de Visual Basic"&gt;Guía de programación de Visual Basic 9&lt;/a&gt; encontramos otra definición, muy simple y pragmática:&lt;blockquote&gt;"Una expresión lambda es una función sin nombre que calcula y devuelve un solo valor. Se pueden utilizar las expresiones lambda dondequiera que un tipo de delegado sea válido"&lt;/blockquote&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2007/04/08/new-orcas-language-feature-lambda-expressions.aspx" title="New 'Orcas' Language Feature: Lambda Expressions" hreflang="en"&gt;ScottGu&lt;/a&gt; también aportó su granito de arena para hacer el concepto más cercano a los desarrolladores; como siempre, al grano:&lt;blockquote&gt;"Las Expresiones Lambda aportan una sintaxis más concisa y funcional para escribir métodos anónimos."&lt;br /&gt;[...]&lt;br /&gt;"La forma más sencilla para conceptualizar las expresiones lambda es pensar en ellas como formas de escribir métodos breves en una línea."&lt;/blockquote&gt;Partiendo de estas definiciones, y de otras muchas aportadas por Google ;-), está claro que las lambda son funciones, es decir, un conjunto de intrucciones capaces de retornar un valor partiendo de los parámetros que se les suministra, aunque en determinados casos es posible que no reciba ningún parámetro, o que realicen una acción sin retornar nada. Igual que una función tradicional, vaya. Y de hecho, en el cuerpo de una expresión lambda puede haber &lt;em&gt;casi&lt;/em&gt; de todo: llamadas a otras funciones, expresiones, bucles, declaraciones de variables...&lt;br /&gt;&lt;br /&gt;Sin embargo, a diferencia de los métodos o funciones habituales, las lambdas no necesitan de un identificador, puesto que se declaran in situ, justo en el momento en que van a asignarse a una variable o a utilizarse como parámetro de una función, pasando el destinatario de esta asignación a actuar como delegado, o puntero, hacia la misma, o a ser el contenedor del árbol de expresión que la representa. Ein? Chino, eh? No pasa nada, dentro de poco estudiaremos estos dos usos en profundidad, pero antes vamos a ver cómo se definen las expresiones lambda a nivel de código.&lt;br /&gt;&lt;h3 id="forma"&gt;Forma de las expresiones lambda&lt;/h3&gt;Las expresiones lambda en C# se escriben según el patrón descrito a continuación, al que le siguen algunos ejemplos que lo ilustran e introducen algunas particularidades.&lt;pre&gt;&lt;code&gt;&lt;div style="background-color: #ffffc0; border: 1px dotted #c0c0c0; padding: 3px;"&gt;Forma general: &lt;strong&gt;parámetros =&amp;gt; expresión&lt;/strong&gt;, donde:&lt;br /&gt;- &lt;strong&gt;parámetros&lt;/strong&gt;: lista de parámetros separados por comas&lt;br /&gt;- &lt;strong&gt;"=&gt;"&lt;/strong&gt; : separador.&lt;br /&gt;- &lt;strong&gt;expresión&lt;/strong&gt;: implementación de las operaciones a realizar&lt;/div&gt;&lt;br /&gt;num =&amp;gt; num * 2     &lt;span style="color: green;"&gt;// Lambda con un parámetro que retorna&lt;br /&gt;                   // el doble del valor que se le pasa.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(a, b) =&amp;gt; a + b    &lt;span style="color: green;"&gt;// Lambda con dos parámetros que retorna&lt;br /&gt;                   // la suma de ambos.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;num =&amp;gt; {                        &lt;span style="color: green;"&gt;// Lambda con cuerpo que recibe un &lt;/span&gt;&lt;br /&gt;   int x = new Random().Next(); &lt;span style="color: green;"&gt;// entero, y retorna la suma de éste&lt;/span&gt;&lt;br /&gt;   return num+x;                &lt;span style="color: green;"&gt;// con un número aleatorio.&lt;/span&gt;&lt;br /&gt;}  &lt;br /&gt;&lt;br /&gt;() =&amp;gt; DateTime.Now &lt;span style="color: green;"&gt;// Lambda que no recibe parámetros&lt;br /&gt;                   // y retorna la fecha y hora del sistema.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;msg =&amp;gt; Console.WriteLine(msg); &lt;span style="color: green;"&gt;// Recibe un parámetro, realiza una&lt;br /&gt;                               // acción y no retorna nada.&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Como se puede observar, cuando sólo existe un parámetro no es necesario utilizar paréntesis en el lado izquierdo de la expresión, mientras que hay que hacerlo en todos los demás casos. También es interesante destacar que las lambda con cuerpo deben utilizar &lt;code&gt;return&lt;/code&gt; para retornar el valor deseado, cuando esto sea necesario.&lt;br /&gt;&lt;br /&gt;Y un último dato: fijaos que ni los parámetros ni el retorno de la función tienen indicado un tipo. Aunque puede hacerse, normalmente no será necesario puesto que el compilador podrá inferir (deducir) el tipo a partir de su contexto, más adelante veremos cómo es esto posible. Por tanto, &lt;strong&gt;no&lt;/strong&gt; es necesario escribir código tan extenso como:&lt;pre&gt;&lt;code&gt;  (int a, int b) =&amp;gt; (int)(a+b)&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Y hasta aquí este primer post introductorio. En el siguiente trataremos de explicar el papel de &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_29.html"&gt;las expresiones lambda como funciones anónimas y facilitadoras del trabajo con delegados&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;www.variablenotfound.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-5659861920250304880?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lfCcXZuDW_7MiBAHJmseDSq2hLA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lfCcXZuDW_7MiBAHJmseDSq2hLA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lfCcXZuDW_7MiBAHJmseDSq2hLA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lfCcXZuDW_7MiBAHJmseDSq2hLA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=zJpPETDokeE:ySud_9A3mgU:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=zJpPETDokeE:ySud_9A3mgU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=zJpPETDokeE:ySud_9A3mgU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=zJpPETDokeE:ySud_9A3mgU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=zJpPETDokeE:ySud_9A3mgU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=zJpPETDokeE:ySud_9A3mgU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=zJpPETDokeE:ySud_9A3mgU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=zJpPETDokeE:ySud_9A3mgU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=zJpPETDokeE:ySud_9A3mgU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/zJpPETDokeE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/5659861920250304880/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=5659861920250304880" title="2 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/5659861920250304880?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/5659861920250304880?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/zJpPETDokeE/c-desmitificando-las-expresiones-lambda.html" title="C#: Desmitificando las expresiones lambda (I)" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s72-c/lambdas.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUERn45fSp7ImA9WxVUF0s.&quot;"><id>tag:blogger.com,1999:blog-27752126.post-7197607904628101112</id><published>2009-03-22T23:50:00.002+01:00</published><updated>2009-03-22T23:50:07.025+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-22T23:50:07.025+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="tecnología" /><category scheme="http://www.blogger.com/atom/ns#" term="blogging" /><category scheme="http://www.blogger.com/atom/ns#" term="servicios on-line" /><title>Windows Live Writer</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 8px 8px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Windows Live Writer" border="0" alt="Windows Live Writer" align="right" src="http://lh6.ggpht.com/_O9D62hXq-ng/ScaVtJ9TF0I/AAAAAAAABAs/CG8Mo_4yHDw/image101.png?imgmax=800" width="240" height="247" /&gt; Aunque lamentablemente no me haya dado&amp;#160; demasiada prisa en hacerlo, tenía ganas de probar este producto. Si habéis utilizado alguna vez el interfaz de edición de Blogger, sabréis que no es precisamente una maravilla, y que a veces complica bastante la publicación de entradas en el blog, y máxime cuando se trata de contenidos con formatos especiales, como puede ser código fuente en cualquier lenguaje.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;a title="Descargar Live Writer" href="http://download.live.com/writer" target="_blank"&gt;Live Writer&lt;/a&gt; &lt;/strong&gt;es una fantástica aplicación de escritorio desarrollada por Microsoft en el contexto de su iniciativa Live, cuyo objetivo es facilitar la edición y publicación de entradas en blogs y, lo más curioso, compatible con los motores más difundidos del mercado: Blogger, WordPress, LiveSpaces, LiveJournal, TypePad, y un largo etcétera. Y cuando digo compatible, al menos con Blogger, me refiero a &lt;strong&gt;realmente compatible&lt;/strong&gt;, una integración casi perfecta, que hace que la edición de entradas sea una gozada.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 8px 8px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Previsualización de la entrada" border="0" alt="Previsualización de la entrada" align="left" src="http://lh6.ggpht.com/_O9D62hXq-ng/ScaMicByPJI/AAAAAAAABAo/WmTltc2zUcg/image17.png?imgmax=800" width="244" height="201" /&gt;Durante la instalación, Writer nos solicita la introducción de los datos de acceso al blog: la dirección, el usuario y clave. Con esta información, y por supuesto previa confirmación por parte del usuario, crea automáticamente una entrada temporal en el blog que utiliza para tomarla como plantilla, eliminándola unos segundos después. De esta forma, cuando estamos escribiendo, podemos acceder a una previsualización del contenido insertada en sobre dicha plantilla, que nos dará una idea muy aproximada, prácticamente real, del resultado final que obtendremos una vez publiquemos la entrada.&lt;/p&gt;  &lt;p&gt;El editor sobre el que escribimos es muy ligero, tiene las opciones justas para poder escribir y dar formato a los textos, siempre de forma visual (el famoso &lt;acronym title="What You See Is What You Get, lo que ves es lo que obtienes"&gt;WYSIWYG&lt;/acronym&gt;). Aunque a primera vista puede parecer que se quedará corto, nada más lejos de la realidad; no he echado en falta prácticamente ninguna característica que realmente pudiera hacerme falta durante la escritura: formatos estándar (negritas-cursivas-tachados, subrayados), colores, tablas, alineados, listas, citas,… y siempre generando un código XHTML realmente limpio y muy bien estructurado, a diferencia de otros editores basados en web (como el de Blogger, por ejemplo). &lt;/p&gt;  &lt;p&gt;Sólo en casos especiales (por ejemplo, la inclusión de una etiqueta &lt;code&gt;&amp;lt;acronym&amp;gt;&lt;/code&gt; para mostrar ayuda sobre el significado de &lt;acronym title="What You See Is What You Get, lo que ves es lo que obtienes"&gt;WYSIWYG&lt;/acronym&gt;, o la inclusión de código fuente marcado con &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; son los únicos casos en los que he tenido que salirme del editor visual y acceder a la vista de código fuente XHTML para introducir las etiquetas.&lt;/p&gt;  &lt;p&gt;Otro aspecto muy importante es su extensibilidad. Existen un gran número de complementos que pueden instalarse sobre este software para dotarlo de nuevas capacidades no contempladas en el producto base. Por aunque la &lt;a title="Galería de complementos para Live Writer" href="http://gallery.live.com/results.aspx?bt=9&amp;amp;pl=8" target="_blank"&gt;galería de complementos de Microsoft&lt;/a&gt; todavía &lt;strike&gt;está a cero&lt;/strike&gt; no está muy transitada, es fácil encontrar muchos sitios web donde se ofrecen plugins de todo tipo. Por ejemplo, he encontrado uno que a priori puede resultar muy útil, &lt;a title="Steve’s Dunn Code Formatter" href="http://stevedunns.googlepages.com/codeformatterforwindowslivewriter" target="_blank"&gt;Steve’s Dunn Code Formatter&lt;/a&gt;, que permite incluir fácilmente porciones de código formateadas como la siguiente:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:ea31e75f-a2e4-459c-bc4d-d37c5a9a3d8a" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"&gt;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;{&lt;br /&gt;    calculate(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Hard work!&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Exception ex)&lt;br /&gt;{&lt;br /&gt;    Logger.Log(ex.Message);&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Pero lo que sin duda más ha llamado mi atención es la gran facilidad para insertar contenidos multimedia, como álbumes de fotos, vídeos, mapas interactivos, y especialmente imágenes, que es lo que más suelo utilizar en mis posts. En este último caso, es sorprendentemente útil la capacidad de Live Writer para abrir imágenes del equipo local o pegarlas directamente desde el portapapeles (por ejemplo capturas de pantalla), ajustarlas al tamaño indicado e incluso agregarle sobre la marcha efectos como sombreados o reflejos (podéis ver ejemplos más arriba). Por fin se acabó el retoque con aplicaciones externas, tener que subir la imagen al servidor, ver cómo queda, retocarla de nuevo, volver a subirla…&lt;/p&gt;&lt;p&gt;Por último, el hecho de tratarse de una herramienta off-line aporta mucha agilidad, y nos brinda la posibilidad de trabajar en modo desconectado, aunque a costa de perder algunas funcionalidades para las que obviamente es necesario disponer de conexión a internet, como la edición de posts ya publicados, almacenados en el blog, o el envío directo de las entradas. En estos casos, el sistema almacena toda la información en local, para que más adelante podamos enviar los cambios realizados.&lt;/p&gt;&lt;p&gt;Ni que decir tiene que este post está completamente escrito sobre Live Writer, e incluso las imágenes las he generado desde la propia herramienta.&lt;/p&gt;&lt;p&gt;En resumen: una maravilla, imprescindible.&lt;/p&gt;&lt;p&gt;Descarga: &lt;strong&gt;&lt;a title="Descargar Live Writer" href="http://download.live.com/writer" target="_blank"&gt;Microsoft Live Writer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;www.variablenotfound.com&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27752126-7197607904628101112?l=www.variablenotfound.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bbgFHK0jlDFwjcQ0LNOmuBgCMoM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bbgFHK0jlDFwjcQ0LNOmuBgCMoM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bbgFHK0jlDFwjcQ0LNOmuBgCMoM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bbgFHK0jlDFwjcQ0LNOmuBgCMoM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/vnf?a=mL0P633IP1k:n23ub1LGV5I:ecdYMiMMAMM"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=ecdYMiMMAMM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=mL0P633IP1k:n23ub1LGV5I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=mL0P633IP1k:n23ub1LGV5I:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=mL0P633IP1k:n23ub1LGV5I:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=mL0P633IP1k:n23ub1LGV5I:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=mL0P633IP1k:n23ub1LGV5I:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=mL0P633IP1k:n23ub1LGV5I:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/vnf?a=mL0P633IP1k:n23ub1LGV5I:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/vnf?i=mL0P633IP1k:n23ub1LGV5I:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/vnf/~4/mL0P633IP1k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.variablenotfound.com/feeds/7197607904628101112/comments/default" title="Enviar comentarios" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=27752126&amp;postID=7197607904628101112" title="0 comentarios" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/7197607904628101112?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/27752126/posts/default/7197607904628101112?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/vnf/~3/mL0P633IP1k/windows-live-writer.html" title="Windows Live Writer" /><author><name>José M. Aguilar</name><uri>http://www.blogger.com/profile/11683750380776435448</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13204222613663593069" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.variablenotfound.com/2009/03/windows-live-writer.html</feedburner:origLink></entry></feed>
