WinDays 2012 KeyNote Demo Step Through

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives


Few days ago I showed the Demo at WinDays 2012 keynote under the name “SharePoint Ralay”. The idea of the keynote was to show some important features which never have been shown or documented in the way as of very one common industry scenario. To keep things simple we didn’t go to deep into details of SharePoint and ServiceBus. We wanted to to build a demo which will show how to build few complex and enterprise relevant scenarios, but to be in the same time interesting for most developers in audience and even for journalists who have been attending the key note.
So I decided to target three common industrial issues which daenet has been asked to solve multiple times during 2011:

1. How to get (or put) SharePoint data out of enterprise without changing of infrastructure?
2. How to build dynamic WCF contract?
3. How to build Failover cluster in 48 Seconds?

1. How to get/put data out of SPS without changing of infrastructure?

Most SharePoint Developers live in their collaborative context which mostly does not require such scenarios. But when building SharePoint solutions you will figure out that SharePoint isn’t application platform in term how one solution or enterprise architect expect to be. Today, complex systems are systems which consist of usually distributed and hybrid hybrid applications.Distributed means they at least do not run in one process and hybrid means they can be build on top of different technologies.
So, imagine now one application which is build in .NET 4.5 which should run in SharePoint. To make it more simpler image a JAVA application which runs at different machine on different geographic location. Now put it in SharePoint and let talk to each other. Application Platform is the platform which enables to do such things. Any other application platform like SharePoint, CRM, BizTalk or anything else is a platform of their own definition with huge limitations. Because of that be careful, when you say platform. “One can be a boss in his village, but just some little peace in the global world”. The part of Microsoft which build such platforms is called Business Platform Division.

So, let’s get now some data out of SharePoint in context of  distributed application scenario. First of all in the world of distributed thinking, you should never allow external parties get in touch with your platform directly. To illustrate this constraint, think on giving the public access to your database. You will probably never allow somebody to send you DB-commands which will be executed against your DB (SQL Injections etc..). If you do it it is wrong and please think change it.. By following the same rule you shouldn’t let anybody to dig in your SharePoint platform for the same reason. You even should not share the secret, that you platform is SPS.

The easiest way is to provide some kind of intermediary component which will abstract the business scenario over secret platform which is running in the background. The technology which does exactly this job is WCF. We will put WCF service between SPS and external party. At some point of time when you have lot of such services, you can start to talk about Middle-Ware. This is a fine solution, but there is a still one practical problem.

The service contract could look in our case as shown below:

