miércoles, 21 de diciembre de 2011

Tags especiales en ASP.NET

Voy a hacer un resumen de las etiquetas o tags especiales que usa ASP.NET para hacer "scripting"

<%  %>  Bloques de código incrustado
http://msdn.microsoft.com/es-es/library/ms178135.aspx

Como indica su definición, sirven para incrustar bloques de código.

<%@ Page Language="C#"%>
<html>
<body>
    <%string[] semana = { "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo" };%>     <ul>
        <%foreach (var s in semana)
        {
            Response.Write("<li>"+s+"</li>");
        }
        %>
    </ul>
</body>
</html>


<%= %> Response.Write
http://msdn.microsoft.com/es-es/library/6dwsdcf5.aspx

Esta etiqueta sustituye al Response.Write

<%@ Page Language="C#"%>
<html>
<body>
    <% string nombre="Pepe";%>
    <span>Hola, <%=nombre%></span>
</body>
</html>


<%# %> Expresión de datos enlazados
http://msdn.microsoft.com/es-es/library/bda9bbfx.aspx

Esta etiqueta crea un enlace a un origen de datos.

<%@ Page Language="C#"%>
<html>
<body>
    <script language="C#" runat="server">
        void BtnClick(Object sender, EventArgs e) {
          Page.DataBind();
        }
    </script>

    <form runat="server">
        <label>Nombre:</label>
        <asp:TextBox runat="server" id="Nombre"></asp:TextBox>
        <br />
        <asp:button Text="Saluda!!!" OnClick="BtnClick" runat="server"/>      
        <br />
        Hola, <%#Nombre.Text%>         <br />
        Hola, <%#DataBinder.Eval(Nombre,"Text")%>         <br />
        Hola, <%#DataBinder.GetPropertyValue(Nombre,"Text")%>     </form>
</body>
</html>



<%$ %> Expresión de ASP.NET
http://msdn.microsoft.com/es-es/library/d5bd1tad.aspx

Evalúa expresiones basadas en cadenas de conexión, configuración de aplicación, recursos,...

Para este ejemplo, he añadido un recurso global y he añadido una cadena


 Nuestro Web.Config tiene las siguientes entradas:

   <connectionStrings>
    <add name="NorthwindConnectionString"
        connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;"
        providerName="System.Data.SqlClient" />
  </connectionStrings>

  <appSettings>
    <add key="Clave1" value="Valor1"/>
  </appSettings>


Nuestra página ASP.NET:


El recurso almacenado es: <asp:Label id="label1" runat="server" Text="<%$Resources:Resource, TextoAlmacenado1 %>"/>     
<br />
El valor almacenado en el AppSettings del Web.config es: <asp:Label id="label2" runat="server" Text="<%$AppSettings:Clave1 %>"/>
<br />
<asp:SqlDataSource ID="SqlDataSource1" Runat="server"
    SelectCommand="SELECT * FROM [Employees]"
    ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>">
    </asp:SqlDataSource>


<%@ %> Directivas de plantilla de texto
http://msdn.microsoft.com/es-es/library/xz702w3e.aspx

Se usan en las directivas de configuración de páginas, controles, etc.

<%@ Page Title="Hello, world" Language="C#"%>

<%-- --%> Comentarios de servidor
http://msdn.microsoft.com/es-es/library/4acf8afk.aspx


Son los comentarios de ASP.NET



<%: %> HtmlEncoding
http://weblogs.asp.net/scottgu/archive/2010/04/06/new-lt-gt-syntax-for-html-encoding-output-in-asp-net-4-and-asp-net-mvc-2.aspx

Este tag sólo está disponible a partir de ASP.NET 4.0

Es el equivalente a Server.HtmlEncode, función usada para evitar ataques de inyección de scripts.

En el ejemplo siguiente, vemos que <%=cadena%> muestra "texto", mientras que <%:cadena%> muestra "<b>Texto<b>"




<%@ Page Language="C#"%>
<html>
<body>
    <%string cadena = "<b>Texto</b>";%>
    <%=cadena%>
    <br />
    <%:cadena%>
</body>
</html>

miércoles, 14 de diciembre de 2011

Liberar el puerto 80 en Windows 7

Me acaba de pasar que, a la hora de depurar un proyecto, el Visual Studio me obsequie con este mensajito:

No se puede iniciar el servidor de desarrollo de Visual Studio.
El puerto 80 está en uso.


