May 2010 - Posts

The repository implementation I am going to discuss here is not exactly what someone would call repository in terms of DDD, but it is an abstraction layer that becomes handy at the moment of unit testing the code around this repository. In other words, you can easily create a mock to replace the real repository implementation.

The WCF Data Services update for .NET 3.5 introduced a nice feature to support two way data bindings, which is very helpful for developing WPF or Silverlight based application but also for implementing the repository I am going to talk about. As part of this feature, the WCF Data Services Client library introduced a new collection DataServiceCollection<T> that implements INotifyPropertyChanged to notify the data context (DataServiceContext) about any change in the association links. This means that it is not longer necessary to manually set or remove the links in the data context when an item is added or removed from a collection.

Before having this new collection, you basically used the following code to add a new item to a collection.

Order order = new Order
{
  Name = "Foo"
};

OrderItem item = new OrderItem
{
  Name = "bar",
  UnitPrice = 10,
  Qty = 1
};

var context = new OrderContext();
context.AddToOrders(order);
context.AddToOrderItems(item);

context.SetLink(item, "Order", order);

context.SaveChanges();

Now, thanks to this new collection, everything is much simpler and similar to what you have in other ORMs like Entity Framework or L2S.

Order order = new Order
{
  Name = "Foo"
};

OrderItem item = new OrderItem
{
  Name = "bar",
  UnitPrice = 10,
  Qty = 1
};

order.Items.Add(item);

var context = new OrderContext();
context.AddToOrders(order);

context.SaveChanges();

In order to use this new feature, you first need to enable V2 in the data service, and then use some specific arguments in the datasvcutil tool (You can find more information about this new feature and how to use it in this post).

DataSvcUtil /uri:"http://localhost:3655/MyDataService.svc/" /out:Reference.cs /dataservicecollection /version:2.0

Once you use those two arguments, the generated proxy classes will use DataServiceCollection<T> rather than a simple ObjectCollection<T>, which was the default collection in V1.

There are some aspects that you need to know to use this feature correctly.

1. All the entities retrieved directly from the data context with a query track the changes and report those to the data context automatically.

2. A entity created with “new” does not track any change in the properties or associations. In order to enable change tracking in this entity, you need to do the following trick.

public Order CreateOrder()
{
  var collection = new DataServiceCollection<Order>(this.context);
  var order = new Order();

  collection.Add(order);

  return order;
}

You basically need to create a collection, and add the entity to that collection with the “Add” method to enable change tracking on that entity.

3. If you need to attach an existing entity (For example, if you created the entity with the “new” operator rather than retrieving it from the data context with a query) to a data context for tracking changes, you can use the “Load” method in the DataServiceCollection.

var order = new Order
{
  Id = 1
};

var collection = new DataServiceCollection<Order>(this.context);
collection.Load(order);

In this case, the order with Id = 1 must exist on the data source exposed by the Data service. Otherwise, you will get an error because the entity did not exist.

These cool extensions methods discussed by Stuart Leeks in this post to replace all the magic strings in the “Expand” operation with Expression Trees represent another feature I am going to use to implement this generic repository.

Thanks to these extension methods, you could replace the following query with magic strings by a piece of code that only uses expressions.

Magic strings,

var customers = dataContext.Customers
.Expand("Orders")
        .Expand("Orders/Items")

Expressions,

var customers = dataContext.Customers
.Expand(c => c.Orders.SubExpand(o => o.Items))

That query basically returns all the customers with their orders and order items.

Ok, now that we have the automatic change tracking support and the expression support for explicitly loading entity associations, we are ready to create the repository.

The interface for this repository looks like this,

public interface IRepository
{
  T Create<T>() where T : new();
  void Update<T>(T entity);
  void Delete<T>(T entity);
  IQueryable<T> RetrieveAll<T>(params Expression<Func<T, object>>[] eagerProperties);
  IQueryable<T> Retrieve<T>(Expression<Func<T, bool>> predicate, 
params Expression<Func<T, object>>[] eagerProperties);
  void Attach<T>(T entity);
  void SaveChanges();
}

The Retrieve and RetrieveAll methods are used to execute queries against the data service context. While both methods receive an array of expressions to load associations explicitly, only the Retrieve method receives a predicate representing the “where” clause.

The following code represents the final implementation of this repository.

public class DataServiceRepository: IRepository
{
  ResourceRepositoryContext context;

  public DataServiceRepository()
      : this (new DataServiceContext())
  {
  }

  public DataServiceRepository(DataServiceContext context)
  {
            this.context = context;
  }

  private static string ResolveEntitySet(Type type)
  {
    var entitySetAttribute = (EntitySetAttribute)type
.GetCustomAttributes(typeof(EntitySetAttribute), true).FirstOrDefault();

   if (entitySetAttribute != null)
      return entitySetAttribute.EntitySet;

   return null;
  }

