Open-source project
DigDes/SoapCore avatar
DigDes/SoapCore

SoapCore: serving SOAP endpoints from ASP.NET Core

SOAP extension for ASP.NET Core

1,058 stars393 forksC#MIT

At a glance

What is it?
SoapCore is a NuGet-packaged ASP.NET Core middleware that lets a .NET service expose a SOAP endpoint, driven by the same interface and attribute model that WCF used, with DataContract, XmlSerializer and custom serializer options. It suits teams that must keep a SOAP contract alive while moving services to ASP.NET Core, and it is the wrong tool for a greenfield API with no legacy clients.
Who is it for?
SoapCore is a good fit for a team moving a WCF or ASMX service onto ASP.NET Core while the client side still speaks SOAP, because the contract stays expressed as an interface with attributes and the hosting changes to the middleware pipeline. It is a poor fit for a new service with no legacy consumers, since a REST or gRPC endpoint would be less work than a SOAP one, and for a team that needs WS-Security or other advanced WCF behaviours, which the README does not mention.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 20 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • DigDes/SoapCore1,058 ★ · +1
Star history
Repository2026-10-192026-11-07
DigDes/SoapCore1.1k1.1k

1 Stars in the last 19 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

SOAP as middleware rather than a hosting model

SoapCore is a SOAP protocol middleware for ASP.NET Core, built on a Microsoft article describing a custom ASP.NET Core middleware example. The framing matters because it explains what the project is not. It is not a reimplementation of WCF as a hosting stack with its own configuration file, its own binding system and its own activation model. It is a component that you register in the ASP.NET Core pipeline, which means a service can expose SOAP and HTTP endpoints side by side in the same process, and it inherits everything the ASP.NET Core host already gives you, from configuration to logging to hosting on Linux. The stated support is for ref and out parameters, for exceptions, and for working with legacy SOAP and WCF clients.

The service contract is a C# interface, and attributes do the rest

The contract model comes straight from WCF. A service implementation class is registered in the dependency injection container, and the endpoint is attached to it with a generic type argument naming that class. The README's example registers ServiceContractImpl as a singleton and then maps the endpoint to it with UseSoapEndpoint, setting the path to /ServicePath.asmx and choosing a serializer. The service contract itself, the operation attributes and the data contract attributes are ordinary C# declarations, so a developer who has written WCF services will recognise the shape immediately, and a developer coming from REST has to learn a different set of attributes but not a different programming model. The sample projects in the repository include a client, a server, shared models and a service reference client, so the round trip is demonstrated end to end.

Two registration styles depending on the routing model

There are two ways to wire the endpoint in, and the difference is whether endpoint routing is in play. On ASP.NET Core 3.1 or higher, with endpoint routing enabled by default, the registration goes through UseRouting and then UseEndpoints, and the SOAP endpoint is one of the mapped endpoints.

csharp
app.UseRouting();

app.UseEndpoints(endpoints => {
    endpoints.UseSoapEndpoint<ServiceContractImpl>(opt =>
    {
        opt.Path = "/ServicePath.asmx",
        opt.SoapSerializer = SoapSerializer.DataContractSerializer
    });
});

On ASP.NET Core 2.1, and on .NET Framework or another .NET Standard 2.0 compliant platform, there is no endpoint routing, so the endpoint is registered directly on the application builder with a path and encoder options.

csharp
app.UseSoapEndpoint<ServiceContractImpl>("/ServicePath.asmx", new SoapEncoderOptions());

The supported frameworks are listed in the README as .NET 8.0 with ASP.NET Core 8.0, .NET Core 3.1 with ASP.NET Core 3.1, and .NET Standard 2.0-2.1 with ASP.NET Core 2.1.

The serializer choice is the compatibility decision

SoapCore ships more than one wire format, and picking the wrong one produces a client that connects and then fails on the response. The DataContractSerializer and the XmlSerializer produce different XML for the same contract, and the README is explicit that for legacy WCF and Web Services usage the primary point is to use XmlSerializer and to mark up messages and operations with the proper XML serialization attributes. If you have pre-generated wrappers from the old stack, you can use those to obtain the contracts, or write them by hand, and the README points at the serialization tests project for an extended example. The choice is made with the SoapSerializer option on the endpoint, and it is the first thing to check when a client complains about the response body.

A custom serializer is a first-class extension point

Beyond the built-in formats, the project lets you supply your own body serializer. The mechanism is a pair of registrations: a DI registration for the implementation of ISoapCoreSerializer, and a call on the endpoint options to say which implementation the service should use.

csharp
services.AddSoapCore();
services.TryAddSingleton<ServiceContractImpl>();
services.AddCustomSoapMessageSerializer<CustomeBodyMessageSerializerImpl>();