El problema es que hay algún servicio que está ocupando el puerto 80, y el servidor de desarrollo de VS "Cassini" no se puede arrancar.

Una solución es cambiar el puerto en el servidor de desarrollo.
En el proyecto, botón derecho, propiedades, y le cambiamos el puerto




Si no queremos cambiar el puerto, otra solución es encontrar el servicio que lo ocupa.
Para ello, abrimos la consola (cmd) y ejecutamos "netstat -ab"


Allí vemos que el TCP 80 lo tiene ocupado un servicio del que no tenemos más información.
Así que nos toca ir a los servicios que pudieran ser sospechosos de estar ocupando el puerto 80, pararlos y probar el "netstat -ab" hasta que el puerto 80 quede liberado.

Para parar los servicios, escribid "services.msc" en el botón "inicio -> buscar programas y archivos"

Los servicios que son candidatos a ocupar el puerto 80 son:
"Servicio Agente de implementación web" (lo instala el Web Deploy 2.0)
"SQL Server Reporting Services (MSSQLSERVER)"
"SQL Server Integration Services 10.0"
 "BrandCache"

Internet Information Server y el Apache o XAMPP también se cogen el puerto 80 por defecto.

La solución correcta es, una vez detectado el programa que lo ocupa, cambiarlo en su configuración a otro puerto en vez de ir parando servicios.

viernes, 2 de diciembre de 2011

Error en el DNS-323: Acceso denegado




Tengo un NAS D-Link DNS-323.

 En él confío todos mis documentos, fotos, programas, etc.

Tiene 2 discos duros y se puede configurar para usarlos por separado, linealmente, Raid0 o Raid1 (en espejo).

Ya empezaba a confiar plenamente en él cuando, de repente un día, al acceder a una carpeta, aparece un mensaje de error:"ACCESO DENEGADO".

Recorro todo el disco y veo que hay algunos archivos y carpetas con ese problema. No puede verlos, ni copiarlos, ni moverlos...

Un sudor frío recorre mi cuerpo cuando veo carpetas de fotos de momentos importantes con ese problema.


WTF?  (¿Pero qué narices le pasa?)

El DNS-323 lleva internamente Linux, y expone un servidor samba a la red.
Parece que el Windows Vista y Windows 7, al haber aumentado los niveles de seguridad, ha perdido alguna compatibilidad con Samba, en el modo Share.

He recopilado los siguientes enlaces que hablan del tema.

http://www.sevenforums.com/network-sharing/3737-samba-network-share-issue-windows-7-a-3.html

http://web.mit.edu/rhel-doc/4/RH-DOCS/rhel-rg-es-4/s1-samba-security-modes.html

http://superuser.com/questions/115337/windows-7-connecting-to-samba-shares

http://www.arkko.com/linux/vistanas.html

Como solución, casi todos hablan de rebajar el nivel de seguridad de Windows7 y ponerlo a la altura de Samba, o cambiar el modo de seguridad de Share a User


Opté por otra línea de trabajo; y así poder saber recuperar los documentos (que es realmente lo que me interesa) : Poder dar permisos a los ficheros.

Aprovechando que el firmware del dns-323 puede ejecutar scripts, instalamos un software llamado fun_plug que nos monta un linux con su servicio Telnet arrancado.


En este enlace se explica de forma extensa los pasos a seguir.
http://nas-tweaks.net/40/installation-of-the-fonz-funplug-0-5-for-ch3snas-ch3mnas-dns-323-and-many-more/

Los pasos a seguir son:
  • Nos descargamos los ficheros fun_plug y fun_plug.tgz de aquí.
  • Lo copiamos al raíz del DNS-323
  • Reiniciamos.
A partir de ahora, tendremos el telnet activado.
También tendremos una carpeta "ffp" que es el sistema de ficheros que ha creado.

Por línea de comando, podemos hacer "telnet 192.168.2.X" (ojo, poned la IP vuestra :))

Para aplicar contraseña, seguiremos los siguientes pasos dentro del telnet:

pwconv
passwd
usermod -s /ffp/bin/sh root

pwck
grpck

login

Comprobamos que funciona todo bien.

Ahora guardamos el password con el comando
store-passwd.sh

Con estos pasos, tenemos acceso al NAS a través de un telnet protegido por contraseña.

Ahora queda localizar las carpetas y ver qué permisos tienen los archivos.

Con ls -l tenemos una vista a los permisos de los ficheros.
El disco se monta en /mnt/HD_a2















Los casos de ficheros que daban problemas tenían permisos rwx --- --- y usuario nobody.

