Archive

Posts Tagged ‘Exception Handling’

Getting something better than “Server not found.” from WCF in Silverlight redux

June 6, 2011 1 comment

I have had a lot of question lately about my blog post concerning “Server not found.” messages coming from WCF to Silverlight. I decided to create a quick post that provides a sample application that has everything wired up with some test buttons.

Here is a screen shot of the application:

Here is a screen shot with an error thrown from the server:

The application just has some buttons at the bottom of the screen that make calls to the service operations. Here is what the code looks like for the WCF service:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
using Web.Core;

namespace ServerExceptions.Web
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "BusinessService" in code, svc and config file together.
    [WcfErrorBehavior()]
    [WcfSilverlightFaultBehavior()]
    public class BusinessService : IBusinessService
    {
        public void RaiseException()
        {
            throw new Exception("Can't log in to the database.");
        }

        public string RaiseInvalidOperation()
        {
            throw new InvalidOperationException("You can't call this method!");
        }

        public void RaiseIndexOutOfRange()
        {
            throw new IndexOutOfRangeException();
        }

        public string GetCustomerName()
        {
            return "Matt Duffield";
        }

    };
}

This is a contrived example but the most important thing to note are the attributes above the service definition.

  • WcfErrorBehavior
  • WcfSilverlightFaultBehavior

It is these attributes that give us the ability to capture the error and send it back down the wire to the client. If you comment out the attributes and try any example that throws an error you will get our favorite message:

Here is what the calling code looks like after you have created a client side reference to the WCF service:

#region Button Click events

private void RaiseException_Click(object sender, RoutedEventArgs e)
{
    BusinessServiceClient client = new BusinessServiceClient();
    client.RaiseExceptionCompleted += (s, ea) =>
    {
        if (ea.Error != null)
        {
            Message = ea.Error.Message;
        }
        else
        {
            Message = "No exceptions.";
        }
    };
    client.RaiseExceptionAsync();
}

private void RaiseInvalidOperation_Click(object sender, RoutedEventArgs e)
{
    BusinessServiceClient client = new BusinessServiceClient();
    client.RaiseInvalidOperationCompleted += (s, ea) =>
    {
        if (ea.Error != null)
        {
            Message = ea.Error.Message;
        }
        else
        {
            Message = "No exceptions.";
        }
    };
    client.RaiseInvalidOperationAsync();
}

private void RaiseIndexOutOfRange_Click(object sender, RoutedEventArgs e)
{
    BusinessServiceClient client = new BusinessServiceClient();
    client.RaiseIndexOutOfRangeCompleted += (s, ea) =>
    {
        if (ea.Error != null)
        {
            Message = ea.Error.Message;
        }
        else
        {
            Message = "No exceptions.";
        }
    };
    client.RaiseIndexOutOfRangeAsync();
}

private void GetCustomerName_Click(object sender, RoutedEventArgs e)
{
    BusinessServiceClient client = new BusinessServiceClient();
    client.GetCustomerNameCompleted += (s, ea) =>
    {
        if (ea.Error != null)
        {
            Message = ea.Error.Message;
        }
        else
        {
            Message = ea.Result;
        }
    };
    client.GetCustomerNameAsync();
}

#endregion

The code is pretty simple and I am not going into the classes behind the attributes. Please refer to this post if you are interested in them. One thing I will point out is that the code that gives us the ability to send these error across the wire is in the Core folder. I did this so that you could pull this out and put it in it own assembly. That way you can use this for all of your projects and not need to write this code over and over.

On the server, you can have a lot of complex logic going on and use as many third parties as you want. I would simply wrap my service methods with a try/catch block and then return the friendly message I want displayed in my user interface.

You can download the sample application here.

Hope this helps….

Getting something better than “Server not found.” from WCF in Silverlight

April 6, 2011 3 comments

When developing applications in Silverlight it is inevitable that you will need to perform a request back to the server for data or processing. The common practice is to use Windows Communication Foundation (WCF). I find that WCF usually handles all of my needs and it works well when everything is happy and just right. However, if anything is not in its correct place, we can have tons of problems. Worse yet, we get your all time favorite message back in Silverlight stating:

“Server not found.”

Basically, WCF is telling us to go screw ourselves but in a much more politically correct way. Well there are several ways to attack this problem but I want to show you what I have come to love and use for all my projects involving WCF and Silverlight.