The matching call on the options object, UseCustomSerializer, names the same implementation for that endpoint, so the pattern is that the serializer type is registered once and then selected per endpoint. This is what a team would reach for when a client expects a body shape that neither built-in serializer produces, rather than forking the library.

Serving a WSDL from disk when the code-generated one will not do

SoapCore can generate the service description from your code, or read it from files on the server, and the second mode is configured through a FileWSDL section in appsettings.

json
"FileWSDL": {
  "UrlOverride": "",
  "SchemeOverride": "",
  "VirtualPath": "",
  "WebServiceWSDLMapping": {
    "Service.asmx": {
      "UrlOverride": "Management/Service.asmx",
      "WsdlFile": "snapshotpull.wsdl",
      "SchemaFolder": "Schemas",
      "WsdlFolder": "Schemas"
    }
  }
}

The overrides exist for the awkward deployment cases. UrlOverride fixes the URL in the service description, which the README says is useful behind a firewall. SchemeOverride handles the case where a proxy sets X-Forwarded-Host but the internal scheme differs from the external one. VirtualPath inserts a path segment between the base URL and the service. The mapping lets one host serve several services under different folders, and it points at both the WSDL file and the folder holding the XSD schemas the WSDL imports. The settings are then read in Startup with a configuration section bind and passed into the endpoint registration.

Three WCF-style extension points sit in the service collection

The Tips and Tricks section shows how to extend the pipeline with services registered in the service collection. AddSoapMessageInspector adds a custom MessageInspector, comparable to WCF's IDispatchMessageInspector, and the README notes that the newer IMessageInspector2 interface allows registering several inspectors and knowing which service was called. AddSingleton with a custom OperationInvoker, similar to WCF's IOperationInvoker, overrides the invocation of a service operation, which is where custom logging or exception handling around a call belongs. AddSoapMessageProcessor adds a SoapMessageProcessor, which works more like ASP.NET Core middleware: it inspects the message on the way in and on the way out, can short-circuit processing and return its own message, and can inspect or modify the HttpContext. There is also a documented use of the processor as a delegate, registered with an async callback that receives the message, the http context and a next function.

MIT licensed, with a release train and a develop branch

The licence is MIT, so the library can be used in a proprietary commercial product as long as the copyright and licence notice is kept, and it is published to NuGet as SoapCore. The default branch is develop, which is worth knowing if you are following the repository, and the recent releases show a four-part version scheme, v1.2.1.16 on 2026-09-11, v1.2.1.15 on 2026-09-04 and v1.2.1.14 on 2026-06-09, meaning patches ship frequently within the same minor version. The last push was on 2026-10-19, so the project is being worked on. The repository also carries a CONTRIBUTING.md and a.globalconfig for analyser settings, and the CI badge at the top of the README is wired to a workflow that builds the project.

Editorial conclusion

SoapCore is a good fit for a team moving a WCF or ASMX service onto ASP.NET Core while the client side still speaks SOAP, because the contract stays expressed as an interface with attributes and the hosting changes to the middleware pipeline. It is a poor fit for a new service with no legacy consumers, since a REST or gRPC endpoint would be less work than a SOAP one, and for a team that needs WS-Security or other advanced WCF behaviours, which the README does not mention. Verify first which serializer your existing clients require, since the DataContractSerializer and XmlSerializer produce different wire formats, and read the WSDL override settings if your service sits behind a proxy that rewrites the scheme or host.

Frequently asked questions

How do I add a SOAP endpoint to an ASP.NET Core project?

Install the package with Install-Package SoapCore, call services.AddSoapCore() in ConfigureServices, register your service implementation, and map the endpoint with endpoints.UseSoapEndpoint or app.UseSoapEndpoint depending on whether endpoint routing is enabled.

Which .NET versions does SoapCore support?

The README lists .NET 8.0 with ASP.NET Core 8.0, .NET Core 3.1 with ASP.NET Core 3.1, and .NET Standard 2.0-2.1 with ASP.NET Core 2.1. On ASP.NET Core 2.1 the endpoint is registered directly on the application builder rather than through endpoint routing.

Which serializer should I use for legacy WCF clients?

The README states the primary point for legacy WCF and Web Services is to use XmlSerializer and to mark up messages and operations with the proper XML serialization attributes, while the DataContractSerializer is the option set in the endpoint examples.

Can SoapCore serve a WSDL file from disk?

Yes. A FileWSDL section in appsettings maps a service endpoint to a WsdlFile, a WsdlFolder and a SchemaFolder, and the resulting WsdlFileOptions is passed to the endpoint registration. UrlOverride, SchemeOverride and VirtualPath handle deployments behind proxies.

Official sources

  1. DigDes/SoapCore on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/digdes-soapcore.svg)](https://hysenlabs.com/projects/digdes-soapcore)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/digdes-soapcore.svg)](https://hysenlabs.com/projects/digdes-soapcore)

Was this useful?