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

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

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….

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: