Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Friday, April 22, 2016

WCF - Getting Started

In this post we are going to learn the basic concepts of WCF and how to create a basic WCF Service.


What is WCF?

WCF or Windows Communication Foundations is a Microsoft platform for creating, building and deploying network-distributed services.


The ABC of Windows Communication Foundation

The "ABC" is the basic concept and also the key to understand the WCF endpoint.
  • "A" stands for Address: Where is the service?
  • "B" stands for Binding: How do I talk to the service?
  • "C" stands for Contract: What can the service do for me?


"ABC" means that creating a WCF service is a three-step process:
  • You define a contract and implement it on a service
  • You choose or define a service binding that selects a transport along with quality of service, security and other options
  • You deploy an endpoint for the contract by binding it (using the binding definition, hence the name) to a network address.


Create a WCF project

Before we start with the three-step process to create a WCF we need to create a WCF project.

When you create the project it will already have a Contract and a Service, but we will create new ones.
Delete the files IService1.cs and Service1.svc.
Now we are ready to through the three-step process.


Step #1 - Defining and Implementing Service Contracts

The Service Contract will define what operations the service supports. An operation is an action that can be executed by the service, if we compare it to the ASMX web services the operation is like the Web Service Method.
To define a Service Contract we need to create an interface and mark it with the ServiceContractAttribute attribute and the methods with the OperationContractAttribute attribute.
First let`s add a WCF Service to the project.


When you add a new WCF Service the visual studio will create a Service and also the Contract. First let`s change the contract. This is shown in the following code.


    [ServiceContract]
    public interface IOnlineDinnerService
    {
        [OperationContract]
        String OrderDinner(int comboNumber);
    }

Above, the interface is marked with the ServiceContractAttribute attribute and the method with the OperationContractAttribute attribute, as explained before it is a requirement to create a WCF Service.
Now let`s implement the interface in the Service. This is shown in the following code.


    public class OnlineDinnerService : IOnlineDinnerService
    {
 
        public String OrderDinner(int comboNumber)
        {
            return $"You have ordered the combo number {comboNumber}. Your Order Number is {new Random().Next(1, 100)}";
        }
    }

Above, we implemented the contract, now we already have our Contract and our Service created, but as you can notice our service operations just accept simple types. What if we want to use a complex type? For that we need to create the Data Contracts.


What are Data Contracts?

The Data Contract describes the data that will be exchanged between a service and a client.
The WCF uses an engine called Data Contract Serializer to serialize and deserialize data.
By default the primitive types and certain types as String and DateTime can be serialize with no proper preparation, but new complex types need to be prepared as a Data Contract. The following code show how to do it.

    [DataContract]
    public class DinnerCombo
    {
        [DataMember]
        public int ComboNumber { get; set; }
        [DataMember]
        public Decimal Price { get; set; }
        [DataMember]
        public String Name { get; set; }
    }
Now that we already have defined a DataContract we are ready to create an operation using it. To do it, first let`s add an operation to the Service Contract (IOnlineDinnerService). This is shown in the following code.

        [OperationContract]
        List<DinnerCombo> GetDinnerCombos();
Now let`s implement the new service operation in the Service. To do it, edit the OnlineDinnerService service as in the following code.

        public List<DinnerCombo> GetDinnerCombos()
        {
            return new List<DinnerCombo>()
            {
                new DinnerCombo {ComboNumber =1, Name="X-Burguer Combo", Price=6.99M },
                new DinnerCombo {ComboNumber =2, Name="Fried Chicken Combo", Price=7.99M },
                new DinnerCombo {ComboNumber =3, Name="Rosted Beef and Desert", Price=8.99M }
            };
        }

Step #2 - Configuring the binding

Bindings are used to specify the transport, encoding, and protocol details required for clients and services to communicate with each other. WCF uses bindings to generate the underlying wire representation of the endpoint, so most of the binding details must be agreed upon by the parties that are communicating.
The WCF by default offers a lot of different bindings, each binding has different types of security, transport or protocols. You can check all system-provided bindings on https://msdn.microsoft.com/en-us/library/ms730879(v=vs.110).aspx.
There are two ways to configure a binding, imperatively in code and declaratively using configuration.
In this example we will do it declaratively in the application`s web config file using the BasicHttpBinding.

  <system.serviceModel>
    <services>
      <service name="WCF.GettingStarted.OnlineDinnerService">
        <endpoint address="" binding="basicHttpBinding" contract="WCF.GettingStarted.IOnlineDinnerService"></endpoint>
        <endpoint address="/mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
      </service>
    </services>
     ...
  </system.serviceModel>