(El usuario Nobody es equivalente al usuario anónimo).

Sin meternos en tema de usuarios, grupos y demás, nos situamos en el directorio de archivos que queramos cambiar y ejecutaremos:

chmod 777 *

Si queremos cambiar los permisos en los subdirectorios:

chmod -R 777 *

En este caso, podemos ver que los permisos cambian a rwx rwx rwx, y ya son accesibles desde Windows.

Esto es todo; espero que os sea de utilidad.








lunes, 21 de noviembre de 2011

El todopoderoso control listview (1)

El control ListView de ASP.NET (no confundirlo con el control ListView de WinForms) es un nuevo control ASP.NET que apareció en el Framework 3.5.

La documentacíón completa del control la tenéis en http://msdn.microsoft.com/es-es/library/system.web.ui.webcontrols.listview.aspx

Otro artículo muy bueno lo tenéis en http://msdn.microsoft.com/es-es/magazine/cc337898.aspx

Lo de "todopoderoso" lo digo porque puede sustituir a todos los controles enlazables (Repeater, gridview, formview, detailsview...), con lo que usando sólo este control puedes hacer cualqier control enlazado.  (pudiendo hacer incluso gridviews con inserciones!!!)

El secreto del ListView es el uso de las plantillas.

Si, por ejemplo, quisiéramos montar una grid, montaríamos algo parecido a esto:


En el Layout template definiríamos el formato de la parte externa a los datos (encabezado, pie...)

En el ItemTemplate definiríamos el formato que queremos de los datos




Un ejemplo básico

Vamos a ver un ejemplo:

Creamos una clase "Persona.cs"

public class Persona
{    
     public int Id { get; set; }    
     public string Nombre { get; set; }    
     public string Apellidos { get; set; }    
     public string Poblacion { get; set; }
}

Creamos una clase "RepPersona.cs", que hará de repositorio y de almacén de datos. Por supuesto, en un entorno real, los métodos irían contra una base de datos, pero por simplificar, lo hacemos con una lista.
public class RepPersona
{
    protected List<Persona> _personas = new List<Persona>();

    public RepPersona()
    {
        _personas.Add(new Persona() { Id = 1, Nombre = "Jose", Apellidos = "Garcia", Poblacion = "Valencia" });
        _personas.Add(new Persona() { Id = 2, Nombre = "Manuel", Apellidos = "Martinez", Poblacion = "Barcelona" });
        _personas.Add(new Persona() { Id = 3, Nombre = "Juan", Apellidos = "Gómez", Poblacion = "Madrid" });
    }

    public List<Persona> DamePersonas()
    {
        return _personas.ToList<Persona>();
    }
}


Ahora crearemos una página ASP.NET y crearemos el ObjectDataSource que lea los datos del repositorio y el ListView

<asp:ObjectDataSource runat="server" ID="odsDatos" DataObjectTypeName="Persona"
    SelectMethod="DamePersonas" TypeName="RepPersona"> </asp:ObjectDataSource>


<asp:ListView runat="server" ID="lvwDatos" DataSourceID="odsDatos">
    <LayoutTemplate>
        <table class="tabla1">
            <tr>
                <th>Id</th>
                <th>Nombre</th>
                <th>Apellidos</th>
                <th>Poblacion</th>
            </tr>

        <asp:PlaceHolder runat="server" ID="ItemPlaceholder"/>
        </table>     
    </LayoutTemplate>
    <ItemTemplate>
        <tr>
            <td><%#Eval("Id") %></td>
            <td><%#Eval("Nombre")%></td>
            <td><%#Eval("Apellidos")%></td>
            <td><%#Eval("Poblacion")%></td>
        </tr>
    

    </ItemTemplate>  
</asp:ListView>


Este código devolvería el siguiente resultado:

Aquí vemos una sección de LayoutTemplate, con un PlaceHolder, y un ItemTemplate.

En el LayoutTemplate, vemos la parte fija; es decir, el <table> y el encabezado.
El PlaceHolder es sustituido por el ItemPlaceHolder tantas veces como registros hayan.

Al ListView, en este caso, no hace falta que se le especifique el nombre del PlaceHolder si el PlaceHolder se llama "ItemPlaceHolder". Si el PlaceHolder se llamara de otra forma, habría que especificar el atributo "ItemPlaceholderID" con el nombre especificado.

Trabajar con plantillas es una forma muy flexible de representar datos.



Vamos a mostrar otro formato de plantilla

