Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

SOAP support

Demis Bellot edited this page · 22 revisions

  1. Getting Started

    1. Creating your first project
      1. Create Service from scratch
    2. Your first webservice explained
    3. ServiceStack's new API Design
    4. Designing a REST-ful service with ServiceStack
    5. Example Projects Overview
    6. Learning Resources
  2. Reference

    1. Order of Operations
    2. The IoC container
    3. Configuration and AppSettings
    4. Metadata page
    5. Rest, SOAP & default endpoints
    6. SOAP support
    7. Routing
    8. Service return types
    9. Customize HTTP Responses
    10. Plugins
    11. Validation
    12. Error Handling
    13. Security
    14. Debugging
    15. JavaScript Client Library (ss-utils.js)
  3. Clients

    1. Overview
    2. C#/.NET client
    3. Add ServiceStack Reference
      1. C# Add Reference
      2. F# Add Reference
      3. VB.NET Add Reference
      4. Swift Add Reference
    4. Silverlight client
    5. JavaScript client
      1. Add TypeScript Reference
    6. Dart Client
    7. MQ Clients
  4. Formats

    1. Overview
    2. JSON/JSV and XML
    3. ServiceStack's new HTML5 Report Format
    4. ServiceStack's new CSV Format
    5. MessagePack Format
    6. ProtoBuf Format
  5. View Engines

    1. Razor & Markdown Razor
    2. Markdown Razor
  6. Hosts

    1. IIS
    2. Self-hosting
    3. Messaging
    4. Mono
  7. Security

    1. Authentication/authorization
    2. Sessions
    3. Restricting Services
  8. Advanced

    1. Configuration options
    2. Access HTTP specific features in services
    3. Logging
    4. Serialization/deserialization
    5. Request/response filters
    6. Filter attributes
    7. Concurrency Model
    8. Built-in caching options
    9. Built-in profiling
    10. Form Hijacking Prevention
    11. Auto-Mapping
    12. HTTP Utils
    13. Virtual File System
    14. Config API
    15. Physical Project Structure
    16. Modularizing Services
    17. ServiceStack Integration
    18. Embedded Native Desktop Apps
    19. Auto Batched Requests
  9. Server Events

    1. Overview
    2. JavaScript Client
    3. C# Server Events Client
    4. Redis Server Events
  10. Plugins

    1. Auto Query
    2. Server Sent Events
    3. Swagger API
    4. Postman
    5. Request logger
    6. Sitemaps
  11. Tests

    1. Testing
    2. HowTo write unit/integration tests
  12. ServiceStackVS

    1. Install ServiceStackVS
    2. Add ServiceStack Reference
    3. AngularJS App Template
    4. ReactJS App Template
  13. Other Languages

    1. FSharp
      1. Add ServiceStack Reference
    2. VB.NET
      1. Add ServiceStack Reference
    3. Swift
      1. Swift Add Reference
  14. Deployment

    1. Deploy Multiple Sites to single AWS Instance
      1. Simple Deployments to AWS with WebDeploy
    2. Advanced Deployments with OctopusDeploy
  15. Install 3rd Party Products

    1. Redis on Windows
    2. RabbitMQ on Windows
  16. Use Cases

    1. Single Page Apps
    2. Azure
      1. Connecting to Azure Redis via SSL
    3. Logging
    4. Bundling and Minification
    5. NHibernate
  17. Performance

    1. Real world performance
  18. How To

    1. Sending stream to ServiceStack
    2. Setting UserAgent in ServiceStack JsonServiceClient
    3. ServiceStack adding to allowed file extensions
    4. Default web service page how to
  19. Future

    1. Roadmap
Clone this wiki locally

If you want to support SOAP, you have to note some important things, because of the lack of other HTTP verbs except for POST in SOAP.

Rest only

If you only want to support REST, you can take the easy route:

//Request DTO
public class Customers {...}
public class CustomersService : Service
{
    //Get customers
    public object Get(Customers request) {...}

    //Add customer
    public object Post(Customers request) {...}

    //Update customer
    public object Put(Customers request) {...}

    //Delete customer
    public object Delete(Customers request) {...}
}
//In the AppHost's configure method
Routes.Add<Customers>("/customers")
      .Add<Customers>("/customers/{Id}");

Soap + Rest

SOAP only supports POST requests. But the REST example makes use of GET, DELETE (...) requests, which aren't available with SOAP. So if you want to support SOAP and REST, you need to create one service for each operation:

//Request DTO - Add DataMember attribute for all properties.
[DataContract]
public class GetCustomers {...}
[DataContract]
public class UpdateCustomer {...}
[DataContract]
public class AddCustomer {...}
[DataContract]
public class DeleteCustomer {...}

//Service
public class CustomersService : Service 
{
   public object Any(GetCustomers request){...}
   public object Any(AddCustomer request){...}
   public object Any(UpdateCustomer request){...}
   public object Post(UpdateCustomer request){...}
   public object Any(DeleteCustomer  request){...}
}

The method Any gets executed on each HTTP verb and on each endpoint. Make sure that all DTO models have [DataContract] attribute (and [DataMember] attribute for all properties) otherwise the XSD-schema embedded within the WSDL will be partially incomplete.

Note: SOAP uses the HTTP POST verb. Therefore, each service must have Any() or Post() methods to support SOAP.

REST-ful registration of multiple services

Now that you have multiple web services you can register them all together to expose them as a single REST-ful resource (as seen with the REST service above):