  public T Create<T>() where T : new()
  {
    var collection = new DataServiceCollection<T>(this.context);
    var entity = new T();

    collection.Add(entity);

    return entity;
  }

  public void Update<T>(T entity)
  {
    this.context.UpdateObject(entity);
  }

  public void Delete<T>(T entity)
  {
    this.context.DeleteObject(entity);
  }

  public void Attach<T>(T entity)
  {
    var collection = new DataServiceCollection<T>(this.context);
    collection.Load(entity);
  }

  public IQueryable<T> Retrieve<T>(Expression<Func<T, bool>> predicate, 
  params Expression<Func<T, object>>[] eagerProperties)
  {
    var entitySet = ResolveEntitySet(typeof(T));
    var query = context.CreateQuery<T>(entitySet);

    foreach (var e in eagerProperties)
    {
      query = query.Expand(e);
    }

    return query.Where(predicate);
  }

  public IQueryable<T> RetrieveAll<T>(params Expression<Func<T, object>>[] eagerProperties)
  {
    var entitySet = ResolveEntitySet(typeof(T));
    var query = context.CreateQuery<T>(entitySet);

    foreach (var e in eagerProperties)
    {
      query = query.Expand(e);
    }

    return query;
  }

  public void SaveChanges()
  {
    this.context.SaveChanges(SaveChangesOptions.Batch);
  }

 }

For instance, you can use the following code to retrieve customers with First name equal to “John”, and all their orders in a single call.

repository.Retrieve<Customer>(
   c => c.FirstName == “John”, //Where
   c => c.Orders.SubExpand(o => o.Items));

In case, you want to have some pre-defined queries that you are going to use across several places, you can put them in an specific class.

public static class CustomerQueries
{
  public static Expression<Func<Customer, bool>> LastNameEqualsTo(string lastName)
  {
    return c => c.LastName == lastName;
  }
}

And then, use it with the repository.

repository.Retrieve<Customer>(
   CustomerQueries.LastNameEqualsTo("foo"),
   c => c.Orders.SubExpand(o => o.Items));

Posted by cibrax | 3 comment(s)

It is very important for the enterprise to know which services are operational at any given point. There are many factors that can affect the availability of the services, some of them are external like a database not responding or any dependant service not working. However, in some cases, you only want to know whether a service is up or down, so a simple heart-beat mechanism with “Ping” messages would do the trick. Unfortunately, WCF does not provide a built-in mechanism to support this functionality, and you probably don’t to implement a “Ping” operation in any service that you have out there. For solving this in a generic way, there is a WCF extensibility point that comes to help us, the “Operation Invokers”. In a nutshell, an operation invoker is the class responsible invoking the service method with a set of parameters and generate the output parameters with the return value.

What I am going to do here is to implement a custom operation invoker that intercepts any call to the service, and detects whether a “Ping” header was attached to the message. If the “Ping” header is detected, the operation invoker returns a new header to tell the client that the service is alive, and the real operation execution is omitted. In that way, we have a simple heart beat mechanism based on the messages that include a "Ping” header, so the client application can determine at any point whether the service is up or down.

My operation invoker wraps the default implementation attached by default to any operation by WCF.

internal class PingOperationInvoker : IOperationInvoker
{
  IOperationInvoker innerInvoker;
  object[] outputs = null;
  object returnValue = null;

  public const string PingHeaderName = "Ping";
  public const string PingHeaderNamespace = "http://tellago.serviceModel";

  public PingOperationInvoker(IOperationInvoker innerInvoker, OperationDescription description)
  {
    this.innerInvoker = innerInvoker;
    outputs = description.SyncMethod.GetParameters()
          .Where(p => p.IsOut)
          .Select(p => DefaultForType(p.ParameterType)).ToArray();

    var returnValue = DefaultForType(description.SyncMethod.ReturnType);
  }

  private static object DefaultForType(Type targetType)
  {
    return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
  }
        
  public object Invoke(object instance, object[] inputs, out object[] outputs)
  {
    object returnValue;

    if (Invoke(out returnValue, out outputs))
    {
      return returnValue;
    }
    else
    {
      return this.innerInvoker.Invoke(instance, inputs, out outputs);
    }
  }