To give us some background, please review the following MSDN reference concerning Creating and Handling Faults in Silverlight. This article explains why we get our beloved message from WCF and what we can do about it. I think this is a must read for anybody wanting to understand what is going on and how they can go about fixing it themselves. I don’t think this is be the best solution but I do think it is a great reference. The reason for looking for something else is that I would like a solution that is a little easier to use and has less configuration required. I tend to follow this pattern because I have clients that want elegant solutions but they want it to be the least disruptive to their development process as possible.

Let’s move to the next blog post that I find very instrumental in dealing with exceptions in WCF. Oleg Sych wrote an excellent article, Simplifying WCF: Using Exceptions as Faults, back in 2008 that I believe is still very pertinent for us today. His solutions is very similar to the MSDN article that we already looked at but I believe it is more comprehensive and provides a good code base with which to use if you wanted to take his approach. I like what I read here but I still wanted something a little less intrusive from the perspective of ceremony and configuration.

This leads us to our last blog post. Here we find Jeroen Bernsen’s entry WCF ExceptionHandling in Silverlight. Like the other two articles, this post tries to solve the problem of dealing with exceptions thrown in WCF and how to get them back to the client in a friendly and easy way. If you read his post, you will see that you only need to create few objects to get our solution working and there is no need to modify your weg.config like in the other solutions. This is the reason why I like this solution the best.

I am going to provide the code below but you can also just follow along Jeroen’s post if you like.

The following class tells WCF to send fault messages with a 200 instead of a 500 response code. This change enables Silverlight to read the body of the message.

public class WcfSilverlightFaultBehavior : IDispatchMessageInspector
{
	public void BeforeSendReply(ref Message reply, object correlationState)
	{
		if (reply.IsFault)
		{
			HttpResponseMessageProperty property = new HttpResponseMessageProperty();

			// Here the response code is changed to 200.
			property.StatusCode = System.Net.HttpStatusCode.OK;

			reply.Properties[HttpResponseMessageProperty.Name] = property;
		}
	}

	public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
	{
		// Do nothing to the incoming message.
		return null;
	}
};

Next we have a sealed class that basically creates our attribute for using the previous class.

public sealed class WcfSilverlightFaultBehaviorAttribute : WcfBehaviorAttributeBase
{
	public WcfSilverlightFaultBehaviorAttribute()
		: base(typeof(WcfSilverlightFaultBehavior))
	{
	}
};

As you can see this is our attribute definition. We are deriving from a base class which we will review shortly.

The next class implements the IErrorHandler and allows us to handle WCF exceptions and package them in a way that we can still read on the client side.

public class WcfErrorBehavior : IErrorHandler
{

	void IErrorHandler.ProvideFault(Exception error, MessageVersion version, ref Message fault)
	{
		try
		{
			// Add code here to build faultreason for client based on exception
			FaultReason faultReason = new FaultReason(error.Message);
			ExceptionDetail exceptionDetail = new ExceptionDetail(error);

			// For security reasons you can also decide to not give the ExceptionDetail back
			// to the client or change the message, etc
			FaultException faultException =
				new FaultException(exceptionDetail, faultReason,
					FaultCode.CreateSenderFaultCode(new FaultCode("0")));

			MessageFault messageFault = faultException.CreateMessageFault();
			fault = Message.CreateMessage(version, messageFault, faultException.Action);
		}
		catch
		{
			// Todo log error
		}
	}

	///
	/// Handle all WCF Exceptions
	///
	bool IErrorHandler.HandleError(Exception ex)
	{
		try
		{
			// Add logging of exception here!
			Debug.WriteLine(ex.ToString());
		}
		catch
		{
			// Todo log error
		}

		// return true means we handled the error.
		return true;
	}

};

IErrorHandler has to methods that we must implement: ProvideFault and HandleError. You can read more on this interface here.

HandleError is just a boolean method that indicates whether or not a Fault message has already been generated (true) or for WCF to do its normal processing (false).

ProvideFault is a void method that allows us to package the fault exactly how we want to. This is very nice and gives us all the flexibility we need to customize or change how we wish to package our faults.

Next we have a sealed class that basically creates our attribute for using the previous class.

public sealed class WcfErrorBehaviorAttribute : WcfBehaviorAttributeBase
{
	public WcfErrorBehaviorAttribute()
		: base(typeof(WcfErrorBehavior))
	{
	}
};

As you can see this is our attribute definition. We are deriving from a base class which we will now review.

public abstract class WcfBehaviorAttributeBase : Attribute, IServiceBehavior
{
	private Type _behaviorType;

	///
	/// Constructor
	///
	/// <param name="typeBehavior" />IDispatchMessageInspector, IErrorHandler of IParameterInspector
	public WcfBehaviorAttributeBase(Type typeBehavior)
	{
		_behaviorType = typeBehavior;
	}

