Control Silverlight RichtTextBox

Julio 21, 2010 :: Posted by - Mario Andujar :: Category - , , ,

image

El otro día en el trabajo me pidieron si podía crear dos controles nuevos en Silverlight para poder introducir texto formateado y poder visionarlo.

Buscando por la red encontré una opción gratuita bastante buena para lo que me pedían. El control en si se encuentra en http://www.vectorlight.net/demos/richtextbox.aspx y es un editor de texto bastante completo (tiene incluso un diccionario ortográfico para corregir errores de escritura y agregar nuevas definiciones). Solo con cambiar y poner las cuatro opciones que me pedían ya quedaron realizados estos dos controles.

Trabajar con Listas (Skip, Take y OrderBy)

Junio 30, 2010 :: Posted by - Emilio Torrens :: Category - , ,
Un poco de código para trabajar con listas.
 
El otro día nos llegaba, en una lista de int, las edades de los paxes y querían que ordenáramos las de los niños de menor a mayor, de eso se puede sacar un ejemplo de uso de Take y Skip, G1 seria el numero de Adultos en la lista, G2 niños y G3 Bebes.
 
int G1 = 2;

int G2 = 3;

int G3 = 1;

List<int> Valores = new List<int>() { 35, 25, 9, 4, 5, 0 };

//Cogemos los valores del segundo Grupo, los ordenamos y los metemos en 

//una nueva lista

List<int> ValoresG2 = Valores.Skip(G1).Take(G2).OrderBy(c => c).ToList();

//Creamos la lista resultado con los valores del Grupo 1, los del Grupo 2 

//Ordenado y el Grupo 3

List<int> result = new List<int>();

result.AddRange(Valores.Take(G1));

result.AddRange(ValoresG2);

result.AddRange(Valores.Skip(G1 + G2));

Ya se que se puede hacer en menos líneas, pero es un ejemplo !!!!! :)

Acortar una URL con TinyURL y PHP

Junio 23, 2010 :: Posted by - Emilio Torrens :: Category - ,
<?php

$url = $_GET['url'];

$curl = curl_init();

curl_setopt($curl,CURLOPT_URL,'http://tinyurl.com/api-create.php?url='.$url);

curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);

curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,5);

$rs = curl_exec($curl);

curl_close($curl);

echo $rs;

?>

Objetos 2 byte[]

Mayo 11, 2010 :: Posted by - Emilio Torrens :: Category - ,

Estoy haciendo unas pruebas con un servicio de cache propio en el que guardamos los datos en byte[] en unos diccionarios, así que a quien pueda interesar, aquí os dejo los métodos de serializacion y desserializacion:

public static byte[] ToByteArray(Object obj)
{
    if (obj == null) return null;

    MemoryStream ms = new MemoryStream();
    BinaryFormatter b = new BinaryFormatter();
    b.Serialize(ms, obj);
    byte[] data = ms.ToArray();
    ms.Close();
    return data;
}

public static T ToObjectSerialize<T>(byte[] serializedObject)
{
    if (serializedObject == null) return default(T);

    MemoryStream ms = new MemoryStream();
    ms.Write(serializedObject, 0, serializedObject.Length);
    ms.Seek(0, 0);
    BinaryFormatter b = new BinaryFormatter();
    Object obj = b.Deserialize(ms);
    ms.Close();
    return (T)obj;
}

Cliente C# para Velocity

Abril 14, 2010 :: Posted by - Emilio Torrens :: Category - , , ,

Hoy he estado liado con este tema con unas pruebas básicas para probar el Cache del AppFabric

El Windows Server AppFabric Beta 2 lo he instalado en un Windows Server 2008 con el Framework 4.0 RC, ojo que tiene que ser el RC no puede ser el final, además tiene otros requisitos con el Windows Power Shell 2.0 RTM y algunas cosas mas, pero el instalador te avisa y te dice de donde bajarlos.

El cliente en C# con VS2010 y Framework 4.0, recién salido del horno :)

