CoreWCF 1.0 has been Released, WCF for .NET Core and .NET 5+

Sam Spencer

The CoreWCF Project team has released the 1.0 version of CoreWCF, a port of WCF to the .NET Core platform. It provides a compatible implementation of SOAP, NetTCP, and WSDL. Usage in code is similar to WCF, but updated to use ASP.NET Core as the service host, and to work with .NET Core. This is the first major release of the project, and provides WCF functionality for .NET Core, .NET Framework, and .NET 5+.

The 1.0 release of CoreWCF is compatible with .NET Standard 2.0 so that it will work with:

  • .NET Framework 4.6.2 (and above)
  • .NET Core 3.1
  • .NET 5 & 6

Support for .NET Framework will enable an easier modernization path to .NET Core. Applications with WCF dependencies can be updated to use CoreWCF in-place on .NET framework, which then will work the same when updated to use .NET Core or .NET 5+.

The assemblies are available on Nuget.org, as described in the Release Notes.

Community Project

CoreWCF was announced as a community project in June of 2019, and has had many contributors during the last 3 years. As a community project, CoreWCF has had more commits from other contributors than Microsoft employees, and regular contributions from AWS and other organizations.

A special thanks to all those who have contributed code, issues or suggestions. The community support has been critical to getting the project to this point, and we hope it will continue for subsequent versions. I’d be remiss if I didn’t make a special callout to @mconnew who has been the backbone of the project and contributed most of the code.

As a community project, the voices of the community guide the direction of the project. For example, the Feature Roadmap Vote issue is highly influential to the planning process for what to work on next. If you are a WCF user, please provide feedback on what you would like to see in subsequent releases.

Features

CoreWCF is a subset of the functionality from WCF, but represents what we believe are the most used features, including:

  • Http & NetTCP transports
  • Bindings:
    • BasicHttpBinding
    • NetHttpBinding
    • NetTcpBinding – some WS-* features not supported
    • WebHttpBinding
    • WSHttpBinding – some WS-* features not supported
  • Security:
    • Transport
    • NetTcpBinding supports Certificate and Windows authentication
    • Http bindings require authentication to be configured in ASP.NET Core
    • Transport With Message Credentials
    • Username, Certificate and Windows Authentication are supported
    • WS Federation
  • WSDL generation
  • Partial configuration support including services & endpoints
  • Extensibility (IServiceBehavior and IEndpointBehavior) – most extensibility is available

Major WCF features not yet implemented include:

  • Transports other than Http and NetTCP.
  • Message security beyond Transport & Transport with Message Credentials
  • Distributed transactions
  • Message Queueing

Who should use CoreWCF?

CoreWCF is intended for customers who have been using WCF on .NET Framework and need WCF support in .NET Core to facilitate modernizing the application. While there is nothing stopping you from adopting CoreWCF in greenfield projects, we would recommend you consider more modern alternatives to SOAP such as gRPC. The sweet spot for CoreWCF is to make it easier to modernize server and clients that have a strong dependency on WCF and SOAP.

Microsoft Support

We recognize how important support is to enterprise customers, and so we are pleased to announce that Microsoft Product Support will be available for CoreWCF customers.

Support for CoreWCF 1.x will depend on the support status for the underlying .NET platforms it runs on.

Runtime Version Support dependency duration
.NET Framework 4.x The specific version of .NET Framework, and ASP.NET Core 2.1.
.NET Core 3.1 .NET 3.1 LTS – December 3, 2022
.NET 5 .NET 5 – May 8, 2022
.NET 6 .NET 6 LTS – November 8, 2024

CoreWCF will use Major.Minor versioning strategy:

  • 1.0 will be the first major release of CoreWCF
  • Minor releases will be numbered 1.x, and will have the same underlying platform requirements as 1.0.
  • Minor version releases (1.x) will be API compatible with the 1.0 release.
  • Support will be primarily for the latest major.minor release of each supported major version.
    • When new major or minor versions are released, then the previous release will be supported for 6 months from the date of the new release, provided the underlying runtime dependency being used is still within support.
  • Subsequent major versions, such as 2.0, may reduce the map of runtimes that are supported. In that case 1.x will continue to be supported beyond the 6 months on the runtimes that are not supported by 2.0, and support duration will be limited only by the underlying platform.
    • This will most likely apply to .NET Framework, and means that 1.x will be supported as long as both ASP.NET Core 2.1 and .NET Framework 4.x are under support.