	void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription,
		System.ServiceModel.ServiceHostBase serviceHostBase,
		System.Collections.ObjectModel.Collection endpoints,
		System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
	{
	}

	void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription,
		System.ServiceModel.ServiceHostBase serviceHostBase)
	{
		object behavior;
		try
		{
			behavior = Activator.CreateInstance(_behaviorType);
		}
		catch (MissingMethodException e)
		{
			throw new ArgumentException("The Type specified in the BehaviorAttribute " +
				"constructor must have a public empty constructor.", e);
		}
		catch (InvalidCastException e)
		{
			throw new ArgumentException("The Type specified in the BehaviorAttribute " +
				"constructor must implement IDispatchMessageInspector, IParamaterInspector of IErrorHandler", e);
		}

		foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
		{
			if (behavior is IParameterInspector)
			{
				foreach (EndpointDispatcher epDisp in channelDispatcher.Endpoints)
				{
					foreach (DispatchOperation op in epDisp.DispatchRuntime.Operations)
						op.ParameterInspectors.Add((IParameterInspector)behavior);
				}
			}
			else if (behavior is IErrorHandler)
			{
				channelDispatcher.ErrorHandlers.Add((IErrorHandler)behavior);
			}
			else if (behavior is IDispatchMessageInspector)
			{
				foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
				{
					endpointDispatcher.DispatchRuntime.MessageInspectors.Add((IDispatchMessageInspector)behavior);
				}
			}
		}

	}

	void IServiceBehavior.Validate(ServiceDescription serviceDescription,
		System.ServiceModel.ServiceHostBase serviceHostBase)
	{
	}

};

As you can see in the code, this class derives from Attribute so that we can use it as an Attribute and also implements the IServiceBehavior interface. By implementing the IServiceBehavior interface, we no longer need to do any ceremony in the weg.config file. We have a single Type variable that allow us to be flexible from our classes that derive from us. As long as they pass in the type of behavior we handle the rest in the base class. IServiceBehavior has three methods: AddBindingParameters, ApplyDispatchBehavior, and Validate. You can read more on this interface here.

AddBindingParameter is used to pass to a binding element the custom information for the service so that it can support the service correctly.

ApplyDispatchBehavior is used to change run-time property values or insert custom extension objects.

Validate is used to examine the description and validate that the service can execute properly.

The method that we are interested in is the ApplyDispatchBehavior. First we try to create an instance of the underlying type that was passed in the constructor. Next we iterate over all of the ChannelDispatchers. Based on what type of behavior object we have, we determine what needs to happen in the current iteration of the ChannelDispatcher.

All of these classes will live on the server side and will need to be accessible from your WCF service.

Here is what you need to do to mark up your service:

[WcfErrorBehavior()]
[WcfSilverlightFaultBehavior()]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class TestService : ITestService
{
	public WcfErrorBehaviorAttribute()
		: base(typeof(WcfErrorBehavior))
	{
		public int DoSomething()
		{
			...
		}
	}
};

Congratulations, you are done! You can now have all of those nasty exceptions from WCF finally show up in your Silverlight client. Here is a sample screen shot of an exception thrown due to bad username and password to SQL Server before we apply the attributes:

Now with our attributes applied:

This makes all the difference! Hope this helps and again I want to stress that the credit of this blog goes to the articles that we previously mentioned.

Silverlight 4 Business Applications

February 27, 2010 Leave a comment

Over then next months, I will be posting about putting together an architecture for line of business applications.  First, I would like to break down the many components that would comprise building enterprise level applications.

Let’s first talk about cross-cutting concerns at a very high level:

  • Security – this would include authentication and authorization.  We will discuss permissions based authorization in order to support more than just screen level authorization but break it down to screen part and individual control level security.
    • Logging – this will provide global logging in a centralized manner.  Our goal will be to facilitate a flexible logging infrastructure without impacting any of modules that desire to log.  We should be able to change out the logging implementation whether it be a flat file, database, or rest service.
  • Exception Handling – this will provide a common means for receiving exceptions and notifying users of issues.  We will provide a mechanism to report exceptions and then allow for the developer to decide whether the end user should see the exception or just silently log to through the logging service.
  • Messaging – this service will be used throughout the other cross-cutting concerns.  It main purpose is to allow other modules to broadcast messages(events) without the need to have references to the other various modules.

We will go into each of these global services in more detail as dedicated posts.  Next we will take a look at one approach as to building a shell and module infrastructure to support the development of modular applications.  These posts will go into detail using both Prism and MEF (Managed Extensible Framework).

Stay tuned for more.