Skip to main content

Blog de Vicente Pazo

Go Search
Home
  

Desarrollando aplicaciones para Windows Phone 7 (I)

Hoy hemos decidido meternos en un nuevo campo: el desarrollo de aplicaciones en Windows Phone 7.

Como ya sabéis, se trata del movimiento de Microsoft para competir con la UI del Iphone.

Lo vi por primera vez en la presentación del Visual Studio 2010 de Valencia. La primera impresión no fue muy buena, las animaciones en el emulador de la presentación parecían ir lentísimas. Eso sí, podías desarrollar una aplicación y luego ejecutarla en PC, un móvil con Windows Phone 7 y, por ejemplo, una XBOX (eso suena bien ;) ).

Realmente, lo que tenemos por detrás es Silverlight 4, así que el código no debería asustarnos.

Aquí podéis descargaros las tools de desarrollo, y aquí algunos ejemplos.

Ojo! Sólo podréis instalaros las tools si tenéis el Windows Vista o el 7.

Es posible que al ejecutar alguno de los ejemplos os encontréis con este error:

 

 

Suele ser por falta de memoria, deberíais ´comprar algun giga... y solucionado!

Buscar un texto en todos los Stored Procedures

Imagina que tienes una base de datos con muchos procedimientos almacenados y necesitas saber cuál es el que inserta en cierta tabla.

Si no tienes documentación de cómo está hecha la base de datos (un clásico), una forma es buscar la cadena de texto "INSERT INTO " y el nombre de la tabla dentro de todos los procedimientos almacenados.

Para ello, podemos usar esta consulta SQL, que nos devolverá el nombre del SP que tiene el texto a buscar:

SELECT ROUTINE_NAME, ROUTINE_DEFINITION 
        FROM INFORMATION_SCHEMA.ROUTINES 
        WHERE ROUTINE_DEFINITION LIKE '%INSERT INTO miTabla%' 
        AND ROUTINE_TYPE='PROCEDURE'

Habrá otros métodos, pero este me ha parecido bastante fácil y rápido.

Haciendo webs para Iphone: mostrar el teclado numérico

Estábamos desarrollando una aplicación web para un Iphone. Esta web es una tienda y, como tal, tiene un formulario de entrada de datos a la hora de hacer el pago.

Realmente estábamos haciendo una aplicación web pero adaptada con ciertos estilos para que tenga un "Iphone feeling", así que los controles del formulario eran controles de .NET de toda la vida (además, lo de "de toda la vida" era literal, ya que el framework en que se ejecuta es el 1.1).

Sin embargo, el cliente quería que el textbox de introducción del número de la tarjeta de crédito fuese numérico, es decir, que al seleccionarlo apareciese el teclado sólo con números en el iphone (por defecto aparece el teclado alfanumérico).

 

Empezamos por buscar cómo podríamos hacer esto en un HTML control, y googleando encontramos que podemos indicar el atributo type para que muestre un tipo de teclado u otro:

 

<input type='tel'/>

 


<input type='number'/>

 


<input type='email'/>

 


<input />

 

 

 

 

 

Esto es correcto, pero… ¿Cómo lo aplicamos a un control de .NET? Evidentemente, no podemos ponerle un atributo "type". Y evidentemente, cuando añadimos un textbox .NET nos hará el renderizado en HTML como un control "type=text".

La solución es extender la clase TextBox y sobreescribir el método de renderizado.

Sin embargo, aún queda un paso más, ya que no podemos borrar los atributos que no son nuestros directamente de la colección "Attributes".

Si hiciésemos esto:

this.Attributes.Remove("type");

 

Para luego añadir el atributo type:

this.Attributes.Add("type", "number");

 

No obtendríamos el resultado esperado, ya que no podemos borrar ese parámetro.

La solución que se nos ocurrió fue hacer un replace dentro del objeto writeruna vez el método render del padre ha sido llamado:

protected override void Render(System.Web.UI.HtmlTextWriter writer)

{

    StringWriter stringWriter = new StringWriter();

    HtmlTextWriter source = new HtmlTextWriter(stringWriter);

    base.Render(source);

    writer.Write(stringWriter.ToString().Replace("type=\"text\"", "type=\"" + _contentType + "\""));

}

Este es el ejemplo completo:

 

public class NumberTextBox:TextBox

{

    private string _contentType;

 

    public string ContentType

