Freigeben über


Avoiding Address Filters

The address filter mode that we looked at last time solved the problem of funneling all of the messages with a given prefix address to our service instance. Changing the filter mode still left us with the problem of dispatching from that universal contract to all of the logical operations that live inside the address space. This is exactly the problem that UriTemplate solves. By combining templates and WebServiceHost, both of the problems get taken care of for us.

Here is an equivalent contract and service implementation with some more semantics filled in for a particular application. All I've done is pick out part of the address space that I want to assign some implementation to.

 [ServiceContract]
public interface IService2
{
   [OperationContract]
   [WebGet(UriTemplate = "/resource/{index}")]
   string Get(string index);

   [OperationContract]
   [WebInvoke(UriTemplate = "/resource")]
   void Add(string value);
}

public class Service2 : IService2
{
   public string Get(string index)
   {
      Console.WriteLine("Get {0} {1}", WebOperationContext.Current.IncomingRequest.Method,
         OperationContext.Current.IncomingMessageHeaders.To);
      return null;
   }

   public void Add(string value)
   {
      Console.WriteLine("Add {0} {1}", WebOperationContext.Current.IncomingRequest.Method,
         OperationContext.Current.IncomingMessageHeaders.To);
   }
}

Hosting this service is basically the same. I can take out the endpoint definition because that gets inferred automatically.

 WebServiceHost host = new WebServiceHost(typeof(Service2), new Uri("localhost:8000/"));
host.Open();
Client();
Console.ReadLine();
host.Close();

Finally, I can use the exact same client code as last time even though in the service I've changed my way of writing the service from a centralized approach to an address-based approach.

 ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(new WebHttpBinding());
factory.Open();
IRequestChannel proxy = factory.CreateChannel(new EndpointAddress("localhost:8000/"));
using (new OperationContextScope((IContextChannel)proxy))
{
   Message request = Message.CreateMessage(MessageVersion.None, string.Empty, "data");
   request.Headers.To = new Uri("localhost:8000/resource");
   WebOperationContext.Current.OutgoingRequest.Method = "POST";
   proxy.Request(request);
}
using (new OperationContextScope((IContextChannel)proxy))
{
   Message request = Message.CreateMessage(MessageVersion.None, string.Empty);
   request.Headers.To = new Uri("localhost:8000/resource/1");
   WebOperationContext.Current.OutgoingRequest.Method = "GET";
   WebOperationContext.Current.OutgoingRequest.SuppressEntityBody = true;
   proxy.Request(request);
}

Next time: System Types in Metadata