Can't add a SOAP reference to a project generated through SS

Have you read through the different SOAP limitations? https://github.com/ServiceStack/ServiceStack/wiki/SOAP-support

If so we’ll need a repro, you can submit one at: https://github.com/ServiceStack/Issues

Hi Demis,

I have found what is wrong, but this a limitation in the SOAP implementation. I have one service call that needs to be exposed through a WSDL out of a service of dozens of rest calls.

I only decorated the DTO I want exposed with DataContract/DataMember, leaving the others DTO’s attribute free, this causes the issue reported above.

You can also hide Services you don’t want exposed in SOAP/WSDL’s by adding annotating Request DTO’s with:

[Exclude(Feature.Soap)]
public class ExcludeFromSoap { ... }

Thanks for the feed back. This is not an ideal solution. We have services with dozens of DTO’s, we literally need to expose only one of these calls in a WSDL.

[Exclude…] will pollute our DTO classes, all except one would require it, ideally we need a mechanism that would work the other way around [Include when…] a specified attribute is present.

Understood, I’ve just made the list of exported types configurable in this commit.
So now you can override ExportSoapTypes in your AppHost and return only the types you want to show up on the WSDL/XSD, e.g:

    public override List<Type> ExportSoapTypes(ICollection<Type> operationTypes)
    {
        return new []{ typeof(RequestDtoForSoap) }.ToList();
    }

This change is available from v4.0.31+ that’s now available on MyGet.

Perfect. Thank you. Will give out a try

HI,

Still fighting with this guy. This is for the use by a large corporate who is using a java soap client in Eclipse, like visual studio, it will not generate referenced types:

http://admin.aivision.co.za/api/soap12

Unfortunately there is no option to use the SS soap client

using System.Runtime.Serialization;

namespace AIVision.ServiceModel.Operations
{

    [DataContract]
    [Route("/{ChannelToken}/orders", "POST")]
    public class CreateOrder
    {
    [DataMember]
    public string ChannelToken { get; set; }
    //[DataMember]
    ////Organisation
    //public LegalPersonType OrganisationType { get; set; }//Always Individual
    [DataMember]
    public string CustomerIDNumber { get; set; }

    //Contact
    [DataMember]
    public string AccountName { get; set; }
    [DataMember]
    public string CustomerPersonTitle { get; set; }
    [DataMember]
    public string CustomerPersonFirstName { get; set; }
    [DataMember]
    public string CustomerPersonLastName { get; set; }
    [DataMember]
    public string CustomerContactTelephoneCell { get; set; }
    [DataMember]
    public string CustomerContactTelephoneOther { get; set; }
    [DataMember]
    public string CustomerContactEmail { get; set; }

    //PostalAddress
    [DataMember]
    public string CustomerLocationStreetAddress1 { get; set; }
    [DataMember]
    public string CustomerLocationStreetAddress2 { get; set; }
    [DataMember]
    public string CustomerLocationSuburb { get; set; }
    [DataMember]
    public string CustomerLocationProvince { get; set; }
    [DataMember]
    public string Region { get; set; }

    //Vehicle
    [DataMember]
    public string VehicleMake { get; set; }
    [DataMember]
    public string VehicleModel { get; set; }
    [DataMember]
    public int VehicleYear { get; set; }
    [DataMember]
    public string VehicleVINNumber { get; set; }
    [DataMember]
    public bool VehicleUnderWarranty { get; set; }
    [DataMember]
    public string VehicleInsuredBy { get; set; }
    [DataMember]
    public string VehicleFinancedBy { get; set; }
    [DataMember]
    public bool VehicleHasTelematics { get; set; }
    [DataMember]
    public bool VehicleHasTracking { get; set; }
    [DataMember]
    public string VehicleFMSby { get; set; }

    ////Order
    //[DataMember]
    //public List<OrderItemView> LineItems { get; set; }
    [DataMember]
    public DateTime DateCreated { get; set; }
    //[DataMember]
    //public OrderStatus Status { get; set; }
    [DataMember]
    public string OrderToken { get; set; }
}