Creamos el proyecto cliente y le añadimos esta referencias del AppFabric (Encontraremos las dll en la carpeta C:\Windows\System32\AppFabric del servidor donde lo hayamos instalado

  • Microsoft.ApplicationServer.Caching.Client.dll
  • Microsoft.ApplicationServer.Caching.Core.dll
  • Microsoft.WindowsFabric.Common.dll
  • Microsoft.WindowsFabric.Data.Common.dll

Podemos configurar el cliente por código o en el AppConfig.

Por código:

private DataCache Client
 {
     get
     {
         if (dataCache != null) return dataCache;

         // Aqui los servidores de cache en este caso 1.
         DataCacheServerEndpoint[] servers = new DataCacheServerEndpoint[1];
         servers[0] = new DataCacheServerEndpoint("CACHESERVER", 22233);

         DataCacheFactoryConfiguration factoryConfig =
                                       new DataCacheFactoryConfiguration();
         factoryConfig.Servers = servers;

         DataCacheFactory mycacheFactory = new DataCacheFactory(factoryConfig);

         //El Cache, en este caso el que pone por defecto al instalarlo
         DataCache myDefaultCache = mycacheFactory.GetCache("default");

         dataCache = myDefaultCache;
         return dataCache;
     }
 }

Por configuración:

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!--configSections must be the FIRST element -->
  <configSections>
    <!-- required to read the <dataCacheClient> element -->
    <section name="dataCacheClient"
       type="Microsoft.ApplicationServer.Caching.DataCacheClientSection,
            Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0,
            Culture=neutral, PublicKeyToken=31bf3856ad364e35"
       allowLocation="true"
       allowDefinition="Everywhere"/>
  </configSections>

  <dataCacheClient>
    <hosts>
      <host name="CACHESERVER" cachePort="22233"/>
    </hosts>
  </dataCacheClient>
</configuration>

Codigo:

private DataCache Client
      {
          get
          {
              if (dataCache != null) return dataCache;

              //Configurado en el app.config
              DataCacheFactory mycacheFactory = new DataCacheFactory();

              // Get a cache client for the cache "default".
              DataCache myDefaultCache = mycacheFactory.GetCache("default");

              dataCache = myDefaultCache;
              return dataCache;
          }
      }

Y listo para probarlo:

private void Test()
{
    DataCache cliente = Client;

    cliente.Add("key", "data");
    object data = cliente.Get("key");
    cliente.Remove("key");
}

Firmar Ensamblados y meterlos en el GAC

Marzo 26, 2010 :: Posted by - Emilio Torrens :: Category - ,

Si quieres meter las dll en el GAC para que sean compartidos por todas las aplicaciones de la maquina tienes que tener en cuenta un par de cosas:

  • Las dll que pongas en el GAC tienen que estar firmadas, el proceso es sencillo, vas a las propiedades del proyecto y la firmas, todo visual.
  • Todas las referencias que use tu dll tienen que estar firmadas también, todas las del Framework lo están ya, así que solo te tienes que preocupar de las tuyas y de las de 3ros que estés usando.
  • Tienes que poner una versión fija a la dll (que no se autoincremente en cada compilación, eso lo haces en AssemblyInfo quitando el * en la versión) ya que las aplicaciones quedaran referenciadas a esa versión y así no necesitaras actualizar las aplicaciones cuando actualices la dll en el GAC.

No es un tema complicado, el único “problema†que encontramos fue cuando generamos una dll de serializarión con los tipos con el sgen, ya que esa dll tiene que estar firmada también, para eso tienes que firmar  primero la dll sin las referencias a la dll de serializacion, después generar la dll de serializacion firmada y volver a poner las referencias, eso solo es necesaria hacerlo la primera vez, después cuando modifiquemos algún tipo y queramos actualizar la dll de serialización como están las dos firmadas no importa quitar referencias.

Para generar la dll de serializacion firmada el comando es este:

sgen.exe /assembly:”$(TargetDir)$(TargetFileName)” /compiler:”\”/keyfile:$(ProjectDir)Signature.snk”\” /force

Para meterlas en el GAC basta que las arrastres a la carpeta Windows/Assembly.

Capturar evento click derecho con SilverLight

Marzo 17, 2010 :: Posted by - Emilio Torrens :: Category - , , ,

Aquí vemos como capturar el evento del botón derecho en silverlight.

Este evento desde la salida de silverlight ha estado inactivo, y dicen que en la siguiente versión, silverlight 4, estará disponible (también dijeron eso en la versión 3).

Cuando haces click derecho en la aplicación Silverlight te muestra un menú contextual y un dialogo de configuración.

¿Y si quieres usar el botón derecho en tu aplicación silverlight? El proceso es muy sencillo, y aquí os detallare unos pasos que deberéis de seguir para poder utilizar dicho evento y mostrar un menú contextual propio.

Paso 1: Tenemos que establecer el control de Silverlight para ventanas. En la pagina web del proyecto (suele ser default.aspx) que contiene el control Silverlight añadir la etiquetawindowless=”true”.

Paso 2: Introducimos el contextmenu donde queramos capturar el evento click derecho. Dentro del xaml creamos una nueva clase llamada ContextMenuInterceptor. En el constructor de esta clase capturamos un evento llamado “OnContextMenu” con HtmlPage.Document.AttachEvent (deberás agregar la referencia System.Window.Browser).

Dentro de este evento llamamos a e.PeventDefault(). Esto cancela la propagación del evento click derecho para que silverlight no lo reciba (así no mostrará su menu contextual).

En este punto, es cuando usted esta capturando el evento y podra mostrar o hacer cualquier cosa. En el ejemplo que pongo a continuación utilizo yo un TextBlock para mostrar cuando capturamos el click derecho.

Page.xml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace SilverlightApplication15
{
    public partial class Page : UserControl
    {
        ContextMenuInterceptor _cmi = null;
        public Page()
        {
            InitializeComponent();
            _cmi = new ContextMenuInterceptor(MyField);
        }
    }       

    public class ContextMenuInterceptor
    {
        TextBlock TextField;

        public ContextMenuInterceptor(TextBlock textField)
        {
            TextField = textField;
            HtmlPage.Document.AttachEvent("oncontextmenu", this.OnContextMenu);
        }

        private void OnContextMenu(object sender, HtmlEventArgs e)
        {
            TextField.Text = "Right Clicked Blocked at "+e.OffsetX+","+e.OffsetY;
            e.PreventDefault();
        }
    }
}

Dependency Injection con Microsoft.Practices.Unity

Marzo 11, 2010 :: Posted by - Emilio Torrens :: Category - , ,

Microsoft.Practices.Unity  nos permite mapear una Clase a un Interface a través de una configuración en el .config de la aplicación, de esta manera podemos cambiar el comportamiento o el escenario en el que esta se ejecuta la aplicación tocando solo esa configuración.

Aquí dejo un ejemplo básico:

1-Creamos el Interface

public interface IMessage
{
    string Get();
}

2-Creamos las clases que implementan el interface

public class Message1 : IMessage
{
    public string Get()
    {
        return "Desde Message 1";
    }
}

public class Message2 : IMessage
{
    public string Get()
    {
        return "Desde Message 2";
    }
}

3-Creamos la clase donde usaremos el Interface, en esta debemos definir un campo del tipo del interface marcado como [Dependency] y un método de load para cargar la clase que corresponde en el interface

public class Message
{
    [Dependency]
    public IMessage IMessage { get; set; }

    public static Message Instance
    {
        get
        {
            using (IUnityContainer container = new UnityContainer())
            {
                UnityConfigurationSection ConfigurationSection =
                    (UnityConfigurationSection)
                    ConfigurationManager.GetSection("DITest");
                ConfigurationSection.Containers.Default.Configure(container);
                Message objMessage = container.Resolve<Message>();
                return objMessage;
            }
        }
    }
}

4-Creamos el archivo de configuración donde hacemos el mapeo

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
  <section name="DITest"
           type="Microsoft.Practices.Unity.Configuration.
                       UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <DITest>
    <containers>
      <container>
        <types>
          <type type="DITest.IMessage,DITest"
                mapTo="DITest.Message2,DITest"/>
        </types>
      </container>
    </containers>
  </DITest>
</configuration>

5-Probamos el código desde la consola y vamos cambiando el “mapTo†del archivo de configuración para ir viendo el cambio

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Message.Instance.IMessage.Get());
        Console.ReadLine();
    }
}

