viernes, 2 de diciembre de 2011

IEnumerable en vez de List para propiedades

Hoy toca un post muy sencillo y básico pero que puedes preguntarte en algunas ocasiones.

Hoy le he hecho una pregunta a mi amigo y maestro Pedro Santos que me estaba rondando por la cabeza, ¿por qué exponer una propiedad como IEnumerable en vez de List, si yo internamente la voy a definir como una List?

Su respuesta ha sido muy clarificadora:

Al exponerla como IEnumerable tu no expones (encapsulas) su estructura interna, además así limitas las operaciones a realizar con esta propiedad y puedes aplicar las reglas de negocio que te interesen, como por ejemplo, que tenga un cierto comportamiento concreto al añadir un nuevo elemento a la lista.

Si tu expones una propiedad como List, también le estas exponiendo la opción de añadir sin que tu controles como se han de añadir estos elementos a tu colección.

Pues bueno, a partir de ahora, todas mis colecciones irán como IEnumerable y cuando me interese le expondré el método AddNewFooItem(FooItem item). Por último, lo ideal también sería exponer el setter de la lista como private o protected, para que no puedan “settearte” una nueva colección.

jueves, 3 de noviembre de 2011

Llamando a un web service sobre https (ssl) desde sharepoint 2010

He estado trabajando en un proyecto donde teniamos que integrar una aplicación externa, esta integración la hacemos mediante servicios webs. Estos servicios webs contienen datos privados por lo que están securizados mediante certificados (el mensaje) y además la información viaja por un medio seguro, es decir, ssl.

Bueno hasta aquí nada nuevo, hice mis pruebas con un proyecto de test, colocando los certificados en los diferentes repositiorios, dependiendo de su función: Trusted Root Certification Authorities, Intermediate Certification Authorities, etc. y todo funcionaba a las mil maravillas.

Pero esta llamada al servicio web ha de ser hecha desde un entorno SharePoint 2010, pensé que esto no sería ningún problema pues en el otro tipo de proyecto me funcionaba correctamente, pero no fue así, de pronto observé que la llamada al servicio web me estaba devolviendo la siguiente excepción:

Type: System.Net.WebException
Message: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
InnerException: The remote certificate is invalid according to the validation procedure.

Esta excepción me extraño mucho, pues si yo accedía mediante el browser a la url del web service me decía que el certificado estaba correctamente instalado.

Entonces empecé a googlear un poco y leía gente que decía de crear un bypass, mediante la creación de tu propia clase CertificatePolicy que implemente la interfaz ICertificatePolicy, y en el método CheckValidationResult devolver true siempre para que se salte la validación.

public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy()
{}

public bool CheckValidationResult(ServicePoint sp,
X509Certificate cert,WebRequest req, int problem)
{
return true;
}
}


La llamada a esta clase se tendría que hacer justo antes de la llamada a tu servicio web.


System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

He visto en muchos foros y blogs que esto lo daban como la solución correcta, pero ojo, aquí estamos aceptando cualquier cosa que nos esté enviando el servidor sin validar el certificado!!


Por lo tanto seguí buscando y el problema reside en la forma que tiene sharepoint de obtener los certificados raíz, que parece ser que usa su propio repositorio de certificados en vez de usar el de la propia máquina. Por lo que tendremos que añadir estos certificados raíz de confianza en el repositorio de sharepoint. Para hacerlo seguiremos los siguientes pasos:



  1. Ir a la administración central

  2. Ir a security

  3. Manage trust

  4. Aquí es donde instalaremos los certificados raíz que nos interese, pulsando new, buscando el certificado y poniéndole un nombre.


Esta información la obtuve del siguiente blog:


http://blog.mattsampson.net/index.php/calling-a-webservice-over-ssl-in-sharepoint-ssl?blog=1

jueves, 9 de junio de 2011

WCF tools

Esta semana me he estado peleando he estado haciendo una integración con un proveedor de servicios para poder consumir su servicio una aplicación que estamos desarrollando. Lo primero que hemos de saber es que toda integración suele dar muchos dolores de cabeza ser un bonito reto.

En nuestro caso teníamos que consumir un servicio elaborado con java axis2. Este servicio tenia que tener seguridad a nivel de transporte (mediante certificado) y seguridad a nivel de mensaje (también mediante certificado), más concretamente en nuestro caso debía contener una firma.

