Archives

Archives / 2011 / March
  • Troubleshooting your WCF Web Apis with AppFabric

    In this last post, I showed how the new WCF Web Apis could be integrated with AppFabric for pushing custom events to the AppFabric tracking database. A great thing about the monitoring infrastructure in AppFabric is that is uses ETW as mechanism for publishing the events, so your services are not hitting the database directly with all the performance penalties that database calls imply.  

    Read more...

  • My frustrations with MVVM in Silverlight

    There is no doubt that the MVVM pattern offers a clean separation of concern for building testable user interfaces with WPF and Silverlight.  This pattern relies on the data binding support in those two technologies for mapping an existing model class (the view model) to the different parts of the UI or view.

    Someone would say, If you want to develop more testable and maintainable applications that can evolve in the long run, MVVM is definitely the way to go in Silverlight, but wait, is that a good decision to make when something that should take a couple of hours instead takes a day with MVVM ?.  

    In my case, I always want to do the things right, so MVVM was the approach I decided to use in some outgoing developments with Silverlight. In used MVVM in the past with WPF with no problems, so I thought it will be the same thing on Silverlight.

    After having worked around six months with the technology, I have to admit that I got frustrated with many of the limitations of I found for implementing MVVM with many of the existing controls. In the way I see it, many of them were definitely developed to support simple RAD scenarios with code behind, but not for scenarios with data templates and bindings.   

    I wrote a couple of posts in the past with some workarounds to support data binding in some of the existing controls (TreeView and ContextMenu), which definitely were not something trivial to find and required investing many hours of research and testing to understand how the things worked under the hood. To give an example of how simple things can become really hard to accomplish with MVVM, I recently came across this thread about implementing MVVM in the Tab Control while trying to do the same on my side. Using a converter for binding a model to the control was not the answer I expected to hear, and sounded like a dirty hack to me. The same thing can be achieved in WPF with data templates, which is a more natural way to do things with this model.

    The only thing I can say is that MVVM works well for simple scenarios and common controls like a dropdown list, but you will probably find a hard time trying to use this pattern in Silverlight unless you know exactly what the limitations are and the different workarounds you can use.

    Read more...

  • Making your WCF Web Apis to speak in multiple languages

    One of the key aspects of how the web works today is content negotiation. The idea of content negotiation is based on the fact that a single resource can have multiple representations, so user agents (or clients) and servers can work together to chose one of them.

    The http specification defines several “Accept” headers that a client can use to negotiate content with a server, and among all those, there is one for restricting the set of natural languages that are preferred as a response to a request, “Accept-Language”. For example, a client can specify “es” in this header for specifying that he prefers to receive the content in spanish or “en” in english.

    However, there are certain scenarios where the “Accept-Language” header is just not enough, and you might want to have a way to pass the “accepted” language as part of the resource url as an extension. For example, http://localhost/ProductCatalog/Products/1.es” returns all the descriptions for the product with id “1” in spanish. This is useful for scenarios in which you want to embed the link somewhere, such a document, an email or a page. 

    Supporting both scenarios, the header and the url extension, is really simple in the new WCF programming model. You only need to provide a processor implementation for any of them.

    Let’s say I have a resource implementation as part of a product catalog I want to expose with the WCF web apis.

    [ServiceContract]
    [Export]
    public class ProductResource
    {
        IProductRepository repository;
     
        [ImportingConstructor]
        public ProductResource(IProductRepository repository)
        {
            this.repository = repository;
        }
     
        [WebGet(UriTemplate = "{id}")]
        public Product Get(string id, HttpResponseMessage response)
        {
            var product = repository.GetById(int.Parse(id));
            if (product == null)
            {
                response.StatusCode = HttpStatusCode.NotFound;
                response.Content = new StringContent(Messages.OrderNotFound);
            }
     
            return product;
        }
    }

    The Get method implementation in this resource assumes the desired culture will be attached to the current thread (Thread.CurrentThread.Culture). Another option is to pass the desired culture as an additional argument in the method, so my processor implementation will handle both options. This method is also using an auto-generated class for handling string resources, Messages, which is available in the different cultures that the service implementation supports. For example,

    Messages.resx contains “OrderNotFound”: “Order Not Found”

    Messages.es.resx contains “OrderNotFound”: “No se encontro orden”

    The processor implementation bellow tackles the first scenario, in which the desired language is passed as part of the “Accept-Language” header.

    public class CultureProcessor : Processor<HttpRequestMessage, CultureInfo>
    {
        string defaultLanguage = null;
     
        public CultureProcessor(string defaultLanguage = "en")
        {
            this.defaultLanguage = defaultLanguage;
            
            this.InArguments[0].Name = HttpPipelineFormatter.ArgumentHttpRequestMessage;
            this.OutArguments[0].Name = "culture";
        }
     
        public override ProcessorResult<CultureInfo> OnExecute(HttpRequestMessage request)
        {
            CultureInfo culture = null;
                        
            if (request.Headers.AcceptLanguage.Count > 0)
            {
                var language = request.Headers.AcceptLanguage.First().Value;
                culture = new CultureInfo(language);
            }
            else
            {
                culture = new CultureInfo(defaultLanguage);
            }
     
            Thread.CurrentThread.CurrentCulture = culture;
            Messages.Culture = culture;
     
            return new ProcessorResult<CultureInfo>
            {
                Output = culture
            };
        }
    }
     
    As you can see, the processor initializes a new CultureInfo instance with the value provided in the “Accept-Language” header, and set that instance to the current thread and the auto-generated resource class with all the messages. In addition, the CultureInfo instance is returned as an output argument called “culture”, making possible to receive that argument in any method implementation
     
    The following code shows the implementation of the processor for handling languages as url extensions.
     
    public class CultureExtensionProcessor : Processor<HttpRequestMessage, Uri>
    {
        public CultureExtensionProcessor()
        {
            this.OutArguments[0].Name = HttpPipelineFormatter.ArgumentUri;
        }
     
        public override ProcessorResult<Uri> OnExecute(HttpRequestMessage httpRequestMessage)
        {
            var requestUri = httpRequestMessage.RequestUri.OriginalString;
     
            var extensionPosition = requestUri.LastIndexOf(".");
     
            if (extensionPosition > -1)
            {
                var extension = requestUri.Substring(extensionPosition + 1);
     
                var query = httpRequestMessage.RequestUri.Query;
     
                requestUri = string.Format("{0}?{1}", requestUri.Substring(0, extensionPosition), query); ;
     
                var uri = new Uri(requestUri);
     
                httpRequestMessage.Headers.AcceptLanguage.Clear();
     
                httpRequestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(extension));
     
                var result = new ProcessorResult<Uri>();
     
                result.Output = uri;
     
                return result;
            }
     
            return new ProcessorResult<Uri>();
        }
    }

    The last step is to inject both processors as part of the service configuration as it is shown bellow,

    public void RegisterRequestProcessorsForOperation(HttpOperationDescription operation, IList<Processor> processors, MediaTypeProcessorMode mode)
    {
        processors.Insert(0, new CultureExtensionProcessor());
        processors.Add(new CultureProcessor());
    }

    Once you configured the two processors in the pipeline, your service will start speaking different languages :).

    Note: Url extensions don’t seem to be working in the current bits when you are using Url extensions in a base address. As far as I could see, ASP.NET intercepts the request first and tries to route the request to a registered ASP.NET Http Handler with that extension. For example, “http://localhost/ProductCatalog/products.es” does not work, but “http://localhost/ProductCatalog/products/1.es” does.

    Read more...