Exchange 2010 y Server 2008 R2

Febrero 24, 2010 :: Posted by - Emilio Torrens :: Category - , ,

Este fin de semana he estado liado con la gente de Viabit migrando el PDC de maquina y de SO y lo mismo con el Exchange, hemos pasado de W 2003 Server a W 2008 Server R2 y de Exchange 2003 a 2010.

Aunque las cosas han ido relativamente bien hemos pasado nuestros momentos de crisis, por lo que creo que hay 3 o 4 “trucos†que conviene compartir :)

imageNo deshabilites el protocolo IPv6 en el servidor 2008 en el que instales el Exchange ya que eso provoca un error 2114 en el arranque del servicio MSExchangeDSAccess que hará que el servidor no arranque, y todos los servicios de Exchange queden en Error.

imageCuando muevas los buzones del antiguo Exchange al nuevo la información de que buzón se esta moviendo, cual tiene error, que % esta completado la encontraras en el apartado de “Solicitudes de Trasladoâ€, además si un buzón acaba en error no te permitirá volver a intentar moverlo hasta que borres la solicitud de traslado que queda en error.

imageSi necesitas que el Exchange envié a través de algún programa de 3ros o que envié a diferentes sitios según el dominio o algo de eso necesitas crear un “enviar conectores†en el “trasporte de concentradoresâ€