[ServiceContract(Name = "EchoContract", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
  public interface ISpsRelayService
  {
       [OperationContract]
      List<MyEntity> Query(QueryEntity query);
  }


You should define the QueryEntity which somehow describes what you want. SPS developer would like to to see here probably SPS- “ClientObjects”. Unfortinatelly they have never been designed for such scenarios. They can only be used by explicit helper libraries. Such libraries do not work out of SharePoint and their dependent entities are not serializable.
But never mind, define your entities like your business needs them (see service contract above).

The service implementation (see code below) will read the QueryEntity instance and build appropriate SPS-query (not shown in the demo below).
After all we will call SPS WebService hosted internally in our enterprise at http://yourhost:44445 and finally build response as collection of MyEntity instances.
This service decouples the SPS from external parties and provides very simple and business related contract as usual in the SOA world.
Following code snippet shows how to implement the service which gets documents from some SharePOint library and returns them as collection to the external party. In fact this is nothing very complicated (not yet)..


public List<MyEntitity> Query(QueryEntity query)
        {
            ClientContext clientContext = new ClientContext("http://yourhost:44445");

            Web oWebsite = clientContext.Web;
            var files = oWebsite.GetFolderByServerRelativeUrl("/Shared%20Documents").Files;
            clientContext.Load(files);
            clientContext.ExecuteQuery();

            List<MyEntitity> items = new List<MyEntitity>();

            foreach (var doc in files)
            {
                dynamic o = new MyEntitity();
                o.Name = doc.Name;
                o.Something = DateTime.Now.Ticks;
                o.Version = doc.UIVersionLabel;

                items.Add(o);
            }

            return items;
        }

To make it available in the internet this service needs to have a public endpoint accessible by the external party. And exactly this is the change demand in infrastructure which is very, very often an organizational issue or even “No go”. First somebody hast to give you an public IP address, then you need to configure NAT and DNS  for it, then Security, port mapping from probably 80 to 4445 etc., etc..
I want to build some kind of VPN between my WCF (talking to SPS) and external caller, but without changing any piece of infrastructure. The next picture shows this scenario. Windows Azure provides a platform service called “Service Bus”. This one provides a feature called relying. Relaying can connect two participants directly thorough firewall. Two participants are connected through Service Bus intermediary by using bidirectional TCP connection, which remains open after once is established.

image

Following code shows how to start-up the service which will listen on Service-Bus packets and relay SharePoint to external caller.

static void Main(string[] args)
      {
          ServicePointManager.ServerCertificateValidationCallback = validateServerCert;

           // create the service URI based on the service namespace which you will obtain when creating the
           // service bus namespace.
          Uri address = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespaceDomain, "SpsRelayService/DocumentLibrary");   

          // create the credential object for the endpoint
          TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();
          sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);

          // create the service host reading the configuration
          ServiceHost host = new ServiceHost(typeof(SpsRelayService), address);

          // create the ServiceRegistrySettings behavior for the endpoint
          IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings()
{ DisplayName = "Sharepoint Relay Document Library Service", DiscoveryMode = DiscoveryType.Public };
      
          foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
          {

               // add the Service Bus credentials to all endpoints specified in configuration
             endpoint.Behaviors.Add(sharedSecretServiceBusCredential);
 
             // Optionally you can add the URI in the registry.
             endpoint.Behaviors.Add(serviceRegistrySettings);
          }

          // Open the service
          host.Open();

          Console.ForegroundColor = ConsoleColor.Cyan;

          Console.WriteLine("Service address: " + address);
          Console.WriteLine("Press [Enter] to exit");
          Console.ReadLine();

          // close the service
          host.Close();
      }

Similarly, external party will also establish the connection as shown in the next snippet:

static void Main(string[] args)
       {
           ServicePointManager.ServerCertificateValidationCallback = validateServerCert;

           // create the service URI based on the service namespace
           Uri address = ServiceBusEnvironment.CreateServiceUri("https", serviceNamespaceDomain, "SpsRelayService/DocumentLibrary");

           // create the credential object for the endpoint
           TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();
           sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);

           // create the channel factory loading the configuration
           ChannelFactory<ISpsRelayService> channelFactory = new ChannelFactory<ISpsRelayService>("RelayEndpoint", new EndpointAddress(address));

           // apply the Service Bus credentials
           channelFactory.Endpoint.Behaviors.Add(/*swtBehavior*/sharedSecretServiceBusCredential);

           // create and open the client channel
           ISpsRelayService channel = channelFactory.CreateChannel();
      
           ((ICommunicationObject)channel).Open();

           Console.WriteLine("Enter text to echo (or [Enter] to exit):");
          
           string input = Console.ReadLine();
           
           List<MyEntity> res = channel.Query(new QueryEntity(){…});

            ((ICommunicationObject)channel).Close();

           channelFactory.Close();
       }

If you ever worked with WCF there is not much more to say. The code shown above contains a bit sugar around standard WCF.Everything else is a matter of channel which is hidden behind RelayBinding. For more information about ports in use take a look here.
Following binding must be configured in both service and client.

<bindings>
    <basicHttpRelayBinding>
      <binding name="myBinding">
        <security mode="Transport"/>
      </binding>
    </basicHttpRelayBinding>
  </bindings>
  

After you start service and then client,the client will send the request to service through firewall. The service will get data out of SPS and relay it back to the client.

2. How to build dynamic WCF contract?

In the world of SOA you always should build a clear contract between two boundaries. That means contracts like following one are not well designed:

