Using WCF in combination with .NET Core SDK

Published 7/19/2016 7:01:00 AM
Filed under .NET

At my current project we're working hard to get a new REST API running on top of ASP.NET Core.
One of the things we need to do is communicate with a set of existing WCF Services in the back office of the company.

This means we need WCF clients inside our ASP.NET Core project. Something that isn't very simple as it turns out.

In this article I will show you some of the options you have for building and connecting to WCF services.
I will also show you which problems you may run into while building or connecting to WCF services.

Building WCF services using the .NET Core SDK

Before you start to think about building WCF services on top of .NET Core framework it's important to know that
only the client part of WCF is supported.

If you want to build WCF services you need to change your project.json so that
you run on top of the full .NET Framework.

{
  "version": "1.0.0-*",
  "dependencies": {},
  "frameworks": {
    "net461": {
      "frameworkAssemblies": {
        "System.Runtime.Serialization": "4.0.0.0",
        "System.ServiceModel": "4.0.0"
      }
    }
  }
}

When you build WCF services with the .NET Core SDK in combination with the full .NET Framework
you need to know that you are limited to running on Windows. WCF isn't fully
supported by Mono and .NET Core framework only supports clients.
Other than that it's perfectly fine to build WCF services with the .NET Core SDK.

Right now there's only one way to host your WCF service when you use the .NET Core SDK.
Normally you'd make a .svc file with a servicehost directive to host on IIS. Applications
build with the .NET Core SDK however don't seem to support this.

The only way to host a WCF service is to create a self-hosting application.

using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
{
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;

    host.Description.Behaviors.Add(smb);

    host.Open();

    Console.WriteLine("The service is ready at {0}", baseAddress);
    Console.WriteLine("Press <Enter> to stop the service.");
    Console.ReadLine();

    host.Close();
}

This is fine when you don't mind running console applications for each of your services.
It does however present problems for companies that want to host several services in a single
host process. So before you jump in and start building WCF services make sure that you think about the hosting model.

Building WCF clients using the .NET Core SDK

While WCF services aren't supported with the .NET Core framework but can be build using the SDK it's good to know
that WCF clients are supported in the .NET core framework.

In order to generate a client for a WCF service you need an extension in
Visual Studio 2015 called the WCF connected service.
This extension makes it possible to add a WCF connected service to your project.
Notice that it only works for Visual Studio 2015 right now. Support for Mac and Linux
is being developed, but not available yet.

The good thing with the connected service code is that while you can only generate it in Visual Studio, you
can use the code on your Mac or Linux machines. Once a WCF client is generated there's no need for
the Visual Studio extension.

The current version of WCF Core supports only a limited set of bindings and transports.
For example WS-* support is missing. Also, you can't use Windows Authentication on Mac and Linux.

If you need this kind of support you need to use the full .NET framework. Which means that you
are required to run on Windows. Since Mono does not support all scenarios for WCF right now.

If you set your project.json to full framework and include the System.ServiceModel and System.Serialization
assemblies you can then generate clients using the good old svcutil commandline utility. Provided that you
work on Windows of course.

For our project I created a custom powershell script that does just that. It takes some settings
and generates a WCF client for me.

$svcutil = "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\SvcUtil.exe"
function Generate-WcfClient {
	param([string] $wsdlPath, [string] $namespace, [string] $outputPath)
	$languageParam = "/language:C#"
	$outputParam = "/out:" + $outputPath
	$namespaceParam = "/n:*," + $namespace
	$svcutilParams = $wsdlPath, $languageParam,$namespaceParam,$outputParam
	& $svcutil $svcutilParams | Out-Null
}

Generate-WcfClient -wsdlPath "../../Metadata/WSDL/MyService.V1.wsdl" -namespace "MyProject.Agents.MyService" -outputPath "./Agents/MyService.cs"

You can extend this to generate several clients if you need to. To integrate it into the build you need
modify your project.json file and add the script to it.

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable"
  },
  "dependencies": {},
  "frameworks": {
    "net461": {
      "frameworkAssemblies": {
        "System.Runtime.Serialization": "4.0.0.0",
        "System.ServiceModel": "4.0.0"
      }
    }
  },
  "scripts": {
    "precompile": [
      "powershell ./generateagents.ps1"
    ]
  }
}

Every time you run a build the agents get generated automatically. Keep in mind though that because you
have a precompile script the build no longer uses incremental compiles. It means things will be slower.
I personally feel that this is not a problem for me, but your situation could be different.

Conclusion

So yes you can use WCF from .NET Core SDK projects, but you will have to spend some time to make a trade-off between
cross platform support and the requirements of the WCF services you connect to.

If you don't need to use WS-* extensions and Windows authentication I suggest you change the bindings of your
WCF services and use .NET Core framework. If you can't then it's good to know you can still work with your
existing WCF services by running on the full .NET Framework on Windows.