Wrong problem with Autofac WCF Integration

Autofac is a brand new .Net Dependency Injection / IoC just like Castle Windsor, etc. Autofac like Castle has a nice WCF integration facility. I was trying hard to establish a self hosted WCF server using Autofac. But was not successful at all. I guessed that is because of IP, Windows Firewall, Administration rights, version incompatibility and everything you say.

I tried Autofac samples but couldn’t get them running. After all I tried Alex’s solution for second or third time and realized that his sample works very fine. By watching error messages from Microsoft WcfTestClient more carefully that was clear that an internal error was occurring. But how an internal error could be viewed by WcfTestClient? Yes you are right, by using IncludeExceptionDetailInFaults. I found that in a question on SO here. So my modified version of Alex’s sample goes as here:

private static void StartServerOriginal()
{
    ContainerBuilder builder = new ContainerBuilder();
    builder.Register(c => new MySecurityManager()).As<IMySecurityManager>();

    using (IContainer container = builder.Build())
    {
        Uri address = new Uri("http://localhost:8046/MySecurityManager");
        ServiceHost host = new ServiceHost(typeof(MySecurityManager), address);
        host.AddServiceEndpoint(typeof(IMySecurityManager), new BasicHttpBinding(), string.Empty);

        IComponentRegistration registration;
        if (!container.ComponentRegistry.TryGetRegistration(new TypedService(typeof(IMySecurityManager)), out registration))
        {
            Console.WriteLine("The service contract has not been registered in the container.");
            Console.ReadLine();
            Environment.Exit(-1);
        }

        (host.Description.Behaviors[typeof(ServiceDebugBehavior)] as ServiceDebugBehavior).IncludeExceptionDetailInFaults = true;
        host.Description.Behaviors.Add(new AutofacDependencyInjectionServiceBehavior(
            container, typeof(MySecurityManager), registration));
        host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true, HttpGetUrl = address });

        host.Open();

        Console.WriteLine("The host has been opened.");
        Console.ReadLine();

        host.Close();
        Environment.Exit(0);
    }
}

By running WcfTestClient again I found that some of my own service contract’s exceptions were not marked as Serializable!

Oh Autofac, please forgive me, as I am a former user of Castle WCF Facility, I was thinking root cause of problem was you! Sorry, the problem was in my own code.

WcfFacility Hello World

WcfFacility is one facilities of Castle Windsor facilities that helps you ignoring adding service reference by Visual Studio. With WcfFacility you can ease server and client service management. Before starting this sample I searched for and found a good starting point here. Unfortunately this sample was usng .svc file. As I didn’t want to use .svc file I wrote my own hello world sample with Wcf Facility:

Service code:

        public static void StartService()
        {
            var windsorContainer = new WindsorContainer()
                .AddFacility<WcfFacility>()
                .Register(Component.For<IDateService>()
                    .ImplementedBy<DateService>()
                    .DependsOn(new { number = 42 })
                    .AsWcfService(new DefaultServiceModel().AddEndpoints(
                            WcfEndpoint.BoundTo(new NetTcpBinding { PortSharingEnabled = true })
                                .At(“net.tcp://localhost:8063/DateService”)
                               ).PublishMetadata()
                ));
        }

Client Code:

        public static string InvokeWcfService()
        {
            var container = new WindsorContainer().AddFacility<WcfFacility>();

            container.Register(Component
                .For<IDateService>()
                .AsWcfClient(DefaultClientModel
                .On(WcfEndpoint.BoundTo(new NetTcpBinding())
                .At(“net.tcp://localhost:8063/DateService”)))
                .LifeStyle.Transient
                );

            var dateService = container.Resolve<IDateService>();
            string message = dateService.SaySomething(“123”);

            return message;
        }

Complete sample source code be downloaded here.

‫سه راه برای ارتباط با سرویس WCF

برای آن که از داخل یک برنامه بتوان از سرویس‌های WCF یک سرور استفاده کرد، یعنی wcf client ایجاد کرد، اقلاً سه راه وجود دارد:

۱- اضافه کردن service reference با کمک ویژوال استودیو: در این روش خود شما فقط url سرویس مورد نظر را به ویژوال استودیو می‌دهید. ویژوال استودیو هم کلاس‌ها و interfaceهای لازم را برای تولید proxy مورد نظر تولید می‌کند. بدی این روش این است که باید مقدار زیادی کد را نگه دارید بدون آن که خودتان آن را تولید کرده باشید. علاوه بر این کد تولیدی وابستگی زیادی به سرویس دارد، با کمترین تغییر در سرویس WCF شما هم باید service reference را update کرده و مجدداً برنامه را کامپایل کنید. ایراد آخر هم این است که موقع برنامه‌نویسی کلاینت باید سرور هم در حال اجرا و در دسترس باشد در غیر این صورت نمی‌توانید عملیات add reference را انجام دهید.

۲-اضافه کردن service reference با کمک ویژوال استودیو و instance گیری با کمک ابزارهای DI و IoC مثل Castle Windsor: این روش هم مشابه روش قبلی است با این تفاوت که روال instance گیری را به Castle Windsor می‌سپارید و خودتان درگیر نمی‌شوید.

۳- استفاده از WCF Facility برای ایجاد پراکسی‌های WCF بدون اجبار به Add Reference کردن یا تهیه کلاس‌های کلاینتی. در این روش به طور runtime و با کمترین دردسری می‌توان برای هر نوع سرویس WCFی پراکسی تعریف کرده و مورد استفاده قرار داد. WCF Facility یکی از امکانات جانبی Castle Windsor است. از WCF Facility حتی برای سرور WCF هم می‌توان استفاده کرد.

منبع:
http://blog.hatchan.nl/2010/07/wcf-facility-for-castle-windsor-client.html