imageSi necesitas cambiar el puerto de ese “conector†no te queda otra que usar el Shell del Exchange
image Si utilizas Sincronización con móviles vía ActiveSync, la url de sincronización cambia a http://tuserver//Microsoft-Server-ActiveSync y debes configurarlo en “Configuración del Servidorâ€/â€Acceso Clienteâ€

Y bueno ahora no me acuerdo de mas “detallitos†ya iré actualizando el POST si recuerdo algo mas, cualquier comentario o truquillo es bienvenido :)

SoapHeader, SoapExtensions y Herencia

Diciembre 03, 2009 :: Posted by - Emilio Torrens :: Category - , , ,

Hace unos días Jordi escribió sobre las SoapExtensions y yo sobre las SoapHeaders, hoy le añadimos herencia y vemos como ahorrarnos bastante código y trabajo en una capa de servicios. :)

La idea es que todos los métodos de todos los servicios web de la aplicación se autentifiquen en el mismo sitio y no tener que poner el código de autentificación en cada método, además no queremos usar cookies ni mantenimiento de sesión.

Para esto usaremos una Cabecera Soap donde el cliente nos enviara Usuario y Contraseña, debemos crear la clase cabecera:

public class SoapHeaderCredentials : SoapHeader
{
    public string Password = "";
    public string UserName = "";
}

Cada servicio web tiene que tener una propiedad con la Cabecera, para ahorrarnos el escribirlo cada vez, creamos una clase que herede de WebService, que contenga la propiedad y heredamos los servicios web de esa clase:

public class MyWebService : System.Web.Services.WebService
{
    public SoapHeaderCredentials soapHeaderCredentials;
}

public class Service : MyWebService

Después creamos una Extensión Soap de autentificación (en este caso la llamamos AuthenticationExtension), Jordi ya explica aquí como crearlas así que solo pongo el código que nos interesa, que es donde buscamos la Cabecera Soap en el Método ProcessMessage:

case SoapMessageStage.AfterDeserialize:
{
    var o = from h in message.Headers.Cast<SoapHeader>()
            where h.GetType() == typeof(SoapHeaderCredentials)
            select h ;
    SoapHeaderCredentials soapHeaderCredentials =
        (SoapHeaderCredentials) o.First();
    AuthenticateUser(
        new Credentials()
        {
          UserName = soapHeaderCredentials.UserName,
          Password = soapHeaderCredentials.Password,
        }, 
      );
    break;
}

Después solo queda añadir los dos atributos [SoapHeader("soapHeaderCredentials")]  y [AuthenticationExtension()] a nuestros WebMethods, eso hará que los métodos tengan la cabecera de usuario y contraseña y que ejecuten el código de autentificación al recibir un mensaje:

[WebMethod]
[SoapHeader("soapHeaderCredentials")]
[AuthenticationExtension()]
public string HelloWorld()
{
    return "Hello World";
}

Y listo :)