<asp:ListView runat="server" ID="LvwDatos2" DataSourceID="odsDatos">
    <LayoutTemplate>
        <h2>Personas</h2>
        <asp:PlaceHolder runat="server" ID="ItemPlaceholder"></asp:PlaceHolder>
    </LayoutTemplate>
    <ItemTemplate>
        <table>
            <tr>
                <td >(<%#Eval("Id") %>)</td>
            </tr>
            <tr>
                <td><%#Eval("Apellidos")%>, <%#Eval("Nombre")%></td>
            </tr>
            <tr>
                <td><%#Eval("Poblacion")%></td>
            </tr>
        </table>
    </ItemTemplate>    
    <ItemSeparatorTemplate>
----------
    </ItemSeparatorTemplate>
</asp:ListView>


Esto mostrará la siguiente salida

Aquí vemos que cada ItemTemplate tiene su propia tabla, y que hay un ItemSeparatorTemplate que permite añadir una plantilla entre cada itemTemplate

Agrupaciones

También podremos usar agrupaciones para poder mostrar items agrupados.

Mostremos un ejemplo de ListView con agrupaciones.

<asp:ListView runat="server" ID="LvwDatos3" DataSourceID="odsDatos" GroupItemCount="2">
    <LayoutTemplate>
        <h2>Personas</h2>
        <table>
            <asp:PlaceHolder runat="server" ID="GroupPlaceholder"></asp:PlaceHolder>
        </table>
    </LayoutTemplate>
    <GroupTemplate>
        <tr>
            <asp:PlaceHolder runat="server" ID="ItemPlaceholder"></asp:PlaceHolder>
        </tr>
    </GroupTemplate>
    <ItemTemplate>
        <td>
            <table>
                <tr>
                    <td>(<%#Eval("Id") %>)</td>
                </tr>
                <tr>
                    <td><%#Eval("Apellidos")%>, <%#Eval("Nombre")%></td>
                </tr> 
                <tr>
                    <td><%#Eval("Poblacion")%></td>
                </tr>                         
            </table>
        </td>
    </ItemTemplate>     
</asp:ListView>


Esta plantilla produciría la siguiente salida:


En este código podemos observar:

  • Con el atributo GroupItemCount indicamos el número de Items que aparecerán por grupo.
  • El LayoutTemplate tiene un PlaceHolder con el ID "GroupPlaceHolder". A este ID le pasa lo mismo que el ID "ItemPlaceHolder" Si se usa este ID, no es necesario especificarlo en el atributo "GroupPlaceHolderID" del listview.
  • Con el elemento "GroupTemplate" indicamos el código a usar por el grupo. En este caso, por cada grupo de 2 elementos, insertará una fila nueva de la tabla (<tr>)


De momento, esto es todo por ahora.
Me quedan otros posts donde introduciré las inserciones, las modificaciones y las paginaciones de este "todopoderoso" control.










domingo, 20 de noviembre de 2011

Enlaces interesantes Marzo

Aquí dejo algunos enlaces interesantes que he visto por el Twitter.

Testeando lo intesteable con el Framework Moles
Building an MVC 3 App with Code First and Entity Framework 4.1
Creating an Up and Down Voting User Interface
X-Icon Editor
Patrón Observador en .NET - pattern Observer
Rounding Corners using CSS3
Design Hacks for the Pragmatic Minded
Libro gratuito de jQuery en español: Fundamentos de jQuery

Pegar código fuente en un blog

Para pegar código fuente en un blog, podemos tener problemas con los símbolos del código fuente (<,>, {, }, tabulaciones, etc...)

Para evita esto, hay una web-utilidad en la que pegas el código y te lo formatea de tal forma que no choca con el código HTML de la web.

http://www.simplebits.com/cgi-bin/simplecode.pl




sábado, 19 de noviembre de 2011

Recuperar archivos no guardados de Excel y Word 2010

Este caso seguro que os ha pasado alguna vez.

Abres un Word o Excel para introducir una información temporal, y luego cierras el Word - Excel y le dices:
"NO guardar cambios".

Al cabo de unas horas te das cuenta que debías de haber guardado esa información ya que te vuelve a hacer falta.

Pues bien, si tienes Word 2010 o Excel 2010, y tienes activado en Opciones "Guardar -> Guardar información de autorrecuperación" y "Conservar la última versión autoguardada", podrás recuperar estos archivos (siempre que haya pasado el tiempo marcado en el autoguardado)















Estos archivos se encuentran en "Archivo -> Reciente -> Recupere libros no guardados".





También se puede acceder mediante "Archivo -> Información -> Administrar versiones -> Recuperar libros no guardados"






Espero que os sirva este "briconsejo".

Saludos.







sábado, 8 de octubre de 2011

Hacer que funcionen los comentarios de Blogger.

Hasta ahora no me había dado cuenta.

No me funcionaban los comentarios del blog!!!

Esto creo que suele pasar porque hay plantillas en los que no funcionan correctamente los comentarios incrustados.

Hay 3 opciones:

Retocar la plantilla

Esta opción la dejo para usuarios valientes.
Se trata de entrar al código y ajustar la plantilla para que funcione. 
http://vagabundia.blogspot.com/2008/06/blogger-fenix-el-formulario-de.html
http://vagabundia.blogspot.com/2008/06/solucin-para-algunos-problemas-al.html


Cambiar de plantilla

Si no van los comentarios incrustados en nuestra plantilla, ¿por qué no cambiarnos a una plantilla en la que funcionen?


Cambiar el formato de los comentarios

Esta opción es algo más facilita.

Como se dan los problemas con los comentarios incrustados, los cambiaremos por ventanas emergentes.

En el interfaz nuevo no he conseguido encontrar el formato de los comentarios, por lo que debemos de cambiar al formato antiguo.


Una vez en el formato antiguo, nos vamos a la pestaña "Comentarios"



y cambiamos la opción a "Ventanas emergentes"

y YA FUNCIONAN LOS COMENTARIOS!!!!

domingo, 2 de octubre de 2011

Expresiones lambda para torpes

Creo que somos muchos (me incluyo) los que usamos las expresiones lambda por inercia y sin saber de dónde salen y cómo sarles su jugo.


Recordemos que una expresión lambda es algo así:

Ctx.articulos.where(art=>art.codigo==’40’)

Pues bien, las expresiones lambda no son más que funciones empaquetadas como un parámetro de una función.
En este ejemplo estamos diciendo que del ienumerable artículos, por cada artículo, devuelva una lista con los elementos que la ejecución de la función "art.codigo=='40'" sea True.

¿De dónde salen las expresiones lambda?

Seguro que este caso os es muy familiar:

static void main() 
{
   int resultado=multiplica(5,2); // ejecutamos la función
}

static int multiplica(int a, int b)  
{
   return a * b;
}

Pues bien,  compliquemos un poco esto.

Un delegado es un puntero a una función; es decir, a una variable de tipo “delegado” le asignamos una función.  El delegado debe de tener los mismos parámetros tanto de entrada como de retorno.
Vamos a usar un delegado para llamar a la función “multiplica”.

delegate int miDelegado(int a, int b);  //declaramos el delegado

static void main()
{
   miDelegado deleg = multiplica;  // asignamos la función al delegado
   int resultado = deleg(5, 2);    // ejecutamos el delegado
}

static int multiplica(int a, int b)  
{
   return a * b;
}


Podemos simplificar un poco esta función llamando a Func<>, que es una nueva forma genérica de crear delegados. (apareció en el Framework 3.5)

static void main()
{
   Func<int,int,int> miMetodo = multiplica;   // asignamos la función al delegado
   int resultado = miMetodo(5, 2);   // ejecutamos el delegado
}

static int multiplica(int a, int b)  
{
   return a * b;
}


En la función Func<int,int,int>, el 1er y el 2º int corresponden a los parámetros de entrada de la función Multiplica, y el último int es la variable de retorno.

Ahora declaremos la función dentro del método Main
static void main()
{
   Func<int, int, int> miMetodo = delegate(int a, int b) { return a * b; };  
   int resultado = miMetodo(5, 2);   // ejecutamos el delegado
}


Esto se puede traducir a una expresión lambda.

static void main()
{
   Func<int, int, int> miMetodo = (a, b)=> { return a * b; };  
   int resultado = miMetodo(5, 2);   // ejecutamos el delegado
}

Y como el cuerpo de la función es sencillo, podríamos incluso resumirlo de esta manera:
static void main()
{
   Func<int, int, int> miMetodo = (a, b)=> a * b ;  
   int resultado = miMetodo(5, 2);   // ejecutamos el delegado
}


Uso de expresiones lambda

Expresiones lambda como parámetros


En este ejemplo tenemos 4 funciones de operaciones básicas, y en la función “opera” le pasamos una expresión lambda como parámetro, tanto declarada como “al vuelo”
static void main()
{
   Func<int, int, int> suma = (x, y) => x + y;
   Func<int, int, int> rest = (x, y) => x - y;
   Func<int, int, int> mult = (x, y) => x * y;
   Func<int, int, int> divi = (x, y) => x / y;

   int result=opera(5, 2, mult);
   int result2=opera(5, 2, (x,y)=>x*y);
}

static int opera(int x, int y, Func<int, int, int> operacion)
{
   return operacion(x, y);
}


Otro ejemplo: contamos y obtenemos los múltipos de 3
static void main()
{
   int[] numeros = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
   int divisiblesx3 = numeros.Count(x =>x % 3 == 0);
   IEnumerable<int> lista = numeros.Where(x => x % 3 == 0);
}

Aquí fijémonos en el intellisense de la función Count.

Nos dice que devuelve un entero, que Count cuelga de un IEnumerable<int> (array números) y que admite una función que probará cada elemento. Esta función admite un int y devuelve un bool, que si cumple la condición,  será un count acertado.

El where lo mismo; nos devolverá una lista con los múltiplos de 3.

Expresión lambda de una función sin parámetros de entrada


Aunque no hayan parámetros de entrada, debemos de poner los paréntesis.
static void main()
{
   Func<string> saludo= () => string.Format("Hola");
   string result = saludo();
}

Expresión lambda de una function compleja

En este ejemplo, vemos cómo la función no debe de ser una simple operación, sino que puede ser de cualquier tamaño

static void main()
{
   Func<string> ObtieneNombre = () =>
   {
       Console.WriteLine("Dime tu nombre");
     string nombre = Console.ReadLine();
     return nombre;
   };
   Console.WriteLine("Hola, " + ObtieneNombre());
}

Expresión lambda de una función que no devuelve datos

Para este caso, sustituyamos la instrucción “func” por “action”

static void main()
{
    Action Saludo = () =>
    {
         Console.WriteLine("Dime tu nombre");
       string nombre = Console.ReadLine();
       Console.WriteLine("Hola, " + nombre);
    };
    Saludo();
}

Espero que este artículo os ayude a que entendáis un poco más las expresiones lambda

Enlaces


Desmitificando las expresiones lambda, por el Maestro Jose María Aguilar.
http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda.html 
Expresiones lambda
http://msdn.microsoft.com/es-es/library/bb397687.aspx

Libro C# 3.0 y LINQ, de Octavio Hernández.
http://www.campusmvp.com/catalogo/Product-C-3.0-y-LINQ_1.aspx



jueves, 22 de septiembre de 2011

Diseñando mediante prototipos (Mocking, prototyping)

Es recomendable, a la hora de montar una interfaz, de sentarte delante de un papel y un lápiz y empezar a pensar en cómo organizar la información de una web o de un formulario.

La inmensa mayoría de los programadores siempre nos hemos llevado mal con el diseño, pero al final nos hemos tenido que meter en él. Un truco que tengo para lidiarme con colores, fuentes, márgenes, etc... es el truco de los sombreros.
  • Me pongo el "sombrero de diseñador" y, sin entrar en código, monto un prototipo con alguna herramienta (gimp, photoshop, excel...) que quede bien organizado y cuya estética sea agradable.
  • Acto seguido, me pongo el "sombrero de programador" y trato de plasmar ese diseño en la herramienta de desarrollo.

Herramientas de prototipado
Mediante un prototipo se consigue, por una parte, centrarte en el "qué quiero", organizar los contenidos e incluso poder acercar al cliente la solución que se le va a entregar.

Para organizar contenidos, con un programa tipo Visio o Word que te proporcionan formas de controles con los que puedes ir montando un borrador de lo que quieres.

Para trabajos más de diseño gráfico, es bueno apoyarse en Gimp o Photoshop e ir montando el diseño a base de capas

Unas herramientas que he descubierto y que facilitan mucho el prototipado son:

Evolus Pencil
http://pencil.evolus.vn/
Proyecto GPLv2 bajo Linux y Windows (parece que también estará pronto para MAC).
También se puede instalar como complemento para Firefox 3.







iPLOTZ
http://iplotz.com/
Producto comercial con una versión libre pero limitada. El acceso libre limita a 1 proyecto y 5 páginas.

Tiene versión offline.


MockFlow
http://www.mockflow.com/
Producto comercial con una versión libre pero limitada a 1 proyecto y 4 páginas.

Tiene también versión descargable.