    {

        get

        {

            return _contentType;

        }

        set

        {

            _contentType = value;

        }

    }

 

    public NumberTextBox()

    {

            

    }

 

    protected override void Render(System.Web.UI.HtmlTextWriter writer)

    {

        StringWriter stringWriter = new StringWriter();

        HtmlTextWriter source = new HtmlTextWriter(stringWriter);

        base.Render(source);

        writer.Write(stringWriter.ToString().Replace("type=\"text\"", "type=\"" + _contentType + "\""));

    }

Y esto cómo se usaría el control:

<cc:NumberTextBox cssclass="ipTextfieldAllWidth" runat="server" id="Zip" ContentType="number" />

 

Comparando fechas en CAML desde una aplicación .Net

Cuando queremos construir una consulta CAML desde .NET puede ocurrir que necesitemos incluir una condición para comparar fechas.

Si insertamos la fecha tal cual no nos ejecutará bien la consulta:

<Gt><FieldRef Name=""Created"" /><Value Type=""DateTime"">" + dtFrom.ToShortDateString() + @"</Value></Gt>

 

Esto sería lo que usaríamos desde un principio, a no ser que sepamos que éste es el método que realmente funciona :P

 

<Gt><FieldRef Name=""Created"" /><Value Type=""DateTime"">" + dtFrom.ToString("s") + @"</Value></Gt>

 

Este formato transforma la fecha así:

17/02/2010 -> 2010-02-17T12:00:00Z

Y con este formato SÍ se pueden comparar fechas.

Cuando necesitéis comprobar la sintaxis de vuestra query generada es buena idea usar alguna aplicación externa para ejecutarla y corregirla. Yo suelo usar U2U CAML, que podéis bajar gratuitamente desde aquí.

App_offline.htm II: Añadiendo imágenes

Vamos a añadir un poco layout a la página offline que citábamos en el anterior post:

Este será el resultado (evidentemente, el path de la imagen es correcto :P )

 

Por lo que parece, el IIS no es capaz de resolver el tag img dentro de esta página. Sin embargo, si usamos un atributo src con un stream Base64 podemos solucionar el problema.

Por ejemplo, vamos a crear un método en .NET para obtener el string correspondiente al stream Base64 de la imagen que queramos:

/// <summary>

/// Images to base64.

/// </summary>

/// <param name="image">The image.</param>

/// <param name="format">The format.</param>

/// <returns></returns>

private static string ImageToBase64(string sPath, ImageFormat format)

{

using (var ms = new MemoryStream())

{

try

{

 

System.Drawing.Image image = System.Drawing.Image.FromFile(sPath);

 

// Convert Image to byte[]

image.Save(ms, format);

var imageBytes = ms.ToArray();

 

// Convert byte[] to Base64 String

var base64String = Convert.ToBase64String(imageBytes);

 

return base64String;

}

catch

{

return null;

}

}

}

 

El string que nos devuelve este método podemos ponerlo dentro del atributo src del tag img (tras poner data:image/jpg;base64,):

 

Y este sería el resultado:

 

Poner una aplicación .NET offline usando app_offline.htm

A veces, necesitamos que nuestra aplicación permanezca durante un tiempo mostrando un mensaje para evitar que los usuarios accedan a la aplicación. Para ello, existe un método rápido y sencillo de poner una aplicación .NET en modo offline.

Creando una página llamada app_offline.htm e incluyéndola en el directorio raíz de nuestra aplicación conseguiremos que el IIS redireccione a ella automáticamente, sin tener que configurar nada:

 

 

De todas formas, tenemos que tener en cuenta ciertas consideraciones. Por extraño que parezca, si el tamaño de este archivo es inferior a 512 bytes, nuestro querido IE mostrará un error:

 

 

Para que funcione, podemos insertar cualquier texto dentro de <!-- --> para aumentar el tamaño del archivo y entonces sí funcionará:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>

<title>Página no disponible en este momento</title>
</head>
<body>

<h1>la página está offline</h1>
<!--
Vamos a añadir unos comentarios para hacer que la página sea mayor que 512 bytes
Vamos a añadir unos comentarios para hacer que la página sea mayor que 512 bytes
Vamos a añadir unos comentarios para hacer que la página sea mayor que 512 bytes
Vamos a añadir unos comentarios para hacer que la página sea mayor que 512 bytes
Vamos a añadir unos comentarios para hacer que la página sea mayor que 512 bytes
-->
</body>

</html>

 

Próximamente veremos cómo añadir imágenes, ya que no es posible usar directamente la etiqueta img

 

URLEncode y HTMLEncode

Muchas veces confundimos ambas funciones y el uso de las mismas no queda muy claro, mucho más tras leer la documentación de la MSDN, que es bastante confusa con estos dos métodos. Además, para liar más las cosas existe otra función llamada HttpUtility.UrlPathEncode que muchas veces nos dará el resultado correcto.

 

Las dos funciones codifican caracteres especiales (no alfanuméricos, acentos, etc) de manera que sean seguras para el protocolo HTTP. Sin embargo, podemos obtener resultados no deseados si no conocemos las diferencias entre ambas.

Imaginemos que tenemos:

string sTest = "Esto es un string de prueba <Test String>.";

string sEncoded = Server.HtmlEncode(sTest);

 

El valor de sEncoded sería "Esto es un string de prueba &lt;Test String&gt;". Sin embargo, esto puede llevar a problemas si vamos a pasar la cadena post, ya que como la cadena incluye un ampersand al hacer un Request.Form hará un Split obtendremos más parámetros de los necesarios.

 

Para solucionar esto, usaremos el HttpUtility.UrlEncode que sí puede ser usado de forma segura en un post, ya que la cadena resultante sería "Esto+es+un+string+de+prueba+%3cTest+String%3e.".

 

URLEncode y HTMLEncode

Muchas veces confundimos ambas funciones y el uso de las mismas no queda muy claro, mucho más tras leer la documentación de la MSDN, que es bastante confusa con estos dos métodos. Además, para liar más las cosas existe otra función llamada HttpUtility.UrlPathEncode que muchas veces nos dará el resultado correcto.

 

Las dos funciones codifican caracteres especiales (no alfanuméricos, acentos, etc) de manera que sean seguras para el protocolo HTTP. Sin embargo, podemos obtener resultados no deseados si no conocemos las diferencias entre ambas.

Imaginemos que tenemos:

string sTest = "Esto es un string de prueba <Test String>.";

string sEncoded = Server.HtmlEncode(sTest);

 

El valor de sEncoded sería "Esto es un string de prueba &lt;Test String&gt;". Sin embargo, esto puede llevar a problemas si vamos a pasar la cadena post, ya que como la cadena incluye un ampersand al hacer un Request.Form hará un Split obtendremos más parámetros de los necesarios.

 

Para solucionar esto, usaremos el HttpUtility.UrlEncode que sí puede ser usado de forma segura en un post, ya que la cadena resultante sería "Esto+es+un+string+de+prueba+%3cTest+String%3e.".

 

Ver el mensaje de error si tenemos “Unexpected error occurred”

Un clásico.

Muchas veces vemos esta pantalla al crear un webpart en instalarlo en nuestro MOSS:

 

 

 

El mensaje de error no es el más explícito del mundo así que nos interesa saber cuál es el error que está produciendo esa excepción.

 

Recordad que MOSS no deja de ser una aplicación .NET y, como tal, podemos modificar la sección "CustomErrors" del web.config para mostrar los errores "enmascarados" o verles las tripas.

En el caso de MOSS vamos a hacer lo mismo, pero habrá que dar un paso más:

 

  1. CustomErrors a OFF:

    <customErrors mode="Off" /><!– cambiar en el web.config original de "On" a "Off" –> 

     

  2. Cambiar la propiedad "CallStack" a true en el tag SafeMode:

    <!- cambiar CallStack de "false" a "true"–><SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" ...

     

     

Establecer el atributo href en XSLT

Si tenemos un documento XSLT y queremos poner un link que vaya a un destino que obtenemos de una variable XSLT, lo primero que nos viene a la cabeza es hacer algo así:

 

<a href='<xsl:value-of select="$AttachmentURL" /></xsl:value-of>'>

<xsl:value-of select="Name"/>

</a>

 

O alguna de sus incorrectas variantes.

Una de las opciones más sencillas y elegantes es añadir un atributo al tag A con xslt:

 

<a>

<xsl:attribute name="href">

<xsl:value-of select="$AttachmentURL" />/<xsl:value-of select="Name"/>

</xsl:attribute>

<xsl:value-of select="Name"/>

</a>

 

 

 

 

1 - 10 Next

 ‭(Hidden)‬ Admin Links