Cuando hacemos este tipo de integraciones lo más normal es que no nos salga a la primera y que tengamos que ver que mensajes estamos enviando al servidor, ya que los errores que nos pueden devolver el servidor pueden ser poco intuitivos. Y he aquí donde realmente empieza el contenido de este post, o sea, que herramientas podemos usar para ver lo que estamos enviando.

Una de las primeras herramientas que podemos utilizar es el tracing de Windows Communication Foundation. En la siguiente página de las MSDN podemos ver como configurar esto:

http://msdn.microsoft.com/en-us/library/ms733025.aspx

En mi caso la configuración ha sido la siguiente:

Justo antes del cierre del tal configuration (</configuration>)

<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true" >
<listeners>
<add name="xml"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\logs\CommandLineSTS.svclog" />
</sharedListeners>
</system.diagnostics>

Y esto dentro del nodo system.serviceModel:

<!-- add trace logging -->
<diagnostics wmiProviderEnabled="true">
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true"
maxMessagesToLog="3000"
/>
</diagnostics>

Otras herramientas que podemos usar para ver que se esa enviando son HTTP monitors, en mi caso he utilizado dos, destacando el último de los que menciono a continuación:

image

Otra de las cosas con las que nos entretendremos mucho es configurando nuestro service model a nivel de configuración o programándolo con código. Para ello nada mejor que las msdn y como punto de partida esta seria una buena página:

http://msdn.microsoft.com/en-us/library/ms733103.aspx

Tampoco podemos olvidar las herramientas de WCF que se nos ofrecen con nuestro visual studio, un resumen de ellas son las que indica la msdn en la siguiente página:

http://msdn.microsoft.com/en-us/library/ms732015(v=vs.90).aspx

Seguramente y debido a las peculiaridades de cada integración, no nos valdrá con las típicas configuraciones de bindings que nos ofrece el framework por defecto, es decir BasicHttpBinding o WSHttpBinding, entre otras, y tengamos que echar mano de custombindings, ahora bien no esta mal partir de uno de los bindings de los que disponemos, para poder hacer esto podemos convertir cualquiera de estos bindings a custom bindings utilizando por ejemplo una herramienta que expone en su blog un crack en la materia como es Yaron Naveh.

http://webservices20.blogspot.com/2009/08/bindingbox-convert-wcf-bindings.html

Sobre el tema de configuración, decir que antes de pensar en desarrollar nosotros una solución como dirian los anglosajones “from scratch”, mirar todas las posibilidades que nos ofrecen las configuraciones de los bindings, seguro que encontraremos alguna que satisface nuestras necesidades.

En caso de que nuestra solución sea muy compleja y no podamos obtenerla con lo que nos ofrece wcf out of the box, siempre podemos pensar en extender estas funcionalidades ya que wcf es un framework de comunicación altamente extensible. Por ejemplo, podemos crear un message inspector o un message encoder (derivando de la interfaz IClientMessageInspector o de la clase MessageEncoder, respectivamente). Para estas posibles extensiones que podamos hacer sobre WCF es interesante descargarnos los ejemplos que encontramos en la msdn, más concretamente en:

http://msdn.microsoft.com/en-us/library/ms751514(v=VS.90).aspx

Aquí podemos encontrar ejemplos divididos en las siguientes categorías:

  • Basic
  • Extensibility
  • Scenario
  • Setup
  • Tools

lunes, 18 de abril de 2011

Alternativa a .NET Reflector

Hoy toca una entrada muy cortita.

El otro día estuve buscando una alternativa open source a la famosa herramienta de Redgate .NET Reflector y encontré una que me ha gustado mucho. Al igual que .NET Reflector, se trata de una herramienta que nos permite navegar por los ensamblados y decompilar codigo IL.

Como podéis apreciar en la siguiente imagen, la interfaz es identica a .NET Refector, por lo que no nos costará nada acostumbrarnos a trabajar con esta nueva herramienta.

ILSpy

Por último os dejo la url de la herramienta:

http://wiki.sharpdevelop.net/ilspy.ashx

jueves, 31 de marzo de 2011

WCF: Windows Authentication and Impersonation

Voy a intentar mostrar todo el procedimiento de poder exponer un servicio WCF alojado en un IIS con autenticación windows, esto es una tarea bien sencilla, pero muchas veces si “googleamos” un poco, nos encontramos con diferentes entradas en los foros y cada uno intenta hacerlo de una forma, al final acabas pensando que es una tarea dificil cuando en realidad no lo es. Acto seguido expondré como poder realizar una impersonación con el usuario que ha llamado a nuestro servicio. 

Parte uno: creación WCF Service y publicación IIS

Lo primero que haremos será crear un proyecto de tipo WCF Service Application, en este proyecto tendremos nuestra interfaz que define el Service Contract con un método que define nuestro Operation Contract:

using System.ServiceModel;

namespace FooWcfService
{
[ServiceContract]
public interface IFooWcfService
{
[OperationContract]
string FooOperation();
}
}


Ahora modificaremos la clase que implementa nuestro Service Contract (en este tipo de proyectos, esta clase esta en el code behind del fichero .svc), en nuestro caso algo parecido a esto:



namespace FooWcfService
{
public class FooWcfService : IFooWcfService
{
public string FooOperation()
{
return "Hello World";
}
}
}


Muy bien, una vez tenemos implementado lo que hará nuestro servicio, hemos de empezar a tratar el tema de seguridad, en nuestro caso hemos dicho que tendremos autenticación windows. Para ello, tendremos que modificar el fichero web.config, y poner el siguiente binding:



<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>


Bueno, para que no haya dudas expondré todo el web.config:



<?xml version="1.0"?>
<configuration>

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="FooWcfService.IFooWcfService">
<endpoint binding="basicHttpBinding" contract="FooWcfService.IFooWcfService" />
</service>
</services>
</system.serviceModel>

</configuration>


Ahora sí, ya estamos preparados para publicar nuestro servicio en un IIS. Supongamos que ya tenemos un IIS instalado, y que tenemos un Default Web Site, entonces sólo tendremos que hacer botón derecho sobre nuestro proyecto y publish.


publish web

Por último tendremos que habilitar en el IIS nuestra seguridad windows, vamos a nuestra web site y suponiendo que tengamos la vista Feature View, hacemos click sobre Authentication y habilitamos Windows Authentication y deshabilitamos Anonymous Authentication.


authentication iis

Parte dos: Impersonación



Para esta parte haremos un pequeño ejemplo de una aplicación cliente (Console application) que consuma nuestro servicio. Y cambiaremos un poco nuestra operación, para que tenga sentido la impersonación. Imaginemos que queremos tener un acceso a un recurso (por ejemplo acceso de escritura en disco) y para ello hemos de garantizar que el usuario que llama a nuestro servicio tenga permisos para ello, esto sería un claro ejemplo de impersonación. No se hable más, vamos a poner un pequeño ejemplo de ello:



using System;
using System.IO;

namespace FooWcfService
{
public class FooWcfService : IFooWcfService
{
public void FooOperation()
{
StreamWriter fileWriter = null;
try
{

fileWriter = File.CreateText(@"C:\dummy.txt");
fileWriter.Write("Hello world");

}
catch(Exception ex)
{
throw;
}
finally
{
if(fileWriter != null)
fileWriter.Close();
}
}
}
}


Para configurar la impersonación lo podemos hacer de modo imperativo o de modo declarativo, aquí podemos ver la explicación, nosotros en el ejemplo, usaremos el modo declarativo.



Este modo es el más simple, simplemente hemos de poner el siguiente atributo en la implementación de nuestro operation contract:

[OperationBehavior Impersonation=ImpersonationOption.Required)]

Si ejecutamos nuestra aplicación de consola, sin esta impersonación, lo más seguro es que nos aparezca un mensaje como el que apunto a continuación:

Access to the path 'C:\dummy.txt' is denied.

En cambio, si ponemos el attributo anterior, nos vuelve a dar una excepción pero ahora es diferente:

Either a required impersonation level was not provided, or the provided impersonation level is invalid.

Este mensaje nos esta diciendo, que nosotros requeriamos un cierto nivel de impersonación en nuestro código, pero que no se esta cumpliendo con la llamada desde el cliente.

Por lo tanto, el cliente cuando haga una llamada a nuestro servicio, ha de indicar que permite la impersonación.

Pongo ahora en código completo del cliente, done permitimos esta impersonación.

using System;
using System.Security.Principal;
using FooConsoleApplication.FooWcfService;

namespace FooConsoleApplication
{
class Program
{
static void Main(string[] args)
{
FooWcfServiceClient client = null;

try
{
client = new FooWcfServiceClient();
client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
var result = client.FooOperation();

Console.Write(result);
Console.Read();
}
finally
{
if(client!= null)
{
client.Close();
}
}
}
}
}