More Support

Other organizations/companies may choose to provide support for CoreWCF in conjunction with the use of their products and services.

Getting started

The definition and implementation of data and service contracts is the same as WCF. The major difference is in the definition of the host which is now based on ASP.NET Core, and the ceremony of how a service is exposed. The following is based on .NET 6, but the same steps apply to other versions of .NET.

Defining the service

1. Create an ASP.NET Core Empty application, this provides the host for the service.

Visual Studio:
Project Template

Command Line:

mkdir CoreWCFDemoServer
dotnet new web -n CoreWCFDemoServer -o CoreWCFDemoServer

2. Add references to the CoreWCF Nuget Packages

Visual Studio:

Using the package Manager console, add:

  • Primitives
  • Http

Package Manager Console

Command Line:

Edit the project file and add:

<ItemGroup>
  <PackageReference Include="CoreWCF.Http" Version="1.0.0" />
  <PackageReference Include="CoreWCF.Primitives" Version="1.0.0" />
</ItemGroup>

3. Create the Service Contract and Data Contract definitions

These are defined the same as with WCF. When modernizing projects, this code can remain largely unchanged.

File: IEchoService.cs

using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using CoreWCF;

namespace CoreWCfDemoServer
{
    [DataContract]
    public class EchoFault
    {
        [AllowNull]
        private string _text;

        [DataMember]
        [AllowNull]
        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }
    }

    [ServiceContract]
    public interface IEchoService
    {
        [OperationContract]
        string Echo(string text);

        [OperationContract]
        string ComplexEcho(EchoMessage text);

        [OperationContract]
        [FaultContract(typeof(EchoFault))]
        string FailEcho(string text);

    }

    [DataContract]
    public class EchoMessage
    {
        [AllowNull]
        [DataMember]
        public string Text { get; set; }
    }
}

File: EchoService.cs

using CoreWCF;

namespace CoreWCfDemoServer
{
    public class EchoService : IEchoService
    {
        public string Echo(string text)
        {
            System.Console.WriteLine($"Received {text} from client!");
            return text;
        }

        public string ComplexEcho(EchoMessage text)
        {
            System.Console.WriteLine($"Received {text.Text} from client!");
            return text.Text;
        }

        public string FailEcho(string text)
            => throw new FaultException<EchoFault>(new EchoFault() { Text = "WCF Fault OK" }, new FaultReason("FailReason"));

    }
}

4. The Service host needs to be told which services to expose via which bindings.

Update Program.cs to expose the Bindings:

using CoreWCF;
using CoreWCF.Configuration;
using CoreWCF.Description;
using CoreWCfDemoServer;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, options) =>
{
options.AllowSynchronousIO = true;
});

// Add WSDL support
builder.Services.AddServiceModelServices().AddServiceModelMetadata();
builder.Services.AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>();

var app = builder.Build();
app.UseServiceModel(builder =>
{
builder.AddService((serviceOptions) => { })
// Add a BasicHttpBinding at a specific endpoint
.AddServiceEndpoint<EchoService, IEchoService>(new BasicHttpBinding(), "/EchoService/basichttp")
// Add a WSHttpBinding with Transport Security for TLS
.AddServiceEndpoint<EchoService, IEchoService>(new WSHttpBinding(SecurityMode.Transport), "/EchoService/WSHttps");
});
var serviceMetadataBehavior = app.Services.GetRequiredService();
serviceMetadataBehavior.HttpGetEnabled = true;

app.Run();

5. Update the appsettings.json to specify fixed ports for the service to listen on

Add the following line before the "Logging" line in appsettings.json:

"Urls": "http://localhost:5000;https://localhost:5001",

6. Run the project so that the services can be called

To consume the service:

1. Create a console application

2. Add a Service Reference

Visual Studio

Use the "Add Service Reference" command, and select "WCF Web Service" as the service type.

Add Service Reference Dialog

Use http://localhost:5000/EchoService/basichttp as the URL for WSDL discovery.

Command line

From the Command Line, the same code can be generated using svcutil:

dotnet tool install --global dotnet-svcutil
dotnet-svcutil --roll-forward LatestMajor http://localhost:5000/EchoService/basichttp?wsdl

