May 2009

.NetTiers Component Business Layer Architecture

I posted a blog on my blog site that takes a look at the Patterns used in the .NetTier Service Layer Architecture.  Check it out at …

http://www.stanfordkennedy.com/2009/05/nettiers-architecture-design-patterns.html

~Stan Kennedy

General

Comments (0)

Permalink

Writing ASP.NET MVC Applications on MacOS X?

Interesting news today, there’s a new build of MonoDevelop that works with MacOS X.  MonoDevelop is a fully functional IDE for writing apps in Mono, a cross platform .NET library.

 

image

 

Follow the link for more info: http://tirania.org/blog/archive/2009/May-05-1.html

.NET Framework
Mono

Comments (0)

Permalink

Recover from a WCF Service Fault, Part 2 (Generic ServiceClientFactory Class)

After finding the simple solution for handling WCF Service Faults in the original post, I figured it should be relatively trivial to find a generic solution to this problem if you’re using similar WCF clients in a project and want to reset ALL of them on a channel fault.  I developed a generic ServiceClientFactory class that will generate a WCF Service Client instance from a generic “GetClient” function and will automatically handle resetting of faulted channels.

Class Implementation Source Code:

/* Service Client Factory
 * Author: Michael Gerety, Senior Consultant, Tallan, Inc.
 * Description: A generic service client factory that automatically
 *              resets faulted channels for WCF services that have
 *              endpoints and behaviors defined in web/app.config files.
 */             

using System;
using System.Collections.Generic;
using System.ServiceModel;
namespace Tallan
{
    /// <summary>
    /// Singleton factory class for WCF Services.
    /// Creates service clients based on interface type and automatically
    /// resets faulted channels.
    /// </summary>
    public class ServiceClientFactory
    {
        private readonly Dictionary<Type, object> factories;
        private static ServiceClientFactory instance;

        private ServiceClientFactory()
        {
            factories = new Dictionary<Type, object>();
        }

        /// <summary>
        /// Retrieves a service client for the interface specified in generic parameter.
        /// </summary>
        /// <typeparam name="T">Interface type to use for Service Client creation.</typeparam>
        /// <returns>Service client instance for specified interface.</returns>
        public T GetClient<T>()
        {
            var genericType = typeof(T);
            Type serviceClientType;
            if (genericType.IsInterface)
            {
                serviceClientType = GetClientType(genericType);

                if (serviceClientType == null)
                    return default(T);

                var client = Activator.CreateInstance(serviceClientType);
                if (!(client is ICommunicationObject))
                {
                    client = null;
                    return (T)client;

                }
                (client as ICommunicationObject).Faulted += Channel_Faulted<T>;

                if (!factories.ContainsKey(typeof(T)))
                {
                    var prop = serviceClientType.GetProperty("ChannelFactory");
                    var factory = prop.GetValue(client, null);
                    factories.Add(typeof(T), factory);
                }
                return (T)client;
            }
            return default(T);
        }

        #region Reflection Utilities
        private static Type GetClientType(Type type)
        {
            var assy = type.Assembly;
            var serviceModelAssy = typeof(ChannelFactory).Assembly;
            var clientBaseType = serviceModelAssy.GetType("System.ServiceModel.ClientBase`1").MakeGenericType(type);

            foreach (var classType in assy.GetTypes())
            {
                if (classType.IsClass && type.IsAssignableFrom(classType))
                {
                    if (classType.IsSubclassOf(clientBaseType))
                        return classType;
                }
            }

            return null;
        }

        #endregion

        /// <summary>
        /// Event handler for ClientBase.Faulted event.
        /// </summary>
        /// <typeparam name="T">Interface type of service</typeparam>
        /// <param name="sender">ClientBase instance</param>
        /// <param name="e">Event Args</param>
        private void Channel_Faulted<T>(object sender, EventArgs e)
        {
            ((ICommunicationObject)sender).Abort();
            var factory = (ChannelFactory<T>)factories[typeof(T)];
            factory.CreateChannel();
        }

        /// <summary>
        /// Returns the singleton instance of ServiceClientFactory.
        /// </summary>
        /// <returns>Singleton instance of ServiceClientFactory</returns>
        public static ServiceClientFactory GetFactory()
        {
            if (instance == null)
            {
                instance = new ServiceClientFactory();
            }
            return instance;
        }
    }
}

Sample Usage:

//Get instance of ServiceClientFactory
            var factory = ServiceClientFactory.GetFactory();
            var client = factory.GetClient<IAuthenticateService>();
            try
            {
                client.AuthenticateUser("joe", "bob");
            }
            catch (Exception)
            {
                //Handle Exception
            }

            //channel isn't in faulted state, you can re-execute.
            client.AuthenticateUser("joe", "bob1");

This was thrown together and proven to work for my purposes.  If anyone has any suggestions about how to improve this utility class, please feel free to comment or contact me with suggestions.

.NET Framework
WCF

Comments (2)

Permalink

Recover from a WCF Service Fault

I’ve been looking for an elegant way to recover from a WCF Service Client’s channel going into a Faulted state, and after searching for some time came across a great simple quick and dirty example:

When creating your WCF Service Client, add an event handler to the ICommunicationObject.Faulted event on your service client:

   1: private static ChannelFactory<IAuthenticateService> AuthChannelFactory = null;

   2:  

   3: public static IAuthenticateService GetClient()

   4: {

   5:     if (AuthChannelFactory == null)

   6:         AuthChannelFactory = new ChannelFactory<IAuthenticateService>();

   7:     var client = AuthChannelFactory.CreateChannel();

   8:     

   9:     (client as ICommunicationObject).Faulted += new EventHandler(AuthChannel_Faulted);

  10:     return client;

  11: }

In the event handler, re-create the channel using the channel factory:

   1: static void AuthChannel_Faulted(object sender, EventArgs e)

   2:        {

   3:            (sender as ICommunicationObject).Abort();

   4:            sender = AuthChannelFactory.CreateChannel();

   5:        }

You can re-use the AuthChannel_Faulted event by checking the object type and using the correct ChannelFactory based on type. 

Method obtained from : Nahid’s Blog

General

Comments (1)

Permalink