viernes, 28 de enero de 2011

DataContracts and Constructors

Imaginemos el siguiente escenario, tengo una clase que será un DataContract utilizado en un método de un servicio WCF y queremos inicializar una variable de esta clase en el constructor.

namespace FooNamespace
{
[ServiceContract]
public interface Foo
{
[OperationContract]
void StartProcess(FooData dataEntrada);
}

[DataContract]
public class FooData
{
[DataMember]
public string FooProperty { get; set; }

protected string InitializedData {get; set;}

public FooData()
{
InitializedData = "Hello world!";
}
}
}


Bueno pues hemos de ser consciente que esa llamada al constructor no se llamará nunca durante la deserialización.



Por lo que si queremos simular esto podemos usar los Serialization Callbacks. De esta forma en el servidor podremos tener inicializada esa clase con el valor que queramos.



namespace FooNamespace
{
[ServiceContract]
public interface Foo
{
[OperationContract]
void StartProcess(FooData dataEntrada);
}

[DataContract]
public class FooData
{
[DataMember]
public string FooProperty { get; set; }

protected string InitializedData {get; set;}

[OnDeserializing]
public void Initialize(StreamingContext context)
{
InitializedData = "Hello world!";
}
}
}

jueves, 27 de enero de 2011

Data Contract Known Types

Hoy me he encontrado con un problemilla (bueno más que un problemilla era que desconocía la manera correcta de hacerlo) a la hora de desarrollar un sevicio WCF.

El problema era que quería construir un método que recibía por parametro un objeto de tipo x, pero quería ofrecer al cliente la opción de poder pasar como parámetro objetos derivados de tipo x que había construido. Yo habia declarado todas estas clases con el atributo [DataContract], pero parece ser que esto no era suficiente, sino que había que especificar en la clase base, que también podiamos pasar objetos derivados usando el atributo [KnownType(typeof(claseBase)]

Aquí va la solución:

using System;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace FooNamespace
{
[ServiceContract]
public interface IFoo
{
[OperationContract]
void DoSomething(FooDataBase dataEntrada);
}

[DataContract]
[KnownType(typeof(FooDataDerived))]
public class FooDataBase
{
[DataMember]
public string FooProperty1 { get; set; }
}

[DataContract]
public class FooDataDerived:FooDataBase
{
[DataMember]
public string FooProperty2 { get; set; }
}
}

miércoles, 26 de enero de 2011

Unit Testing con Pex and Moles

Siguiendo la llamada de mi compañero Luis Ruiz, voy a entrar un poco en el mundo de Pex and Moles. A ver que es lo que me encuentro. Para ello empezaremos con una mini guia de tutoriales que voy a ir leyendo. Tal y como los vaya leyendo intentaré postear un pequeño resumen y las prácticas que voy realizando.

- Getting Started with Microsoft Pex and Moles: Aquí podemos ver lo que yo llamo un meta-tutorial, es decir, un tutorial de tutoriales, o más bien un tutorial que nos dice los siguientes pasos a realizar y que tutoriales podemos seguir.

En definitiva lo primero que deberiamos hacer es instalarnos Pex and Moles y continuar con otros tutoriales. Lo que me ha gustado es que nos muestra un conjunto de conceptos básicos sobre unit testing en forma de glosario de términos que puede ser muy útil para los neófitos, algunos de estos conceptos serian:

  • code coverage
  • integration test
  • mock
  • mole type
  • stub type

- Getting Started with Microsoft Code Contracts and Microsoft Pex: Este tutorial esta dividido en dos secciones, una primera en la que crearemos un proyecto en Visual Studio (una clase llamada StringExtensions con un método estático que devuelva un substring, desde el inicio hasta la primera aparición de otro string que nos pasen, también por parámetro) y ejecutamos lo que se conoce como Pex Explorations, esto lo que hace es ejecutar nuestro código muchas veces con diferentes valores de entrada, entonces se nos muestra una tabla con las diferentes salidas o excepciones de nuestro código. Para hacer eso sólo tendremos que hacer botón derecho en la función que queramos probar y hacer click en Run Pex.

image

Vemos que lo que hace Pex es intentar crear diferentes combinaciones de parámetros de entrada para cubrir la mayor parte de nuestro código. Entonces hace diferentes llamadas a nuestro método, pasándole como parámetros los que ha calculado, acto seguido nos muestra una tabla con estos resultados.

image