Message Operation(Message msg);

I have also seen in some projects following variant of the similar contract, which is semantically the same one as previous one:

string Operation(string msg);

By using such contract the client has no way to know how to serialize the message. Even after the service version is changed, there is no way to communicate this to anybody instead of verbal human communication which is time intensive and error prone. Compare it with “add service reference” to create the proxy. The client and service must in such cases implement code which serializes/deserializes respectively the message (string).
In other words, using service contracted this way is called “Anti-Pattern”, which should not be used in the SOA world.

Many developers think they can build SOA solution if they are just able to build WCF based service. This is a mistake. When you use WCF it doesn’t mean at all that you are by default SOAP capable.  In our scenario I will use out this fact as my advantage. Connecting external party to our relay service is not SOA focused scenario. It is more about classical EAI and not SOA. Such kind of connecting system is known as interface with point-to-point connection. This is also not the best pattern in the world of SOA (I mean point2point interface).  and it should b e avoided when building middle-wares. But this is another story.
 
In other words, If you are connecting two systems as point2poin it might be valid to apply SOA anti-pattern.This is in context of SOA an anti-pattern, but not an anti-pattern in universe of possible solutions. If you have two parties talking to each other then you can often change the contract between them without of too much organizational difficulties.If you are changing often the contract (in our case MyEntity and MyQuery) it is easier to make it dynamic. In this case you can build it once without need to change it in the future, because it is dynamic one. Following example shows how to use ExpandoObject to build dynamic WCF contract. If you don’t know what this is take a look on Alexandra’s  and Rick’s posts.

ServiceContract(Name = "SpsRelayContract", Namespace = "http://daenet.deServiceModel/Relay/")]
  public interface ISpsRelayService
  {
     [OperationContract]
      List<ExpandoObject> Query(ExpandoObject expression);
  }

The good thing on Expando-contract is that you can do something like this:

dynamic o = new ExpandoObject();
               o.Name = “bla bla”;
               o.Something = DateTime.Now.Ticks;
               o.Method= new SomeDelegate(someMethod);

You can set on this object whatever property you want (more or less). But  note in a case of WCF the method instance as property wouldn’t make a sense, because that instance will not exist on some other process and some other machine. However all other properties can be set as you like. And WCF will serialize them automatically for you. In other words, if you have a new property you don’t have to change contract. You just set it like:

o.NewPropery = 17;

The consumer of this value just hast to know that is there (because,. remember, there is not clear contract, Add-Reference or SVCUTIL).

As a recap, note that ExpandoObject provides a dynamic contract. Build your Service on top of this entity and you will not have to change the contract when new properties are added in the business scenario, which service implements. Remember that this is not a SOA capable solution, but it is valid to build Point-To-Point scenarios when one party is connecting to another one.

3. How to build Failover cluster in 48 Seconds?

Last but not least I there is an issue which has been mostly forgotten in almost all our discussion when building relaying scenarios. I every project you will reach a point when the solution has to be deployed in the production. Then you will ask yourself how to build redundancy based on relying? This means, you want to provide a fail-over instance of you WCF relaying service which will be used when the first one is not reachable. The picture shown bellow illustrates this requirement.

image

To make this working you really do not have to change any peace of infrastructure. Just start the another instance of the service on another machine. That’s all. This will work by using both protocols TCP and HTTP. There are currently few undocumented differences in routing when using different protocols, nut in general both will provide you the stable and reliable fail-over mechanism.

Remark: If you are demoing this scenario with both WCF-instances on one machine, the basicHttpRelayBinding will not work with out-of-the-box configuration, because both instances will try to start listening for contract sharing at the same address. In a case of netTcpRelayBindig this will not happen. So, the latter one can be started multiple timas at one box.

 

Thanks to Tomislav Tipuric director of WinDays technical track who has visionary recognized the industry need for this scenario.


Posted May 12 2012, 01:54 PM by Damir Dobric
developers.de is a .Net Community Blog powered by daenet GmbH.