3. Replace the code of the console app with:

using ServiceReference1;
// Instantiate the Service wrapper specifying the binding and optionally the Endpoint URL. The BasicHttpBinding could be used instead.
var client = new EchoServiceClient(EchoServiceClient.EndpointConfiguration.WSHttpBinding_IEchoService, "https://localhost:5001/EchoService/WSHttps");

var simpleResult = await client.EchoAsync("Hello");
Console.WriteLine(simpleResult);

var msg = new EchoMessage() { Text = "Hello2" };
var msgResult = await client.ComplexEchoAsync(msg);
Console.WriteLine(msgResult);

Other Samples

Other samples, including samples for desktop framework are available at CoreWCF/src/Samples

See it in action

On an recent episode of On .NET, Matthew Connew joined James Montemagno to walk through all of the new features and roadmap for CoreWCF:

Summary

We are pleased to see the community investment in the CoreWCF project, and congratulate them on this release. The project is ongoing and they welcome your feedback via issues and discussions in GitHub, in particular which features you think should be worked on next.

13 comments

Discussion is closed. Login to edit/delete existing comments.

    • Michael Taylor 1

      https://github.com/dotnet/wcf is the client library. It is used to consume WCF services. It was migrated so .NET Core apps could call WCF services.

      The library posted here is the far larger codebase that is used to build WCF services. Originally MS planned to only support consuming WCF services and recommended everyone switch to REST/gRPC services instead. Hence they had no intention of porting WCF. WCF server also has dependencies on WIndows-specific stuff which won’t work in .NET Core.

      The new CoreWCF library is a subset of the WCF code to help migrate WCF services to .NET Core/5/6. It is not full featured but rather is a stopgap to help get people off of .NET Framework. I don’t believe MS’es position has changed at all on this though. They will still recommend switching to REST/gRPC services for a variety of reasons but for those cases where it is not practical to migrate then this new library can be used to at least build WCF services now. Before you had to stick with .NET Framework.

      If you are writing .NET Core code and need to consume a WCF service then use the standard dotnet/wcf client library like you should be now. If you are needing to migrate an existing .NET Framework WCF service to .NET Core then use the CoreWCF library for the server side implementation. The client side will continue to use dotnet/wcf. It is very common for a client-server architecture to have different models for the same services. That is all that is going on here.

  • Aleksandras T. 1

    Finally! I will certainly dig into it, since we have a big part of codebase as WCF services, which are publicly faced and cannot be easily rewritten.
    Therefore we kind of stuck forever with “classic” .NET Framework.

    However we have both *.asmx and *.svc webservices – does this library support both cases?

  • David N 0

    This is great, thank you to everyone involved.

    I have an application with a client component that gets loaded by another companies .Net Framework application and then communicates bi-directionally with my server using WCF. They aren’t changing their app to modern .Net so I can’t use the new gRPC support at that end, there seemed to be no good options for a mixed .Net Framework and .Net 6 environment that didn’t involve a lot of work on both ends.

    But now it looks like I have a way forward to modernise the server end.

  • Steve Naidamast 0

    This is all great news as I have been waiting for this release for some time.

    I am interested in building a multi-user/client-server version of my desktop document management system as an alternative to using web development from Microsoft, which seems to be in a constant state of change.

    As a result, I have wanted to stay with the WCF implementation, which I have tinkered with in the past and found it quite easy to work with. My alternative was to purchase the RemObject’s Remoting SDK, which is quite pricey. However, this SDK does support binary transport protocols, which is big plus in an era of constant system breaches.

    I know this presents a limitation on where such implementations can be run but they have always been the most secure in our profession.

    Does the CoreWCF team have any plans to implement binary transport protocols?

    • Matt ConnewMicrosoft employee 1

      CoreWCF does support the binary XML feature that WCF on .NET Framework supports. This is basically a method to drastically reduce the size of the message by representing it using a binary format. I won’t go into too much detail, but basically the XML structure is tokenized, primitives are emitted in their natural in memory form or better (it has variable length integers so smaller ints use less bytes), and all strings get added to a dictionary and tokenized, including the XML Element name and XML namespace). We also support compressing the binary message using GZip or Deflate on top of the binary tokenization.

      To give you an idea of size, I found this blog post comparing a large number of serializers on .NET. Protobuf is normally touted as being one of the most size efficient serializers and in that test produces an output which is 18.8MB while the binary XML came out to 35.8MB. That’s not too bad considering it’s still encoding the semantic structure of an XML document, and you can add data compression on top of that if size is super important.

      There are 2 bindings which use binary encoded XML by default. If you are using http, then the NetHttpBinding uses the binary message encoder. If you want a TCP based transport, then NetTcpBinding also uses it. Compression is off by default, but it can be enabled. The only thing to be aware of is that the binary encoded XML is proprietary (although the spec is published openly) which means only .NET clients will talk to your service. CoreWCF can expose multiple endpoints to your service at the same time, so you could have a less efficient text XML endpoint for non .NET Clients, and a more efficient binary XML endpoint for .NET clients.

      • Steve Naidamast 0

        Thank you, Matt, for taking the time to provide me with a very informative and detailed answer. From what you described, it appears that CoreWCF will exactly what I would want for my plans for a new client-server application.

        As it regards general TCP Transport, years ago there is a story at the financial company I was working at where the vice-president of data processing had invited certain types of investors to a conference regarding the plans of the company to look to placing a lot of new applications on the Internet using the TCP\IP protocol.

        Two of these investors st the conference were 2 of the scientist that actually created the Internet at DARPA. When told of the plans to move many of the company’s applications to the Internet, they both stood up looking white as sheets and clearly stated, “Are you mad?” to the vp. They went on to say that the Internet was originally designed within a closed-loop system with no security protocols whatsoever. As a result, they informed everyone that the Internet for public use should not be used for any form of sensitive information.

        Needless to say, these scientists have been continuously proven correct.

        This is why I have an interest in the use of Binary Transport Protocols; they are very difficult to breach and decrypt, though I imagine professional state actors now have the tools for such operations. But still, the security level is still the best available that I am aware of.

        Thank you again… 🙂

  • Stuart Ballard 0

    This sounds really useful for anyone who has legacy implementations of WCF services.

    I don’t suppose there’s anyone working to do the same thing for people with legacy apps built around WebForms?

  • Peasley, Alex 0

    Is there an upgrade path for taking an existing WCF Service written in 4.6.1 and upgrading it to CoreWCF? Can I use the core upgrade assistant than just install the CoreWCF nuget? Potentially that simple?

    • Sam SpencerMicrosoft employee 0

      The upgrade assistant does not yet have built-in support for WCF migration, but it is on the backlog. A colleague is working on a subsequent post walking through the upgrade experience, so stay tuned for that.

  • Gert-Jan van der Kamp 0

    Good stuff. We’ve built our app around raw asp / http / json / (de)serialization and tbh I never saw the benefits over wcf I was using 15 years ago.. We could have saved so much time. Next project will be wcf again, glad to see it alive and kicking!

  • Luis Felipe La Rotta Ospina 2

    Hi Sam!

    Thank you for this great implementation. Is there a place where I could get a sample project showing how to expose a SOAP web service using your project?
    Tried adding EchoService and IEchoservice to a new project, but got the following compile errors:

    builder.AddService((serviceOptions) => { })

    Error CS1660 Cannot convert lambda expression to type ‘Type’ because it is not a delegate type ServiceBrokerDotNet

    var serviceMetadataBehavior = app.Services.GetRequiredService();

    The type arguments for method ‘ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider)’ cannot be inferred from the usage. Try specifying the type arguments explicitly.

    Before finding your project my first approach to SOAP was the example below (I’m more familiar with REST). But I’m unable to use it because it lacks a way to await a Task defined on an external cass.

     [WebService(Namespace = "www.business.com")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        [System.ComponentModel.ToolboxItem(false)]
        public class WebService1 : System.Web.Services.WebService
        {
            [WebMethod]
            public GetProfileResponse GetClientProfile(Request request)
            {
                GetProfileResponse getProfileResponse = new GetProfileResponse();
    
                getProfileResponse.responseSuccess = true;
                getProfileResponse.responseDetails = "Here are some details";      
    
                return getProfileResponse;
            }
        }

    Thank you very much

  • Gab 0

    Is it possible to inject dependencies to the EchoService ?

    Like

    public EchoService(ILogger logger, IConfiguration configuration)

Feedback usabilla icon