Wednesday 4 April 2012

Wcf REST and IErrorHanlder:-

The interface comes with two methods.

ProvideFault allows you to handle the error and determine what is returned to the client.
HandleError method is called after the call has already completed, to possibly log the error.

If you use wcf starter kit it doesn’t work.A little work around  will solve the problem.

->Create wcf REST service.

    [ServiceContract]
    public class Service
    {
        [OperationContract]
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        public string SayHello(string name)
        {
            int i = 0;
            int j = 1;
            int k = j / i;

            return "Hello " + name;
        }
    }
    [DataContract]
    public class CustomException
    {
        [DataMember]
        public string Description { getset; }
    }

->Create ErrorHandler class and inherit it from IErrorHandler and implement HandleError and ProvideFault methods.

public class ErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            //Log error here.
            return true;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            //Create error object .
            CustomException objCustomException = new CustomException();
            objCustomException.Description = error.Message;

            //Construct error message here.
            fault = Message.CreateMessage(version, "", objCustomException, new DataContractJsonSerializer(typeof(CustomException)));

            HttpResponseMessageProperty responseMessageProperty = new HttpResponseMessageProperty();

            //Set the status code here.
            responseMessageProperty.StatusCode = HttpStatusCode.InternalServerError;

            //Set the content type to json.
            responseMessageProperty.Headers[HttpResponseHeader.ContentType] = "application/json";

            fault.Properties[HttpResponseMessageProperty.Name] = responseMessageProperty;

            WebBodyFormatMessageProperty formatMessageProperty = new WebBodyFormatMessageProperty(WebContentFormat.Json);
            fault.Properties[WebBodyFormatMessageProperty.Name] = formatMessageProperty;
        }
    }
->Create Behavior Class and inherit it from WebHttpBehavior2.
public class Behavior : WebHttpBehavior2
    {
        protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            //Add error handler.
            endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new ErrorHandler());
        }
    }
->Create Host class and inherit it from WebServiceHost2 and override OnOpening method.
public class Host : WebServiceHost2
    {
        public Host(Type serviceType, bool dummy, params Uri[] baseAddresses)
            : base(serviceType, dummy, baseAddresses)
        {

        }

        protected override void OnOpening()
        {
            //Call base class OnOpening method.
            base.OnOpening();

            //Get the description of the service hosted.
            if (base.Description != null)
            {
                //Get the endpoints.
                foreach (var endpoint in base.Description.Endpoints)
                {
                    //Remove the WebHttpBehavior2(If you use wcfREST starter kit it automatically added to the service).
                    endpoint.Behaviors.Remove<WebHttpBehavior2>();
                   
                    //Get our custom behavior.
                    var item = new Behavior();

                    //Add the bahavior to endpoint.
                    endpoint.Behaviors.Add(item);
                }
            }
        }
    }

->Now open ServiceHost.svc file and add our custom factory class.

<%@ ServiceHost Language="C#" Debug="true" Service="WcfRESTIErrorHanlder.Service"
    CodeBehind="Service.svc.cs" Factory="WcfRESTIErrorHanlder.HostFactory" %>

using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using Microsoft.ServiceModel.Web;

namespace WcfRESTIErrorHanlder
{
    public class HostFactory : WebServiceHost2Factory
    {
        protected override ServiceHost CreateServiceHost(System.Type serviceType, System.Uri[] baseAddresses)
        {
            //Create host object.
            Host objHost = new Host(serviceType, true, baseAddresses);

            //Return host.
            return objHost;
        }
    }
}
Let me know, if you have any feedback. Mail me for source code. Enjoy reading my articles…
sekhartechblog@gmail.com

No comments:

Post a Comment