<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>XAML Sorpresa</title>
	<atom:link href="http://xamlsorpresa.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://xamlsorpresa.wordpress.com</link>
	<description>Experiencias de Pablo con .net y WPF</description>
	<lastBuildDate>Fri, 16 Dec 2011 08:26:17 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='xamlsorpresa.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>XAML Sorpresa</title>
		<link>http://xamlsorpresa.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://xamlsorpresa.wordpress.com/osd.xml" title="XAML Sorpresa" />
	<atom:link rel='hub' href='http://xamlsorpresa.wordpress.com/?pushpress=hub'/>
		<item>
		<title>De c&#243;mo en AspNetMVC prevalece QueryString sobre el propio Modelo</title>
		<link>http://xamlsorpresa.wordpress.com/2011/12/16/de-cmo-en-aspnetmvc-prevalece-querystring-sobre-el-propio-modelo/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/12/16/de-cmo-en-aspnetmvc-prevalece-querystring-sobre-el-propio-modelo/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 00:16:25 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">https://xamlsorpresa.wordpress.com/?p=134</guid>
		<description><![CDATA[Imaginemos una página MVC muy sencilla: un buscador con dos datos, el texto a buscar y una casilla para indicar si se quiere coincidencia estricta de mayúsculas o no. La búsqueda se ejecuta mediante un botón y los resultados se &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/12/16/de-cmo-en-aspnetmvc-prevalece-querystring-sobre-el-propio-modelo/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=134&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Imaginemos una página MVC muy sencilla: un buscador con dos datos, el texto a buscar y una casilla para indicar si se quiere coincidencia estricta de mayúsculas o no. La búsqueda se ejecuta mediante un botón y los resultados se muestran en la misma página tras un roundtrip completo al servidor, sin AJAX. Para construir esta página, vamos a elaborar sus tres piezas M.V.C.</p>
<h3>Modelo</h3>
<p>Una clase ViewModel con los parámetros de la búsqueda y con una lista de resultados.</p>
<pre class="code"><span style="color:#400080;">public class </span><span style="color:#305fb6;">BuscarViewModel
</span>{
    <span style="color:#400080;">public string </span>Texto { <span style="color:#400080;">get</span>; <span style="color:#400080;">set</span>; }
    <span style="color:#400080;">public bool </span>EnMayusculas { <span style="color:#400080;">get</span>; <span style="color:#400080;">set</span>; }
    <span style="color:#400080;">public </span><span style="color:#305fb6;">IEnumerable</span><span style="color:#2e53d1;">&lt;</span><span style="color:#400080;">dynamic</span><span style="color:#2e53d1;">&gt; </span>Resultados { <span style="color:#400080;">get</span>; <span style="color:#400080;">set</span>; }
}</pre>
<h3>Controlador</h3>
<p>Una acción Buscar de tipo GET que recibe los parámetros de la búsqueda. Por simplicidad, uso el mismo ViewModel como parámetro de entrada, para aprovechar el trabajo del ModelBinder de MVC. La acción rellena el valor de Resultados, en teoría considerando los parámetros de búsqueda, aunque en este caso he usado valores de ejemplo.</p>
<p>Imaginemos también una peculiar regla de negocio que nos exige que la casilla “Coincidir mayúsculas” se devuelva siempre desmarcada, incluso si ha sido marcada en la búsqueda anterior. Para ello, en el modelo recibido la establecemos a falso.</p>
<pre class="code"><span style="color:#400080;">public </span><span style="color:#305fb6;">ActionResult </span>Buscar(<span style="color:#305fb6;">BuscarViewModel </span>buscarViewModel)
{
    buscarViewModel<span style="color:#2e53d1;">.</span>EnMayusculas <span style="color:#2e53d1;">= </span><span style="color:#400080;">false</span>;                         <span style="color:#937a42;">//Siempre se pone a falso
    </span><span style="color:#400080;">var </span>ejemplo <span style="color:#2e53d1;">= </span><span style="color:#400080;">new </span>{Texto <span style="color:#2e53d1;">= </span><span style="color:#259241;">"Ejemplo" </span>};
    buscarViewModel<span style="color:#2e53d1;">.</span>Resultados <span style="color:#2e53d1;">= </span><span style="color:#305fb6;">Enumerable</span><span style="color:#2e53d1;">.</span>Repeat(ejemplo, <span style="color:#259241;">50</span>);  <span style="color:#937a42;">//Ficticio
    </span><span style="color:#400080;">return </span>View(buscarViewModel);</pre>
<pre class="code">}</pre>
<p>Esta acción responde a las siguientes URI (suponiendo un controlador EntidadController):</p>
<ul>
<li>/Entidad/Buscar
<li>/Entidad/Buscar?Texto=abc&amp;EnMayusculas=true</li>
</ul>
<h3>Vista</h3>
<p>Una vista muy sencilla podría ser:</p>
<pre class="code"><span style="background:#e3d5c1;color:#a31515;"></span><span style="background:#e3d5c1;color:#a31515;">@</span><span style="background:#e3d5c1;color:#a31515;">model </span><span style="background:#e3d5c1;color:#a31515;"></span>MvcCheckBoxForFail<span style="color:#2e53d1;">.</span>Models<span style="color:#2e53d1;">.</span><span style="color:#305fb6;">BuscarViewModel
</span><span style="background:#e3d5c1;color:#a31515;">@{
</span>    ViewBag<span style="color:#2e53d1;">.</span>Title <span style="color:#2e53d1;">= </span><span style="color:#259241;">"Buscar"</span>;
    <span style="color:#400080;">var </span>grid <span style="color:#2e53d1;">= </span><span style="color:#400080;">new </span><span style="color:#305fb6;">WebGrid</span>(Model<span style="color:#2e53d1;">.</span>Resultados);
<span style="background:#e3d5c1;color:#a31515;">}

</span><span style="color:#305fb6;">&lt;</span><span style="color:#400080;">h2</span><span style="color:#305fb6;">&gt;</span>Búsqueda<span style="color:#305fb6;">&lt;/</span><span style="color:#400080;">h2</span><span style="color:#305fb6;">&gt;
</span><span style="background:#e3d5c1;color:#a31515;">@</span><span style="color:#400080;">using </span>(Html<span style="color:#2e53d1;">.</span>BeginForm(<span style="color:#259241;">"Buscar"</span>, <span style="color:#259241;">"Entidad"</span>, <span style="color:#2b91af;">FormMethod</span><span style="color:#2e53d1;">.</span>Get)) {
    <span style="color:#305fb6;">&lt;</span><span style="color:#400080;">fieldset</span><span style="color:#305fb6;">&gt;
        &lt;</span><span style="color:#400080;">legend</span><span style="color:#305fb6;">&gt;</span>Buscar <span style="background:#e3d5c1;color:#a31515;">@</span>Model<span style="color:#2e53d1;">.</span>Texto en mayúsculas <span style="background:#e3d5c1;color:#a31515;">@</span>Model<span style="color:#2e53d1;">.</span>EnMayusculas<span style="color:#305fb6;">&lt;/</span><span style="color:#400080;">legend</span><span style="color:#305fb6;">&gt;

        &lt;</span><span style="color:#400080;">div</span><span style="color:#305fb6;">&gt;
            </span>Texto
            <span style="background:#e3d5c1;color:#a31515;">@</span>Html<span style="color:#2e53d1;">.</span>EditorFor(model <span style="color:#2e53d1;">=&gt; </span>model<span style="color:#2e53d1;">.</span>Texto)
            Mayúsculas
            <font><span style="background:#e3d5c1;color:#a31515;">@</span>Html<span style="color:#2e53d1;">.</span>EditorFor(model <span style="color:#2e53d1;">=&gt; </span>model<span style="color:#2e53d1;">.</span>EnMayusculas)</font>
            <span style="color:#305fb6;">&lt;</span><span style="color:#400080;">input </span><span style="color:#305fb6;">type</span><span style="color:blue;">=</span><span style="color:#259241;">"submit" </span><span style="color:#305fb6;">value</span><span style="color:blue;">=</span><span style="color:#259241;">"Buscar" </span><span style="color:#305fb6;">/&gt;
        &lt;/</span><span style="color:#400080;">div</span><span style="color:#305fb6;">&gt;

        </span><span style="background:#e3d5c1;color:#a31515;">@</span>grid<span style="color:#2e53d1;">.</span>GetHtml()

    <span style="color:#305fb6;">&lt;/</span><span style="color:#400080;">fieldset</span><span style="color:#305fb6;">&gt;
</span>}</pre>
<p>Sus elementos principales son:</p>
<ul>
<li>Un WebGrid nativo de MVC para mostrar los resultados con una sencilla paginación en servidor.
<li>Un Form con método GET.
<li>Los campos para el texto y para forzar la coincidencia de mayúsculas, generados ambos con EditorFor.</li>
</ul>
<h3>Problemática</h3>
<p>Si probamos esta sencilla página, nos encontraremos con un curioso comportamiento: no sigue la regla de que la casilla de forzar mayúsculas debe salir siempre desactivada. Por el contrario, mantiene el valor usado para la búsqueda. Pero nosotros hemos asignado <span style="color:#400080;">false</span> claramente en el controlador, por lo que ¿quién es el responsable de que se muestre la casilla activada? A este nivel, el culpable es el método EditorFor, que no usa el valor que trae el modelo (sí, de ahí el resaltado amarillo, soy muy malo para mantener el suspense). Más adelante depuraremos mejor las responsabilidades.</p>
<p>Antes de eso, probamos con otras opciones. Por ejemplo, en lugar de EditorFor, usaremos CheckBoxFor:</p>
<pre class="code"><span style="background:#e3d5c1;color:#a31515;">@</span>Html<span style="color:#2e53d1;">.</span>CheckBoxFor(model <span style="color:#2e53d1;">=&gt; </span>model<span style="color:#2e53d1;">.</span>EnMayusculas)</pre>
<p>El comportamiento, como era de esperar, es idéntico. Así que vamos un paso más allá y usamos el método CheckBox:
<pre class="code"><span style="background:#e3d5c1;color:#a31515;">@</span>Html<span style="color:#2e53d1;">.</span>CheckBox(<span style="color:#259241;">"EnMayusculas"</span>, Model<span style="color:#2e53d1;">.</span>EnMayusculas)
</pre>
<p>Para nuestra sorpresa, el comportamiento sigue siendo el mismo, aún cuando Model<span style="color:#2e53d1;">.</span>EnMayusculas es siempre falso. Pero es más, si escribimos:</p>
<pre class="code"><span style="background:#e3d5c1;color:#a31515;">@</span>Html<span style="color:#2e53d1;">.</span>CheckBox(<span style="color:#259241;">"EnMayusculas"</span>, false)</pre>
<p>Incluso indicando el valor de false explícitamente, el input se renderiza marcado (<em>checked</em>) en ciertas ocasiones. ¿Cómo es esto posible?</p>
<h3>Primera explicación</h3>
<p>En primer lugar, ya hemos identificado en qué casos se activa la casilla: cuando estaba marcada al hacer la búsqueda, es decir, cuando se recibe en la QueryString un EnMayusculas=true.</p>
<blockquote>
<p>NOTA: En la QueryString se recibirá siempre un EnMayusculas=false, independientemente de que se marque o no la casilla. Esto es debido al hidden que genera CheckBoxFor. Para más información sobre este comportamiento, ver esta <a href="http://forums.asp.net/t/1314753.aspx">respuesta de Jeremy</a>.</p>
</blockquote>
<p>¿Qué se deduce de aquí? Pues que al usar los métodos del helper Html para renderizar un control (no sucede sólo con el CheckBox, probadlo con otros), si el <em>nombre </em>indicado existe en la QueryString recibida, se usará ese valor independientemente de su valor en el modelo o del valor estricto que le pasemos al helper. Hay más información sobre este comportamiento en <a href="http://aspnet.codeplex.com/workitem/9468">esta incidencia</a> respondida por RanjiniM de forma contundente: “Este es el comportamiento esperado en ASP.NET MVC”.</p>
<h3>Soluciones</h3>
<p>Ante esto, pueden buscarse distintas soluciones. Yo voy a plantear las dos más extremas.</p>
<p>La primera es dejar de usar el helper CheckBox e insertar un input en HTML directamente. Incluso podemos elaborar nuestro propio helper que evite este comportamiento.</p>
<p>Pero antes veamos la segunda solución, que es la que propone RanjiniM en la respuesta anterior: excluir la propiedad en cuestión del uso del ModelBinder. La firma de la acción incluirá un nuevo atributo, quedando así en nuestro controlador:</p>
<pre class="code"><span style="color:#400080;">public </span><span style="color:#305fb6;">ActionResult </span>Buscar([<span style="color:#305fb6;">Bind</span>(Exclude<span style="color:#2e53d1;">=</span><span style="color:#259241;">"EnMayusculas"</span>)] <span style="color:#305fb6;">BuscarViewModel </span>buscarViewModel)</pre>
<p>El atributo se aplica al parámetro, no al método completo, y define la propiedad (o propiedades, separadas por comas) para las que queremos evitar el comportamiento descrito. Una vez establecido este atributo, el código original (usando CheckBoxFor) funciona correctamente, y la casilla sale desmarcada en todos los casos.</p>
<h3>ModelBinder y ValueProvider</h3>
<p>Con la ayuda de <a href="http://geeks.ms/blogs/lruiz/">Luis Ruiz Pavón</a> y de <a href="http://geeks.ms/blogs/etomas/">Eduard Tomàs</a> he revisado cómo puede afectar el orden de definición de los ValueProvider a esta incidencia, pero mis pobres conocimientos no me han permitido llegar a una conclusión.</p>
<p>Yo entiendo que tanto el ModelBinder como los ValueProvider se utilizan a la hora de generar el modelo, es decir, de construir la instancia que se pasa como argumento a la acción Buscar. Pero una vez generada esa instancia de BuscarViewModel, no consigo entender por qué vuelve a prevalecer el valor de QueryString sobre lo que pone en el modelo. Si los valores de QueryString ya se han trasladado al modelo, lo lógico después es trabajar con el modelo, que puede haber sufrido cambios como en nuestro supuesto.</p>
<p>La intención de toda esta exposición es doble: en primer lugar, servir de ayuda a quien pueda encontrarse esta misma incidencia; y por otro lado, tratar de comprender mejor la justificación de este comportamiento, que según afirma RanjiniM no es un bug sino el comportamiento esperado (a no ser que estemos disfrazando un bug de feature como tantas veces <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Por eso agradezco vuestros comentarios y opiniones al respecto.</p>
<p>Un placer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/134/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=134&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/12/16/de-cmo-en-aspnetmvc-prevalece-querystring-sobre-el-propio-modelo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>
	</item>
		<item>
		<title>[ASP.NET MVC] Detectando DEBUG en c&#243;digo y en Razor</title>
		<link>http://xamlsorpresa.wordpress.com/2011/10/20/asp-net-mvc-detectando-debug-en-cdigo-y-en-razor/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/10/20/asp-net-mvc-detectando-debug-en-cdigo-y-en-razor/#comments</comments>
		<pubDate>Thu, 20 Oct 2011 01:13:54 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">https://xamlsorpresa.wordpress.com/2011/10/20/asp-net-mvc-detectando-debug-en-cdigo-y-en-razor/</guid>
		<description><![CDATA[Últimamente he aumentado bastante mi productividad usando un mecanismo muy sencillo: implementando código sólo para depuración que me ayuda en las sesiones de depuración, y ahora no me estoy refiriendo a trazas ni logs. Me refiero a cosas tan sencillas &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/10/20/asp-net-mvc-detectando-debug-en-cdigo-y-en-razor/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=133&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Últimamente he aumentado bastante mi productividad usando un mecanismo muy sencillo: implementando código sólo para depuración que me ayuda en las sesiones de depuración, y ahora no me estoy refiriendo a trazas ni <em>logs</em>. Me refiero a cosas tan sencillas como:</p>
<ul>
<li>Iniciar sesión automáticamente con un usuario y contraseña dados (suponiendo, como en mi proyecto, que se prohíbe por requisito que el navegador recuerde al usuario).</li>
<li>Rellenar valores de mi conveniencia en un formulario.</li>
</ul>
<p>Como estas cosas, aunque las implemente, no quiero que ni por lo más remoto puedan llegar a producción, uso la <a href="http://msdn.microsoft.com/es-es/library/76zdzba1(v=vs.90).aspx">constante de compilación DEBUG</a> que indica si estamos ejecutando en <em>Debug</em> o en <em>Release</em> (y si tenemos más configuraciones, podremos indicar si la queremos declarar o no). Como mi código en producción irá como <em>Release</em>, no corro el riesgo de ejecutar mis atajos para depuración.</p>
<p>En un proyecto web MVC, según dónde nos encontremos, la forma de detectar si estamos en <em>Debug</em> o <em>Release</em> es distinta como vamos a ver a continuación.</p>
<h1>Directivas de precompilación y DEBUG</h1>
<p>Las directivas de precompilación de C# permiten que el compilador considere un código u otro en función de unas constantes, como DEBUG en nuestro caso. Por ejemplo, algo como:</p>
<pre class="code"><span style="color:#400080;">#if </span>DEBUG
        <span style="color:#400080;">string </span>username <span style="color:#2e53d1;">= </span><span style="color:#259241;">"pablo"</span>;
<span style="color:#400080;">#else
        </span><span style="color:gray;">string username = null;
</span><span style="color:#400080;">#endif</span></pre>
<p>Hace que los programas generados en <em>Debug</em> y en <em>Release</em> sean distintos: uno llevará una asignación a “pablo” y el otro a <em>null</em>. Ojo que no existe doble declaración de la variable: en un caso se declarará una y el propio compilador ignorará la otra línea, no sólo no se ejecuta, es que ni se compila.</p>
<p>Usando estas directivas no corro el riesgo de olvidarme de quitar este código de depuración cuando genere mi versión para producción: se usará el código que asigna null.</p>
<p>Un código similar he usado en mi <em>MembershipProvider</em> (no pongo el ejemplo porque mi caso es muy particular y dependiente de un motor de bases de datos muy particular) para iniciar una sesión concreta siempre en <em>Debug</em>, mientras que en <em>Release</em> el usuario debe iniciar sesión.</p>
<p>Las directivas de precompilación tienen más usos, como usar un mismo código base para diferentes targets, como Silverlight, Windows Phone… con algo como:</p>
<pre class="code"><span style="color:#400080;">#if </span>SILVERLIGHT</pre>
<p>Lo cual nos acerca a aquello de un código, tres pantallas. Aunque no es el tema de hoy.</p>
<h1>Detectando modo Debug en Razor</h1>
<p>Pensando bien, uno interpreta que esto se puede aplicar al código C# incrustado en Razor. Yo he intentado usarlo para el segundo punto planteado al inicio de este artículo, y de forma natural uno piensa que puede hacer:</p>
<pre class="code">@{
<span style="color:#400080;">#if </span>DEBUG
        <span style="color:#400080;">string </span>titulo <span style="color:#2e53d1;">= </span><span style="color:#259241;">"pablo"</span>;
<span style="color:#400080;">#else
        </span><span style="color:gray;"><font color="#0000ff">string</font> <font color="#000000">titulo</font> = <font color="#0000ff">null</font>;
</span><span style="color:#400080;">#endif
</span>}</pre>
<p>Cuidado, esto no funciona. Y tiene sentido que no lo haga: este código dentro de Razor no es compilado al publicar el proyecto, sino que es incrustado en las vistas, y luego las vistas son compiladas por IIS según necesidad. Por lo que <em>#if DEBUG</em> siempre devuelve <em>true</em>. No sirve.</p>
<p>Pero hay otra forma de detectar que estamos en <em>Debug</em> desde Razor, y aunque no es exactamente igual, en la mayoría de los casos será equivalente y nos servirá. Se trata de la propiedad:</p>
<pre class="code">Context.IsDebuggingEnabled</pre>
<p>Que nos ofrecen las páginas Razor a través de su <em>HttpContext</em>. De esta forma sí podemos hacer:</p>
<pre class="code"><span style="background:#e3d5c1;color:#a31515;">@{
</span>    <span style="color:#400080;">string </span>titulo;
    <span style="color:#400080;">if</span>(Context<span style="color:#2e53d1;">.</span>IsDebuggingEnabled)
        titulo <span style="color:#2e53d1;">= </span><span style="color:#259241;">"pablo"</span>;
    <span style="color:#400080;">else
        </span>titulo <span style="color:#2e53d1;">= </span><span style="color:#400080;">null</span>;
<span style="background:#e3d5c1;color:#a31515;">}</span></pre>
<p>Con lo que podemos usar esa variable <em>@titulo</em> como valor del elemento <em>input</em> correspondiente para que al cargar la página tengamos un valor inicial. Ojo, esto se podría (debería) hacer en el modelo (<em>viewmodel</em>) usado en la página, pero entonces podríamos usar directivas de precompilación y no tendría gracia el uso de <em>IsDebuggingEnabled</em>, así que he forzado un poco el ejemplo para mostrar este caso.</p>
<h1>Conclusión</h1>
<p>Podemos hacer trucos en nuestro código que nos faciliten la tarea rutinaria de ejecutar una y otra vez una aplicación en desarrollo para llegar a la página que estamos implementando, saltando los pasos que un usuario debería recorrer. Esta simplificación puede aumentar considerablemente nuestra productividad, pero cuando lo hagamos, debemos seguir los cauces que existen para ello (detección de <em>DEBUG</em> con <em>#if</em>, propiedad <em>IsDebuggingEnabled</em>) para que al pasar la aplicación a producción no quede ni rastro de nuestros trucos. Y ojito también con lo que subimos al control de código fuente, a ver si otro compañero se va a encontrar con nuestros atajos y quizá no le vayan a hacer mucha gracia.</p>
<p>Un placer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/133/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=133&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/10/20/asp-net-mvc-detectando-debug-en-cdigo-y-en-razor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>
	</item>
		<item>
		<title>Primer contacto con Code Contracts (no es un tutorial)</title>
		<link>http://xamlsorpresa.wordpress.com/2011/10/05/primer-contacto-con-code-contracts-no-es-un-tutorial/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/10/05/primer-contacto-con-code-contracts-no-es-un-tutorial/#comments</comments>
		<pubDate>Wed, 05 Oct 2011 22:30:02 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">https://xamlsorpresa.wordpress.com/2011/10/05/primer-contacto-con-code-contracts-no-es-un-tutorial/</guid>
		<description><![CDATA[Hola, me llamo Pablo y hoy he sufrido mi primer contacto forzoso con Code Contracts. Lo de forzoso no es porque no me guste ese proyecto, sino porque ha sido completamente involuntario. Pero antes de nada, ¿qué es Code Contracts? &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/10/05/primer-contacto-con-code-contracts-no-es-un-tutorial/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=132&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hola, me llamo Pablo y hoy he sufrido mi primer contacto forzoso con Code Contracts. Lo de forzoso no es porque no me guste ese proyecto, sino porque ha sido completamente involuntario. Pero antes de nada, ¿qué es Code Contracts?</p>
<h2>Code Contracts</h2>
<p><a href="http://research.microsoft.com/en-us/projects/contracts/">Code Contracts</a> es un proyecto de Microsoft Research para incluir en nuestro código las <a href="http://es.wikipedia.org/wiki/Precondici%C3%B3n">precondiciones</a> y <a href="http://es.wikipedia.org/wiki/Postcondici%C3%B3n">poscondiciones</a> que deben cumplirse antes y después de su ejecución, así como los <a href="http://es.wikipedia.org/wiki/Invariante_(inform%C3%A1tica)">invariantes</a> que deben cumplirse siempre. Muchos no habrán usado estas palabrejas desde que dejaron la Universidad, otros ni eso, pero al programar todos estamos asumiendo premisas que deben cumplirse (por ejemplo, que un método debe llamarse antes que otro, o que una variable tenga un rango de valores concreto), sólo que no los reflejamos en ningún sitio, sólo están en nuestra cabeza. Ahí es donde interviene Code Contracts, permitiendo poner negro sobre blanco (pixel negro sobre pixel blanco, quiero decir) esas condiciones, y además verificando que se cumplan tanto durante la ejecución de nuestro programa como de nuestros <em>tests</em>.</p>
<p>Como idea es muy interesante, y permite incrementar la calidad de nuestro código, difuminando un poco la división entre programa y tests, ya que estas comprobaciones (equivalentes a los Assert de un test) están en el propio programa. También ayuda a la legibilidad del código y a su comprensión por parte de quien venga detrás (que normalmente somos nosotros mismos dentro de un tiempo). Y su uso no es nada difícil, como muestra un botón:</p>
<pre class="code"><span style="color:#400080;">public void </span>Bind(<span style="color:#305fb6;">FrameworkElement </span>bindingObject, <span style="color:#305fb6;">Func</span><span style="color:#2e53d1;">&lt;</span><span style="color:#305fb6;">FrameworkElement</span>, <span style="color:#305fb6;">FrameworkElement</span><span style="color:#2e53d1;">&gt; </span>bindingObjectParentFunc)
{
    <span style="color:#305fb6;">Contract</span><span style="color:#2e53d1;">.</span>Requires<span style="color:#2e53d1;">&lt;</span><span style="color:#305fb6;">ArgumentNullException</span><span style="color:#2e53d1;">&gt;</span>(bindingObject <span style="color:#2e53d1;">!= </span><span style="color:#400080;">null</span>, <span style="color:#259241;">"Binding object cannot be null."</span>);
    <span style="color:#305fb6;">Contract</span><span style="color:#2e53d1;">.</span>Requires<span style="color:#2e53d1;">&lt;</span><span style="color:#305fb6;">ArgumentNullException</span><span style="color:#2e53d1;">&gt;</span>(bindingObjectParentFunc <span style="color:#2e53d1;">!= </span><span style="color:#400080;">null</span>, <span style="color:#259241;">"Binding object function cannot be null."</span>);
…
</pre>
<p>En lugar de comprobar si nos han pasado bien los atributos con un <font face="Consolas">if</font>, lo estamos <em>declarando</em> usando <font face="Consolas">Contract</font>, el punto de acceso principal a la librería Code Contracts. Se entiende fácil, ¿verdad? Pues si queréis saber más, os dejo aquí una <a href="http://www.slideshare.net/eduardtomas/microsoft-code-contracts">presentación</a> de un chico que parece que sabe de esto.</p>
<h2>¿Pero qué te ha pasado hoy?</h2>
<p>Pues nada, que estaba tratando de localizar un error en la versión que estamos preparando para WPF de SilverDiagram, y entre cambios de código y recompilaciones de librerías me he encontrado con este error:</p>
<p><a href="http://xamlsorpresa.files.wordpress.com/2011/10/image2.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://xamlsorpresa.files.wordpress.com/2011/10/image_thumb2.png?w=652&#038;h=158" width="652" height="158"></a></p>
<p>El texto es bastante más extenso, pero qué os voy a contar de esas hermosas pilas de llamadas listadas en enormes MessageBox. Todo un símbolo, y perfecto para demostrar a nuestro jefe/usuarios lo difícil que es nuestra profesión.</p>
<p>La cuestión es que este error viene provocado por Code Contract, porque se da una situación curiosa: Tengo dos librerías, A y B. La librería B referencia a A (pero están en soluciones distintas, así que referencia el ensamblado A.dll, pongamos).</p>
<p>Yo estaba probando B sin problemas, tratando de corregir el error, haciendo cambios y pruebas normalmente. Cuando identifico que el error parece estar en A, abro su solución, lo corrijo y compilo para usar esta nueva A.dll. Esta compilación no se queja.</p>
<p>Compilo B con la nueva A.dll y de nuevo sin problema. Pero al ejecutar, el error, ah, el error: <em>Must use the rewriter when using Contract.Requires&lt;TException&gt;</em>.</p>
<p>Está claro que la culpa es de Code Contracts. Echo una búsqueda rápida, y encuentro en el <a href="http://devlicio.us/blogs/derik_whittaker/archive/2010/06/30/error-contract-requires-lt-texception-gt-must-use-the-rewriter.aspx">blog de Derik Whittacker</a> una coincidencia. Y hace especial hincapié en que la culpa no es de B, sino del proyecto A, a pesar de no haber dado errores en su compilación. Y el motivo es sencillo: no tengo instalado Code Contracts en mi ordenador.</p>
<h2>Instalando… y solucionado</h2>
<p>Así que tras cerrar los Visuales Estudios, descargo e instalo desde la web de <a href="http://research.microsoft.com/en-us/projects/contracts/">Code Contracts</a> (hay versión comercial y académica, pero no me preguntéis sobre eso). Una vez instalado, conseguimos dos cosas:</p>
<ol>
<li>En las Propiedades de los proyectos hay una nueva pestaña Code Contracts donde podemos definir el comportamiento de esta librería en nuestro proyecto.</li>
<li>Al volver a compilar el proyecto, ya podemos usar A.dll con normalidad en otros proyectos (si estaba bien configurada la comprobación en tiempo de ejecución de las propiedades de Code Contracts, pero esto es harina de otro costal).</li>
</ol>
<p>Espero que esto pueda servir de ayuda para quienes sufran el mismo problema, y también para que algunos nos empecemos a introducir en Code Contracts (<em>…por mi primero</em>).</p>
<p>Un placer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/132/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=132&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/10/05/primer-contacto-con-code-contracts-no-es-un-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>

		<media:content url="http://xamlsorpresa.files.wordpress.com/2011/10/image_thumb2.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Carencias de Sql CE 4.0 en Visual Studio 2010</title>
		<link>http://xamlsorpresa.wordpress.com/2011/10/03/carencias-de-sql-ce-4-0-en-visual-studio-2010/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/10/03/carencias-de-sql-ce-4-0-en-visual-studio-2010/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 00:37:04 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">https://xamlsorpresa.wordpress.com/2011/10/03/carencias-de-sql-ce-4-0-en-visual-studio-2010/</guid>
		<description><![CDATA[Hoy domingo he estado preparando una demo introductoria a Entity Framework, con el objetivo de que fuera lo más sencilla posible. Para ello, no he querido trabajar ni en un proyecto web ni en una aplicación Windows, sino en un &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/10/03/carencias-de-sql-ce-4-0-en-visual-studio-2010/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=129&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hoy domingo he estado preparando una demo introductoria a Entity Framework, con el objetivo de que fuera lo más sencilla posible. Para ello, no he querido trabajar ni en un proyecto web ni en una aplicación Windows, sino en un proyecto de consola, para no exigir ningún conocimiento previo en el destinatario. Y desde un principio había elegido basarme en SQL Server Compact Edition (Sql CE), y su última versión 4.0, para evitar la necesidad de instalar un motor de bases de datos y profundizar en su configuración, pero todavía manteniendo un proveedor nativo de .net y de Entity Framework. Todo sobre Visual Studio 2010. También debo adelantar que mi contacto previo con Sql CE es mínimo, sólo como registro de Elmah y poco más. Pero como hoy he aprendido algunos hechos, los quiero compartir en este artículo.</p>
<p>Aunque yo suelo trabajar con EF aplicando la metodología Code-First, de nuevo por simplicidad decido plantear la demo como Model-First, por aquello del interfaz gráfico y demás (que está sobrevalorado, donde se ponga un buen interfaz de código fluido…). Bueno, creo un archivo .edmx y defino en él 2 tablas con su propio Id autonumérico como clave primaria y una clave foránea entre ambas. Cuando pido <font face="Lucida Console">Crear base de datos a partir del modelo</font> en el menú contextual, me pide crear una conexión a base de datos, y me ofrece 3 proveedores: SQL Server, archivo mdf y Sql CE 3.5. </p>
<p><a href="http://xamlsorpresa.files.wordpress.com/2011/10/image.png"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="image" border="0" alt="image" src="http://xamlsorpresa.files.wordpress.com/2011/10/image_thumb.png?w=545&#038;h=527" width="545" height="527"></a></p>
<p>Decido continuar con mi idea de usar CE aunque sea 3.5 (ya veré después… sólo estoy preparando una demo). Creo un nuevo archivo sdf para la conexión y Visual Studio me genera un archivo edmx.sqlce con el script de base de datos para generar las tablas. Lo conecto al sdf y ejecuto sin problemas. Pero al incluir código para crear una entidad y ejecutarlo, obtengo el error:</p>
<blockquote><p>Server-generated keys and server-generated values are not supported by SQL Server Compact.</p>
</blockquote>
<p>Lo cual no es del todo cierto, bueno, casi lo era cuando se escribió ese mensaje de error, ya que <strong>Sql CE 3.5 no soporta autonuméricos generados en el servidor <em>a través de Entity Framework, </em></strong>es decir, realmente es una <a href="http://stackoverflow.com/questions/648449/server-generated-keys-and-server-generated-values-are-not-supported-by-sql-server">carencia del provider</a><em></em> y no del motor. Con esto, Sql CE 3.5 no me sirve para mi sencillo ejemplo, donde no voy a montar ningún generador de claves. Esta carencia ha sido subsanada en Sql CE 4.0, así que doy marcha atrás y me lanzo a la búsqueda de esta versión.</p>
<p>Hasta ahora, cuando lo había necesitado (para Code-First y para Elmah) había usado el paquete nuget. Pero esto no sirve para EDMX, ya que debe estar registrado el proveedor en Visual Studio. De ahí que me descargo las <a href="http://go.microsoft.com/fwlink/?LinkId=212219">SQL CE Tools for Visual Studio</a> SP1 (que ya lo tenía) desde este <a href="http://weblogs.asp.net/scottgu/archive/2011/01/11/vs-2010-sp1-and-sql-ce.aspx">artículo de ScottGu</a> (no sé si también estará en español, he buscado un poco y no lo he encontrado). Pero tras instalarlo, me siguen saliendo los mismos proveedores que antes, por lo que investigo un poco y descubro que <strong>el proveedor Sql CE 4.0 sólo se ofrece en el EDMX <a href="http://social.msdn.microsoft.com/Forums/en-US/sqlce/thread/4924965a-1232-4a48-bbb9-73c1995d3f43">dentro de proyectos web</a></strong>, no en mi humilde proyecto de consola. De hecho si en un proyecto web creo el sdf de la versión 4.0 y añado una conexión a él en el Explorador de servidores de Visual Studio, al tratar de usarlo desde el EDMX no se incluye en el combo (sólo se incluyen las conexiones con Sql CE 3.5 o con Sql Server). Es realmente desagradable ver cómo un EDMX añadido a una librería de clases (que es lo aconsejable, extraer el modelo fuera del proyecto web) sólo permite usar Sql CE 3.5 mientras que en un EDMX dentro de un proyecto web sí se ofrece Sql CE 4.0:</p>
<p><a href="http://xamlsorpresa.files.wordpress.com/2011/10/image1.png"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="image" border="0" alt="image" src="http://xamlsorpresa.files.wordpress.com/2011/10/image_thumb1.png?w=459&#038;h=264" width="459" height="264"></a></p>
<p>Todo esto me parece una situación extraña y limitadora, ya que Sql CE 4.0 es una solución ideal para pequeñas aplicaciones o utilidades, o para la primera fase de algunas aplicaciones mayores, incluso para instalaciones pequeñas de esas mismas aplicaciones; y con esta carencia se dificulta su utilización práctica para quienes prefieren usar el EDMX en lugar de la aproximación Code-First. Sólo me queda añadir que esta restricción puede salvarse siguiendo <a href="http://erikej.blogspot.com/2010/11/using-entity-framework-with-sql-server.html">este truco (en inglés)</a>, que implica modificar el EDMX a mano, y que puede servir a los más tenaces (los demás habrán desistido antes, tristemente).</p>
<p>Y para terminar tengo que dar las gracias a mis agazapados del Twitter, <a href="http://geeks.ms/blogs/mrubino/">Marc Rubiño</a> y <a href="http://geeks.ms/blogs/rcorral/">Rodrigo Corral</a>, por echarme una mano y compartir experiencias acerca de Sql CE (incluso siendo el día del Señor). Es un gustazo tener a gente así leyendo mis tonterías para ayudar. Otra vez gracias.</p>
<p>Un placer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/129/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=129&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/10/03/carencias-de-sql-ce-4-0-en-visual-studio-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>

		<media:content url="http://xamlsorpresa.files.wordpress.com/2011/10/image_thumb.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://xamlsorpresa.files.wordpress.com/2011/10/image_thumb1.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>[ASP.NET MVC] Discriminar acciones seg&#250;n el nombre de los par&#225;metros</title>
		<link>http://xamlsorpresa.wordpress.com/2011/09/09/asp-net-mvc-discriminar-acciones-segn-el-nombre-de-los-parmetros/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/09/09/asp-net-mvc-discriminar-acciones-segn-el-nombre-de-los-parmetros/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 00:53:50 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">https://xamlsorpresa.wordpress.com/2011/09/09/asp-net-mvc-discriminar-acciones-segn-el-nombre-de-los-parmetros/</guid>
		<description><![CDATA[El caso que voy a exponer hoy está “basado en hechos reales”, como las películas de Antena 3. Me encontré con la necesidad de ofrecer dos rutas como: http://mi.com/Form/Show?url=http://geeks.ms http://mi.com/Form/Show?name=Geeks Es decir, para quien usa la página, nuestra acción Show &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/09/09/asp-net-mvc-discriminar-acciones-segn-el-nombre-de-los-parmetros/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=124&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>El caso que voy a exponer hoy está “basado en hechos reales”, como las películas de Antena 3. Me encontré con la necesidad de ofrecer dos rutas como:</p>
<blockquote><p><a href="http://mi.com/Form/Show?url=http://geeks.ms">http://mi.com/Form/Show?url=http://geeks.ms</a></p>
<p><a href="http://mi.com/Form/Show?name=Geeks">http://mi.com/Form/Show?name=Geeks</a></p>
</blockquote>
<p>Es decir, para quien usa la página, nuestra acción <em>Show</em> puede recibir una URL o bien el nombre de una página que ya tengamos previamente guardada. Son las dos formas de acceder al servicio. Por poner algo más de contexto, puede imaginar el lector un servicio como Google Mobilizer (transformar una página para facilitar su lectura en dispositivos móviles) mezclado con un gestor de marcadores (bookmarks). El uso de la misma ruta en ambos casos es una decisión de diseño que no depende de nosotros.</p>
<p>Este diseño admite dos posibles planteamientos en MVC:</p>
<ul>
<li>Una única acción con dos parámetros opcionales, url y name.
<ul>
<li>Según el parámetro dado, elegir un comportamiento u otro.
<li>Decidir qué hacer si nos pasan los dos parámetros (por ejemplo, dar un error). </li>
</ul>
<li>Dos acciones separadas, una con un parámetro url y otra con name.
<ul>
<li>Pro: podemos organizar mejor nuestro código (en cada acción lo suyo).
<li>Pro: la decisión la hace MVC, no necesitamos discriminar según los parámetros recibidos. Queda más natural.
<li>Contra: no es soportado de forma nativa en MVC 3, como veremos. </li>
</ul>
</li>
</ul>
<p>Como el código de ambas acciones no tiene apenas nada en común, me gustaba más la segunda opción, por lo que vamos a ver si podemos ir salvando los obstáculos que nos encontremos en el desarrollo del ejemplo. Para comenzar:</p>
<ol>
<li>Creamos un nuevo proyecto ASP.NET MVC 3 de nombre SelectingActionByArgumentsName.
<li>Usamos la plantilla Vacía (Empty) y motor de vistas Razor (View engine).
<li>Añadimos un nuevo controlador: clic derecho en la carpeta Controllers, y elegimos Agregar (Add) &gt; Controller.
<li>Le llamamos FormController, y lo creamos vacío (Empty controller). </li>
</ol>
<p>Ya tenemos el proyecto listo para incluir nuestras dos acciones. Bajo la acción Index que se genera siempre, añadimos las dos nuestras, devolviendo sólo un contenido (para simplificar):</p>
<pre class="code"><span style="color:#400080;">public </span><span style="color:#305fb6;">ActionResult </span>Show(<span style="color:#400080;">string </span>url)
{
    <span style="color:#400080;">return </span>Content(<span style="color:#259241;">"Loaded from url"</span>);
}

<span style="color:#400080;">public </span><span style="color:#305fb6;">ActionResult </span>Show(<span style="color:#400080;">string </span>name)
{
    <span style="color:#400080;">return </span>Content(<span style="color:#259241;">"Loaded from name"</span>);
}</pre>
<p>Y encontramos el <strong>primer obstáculo</strong>:</p>
<blockquote>
<p>C# no admite dos métodos con la misma firma en una clase.</p>
</blockquote>
<p>Evidentemente, aunque el nombre de los parámetros sea distinto, son del mismo tipo, por lo que C# (no ASP.NET MVC, sino el compilador) nos dará un error. Contra esto, poco podemos hacer, hay que cambiar algo. Pero existe una solución sencilla: añadir un parámetro opcional. Esto hará que los métodos sean diferentes. Por ejemplo, vamos a añadir un parámetro opcional save a la acción que recibe una url:</p>
<blockquote>
<p><a href="http://mi.com/Form/Show?url=http://geeks.ms&amp;saveAs=Geeks">http://mi.com/Form/Show?url=http://geeks.ms&amp;saveAs=Geeks</a></p>
</blockquote>
<p>Este parámetro indica que queremos que se guarde la dirección con ese nombre. De hecho, hemos aprovechado para añadir funcionalidad, pero en la práctica podríamos haber añadido un parámetro sin utilidad y no usarlo nunca (su única utilidad sería permitir que el compilador acepte nuestros dos métodos de forma válida). Y lo haremos opcional, por lo que la URL inicial seguirá funcionando. Así que cambiamos la primera acción por:</p>
<pre class="code"><span style="color:#400080;">public </span><span style="color:#305fb6;">ActionResult </span>Show(<span style="color:#400080;">string </span>url, <span style="color:#400080;">string </span>saveAs <span style="color:#2e53d1;">= </span><span style="color:#259241;">""</span>)</pre>
<p>Y ya tenemos el primer obstáculo salvado: el compilador no se queja. Ya podemos ejecutar. Pero si navegamos a (en xxx irá el puerto de vuestro servidor web):</p>
<blockquote>
<p><a href="http://localhost:xxx/Form/Show?name=Geeks">http://localhost:xxx/Form/Show?name=Geeks</a></p>
</blockquote>
<p>Recibimos un error ahora de ASP.NET MVC (<strong>segundo obstáculo</strong>):</p>
<blockquote>
<h4>The current request for action &#8216;Show&#8217; on controller type &#8216;FormController&#8217; is ambiguous between the following action methods: <br />System.Web.Mvc.ActionResult Show(System.String, System.String) on type SelectingActionByArgumentsName.Controllers.FormController <br />System.Web.Mvc.ActionResult Show(System.String) on type SelectingActionByArgumentsName.Controllers.FormController</h4>
</blockquote>
<p>ASP.NET MVC no sabe elegir qué acción utilizar. ¿Pero no hemos puesto <em>name</em> en nuestra URL? Pues usa la acción que tiene un argumento <em>name</em>, so tonto (no sé si vosotros también soléis insultar a la pantalla). Pero no: ASP.NET MVC no usa los nombres de los argumentos para elegir qué acción llamar durante el proceso de enrutado (por defecto, que como casi todo en MVC 3, esto puede cambiarse). Ojo, sí usa los nombres después para asignar los parámetros, pero eso es cuando ya ha elegido la acción; es para elegirla cuando no los considera. Sólo sus tipos. Y usando sólo los tipos, se encuentra con esa ambigüedad.</p>
<p>Pero como hemos dicho, casi todo en MVC 3 puede cambiarse, y además de diferentes formas. En este caso, vamos a usar una solución <a href="http://stackoverflow.com/questions/1045316/asp-net-mvc-ambiguous-action-methods/1045616#1045616">vista en StackOverflow</a>, aunque modificada para hacerla más genérica, dirigida a cambiar el mecanismo de selección de acciones (sí, ese que hemos dicho que se basa en los tipos) para que considere también los nombres de los argumentos. Y además vamos a hacerlo mediante un atributo para que sólo afecte a las acciones donde lo necesitemos. Para esto, sólo debemos crear una clase que extienda de ActionMethodSelectorAttribute y sobreescribir el método IsValidForRequest, que es quien realizará la comprobación.</p>
<pre class="code"><span style="color:#400080;">public class </span><span style="color:#305fb6;">SelectByArgumentNamesAttribute </span>: <span style="color:#305fb6;">ActionMethodSelectorAttribute </span>{
    <span style="color:#400080;">public override bool </span>IsValidForRequest(<span style="color:#305fb6;">ControllerContext </span>controllerContext,
                                           <span style="color:#305fb6;">MethodInfo </span>methodInfo) {
        <span style="color:#400080;">return </span>methodInfo<span style="color:#2e53d1;">.</span>GetParameters()
                <span style="color:#2e53d1;">.</span>All(pi <span style="color:#2e53d1;">=&gt; </span>pi<span style="color:#2e53d1;">.</span>IsOptional
                        <span style="color:#2e53d1;">|| </span>controllerContext<span style="color:#2e53d1;">.</span>HttpContext<span style="color:#2e53d1;">.</span>Request[pi<span style="color:#2e53d1;">.</span>Name] <span style="color:#2e53d1;">!= </span><span style="color:#400080;">null</span>);
    }
}</pre>
<p>Un detalle aclaratorio: no tenemos que comprobar el nombre del método, ya que esto lo hace ASP.NET MVC antes de llamar a esta validación. Sólo tenemos que comprobar si, según los datos de la petición (<em>Request</em>), este método (<em>methodInfo</em>) es el apropiado o no. Por lo que comprobamos que todos los argumentos del método vienen en la <em>Request</em> (con su nombre), salvo que sean opcionales.</p>
<p>Ahora sólo tenemos que usar este atributo en las acciones conflictivas (en ambas). Por ejemplo:</p>
<pre class="code">[<span style="color:#305fb6;">SelectByArgumentNames</span>]
<span style="color:#400080;">public </span><span style="color:#305fb6;">ActionResult Show</span>(<span style="color:#400080;">string </span>url, <span style="color:#400080;">string </span>saveAs <span style="color:#2e53d1;">= </span><span style="color:#259241;">""</span>) {
…</pre>
<p>Tras usar el atributo en las dos acciones, ya podemos probar a navegar a las URL:</p>
<blockquote>
<p><a href="http://localhost:xxx/Form/Show?url=http://geeks.ms">http://localhost:xxx/Form/Show?url=http://geeks.ms</a></p>
<p><a href="http://localhost:xxx/Form/Show?name=Geeks">http://localhost:xxx/Form/Show?name=Geeks</a></p>
</blockquote>
<p>¿Pero qué sucede? Que todavía nos queda por salvar el <strong>tercer obstáculo</strong>, aunque no está relacionado con lo anterior. Si comprobáis, veréis que funciona correctamente con la primera dirección (con o sin el parámetro opcional) pero falla con la segunda, la que usa el parámetro <em>name</em>.</p>
<p>¿Por qué? Bueno, pues este es uno de esos problemas que nos invitan a creer en la magia y abandonar la programación para dedicarnos a echar las cartas, hasta que descubrimos de qué se trata: la culpa es del nombre elegido para el parámetro <em>url</em>, dado que siempre que preguntemos por <em>Request[“url”]</em> obtendremos un valor, nunca es <em>null</em>, aunque no hayamos pasado ningún parámetro con ese nombre en la URL, porque el valor obtenido es ¡el de la propia URL de la petición!</p>
<p>Por suerte, este obstáculo es el de más fácil solución: en lugar de buscar en <em>Request</em>, profundizamos un poco más hasta <em>Request.QueryString</em>, donde sólo están los parámetros que vienen en la <em>QueryString</em>, con lo que sólo habrá un <em>url</em> si se lo pasamos, y si no devolverá <em>null</em>. La solución pasa por cambiar:</p>
<pre class="code">controllerContext<span style="color:#2e53d1;">.</span>HttpContext<span style="color:#2e53d1;">.</span>Request[pi<span style="color:#2e53d1;">.</span>Name] <span style="color:#2e53d1;">!= </span><span style="color:#400080;">null</span></pre>
<p>por</p>
<pre class="code">controllerContext<span style="color:#2e53d1;">.</span>HttpContext<span style="color:#2e53d1;">.</span>Request<span style="color:#2e53d1;">.</span>QueryString[pi<span style="color:#2e53d1;">.</span>Name] <span style="color:#2e53d1;">!= </span><span style="color:#400080;">null</span></pre>
<p>Y resuelto. He querido incluir este último obstáculo por 1. ser fiel a la realidad (recordad que el artículo está basado en hechos reales) y 2. por la moraleja, parafraseando: “el más mínimo desconocimiento de la herramienta puede hacerse pasar por magia”.</p>
<p>En conclusión, hemos visto cómo se puede cambiar de forma muy sencilla la forma en que ASP.NET MVC selecciona la acción a partir de la URL. Recordad que, igualmente, muchos otros comportamientos generales se pueden modificar y adaptar a los casos concretos, o incluso esto podíamos haberlo conseguido de otras formas. Y sobre todo, lo más importante: hay que conocer bien la herramienta con la que trabajamos para adaptarla, entenderla&#8230; y distinguirla de la magia.</p>
<p>Un placer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/124/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/124/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/124/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/124/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/124/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/124/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/124/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/124/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/124/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/124/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/124/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/124/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/124/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/124/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=124&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/09/09/asp-net-mvc-discriminar-acciones-segn-el-nombre-de-los-parmetros/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>
	</item>
		<item>
		<title>Recibiendo un par&#225;metro de tipo Array en un Controller de ASP.NET MVC</title>
		<link>http://xamlsorpresa.wordpress.com/2011/07/26/recibiendo-un-parmetro-de-tipo-array-en-un-controller-de-asp-net-mvc/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/07/26/recibiendo-un-parmetro-de-tipo-array-en-un-controller-de-asp-net-mvc/#comments</comments>
		<pubDate>Tue, 26 Jul 2011 20:49:49 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">https://xamlsorpresa.wordpress.com/2011/07/26/recibiendo-un-parmetro-de-tipo-array-en-un-controller-de-asp-net-mvc/</guid>
		<description><![CDATA[Implementando una acción en un controlador (Controller) de ASP.NET MVC he necesitado que uno de los parámetros fuera una lista o array de enteros, en concreto los Id a considerar para un pequeño informe. Por ponerlo negro sobre blanco, o &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/07/26/recibiendo-un-parmetro-de-tipo-array-en-un-controller-de-asp-net-mvc/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=123&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Implementando una acción en un controlador (<em>Controller</em>) de ASP.NET MVC he necesitado que uno de los parámetros fuera una lista o array de enteros, en concreto los Id a considerar para un pequeño informe. Por ponerlo negro sobre blanco, o mejor, pixel sobre pantalla:</p>
<blockquote><pre class="code"><span style="color:#400080;">public class </span><span style="color:#305fb6;">InformeController </span>: <span style="color:#305fb6;">Controller
</span>{
    <span style="color:#937a42;">//
    // GET: /Informe/Ventas?desde=6/1/2011&amp;hasta=6/30/2011&amp;centros=1,2,3

    </span><span style="color:#400080;">public </span><span style="color:#305fb6;">ActionResult </span>Ventas(<span style="color:#305fb6;">DateTime </span>desde, <span style="color:#305fb6;">DateTime </span>hasta, <span style="color:#400080;">int</span>[] centros)
    {
        <span style="color:#400080;">return </span>Content(<span style="color:#259241;">"Centros: " </span><span style="color:#2e53d1;">+ </span><span style="color:#400080;">string</span><span style="color:#2e53d1;">.</span>Join(<span style="color:#259241;">" / "</span>, centros));
    }
}
</pre>
</blockquote>
<p>Para mi informe necesito un rango de fechas definido por desde y hasta, y una <strong>lista de centros definidos por sus Id</strong>. El paso de parámetros en la URL, mediante HTTP GET, tiene para mí muchas ventajas, entre ellas la facilidad para realizar pruebas.</p>
<p>A modo de test devuelvo una cadena con los centros separados por barras, para que se vea que no hay truco. En el comentario del propio código puede verse cómo sería una llamada, el interés está en el parámetro centros que recibe una lista separada por comas de los Id (dejando de lado que las fechas deben ir en inglés, pero esa es otra cuestión). La elección de la coma como separador es mía, aunque sigue una convención bastante extendida.</p>
<p>La cuestión es que esta acción tan sencilla e intuitiva <strong>no funciona</strong> puesto que en el argumento <em>centros</em> no se recibe el valor deseado en todos los casos.</p>
<ul>
<li>En el ejemplo del comentario, con <em>centros=1,2,3</em> en la QueryString, <strong>recibiremos <em>null</em> en <em>centros</em></strong>. Mal.
<li>En cambio, si pasamos <em>centros=1</em> recibiremos un array con un entero de valor 1. Bien. </li>
</ul>
<p>¿A qué se debe esto? Bien, tenemos que saber que estamos confiando en el <em>ModelBinder</em> de ASP.NET MVC para convertir los valores de la QueryString (nuestra URL) en los parámetros de nuestras acciones. Este <em>ModelBinder</em> tiene una funcionalidad muy completa con los tipos sencillos, pero poco más. Si necesitamos algo extra, como es nuestro caso, no nos ayuda.</p>
<p>Pero ASP.NET MVC tiene múltiples puntos de extensión, entre ellos la posibilidad de definir nuestros propios ModelBinder para cubrir los tipos que necesitemos. Así que vamos a definir uno para permitir la recepción de un array de enteros en un formato separado por comas. Sólo <strong>tenemos que</strong> <strong>extender de <em>IModelBinder</em></strong>:</p>
<blockquote><pre class="code"><span style="color:#400080;">public class </span><span style="color:#305fb6;">ArrayOfIntModelBinder </span>: <span style="color:#305fb6;">IModelBinder
</span>{
    <span style="color:#400080;">public object </span>BindModel(<span style="color:#305fb6;">ControllerContext </span>controllerContext, <span style="color:#305fb6;">ModelBindingContext </span>bindingContext)
    {
        <span style="color:#400080;">return </span>controllerContext<span style="color:#2e53d1;">.</span>HttpContext<span style="color:#2e53d1;">.</span>Request[bindingContext<span style="color:#2e53d1;">.</span>ModelName]
            <span style="color:#2e53d1;">.</span>Split(<span style="color:#259241;">','</span>)
            <span style="color:#2e53d1;">.</span>Select(<span style="color:#400080;">int</span><span style="color:#2e53d1;">.</span>Parse)
            <span style="color:#2e53d1;">.</span>ToArray();
    }
}
</pre>
</blockquote>
<p>Esta interfaz sólo nos exige implementar el método <em>BindModel</em> que tiene la responsabilidad de transformar el trozo de la QueryString donde va nuestro parámetro (y que es un string, no lo olvidemos) en el valor destino, en nuestro caso un array de enteros. Recibe dos argumentos:</p>
<ul>
<li>El contexto del controlador, que incluye la información de la petición (<em>Request</em>). De aquí obtenemos el valor del parámetro en la QueryString.
<li><em></em>El contexto del modelo, en nuestro caso el argumento destino de la conversión. De aquí obtenemos el nombre del argumento buscado, que en nuestro ejemplo anterior sería “centros” pero que si usamos <em>bindingContext.ModelName</em> tenemos un <em>Binder</em> genérico que nos sirve para cualquier otro uso de array de enteros en otra acción (o incluso como otro parámetro en la misma). </li>
</ul>
<p>El resto del método es sencillo: dividimos la lista de enteros usando la coma como separador, los convertimos a enteros con int.Parse y convertimos el IEnumerable resultante en un array. Pido perdón por mi concisión en el código, parte de la culpa la tiene Linq, otra buena parte Resharper, y otra yo mismo, qué pasa, si tenemos un lenguaje potente y hermoso como C# es para aprovecharlo, ¿no?</p>
<p>Bueno, nos queda la parte más importante, porque como ya imagináis esta clase por sí misma no hace nada si no le decimos a ASP.NET MVC que la utilice al procesar las peticiones. Para esto, basta con incluir en el Global.asax.cs una línea como:</p>
<blockquote><pre class="code"><span style="color:#305fb6;">ModelBinders</span><span style="color:#2e53d1;">.</span>Binders[<span style="color:#400080;">typeof</span>(<span style="color:#400080;">int</span>[])] <span style="color:#2e53d1;">= </span><span style="color:#400080;">new </span><span style="color:#305fb6;">ArrayOfIntModelBinder</span>();</pre>
</blockquote>
<p>Podemos ponerla en Application_Start(), y su mandato es sencillo de definir con palabras: “cuando encuentres un parámetro de tipo array de entero, lo procesas con esta instancia y no con el ModelBinder genérico.” Dicho y hecho, si todavía tenéis la URL anterior, volved a ejecutar el proyecto y refrescar esa página, podéis comprobar como ahora el parámetro <em>centros</em> devuelve todos los enteros que hayamos tenido a bien suministrarle en la URL.</p>
<p>Un placer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/123/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=123&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/07/26/recibiendo-un-parmetro-de-tipo-array-en-un-controller-de-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>
	</item>
		<item>
		<title>Nuevos videos en SilverDiagram</title>
		<link>http://xamlsorpresa.wordpress.com/2011/06/29/nuevos-videos-en-silverdiagram/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/06/29/nuevos-videos-en-silverdiagram/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 23:31:04 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
				<category><![CDATA[SilverDiagram]]></category>
		<category><![CDATA[Diagram]]></category>
		<category><![CDATA[Learn]]></category>
		<category><![CDATA[Samples]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Videos]]></category>

		<guid isPermaLink="false">https://xamlsorpresa.wordpress.com/?p=119</guid>
		<description><![CDATA[Desde hace unas semanas formo parte del equipo de SilverDiagram, una librería para la edición de diagramas en Silverlight. Estamos dándola a conocer, implementando nueva funcionalidad y elaborando documentación, ejemplos y videos. Para agrupar toda este nuevo material en un &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/06/29/nuevos-videos-en-silverdiagram/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=119&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Desde hace unas semanas formo parte del equipo de <a href="http://www.silverdiagram.net">SilverDiagram</a>, una librería para la edición de diagramas en Silverlight. Estamos dándola a conocer, implementando nueva funcionalidad y elaborando documentación, ejemplos y videos. Para agrupar toda este nuevo material en un único sitio hemos creado una nueva sección en la web, <a href="http://www.silverdiagram.net/Projects/SilverDiagram/Learn.aspx">Learn SilverDiagram</a>.</p>
<p>En esta página podemos encontrar:</p>
<ul>
<li>Enlace a los ejemplos y extensiones alojados en <a href="http://silverdiagram.codeplex.com/">codeplex</a>.
<li>Videotutoriales del <a href="http://www.youtube.com/user/SilverDiagramVideos">canal de Youtube de Silverdiagram</a>:
<ul>
<li><a href="http://www.youtube.com/watch?v=5UAkAXHZOz8">Como construir los ejemplos alojados en Codeplex</a> (en inglés).
<li><a href="http://www.youtube.com/watch?v=dsNY6AUmSZ4">Como crear formas personalizadas</a> (en inglés).</li>
</ul>
<li>Enlaces a la documentación.
<li>Próximamente, recopilación de artículos, posts…</li>
</ul>
<p>Seguid atentos a los nuevos videos y ejemplos. Esperamos que todo este material sea de ayuda a quienes queráis conocer más sobre SilverDiagram.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/119/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=119&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/06/29/nuevos-videos-en-silverdiagram/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>
	</item>
		<item>
		<title>Integrando MVC 3 en una aplicación de Dynamic Data</title>
		<link>http://xamlsorpresa.wordpress.com/2011/06/28/integrando-mvc-3-en-una-aplicacion-de-dynamic-data/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/06/28/integrando-mvc-3-en-una-aplicacion-de-dynamic-data/#comments</comments>
		<pubDate>Tue, 28 Jun 2011 16:39:47 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">http://xamlsorpresa.wordpress.com/?p=111</guid>
		<description><![CDATA[Basándome en los buenos consejos de Eduard Tomás en su post ¿WebForms y ASP.NET MVC juntos? vamos a  intentar aplicar esas mismas ideas para migrar una aplicación ASP.NET Dynamic Data a MVC 3. Una aplicación Dynamic Data es realmente una aplicación &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/06/28/integrando-mvc-3-en-una-aplicacion-de-dynamic-data/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=111&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Basándome en los buenos consejos de Eduard Tomás en su post <a href="http://geeks.ms/blogs/etomas/archive/2011/05/13/191-webforms-y-asp-net-mvc-juntos-pues-claro.aspx">¿WebForms y ASP.NET MVC juntos?</a> vamos a  intentar aplicar esas mismas ideas para migrar una aplicación <a href="http://www.asp.net/dynamicdata">ASP.NET Dynamic Data</a> a MVC 3. Una aplicación Dynamic Data es realmente una aplicación Web Forms con algunos enrutamientos particulares ya definidos.</p>
<ol>
<li>Convertir el proyecto a .<strong>net 4.0</strong> (necesario)<br />
Basta con cambiarlo en propiedades del proyecto, pero no os olvidéis de confirmar con vuestro hosting que soporta el framework 4 (yo no tengo problemas porque los chicos de <a href="http://www.domitienda.com/">Domitienda-Businet</a> están siempre a la última).<br />
NOTA: Cuidado porque al cambiar el framework se pierde la sección <em>&lt;configSections&gt;</em> del web.config, hay que volver a introducirla, como se indica <a href="http://forums.iis.net/p/1166889/1944388.aspx#1944388">aquí</a>. Puedes recuperarla comparando diferencias con la versión anterior del control de código fuente que uses (y si no lo usas, sigue cavando tu tumba).</li>
<li>Añadir <strong>assemblies</strong> en <em>Web.config / compilation</em>. Algunas de las librerías que indica Eduard ya estarán, puesto que Dynamic Data ya las incluye. En mi caso sólo he tenido que añadir:
<pre>&lt;add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
&lt;add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;
&lt;add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /&gt;</pre>
</li>
<li>Incluir <strong>espacios de nombres de MVC</strong> para las páginas, en <em><em>Web.config / system.web / configuration / pages<br />
</em></em></p>
<pre>&lt;pages&gt;
  &lt;namespaces&gt;
    &lt;add namespace="System.Web.Helpers" /&gt;
    &lt;add namespace="System.Web.Mvc" /&gt;
    &lt;add namespace="System.Web.Mvc.Ajax" /&gt;
    &lt;add namespace="System.Web.Mvc.Html" /&gt;
    &lt;add namespace="System.Web.Routing" /&gt;
    &lt;add namespace="System.Web.WebPages"/&gt;
  &lt;/namespaces&gt;
&lt;/pages&gt;</pre>
<p><span class="Apple-style-span" style="font-size:15px;white-space:pre;background-color:#f7f7f7;"><br />
</span></li>
<li>Agregar <strong>referencias</strong> a <em>System.Web.Mvc.dll</em> (normalmente desde C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies). Si vas a usar Razor (¡cómo no!) también <em>System.Web.WebPages.dll</em> (desde C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies).</li>
<li><strong>Inicializar MVC</strong> en el <em>Global.asax.cs</em><br />
Uso el mismo código de Eduard, pero ojo porque Dynamic Data ya genera un método RegisterRoutes, así que renombramos el nuestro por RegisterRoutesMvc (también su uso en MvcInit).</p>
<pre>private void MvcInit()
{
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutesMvc(RouteTable.Routes);
}

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutesMvc(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute("Default", "{controller}/{action}/{id}",
        new {action = "index", id = UrlParameter.Optional});
}</pre>
</li>
<li><strong>Cambiar el tipo de proyecto</strong> (para que Visual Studio nos ofrezca las herramientas de MVC, como Add controller, Go to view y demás comandos).<br />
Hay que añadir <em>{E53F8FEA-EAE0-44A6-8774-FFD645390401}</em> en <em>&lt;ProjectTypeGuids&gt;</em> del .csproj (ya sabes, Unload project y después Edit .csproj). Ojo que ese Guid debe ser el primero, los dos que ya estaban deben seguir pero detrás de este (así viene en un nuevo proyecto de MVC, puedes consultarlo si tienes dudas).</li>
<li>Añadir manualmente la <strong>estructura de carpetas</strong> de MVC: <em>Controllers</em>, <em>Views</em> y <em>Shared</em> con las plantillas <em>_ViewStart.cshtml</em>, <em>Layout.cshtml</em> y el <em>Web.config</em> de Razor (sí, fíjate que en los proyectos de MVC tienes un Web.config dentro de Views; pues cópialo en tu carpeta Views y listo). Y bueno, ya estás en MVC, el resto ya es cosa tuya, ¿no? Si quieres echa un vistazo a <a href="http://xamlsorpresa.wordpress.com/2011/06/08/como-iniciarse-con-mvc/">cómo puedes empezar</a>.</li>
</ol>
<p>Dynamic Data es una herramienta potente para elaborar prototipos, poner en marcha rápidamente proyectos, y para ofrecer un mantenimiento sencillo de tablas (CRUD) a usuarios finales. Pero cuando la aplicación comienza a crecer, toda la ayuda que ha prestado en la fase inicial se convierte en obstáculos, por lo que es una buena idea ir abandonándolo, al menos para las páginas que tengan cierta lógica de negocio. Y es esa la oportunidad para ir migrando a MVC, ya que se va a llevar muy bien con Dynamic Data, se permite incluso tener rutas parcialmente comunes entre ambos: por ejemplo, yo tengo <em>Acciones/List.aspx</em> de Dynamic Data y <em>Acciones/Notificar</em> atendida por un Controller de MVC.</p>
<p>Por cierto, comentar que hace un tiempo oí que el equipo de Dynamic Data estaba planteando su migración a MVC (todavía su base es el ASP.net clásico, ya que Dynamic Data es anterior a MVC). En ese caso la integración con MVC resultará mucho más natural. Pero con las novedades de MVC que han llegado y que se esperan, quizá dicha evolución no llegue nunca a ver la luz, ya que MVC ofrece una gran facilidad para el desarrollo rápido de aplicaciones y prototipos.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/111/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=111&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/06/28/integrando-mvc-3-en-una-aplicacion-de-dynamic-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>
	</item>
		<item>
		<title>Cómo iniciarse con ASP.net MVC</title>
		<link>http://xamlsorpresa.wordpress.com/2011/06/08/como-iniciarse-con-mvc/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/06/08/como-iniciarse-con-mvc/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 16:28:02 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
		
		<guid isPermaLink="false">http://xamlsorpresa.wordpress.com/?p=108</guid>
		<description><![CDATA[Un buen amigo me pide enlaces e información para iniciarse con ASP.net MVC, y cuando el correo que le estaba escribiendo ha alcanzado un cierto tamaño, me he dado cuenta de que era mejor ponerlo en una entrada del blog. &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/06/08/como-iniciarse-con-mvc/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=108&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Un buen amigo me pide enlaces e información para iniciarse con ASP.net MVC, y cuando el correo que le estaba escribiendo ha alcanzado un cierto tamaño, me he dado cuenta de que era mejor ponerlo en una entrada del blog.</p>
<p>Lo que sigue no es un tutorial sino una recopilación de enlaces (pocos), consejos y opiniones para comenzar con ASP.net MVC. Y está escrito de forma informal porque con mi amigo tengo mucha confianza <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<ol>
<li><span style="font-family:georgia, serif;">Ya está la versión 3.0, olvídate de las anteriores (y ten cuidado al seguir artículos o tutoriales, ha habido una evolución importante desde las anteriores: ojo a la fecha de los artículos).</span></li>
<li><span style="font-family:georgia, serif;">Además de instalar VS2010 y su SP1, debes instalar las MVC 3 Tools Update.<br />
</span>Pero para no tener que hacer todo esto, en <a href="http://www.asp.net/mvc">http://www.asp.net/mvc</a> hay un botón <em>Install Visual Studio Express</em> que te lo hace todo. Y con la versión Express tienes suficiente para empezar&#8230; y para terminar la aplicación.</li>
<li><span class="Apple-style-span" style="font-family:georgia, serif;">Apúntate a AUGES (<a href="http://www.auges.org/">http://www.auges.org/</a>), un grupo online centrado en ASP.NET.</span></li>
<li><span style="font-family:georgia, serif;">Su primer evento fue <a href="http://www.auges.org/post/2011/05/19/Materiales-del-evento-%E2%80%9CUn-paseo-por-ASPNET-MVC%E2%80%9D.aspx">Un paseo por ASP.NET MVC</a>, impartido por Eduard Tomàs, de Raona. Puedes descargar los materiales y volver a ver el evento online.</span></li>
<li>De paso, apúntate también a <a href="http://secondnug.com/">http://secondnug.com/</a>, un grupo online con muchísima actividad, tanto de desarrollo como de sistemas (aunque yo de sistemas, ya sabes&#8230;) Tienen muchísimo material, sobre todo vídeos de charlas.</li>
<li><span class="Apple-style-span" style="font-family:georgia, serif;">Consejo personal para MVC: En las primeras versiones usaban la sintaxis clásica para las vistas, lo del &lt;% %&gt;, pero ahora tienen una sintaxis nueva llamada Razor. Los archivos en vez de .aspx son .cshtml (o .vbhtml). Aunque puedes escoger entre las dos, te recomiendo entrar en Razor directamente.</span></li>
<li><span style="font-family:georgia, serif;">Y sobre el acceso a datos, no sé si has probado EF, ya va por la versión EF 4.1 (aka CodeFirst). También muy recomendable para iniciarse en MVC, además muchos de los ejemplos combinan EF y MVC, así que matas dos cerdos de un pajarazo.</span></li>
<li><span style="font-family:georgia, serif;">Hay un ejemplo &#8220;oficial&#8221; con un tutorial muy muy extenso: </span><a href="http://mvcmusicstore.codeplex.com/">http://mvcmusicstore.codeplex.com/</a> Puedes descargarlo para bichearlo, o tratar de hacerlo tú mismo con el tutorial. Se aprende mucho.</li>
</ol>
<p>Bueno, hay muchos más enlaces pero para eso Google, o mejor, sigue la pista a los blogs de los miembros de Auges, que son todos unos cracks.</p>
<p>Suerte y para cualquier duda aquí me tienes.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/108/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=108&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/06/08/como-iniciarse-con-mvc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>
	</item>
		<item>
		<title>[WiX] Incluyendo ventanas en un instalador</title>
		<link>http://xamlsorpresa.wordpress.com/2011/04/14/wix-incluyendo-ventanas-en-un-instalador/</link>
		<comments>http://xamlsorpresa.wordpress.com/2011/04/14/wix-incluyendo-ventanas-en-un-instalador/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 17:28:52 +0000</pubDate>
		<dc:creator>pablonete</dc:creator>
				<category><![CDATA[Setup]]></category>
		<category><![CDATA[instalador]]></category>
		<category><![CDATA[msi]]></category>
		<category><![CDATA[setup]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[ventanas]]></category>
		<category><![CDATA[wix]]></category>

		<guid isPermaLink="false">http://xamlsorpresa.wordpress.com/?p=100</guid>
		<description><![CDATA[En las entradas anteriores hemos generado un instalador sencillo que permite actualizar instalaciones anteriores, pero su interfaz de usuario es cuasi nulo: sin preguntar nada, sale la ventana de Windows Installer y procede a realizar la instalación. Al terminar, se &#8230; <a href="http://xamlsorpresa.wordpress.com/2011/04/14/wix-incluyendo-ventanas-en-un-instalador/">Sigue leyendo <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=100&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>En las entradas anteriores hemos <a href="http://xamlsorpresa.wordpress.com/2011/04/14/primeros-pasos-con-wix/">generado un instalador sencillo</a> que permite <a href="http://xamlsorpresa.wordpress.com/2011/04/14/wix-actualizando-una-aplicacion-existente/">actualizar instalaciones anteriores</a>, pero su interfaz de usuario es <em>cuasi</em> nulo: sin preguntar nada, sale la ventana de Windows Installer y procede a realizar la instalación.</p>
<p style="text-align:center;"><a href="http://xamlsorpresa.files.wordpress.com/2011/04/instalando-pica.png"><img class="size-full wp-image-101 aligncenter" title="Instalando Pica" src="http://xamlsorpresa.files.wordpress.com/2011/04/instalando-pica.png?w=640" alt="Instalación básica"   /></a></p>
<p>Al terminar, se cierra sin mostrar confirmación alguna. Aunque esto puede ser suficiente en algunos casos, vamos a ver como incluir en la instalación las típicas ventanas de Bienvenida, Seleccionar carpeta, Proceso y Fin de la instalación.</p>
<p>En primer lugar, WiX ofrece por separado las interfaces gráficas en la librería WixUIExtension.dll, que debemos incluir en la generación del instalador en la herramienta light con los siguientes parámetros:</p>
<pre>light PicaSetup.wixobj -cultures:es-ES -ext WixUIExtension.dll</pre>
<p>Con esto tendremos disponibles las ventanas en nuestro instalador, y además en nuestro idioma. Pero para que se usen tenemos que activarlas dentro de la etiqueta <em>Project</em>:</p>
<pre>&lt;Property Id="WIXUI_INSTALLDIR" Value="AppDir"/&gt;
&lt;UIRef Id="WixUI_InstallDir" /&gt;</pre>
<p>Empecemos por el final: la etiqueta <em>UIRef</em> es la que incorpora las ventanas al instalador. Su valor es la plantilla de instalador que queremos usar, en este caso <em>WixUI_InstallDir</em> identifica la típica instalación con Bienvenida, Licencia, Carpeta, Progreso y Fin. Hay otras plantillas</p>
<p>Por otro lado, la etiqueta <em>Property</em> tiene una utilidad auxiliar pero muy importante: asociar el resultado de la ventana donde se selecciona la carpeta destino con el valor usado en el elemento <em>Directory</em> para instalar el producto. De no indicarla, el directorio seleccionado en esa ventana no se usaría después. Debe contener como <em>Value </em>el <em>Id </em>de la etiqueta <em>Directory</em> final donde vamos a instalar. En nuestro ejemplo anterior era AppDir, ya que se corresponde con la carpeta última donde se instalan los componentes.</p>
<p>Con esto ya podemos generar (usando los parámetros de light indicados antes para considerar la librería de UI) y tendremos un instalador totalmente funcional. Pero podemos personalizar su apariencia mediante variables de WiX.</p>
<h2>Variables de WiX</h2>
<p>Mediante las variables de WiX podemos pasar parámetros para la generación del instalador. Son parámetros para su construcción, no para el momento de la instalación. El valor de estas variables puede establecerse de dos formas:</p>
<ul>
<li>En el archivo wxs, mediante un elemento <em>WixVariable</em> dentro de <em>Wix</em>:<br />
<em>&lt;WixVariable Id=&#8221;var&#8221; Value=&#8221;valor&#8221;/&gt;</em></li>
<li>Como argumento de línea de comandos de la herramienta <em>light</em>:<br />
<em>light PicaSetup.wxsobj</em> -d<em>var</em>=<em>valor</em></li>
</ul>
<p>Estas variables pueden ser consumidas también por las extensiones de WiX, y en nuestro caso WixUIExtension.dll acepta unas cuantas de ellas, como WixUIBannerBmp o WixUIDialogBmp.</p>
<h2>Cambiando el texto de licencia</h2>
<p>Una aplicación práctica, y quizá la más prioritaria en un instalador comercial, se refiere a la ventana de licencia, que por defecto muestra la licencia CPLv2 en inglés:</p>
<p style="text-align:center;"><a href="http://xamlsorpresa.files.wordpress.com/2011/04/licencia-cpl-por-defecto-en-wix.png"><img class="size-medium wp-image-103 aligncenter" title="Licencia CPL por defecto en WIX" src="http://xamlsorpresa.files.wordpress.com/2011/04/licencia-cpl-por-defecto-en-wix.png?w=300&#038;h=235" alt="Licencia CPL por defecto en WIX" width="300" height="235" /></a></p>
<p>Esto desentona tanto por el idioma como porque quizá esta no sea nuestra licencia elegida. Para cambiarlo, podemos establecer la variable <em>WixUILicenseRtf</em> con la ruta donde encontrar un archivo RTF con la licencia. Esta variable puede declararse en el archivo wxs:</p>
<pre>&lt;WixVariable Id="WixUIDialogBmp" Value="licencia.rtf"/&gt;</pre>
<p>o bien como parámetro de la herramienta light:</p>
<pre>light PicaSetup.wxsobj -dWixUIDialogBmp=licencia.rtf</pre>
<p>En resumen, las posibilidades de configuración del interfaz gráfica del instalador son enormes en WiX, sirva este artículo como sencillo ejemplo de cómo conseguir un instalador decente y muy estándar para nuestras aplicaciones.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/xamlsorpresa.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/xamlsorpresa.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/xamlsorpresa.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/xamlsorpresa.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/xamlsorpresa.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/xamlsorpresa.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/xamlsorpresa.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/xamlsorpresa.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/xamlsorpresa.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/xamlsorpresa.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/xamlsorpresa.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/xamlsorpresa.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/xamlsorpresa.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/xamlsorpresa.wordpress.com/100/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=xamlsorpresa.wordpress.com&amp;blog=9936144&amp;post=100&amp;subd=xamlsorpresa&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://xamlsorpresa.wordpress.com/2011/04/14/wix-incluyendo-ventanas-en-un-instalador/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58c176382cc5eef8c9a4b35bba84f116?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">pablonete</media:title>
		</media:content>

		<media:content url="http://xamlsorpresa.files.wordpress.com/2011/04/instalando-pica.png" medium="image">
			<media:title type="html">Instalando Pica</media:title>
		</media:content>

		<media:content url="http://xamlsorpresa.files.wordpress.com/2011/04/licencia-cpl-por-defecto-en-wix.png?w=300" medium="image">
			<media:title type="html">Licencia CPL por defecto en WIX</media:title>
		</media:content>
	</item>
	</channel>
</rss>