Above, we the service for our OnlineDinnerService and then we created 2 endpoints, the first one uses the basicHttpBinding to communicate with the service. The second one uses mexHttpBinding, this binding will enable the service to publish it`s metadata. Check the link https://msdn.microsoft.com/en-us/library/aa751951(v=vs.110).aspx for more details about publishing metadata.


Step #3 - Deploying and endpoint for the contract

In the Step #2 we defined the binding for the endpoint, in that same endpoint you can see the tag "contract", there we defined the contract for that endpoint.
Now our service has the OnlineDinnerService implementation and this service has an endpoint using the contract IOnlineDinnerService with the basicHttpBinding.


You can download the full from the github (https://github.com/rbercocano/WCF-Getting-Started).
Enjoy!

Sunday, April 17, 2016

WCF - Dependency Injection using Ninject

In this example we are going to create a simple WCF Service using Dependency Injection with Ninject.


Step #1 - Create a WCF Service Application project



Step #2 - Create an interface for your business class

This is shown in the following code.

namespace WCF.DependencyInjection
{
    public interface IDependencyInjectionApp
    {
        string GetData(int value);
    }

}

Step #3 - Implement the interface

Create a class that implements the interface created on the Step #2. This is shown in the following code.

namespace WCF.DependencyInjection

{
    public class DependencyInjectionApp : IDependencyInjectionApp
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }
    }

}


Step #4 - Install the Ninject package

Step #5 - Register the dependencies

Create a class to register the dependencies using the Ninject. This is shown in the following code.

using Ninject;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WCF.DependencyInjection

{
    public static class NinjectContainer
    {
        private static IKernel _kernel;
        static NinjectContainer()
        {
            _kernel = new StandardKernel();
            ConfigureContainer();

        }

        static void ConfigureContainer()
        {
            _kernel.Bind<IDependencyInjectionApp>().To<DependencyInjectionApp>();
        }
        public static object Resolve(Type service)
        {
            return _kernel.Get(service);
        }
    }

}


Step #6 - Create the instance provider

Now that the dependencies are registered we can create a custom instance provider.To create a custom instance provider, create a class that implements IInstanceProvider. This is shown in the following code.

using System;

using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Web;

namespace WCF.DependencyInjection

{
    public class DependencyInjectionInstanceProvider : IInstanceProvider
    {
        private readonly Type _serviceType;

        /// <summary>

        /// Initializes a new instance of the <see cref="DependencyInjectionInstanceProvider"/> class.
        /// </summary>
        /// <param name="serviceType">Type of the service.</param>
        public DependencyInjectionInstanceProvider(Type serviceType)
        {
            _serviceType = serviceType;
        }

        /// <summary>

        /// Returns a service object given the specified <see cref="T:System.ServiceModel.InstanceContext"/> object.
        /// </summary>
        /// <param name="instanceContext">The current <see cref="T:System.ServiceModel.InstanceContext"/> object.</param>
        /// <returns>A user-defined service object.</returns>
        public object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }

        /// <summary>

        /// Returns a service object given the specified <see cref="T:System.ServiceModel.InstanceContext"/> object.
        /// </summary>
        /// <param name="instanceContext">The current <see cref="T:System.ServiceModel.InstanceContext"/> object.</param>
        /// <param name="message">The message that triggered the creation of a service object.</param>
        /// <returns>The service object.</returns>
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return NinjectContainer.Resolve(_serviceType);
        }

        /// <summary>

        /// Called when an <see cref="T:System.ServiceModel.InstanceContext"/> object recycles a service object.
        /// </summary>
        /// <param name="instanceContext">The service's instance context.</param>
        /// <param name="instance">The service object to be recycled.</param>
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }



}


Step #7 - Create the service behavior.

The next step is to create a service behavior that registers the instance provider. This is shown in the following code.

using System;

using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using WCF.DependencyInjection;
/// <summary>
/// A custom service behavior which will register the dependency injection instance provider.
/// </summary>
public class DependencyInjectionServiceBehavior : Attribute, IServiceBehavior
{
    #region IServiceBehavior Members

    /// <summary>

    /// Provides the ability to pass custom data to binding elements to support the contract implementation.
    /// </summary>
    /// <param name="serviceDescription">The service description of the service.</param>
    /// <param name="serviceHostBase">The host of the service.</param>
    /// <param name="endpoints">The service endpoints.</param>
    /// <param name="bindingParameters">Custom objects to which binding elements have access.</param>
    public void AddBindingParameters(ServiceDescription serviceDescription,
        System.ServiceModel.ServiceHostBase serviceHostBase,
        System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
        System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    { }

    /// <summary>

    /// Provides the ability to change run-time property values or insert custom extension objects such as error handlers, message or parameter interceptors, security extensions, and other custom extension objects.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param>
    /// <param name="serviceHostBase">The host that is currently being built.</param>
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
        foreach (var cdb in serviceHostBase.ChannelDispatchers)
        {
            var cd = cdb as ChannelDispatcher;

            if (cd != null)

            {
                foreach (var ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider = new DependencyInjectionInstanceProvider(serviceDescription.ServiceType);
                }
            }
        }
    }

    /// <summary>

    /// Provides the ability to inspect the service host and the service description to confirm that the service can run successfully.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param>
    /// <param name="serviceHostBase">The service host that is currently being constructed.</param>
    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    { }

    #endregion

}

Step #8 - Add the behavior to the service

Now that we have the instances registered and the behavior created we just need  add the behavior to your service and set the parameters in the service constructor. This is shown in the following code.



namespace WCF.DependencyInjection

{

    [DependencyInjectionServiceBehavior]

    public class DependencyInjectionService : IDependencyInjectionService

    {

        private readonly IDependencyInjectionApp _iApp;
        public DependencyInjectionService(IDependencyInjectionApp iApp)
        {
            _iApp = iApp;
        }
        public string GetData(int value)
        {
            return _iApp.GetData(value);
        }
    }
}

The behavior will resolve all the instances that the service needs and pass these instances to the contructor as parameters, but remember, you need to register the instances as we did in the Step #5.

The full example can be downloaded here. Enjoy!

Microservices – Creating Resilient Services

Dealing with unexpected failures is one of the hardest problems to solve, especially in a distributed system . A microservice needs to...