  private bool Invoke(out object returnValue, out object[] outputs)
  {
    object untypedProperty = null;
    if (OperationContext.Current
.IncomingMessageProperties.TryGetValue(HttpRequestMessageProperty.Name, out untypedProperty))
    {
      var httpRequestProperty = untypedProperty as HttpRequestMessageProperty;
      if (httpRequestProperty != null)
      {
        if (httpRequestProperty.Headers[PingHeaderName] != null)
        {
          outputs = this.outputs;

          if (OperationContext.Current
.IncomingMessageProperties.TryGetValue(HttpRequestMessageProperty.Name, out untypedProperty))
          {
             var httpResponseProperty = untypedProperty as HttpResponseMessageProperty;

             httpResponseProperty.Headers.Add(PingHeaderName, "Ok");
          }

          returnValue = this.returnValue;

          return true;
       }
    }
   }           

   var headers = OperationContext.Current.IncomingMessageHeaders;
   if (headers.FindHeader(PingHeaderName, PingHeaderNamespace) > -1)
   {
     outputs = this.outputs;

     MessageHeader<string> header = new MessageHeader<string>("Ok");
     var untyped = header.GetUntypedHeader(PingHeaderName, PingHeaderNamespace);

     OperationContext.Current.OutgoingMessageHeaders.Add(untyped);

     returnValue = this.returnValue;

     return true;
   }            

   returnValue = null;
   outputs = null;

   return false;
 }
}

The implementation above looks for the “Ping” header either in the Http Request or the Soap message.
The next step is to implement a behavior for attaching this operation invoker to the services we want to monitor.