//In the AppHost's configure method
Routes.Add<GetCustomers>("/customers", "GET")
      .Add<GetCustomers>("/customers/{Id}", "GET")
      .Add<AddCustomer>("/customers", "POST")
      .Add<UpdateCustomer>("/customers/{Id}", "PUT")
      .Add<DeleteCustomer>("/customers/{Id}", "DELETE")

Note: Don't forget to specify the HTTP verb filters!

Now this webservice supports REST and SOAP and has the same REST endpoint as the above service, they equal 1:1.

Raw Access to WCF SOAP Message

IRequiresSoapMessage works similar to IRequiresRequestStream interface to tell ServiceStack to skip de-serialization of the request and instead pass the raw WCF Message to the Service instead for manual processing, e.g:

public class RawWcfMessage : IRequiresSoapMessage {
    public Message Message { get; set; }
}

public object Post(RawWcfMessage request) { 
    request.Message... //Raw WCF SOAP Message
}

SOAP Limitations

SOAP expects that each request always returns the same response DTO. So you need to follow the response DTO naming convention, otherwise ServiceStack won't be able to generate the WSDLs and the SOAP endpoint won't work.

DTO Naming Conventions

Naming convention: {Request DTO Name} + Response

Example: Request DTO: DeleteCustomer --> Response DTO: DeleteCustomerResponse.

If you would leave the services as they are, the REST endpoint wouldn't exist. So you need to hook them all up on the same URL like that:

Single WSDL Namespace

If you happen to generate requests from the WSDLs with a tool like SoapUI you may end up with an incorrectly generated request like this:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
               xmlns:type="http://schemas.servicestack.net/types">
  <soap:Header/>
  <soap:Body>
    <type:Hello/>
  </soap:Body>
</soap:Envelope>

You can resolve this issue by adding the following line to your AssemblyInfo file

[assembly: ContractNamespace("http://schemas.servicestack.net/types", 
           ClrNamespace = "<YOUR NAMESPACE>")]

e.g:

[assembly: ContractNamespace("http://schemas.servicestack.net/types",
           ClrNamespace = "MyApp.ServiceModel")]
[assembly: ContractNamespace("http://schemas.servicestack.net/types",
           ClrNamespace = "MyApp.ServiceModel.Types")]

Rebuild and regenerate the request from the updated wsdl. You should get a correct request this time.

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
               xmlns:type="http://schemas.servicestack.net/types">
   <soap:Header/>
   <soap:Body>
      <type:Hello>
         <!--Optional:-->
         <type:Name>?</type:Name>
      </type:Hello>
   </soap:Body>
</soap:Envelope>

Changing the default namespace

A requirement with SOAP endpoints is for all DTO types to share the same single namespace which should match the Config.WsdlServiceNamespace if you want to change it from the default namespace: http://schemas.servicestack.net/types. E.g. You can change the default WSDL Namespace in your AppConfig with:

SetConfig(new HostConfig {
    WsdlServiceNamespace = "http://my.new.namespace.com/types",
});

This can easily be done by using the [assembly:ContractNamespace] attribute usually defined in the DTO project's AssemblyInfo.cs file, here is how this is done in the ServiceStack.Examples project:

[assembly: ContractNamespace("http://my.new.namespace.com/types",
           ClrNamespace = "ServiceStack.Examples.ServiceModel.Operations")]
[assembly: ContractNamespace("http://my.new.namespace.com/types",
           ClrNamespace = "ServiceStack.Examples.ServiceModel.Types")]

SOAP Exceptions

Exceptions in SOAP responses are returned with an 200 OK HTTP Status so they are deserialized as normal responses in code-generated SOAP clients. The original HTTP Status code is available in the X-Status HTTP Header or SOAP Response Header named X-Status. This is transparently converted into a typed WebServiceException when using ServiceStack's built-in Soap 1.1/1.2 generic Service Clients as seen in WebServicesTests.

To check if the response was an error in non ServiceStack SOAP clients, check the response.ResponseStatus.ErrorCode property for a non-null value.

Convert SOAP Exceptions to SOAP Faults

If preferred, you can also convert SOAP Exceptions into a SOAP Fault by adding a ServiceExceptionHandler, e.g:

ServiceExceptionHandlers.Add((req, request, ex) => {
    var requestMsg = req.GetItem("SoapMessage") as System.ServiceModel.Channels.Message;
    if (requestMsg != null)
    {
        var msgVersion = requestMsg.Version;
        using (var response = XmlWriter.Create(req.Response.OutputStream))
        {
            var message = System.ServiceModel.Channels.Message.CreateMessage(
                msgVersion, new FaultCode("Receiver"), ex.ToString(), null);
            message.WriteMessage(response);
        }
        req.Response.End();
    }
    return null;
});

Visual Studios Add Service Reference

Since VS.NET's Add Service Reference is optimized for consuming .asmx or WCF RPC method calls it doesn't properly support multiple return values (e.g. when you also want a ResponseStatus property) where it will generate an ugly proxy API complete with out parameters.

If you want to ensure a pretty proxy is generated you should only have 1 first-level property which contains all the data you want to return.

Using XSD.exe

One way around it is to share your services DTO's and use any of the typed Generic Service Clients that are in-built into ServiceStack. Alternatively you can use the XSD.exe command-line utility to generate your types on the client and use those in the typed Service Clients.

Something went wrong with that request. Please try again.