    [DataContract]
    public class CreateOrderResponse
    {
        [DataMember]
        public string Result { get; set; }
    }

}

AssemblyInfo:

[assembly: ContractNamespace("http://erp.goseamless.co.za/types",
           ClrNamespace = "AIVision.ServiceModel.Operations")]

[assembly: ContractNamespace("http://erp.goseamless.co.za/types",
           ClrNamespace = "AIVision.ServiceModel.Types")]

Note: we don’t support other 3rd party SOAP tools, just the WCF-flavor of SOAP and VS’s Add Service Reference.

Can you post a stand-alone example on GitHub so I can test this locally.

Personally I’d strongly recommend using the new Java support added in the latest v4.0.40 release which has a much cleaner, faster and more succinct typed API than any SOAP tool can generate. You can use the Java DTO’s generated at /types/java (e.g. http://techstacks.io/types/java) with the generic JsonServiceClient in the ServiceStack.Client Java Package to provide an end-to-end typed API.

OK, I’ve had a look at this.

The docs were not followed correctly.

The [assembly: ContractNamespace...] attributes need to be in the AssemblyInfo of the ServiceModel project (where the exported DTOs are). Ours had been added to the AssemblyInfo of the asp.net service host project, so it didn’t work.

The generated WSDL now looks correct, except for one problem:

If the ServerEventsFeature plugin is registered, some additional SSE-related operations and messages show up in the WSDL, even though they’re I’m not returning them from the ExportSoapTypes method. The DTOs themselves don’t show up in the <xs:schema> section.

Exported types:

public override List<Type> ExportSoapTypes(ICollection<Type> operationTypes)
{
	return new List<Type>
	{
		typeof(CreateOrder),
		typeof(CreateOrderResponse)
	};
}

WSDL with additional SSE messages and operations:

  <wsdl:types>
    <xs:schema xmlns:tns="http://schemas.goseamless.co.za/types" elementFormDefault="qualified" targetNamespace="http://schemas.goseamless.co.za/types" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:complexType name="CreateOrder">
        <xs:sequence>
          ...
        </xs:sequence>
      </xs:complexType>
      <xs:element name="CreateOrder" nillable="true" type="tns:CreateOrder" />
      <xs:complexType name="CreateOrderResponse">
        <xs:sequence>
          ...
        </xs:sequence>
      </xs:complexType>
      <xs:element name="CreateOrderResponse" nillable="true" type="tns:CreateOrderResponse" />
    </xs:schema>
  </wsdl:types>

  <wsdl:message name="CreateOrderIn">
    <wsdl:part name="par" element="tns:CreateOrder" />
  </wsdl:message>
  <wsdl:message name="CreateOrderOut">
    <wsdl:part name="par" element="tns:CreateOrderResponse" />
  </wsdl:message>
  <wsdl:message name="UnRegisterEventSubscriberIn">
    <wsdl:part name="par" element="tns:UnRegisterEventSubscriber" />
  </wsdl:message>
  <wsdl:message name="UnRegisterEventSubscriberOut">
    <wsdl:part name="par" element="tns:UnRegisterEventSubscriberResponse" />
  </wsdl:message>
  <wsdl:message name="GetEventSubscribersIn">
    <wsdl:part name="par" element="tns:GetEventSubscribers" />
  </wsdl:message>
  <wsdl:message name="GetEventSubscribersOut">
    <wsdl:part name="par" element="tns:GetEventSubscribersResponse" />
  </wsdl:message>

  <wsdl:portType name="ISyncReply">
    <wsdl:operation name="CreateOrder">
      <wsdl:input message="svc:CreateOrderIn" />
      <wsdl:output message="svc:CreateOrderOut" />
    </wsdl:operation>
    <wsdl:operation name="UnRegisterEventSubscriber">
      <wsdl:input message="svc:UnRegisterEventSubscriberIn" />
      <wsdl:output message="svc:UnRegisterEventSubscriberOut" />
    </wsdl:operation>
    <wsdl:operation name="GetEventSubscribers">
      <wsdl:input message="svc:GetEventSubscribersIn" />
      <wsdl:output message="svc:GetEventSubscribersOut" />
    </wsdl:operation>
  </wsdl:portType>

ok it looks like the WSDL and XSD weren’t both sourced from the ExportSoapTypes() API. I’ve re-factored the SOAP support to look at these 2 new API’s one for Operation Type (e.g. Request DTO) and one XSD Type in these new overridable AppHost API’s:

List<Type> ExportSoapOperationTypes(List<Type> operationTypes)

bool ExportSoapType(Type type)

I’ve also excluded many of ServiceStack built-in services by default so the SSE Request DTO’s shouldn’t be showing up now. I’ll probably need to tweak the impl a bit more so it’s not so aggressive in the types/operations that it includes by default, but in the meantime these new API’s should provide full control and the latest version with these changes is now available on MyGet.

Great, that works for now.

One more issue:

There seem to be some inconsistencies in the Soap12WsdlTemplate.cs file.

The SOAP 1.2 spec (as described here) seems to require some of the elements used to be the ones in the soap12 namespace., but in the WSDL template, they’re still using the older soap namespace:

<soap12:binding>
<soap12:operation>
<soap12:body>
<soap12:address>

ServiceStack currently generates this:

<wsdl:binding name="WSHttpBinding_ISyncReply" type="svc:ISyncReply">
	<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
	<wsdl:operation name="CreateOrder">
	  <soap:operation soapAction="http://myschema.example.test/CreateEntity" style="document" />
	  <wsdl:input>
		<soap:body use="literal" />
	  </wsdl:input>
	  <wsdl:output>
		<soap:body use="literal" />
	  </wsdl:output>
	</wsdl:operation>
</wsdl:binding>

<wsdl:service name="SyncReply">
	<wsdl:port name="WSHttpBinding_ISyncReply" binding="svc:WSHttpBinding_ISyncReply">
		<soap:address location="http://example.test/api/soap12" />
	</wsdl:port>
</wsdl:service>

The correct output would be this:

<wsdl:binding name="WSHttpBinding_ISyncReply" type="svc:ISyncReply">
	<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
	<wsdl:operation name="CreateOrder">
	  <soap12:operation soapAction="http://myschema.example.test/CreateEntity" style="document" />
	  <wsdl:input>
		<soap12:body use="literal" />
	  </wsdl:input>
	  <wsdl:output>
		<soap12:body use="literal" />
	  </wsdl:output>
	</wsdl:operation>
</wsdl:binding>

<wsdl:service name="SyncReply">
	<wsdl:port name="WSHttpBinding_ISyncReply" binding="svc:WSHttpBinding_ISyncReply">
		<soap12:address location="http://example.test/api/soap12" />
	</wsdl:port>
</wsdl:service>

Some SOAP validators will accept the current output, but some complain that it’s missing certain elements.

SOAP is still somewhat confusing to me, but our client requires it :confounded:

Yes, I noticed that soap ns issue too. As a temporary workaround You may use the

public override string GenerateWsdl(WsdlTemplateBase wsdlTemplate)

So I did (read post 5) for the value of the attribuite name within the wsdl:part element.

It would be great have all this fixs/changes included in the next release

Hi All,

The latest version of ServiceStack on MyGet is now using soap12 prefixes. The List of Types included in SOAP WSDL and XSD’s have also been optimized to only include the types required. Please let me know if there are any issues with the latest release.

If you already have v4.0.41 installed you’ll need to clear out your NuGet package cache and delete the NuGet /packages folder to ensure the latest version is downloaded and installed, see: https://github.com/ServiceStack/ServiceStack/wiki/MyGet#redownloading-myget-packages