[AttributeUsage(AttributeTargets.Method 
  | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
 public class PingBehavior : Attribute, IServiceBehavior, IOperationBehavior
 {
   public void AddBindingParameters(ServiceDescription serviceDescription, 
       ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, 
       BindingParameterCollection bindingParameters)
   {
   }

   public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
        ServiceHostBase serviceHostBase)
   {
   }

   public void Validate(ServiceDescription serviceDescription, 
        ServiceHostBase serviceHostBase)
   {
     foreach (var endpoint in serviceDescription.Endpoints)
     {
       foreach (var operation in endpoint.Contract.Operations)
       {
         if (operation.Behaviors.Find<PingBehavior>() == null)
              operation.Behaviors.Add(this);
       }
     }
   }

   public void AddBindingParameters(OperationDescription operationDescription, 
        BindingParameterCollection bindingParameters)
   {
   }

   public void ApplyClientBehavior(OperationDescription operationDescription, 
          ClientOperation clientOperation)
   {
   }

   public void ApplyDispatchBehavior(OperationDescription operationDescription, 
        DispatchOperation dispatchOperation)
   {
      dispatchOperation.Invoker = 
          new PingOperationInvoker(dispatchOperation.Invoker, operationDescription);
   }

   public void Validate(OperationDescription operationDescription)
   {

   }
 }

As an operation invoker can only be added in an “operation behavior”, a trick I learned in the past is that you can implement a service behavior as well and use the “Validate” method to inject it in all the operations, so the final configuration is much easier and cleaner. You only need to decorate the service with a simple attribute to enable the “Ping” functionality.

[PingBehavior]
public class HelloWorldService : IHelloWorld
{
  public string Hello(string name)
  {
    return "Hello " + name;
  }
}

On the other hand, the client application needs to send a dummy message with a “Ping” header to detect whether the service is available or not. In order to simplify this task, I created a extension method in the WCF client channel to do this work.

public static class ClientChannelExtensions
{
  const string PingNamespace = "http://tellago.serviceModel";
  const string PingName = "Ping";

  public static bool IsAvailable<TChannel>(this IClientChannel channel, 
       Action<TChannel> operation)
  {
    try
    {
      using (OperationContextScope scope = new OperationContextScope(channel))
      {
        MessageHeader<string> header = new MessageHeader<string>(PingName);
        var untyped = header.GetUntypedHeader(PingName, PingNamespace);
        OperationContext.Current.OutgoingMessageHeaders.Add(untyped);

        try
        {
          operation((TChannel)channel);
          var headers = OperationContext.Current.IncomingMessageHeaders;
          if (headers.Any(h => h.Name == PingName && h.Namespace == PingNamespace))
          {
            return true;
          }
          else
          {
            return false;
          }
        }
        catch (CommunicationException)
        {
          return false;
        }
       }
     }
     catch (Exception)
     {
       return false;
     }
   }
  }

This extension method basically adds a “Ping” header to the request message, executes the operation passed as argument (Action<TChannel> operation), and looks for the corresponding “Ping” header in the response to see the results.

The client application can use this extension with a single line of code,

var client = new ServiceReference.HelloWorldClient();
var isAvailable = client.InnerChannel.IsAvailable<IHelloWorld>((c) => c.Hello(null));

The “isAvailable” variable will tell the client application whether the service is available or not.

You can download the complete implementation from this location.

 

 

Posted by cibrax | 1 comment(s)
Filed under: ,

The need of loading WCF bindings or behaviors from different sources such as files in a disk or databases is a common requirement when dealing with configuration either on the client side or the service side.

The traditional way to accomplish this in WCF is loading everything from the standard configuration section (serviceModel section) or creating all the bindings and behaviors by hand in code. However, there is a solution in the middle that becomes handy when more flexibility is needed. This solution involves getting the configuration from any place, and use that configuration to automatically configure any existing binding or behavior instance created with code. 

In order to configure a binding instance (System.ServiceModel.Channels.Binding) that you later inject in any endpoint on the client channel or the service host, you first need to get a binding configuration section from any configuration file (you can generate a temp file on the fly if you are using any other source for storing the configuration).

 

private BindingsSection GetBindingsSection(string path)
{
  System.Configuration.Configuration config = 
System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(
    new System.Configuration.ExeConfigurationFileMap() { ExeConfigFilename = path },
      System.Configuration.ConfigurationUserLevel.None);

  var serviceModel = ServiceModelSectionGroup.GetSectionGroup(config);
  return serviceModel.Bindings;
}

 

The BindingsSection contains a list of all the configured bindings in the serviceModel configuration section, so you can iterate through all the configured binding that get the one you need (You don’t need to have a complete serviceModel section, a section with the bindings only works).

 

public Binding ResolveBinding(string name)
{
  BindingsSection section = GetBindingsSection(path);

  foreach (var bindingCollection in section.BindingCollections)
  {
    if (bindingCollection.ConfiguredBindings.Count > 0 
&& bindingCollection.ConfiguredBindings[0].Name == name)
    {
      var bindingElement = bindingCollection.ConfiguredBindings[0];
      var binding = (Binding)Activator.CreateInstance(bindingCollection.BindingType);
      binding.Name = bindingElement.Name;
      bindingElement.ApplyConfiguration(binding);

      return binding;
    }
  }

  return null;
}

 

The code above does just that, and also instantiates and configures the Binding object (System.ServiceModel.Channels.Binding) you are looking for. As you can see, the binding configuration element contains a method “ApplyConfiguration” that receives the binding instance that needs to be configured.

A similar thing can be done for instance with the “Endpoint” behaviors. You first get the BehaviorsSection, and then, the behavior you want to use.

 

private BehaviorsSection GetBehaviorsSection(string path)
{
  System.Configuration.Configuration config = 
System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(
       new System.Configuration.ExeConfigurationFileMap() { ExeConfigFilename = path },
          System.Configuration.ConfigurationUserLevel.None);

  var serviceModel = ServiceModelSectionGroup.GetSectionGroup(config);
  return serviceModel.Behaviors;

}
public List<IEndpointBehavior> ResolveEndpointBehavior(string name)
{
  BehaviorsSection section = GetBehaviorsSection(path);
  List<IEndpointBehavior> endpointBehaviors = new List<IEndpointBehavior>();

  if (section.EndpointBehaviors.Count > 0 
&& section.EndpointBehaviors[0].Name == name)
  {
    var behaviorCollectionElement = section.EndpointBehaviors[0];

    foreach (BehaviorExtensionElement behaviorExtension in behaviorCollectionElement)
    {
      object extension = behaviorExtension.GetType().InvokeMember("CreateBehavior",
            BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
            null, behaviorExtension, null);

      endpointBehaviors.Add((IEndpointBehavior)extension);
    }

   return endpointBehaviors;
 }

 return null;
}

 

In this case, the code for creating the behavior instance is more tricky. First of all, a behavior in the configuration section actually represents a set of “IEndpoint” behaviors, and the behavior element you get from the configuration does not have any public method to configure an existing behavior instance. This last one only contains a protected method “CreateBehavior” that you can use for that purpose.

Once you get this code implemented, a client channel can be easily configured as follows

 

var binding = resolver.ResolveBinding("MyBinding");
var behaviors = resolver.ResolveEndpointBehavior("MyBehavior");

SampleServiceClient client = new SampleServiceClient(binding, 
       new EndpointAddress(new Uri("http://localhost:13749/SampleService.svc"),
       new DnsEndpointIdentity("localhost")));
            
foreach (var behavior in behaviors)
{
   if(client.Endpoint.Behaviors.Contains(behavior.GetType()))
   {
     client.Endpoint.Behaviors.Remove(behavior.GetType());
   }
   client.Endpoint.Behaviors.Add(behavior);
}

 

The code above assumes that a configuration file (in any place) with a binding “MyBinding” and a behavior “MyBehavior” exists. That file can look like this,

 

<system.serviceModel>
   <bindings>
     <basicHttpBinding>
       <binding name="MyBinding">
         <security mode="Transport"></security>
       </binding>
     </basicHttpBinding>
   </bindings>
   <behaviors>
     <endpointBehaviors>
       <behavior name="MyBehavior">
         <clientCredentials>
           <windows/>
         </clientCredentials>
       </behavior>
     </endpointBehaviors>
   </behaviors>
 </system.serviceModel>

 

The same thing can be done of course in the service host if you want to manually configure the bindings and behaviors.

 

Posted by cibrax | 3 comment(s)
Filed under: ,
More Posts