miércoles, 30 de noviembre de 2011

Ojo al modificar tu servicio WCF…

Hoy he pasado un mal rato intentando solucionar un problema que, al final, era más simple de lo que parecía. Resulta que para cambiar una pequeña funcionalidad tuve que añadir un parámetro a uno de los métodos de un servicio WCF. El cambio vendría ser de lo siguiente:

[OperationContract,
WebGet(UriTemplate = "/MyMethod?parameter1={parameter1}",
       ResponseFormat = WebMessageFormat.Json)]
int MyMethod(int parameter1);

A lo siguiente:

[OperationContract,
WebGet(UriTemplate = "/MyMethod?parameter1={parameter1}",
       ResponseFormat = WebMessageFormat.Json)]
int MyMethod(int parameter1, int parameter2);

Bueno, pues que sepáis que hacer esto hacía que cualquier otro método de mi servicio dejara de funcionar con un error 401 (cortesía de SharePoint). Tras depurar el error vi que en realidad la causa de mi problema era que el método está declarado como GET y que en el UriTemplate no estaba especificando mi nuevo parámetro. Al final el método debería quedar así:

[OperationContract,
WebGet(UriTemplate = "/MyMethod?parameter1={parameter1}&parameter2={parameter2}",
       ResponseFormat = WebMessageFormat.Json)]
int MyMethod(int parameter1, int parameter2);

Sí, lo sé, es una chorrada de artículo y no sólo no aporto nada sino que os he hecho perder el tiempo a la mayoría, pero de alguna manera tenía que expulsar la mala leche que me ha entrado al descubrir el motivo de que mi sitio hubiera dejado de funcionar.

lunes, 28 de noviembre de 2011

[EVENTO] SharePoint 2010 y ALM ¿Es posible?

Antes de que lo digáis, no, no es un dejavú. Será el tercer evento relacionado con SharePoint 2010 y ALM en muy poco tiempo, pero es un tema que merece la pena y seguiré insistiendo tanto como pueda en su importancia. Después de haber hecho un evento presencial en Barcelona y otro presencial en Andorra, le ha llegado el momento a la gente del SUGES (Grupo de Usuarios de SharePoint de España) para aguantarme una hora y media hablando de conceptos tales como calidad de software, pruebas unitarias y de integración, tests de aceptación o integración contínua y, evidentemente, siempre desde el punto de vista del profesional del mundo del SharePoint.

Sé que mezclar ambos mundos no es tarea sencilla, y sé que muchos de vosotros tendríais mucho que decir al respecto, tanto si trabajáis con SharePoint como si no, así que espero que se presente tanta gente como sea posible y me déis caña hasta en el carné de identidad.

Decir también que dejé parada la serie de artículos que tengo preparada relacionados con esta temática, justamente esperando a estos tres eventos, con la intención de recoger vuestro feedback y, sobretodo, vuestras dudas. Os invito, por tanto, a que vengáis y me expongáis aquellas cuestiones que más despierten vuestro interés. Además de responder todas las dudas que me sea posible, prometo escribir tantos artículos específicos como sea necesario para resolver todas las cuestiones que se abran.

Os dejo aquí más información del evento así como los links de registro.

SharePoint 2010, Servicios REST y Claims

Una de las cosas en las que estoy trabajando actualmente requería disponer de un servicio WCF REST para interactuar con SharePoint 2010. Este servicio se consumía mayoritariamente desde javascript via AJAX y no presentaba mayores problemas y hace un tiempo surgió la necesidad de hacer llamadas al mismo servicio desde diversos webparts y event receivers de manera que el punto de entrada al corazón de la aplicación fuera siempre el mismo. Todo parecía funcionar correctamente hasta que en una de las pruebas de despliegue detectamos un error extraño similar al siguiente:

The remote server returned an error: (400) Bad Request. Exception: System.Net.WebException: The remote server returned an error: (400) Bad Request.     at System.Net.WebClient.UploadDataInternal

Como el error en sí no era demasiado descriptivo metí unas cuantas trazas y utilicé algún que otro Fiddler para determinar la causa real del problema. Así es como di con el siguiente error:

Message: 403 FORBIDDEN

Perfecto, habíamos pasado de un Bad Request (400) a un Forbidden (403). Además tenía todo el sentido del mundo porque el error se daba únicamente en el entorno donde teníamos corriendo el código en una aplicación web con autenticación basada en Claims. Determinado el error y su más que probable causa, encontrar una solución era sólo cuestión de tiempo. Y la solución vino de la mano de Justin Kobel y de este artículo.

Aquí no sólo encontramos el código necesario para realizar las llamadas de manera adecuada, sino que se explica también cómo hacer para distinguir si estamos en una aplicación web clásica o en una basada en notificaciones. Yo tuve que cambiar algo el código para adaptarlo a mis necesidades pero la esencia es la misma y consiste en aprovechar la cabecera Cookie para nuestra llamada, tal y como muestra el siguiente listado.

webClient = new WebClient { Credentials = CredentialCache.DefaultNetworkCredentials };
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
 
IClaimsPrincipal principal = HttpContext.Current.User as IClaimsPrincipal;
if (principal != null)
{
   NameValueCollection headers = HttpContext.Current.Request.Headers;
   webClient.Headers["Cookie"] = headers["Cookie"];
}
 
var receivedData = webClient.UploadData(url, verb, memoryStream.ToArray());
var response = (T)jsonSerializer.ReadObject(new MemoryStream(receivedData));

Veréis que en un punto del artículo hace el autor se salta la validación de los certificados en el momento de la autenticación. Si queréis información sobre como hacer esto de manera adecuada, os recomiendo este artículo de mi compañero Jordi Ruiz.