Visual Studio引用ServiceStack SOAP方法

The*_*est 4 c# visual-studio-2010 servicestack

我有一个使用ServiceStack的简单API设置.我使用以下代码来运行它:

namespace TheGuest.Test
{
    [DataContract]
    [Description("A sample web service.")]
    public class Greet
    {
        [DataMember]
        public string Name { get; set; }
    }

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

    /// <summary>
    /// An example of a very basic web service.
    /// </summary>
    public class GreetService : IService<Greet>
    {
        public object Execute(Greet request)
        {
            return new GreetResponse { Result = "Hello " + request.Name };
        }
    }

    public static class Constants
    {
        public const string DefaultNamespaceV1 = "http://my/custom/namespace";
    }

    public class MyAppHost : AppHostBase
    {
        // Tell Service Stack the name of your application and where to find your web services.
        public MyAppHost()
            : base("My Web Services", typeof(GreetService).Assembly)
        {
        }

        public override void Configure(Container container)
        {
            SetConfig(new EndpointHostConfig { WsdlServiceNamespace = Constants.DefaultNamespaceV1 });

            // Register user-defined REST-ful URLs.
            Routes
                .Add<Greet>("/hello")
                .Add<Greet>("/hello/{Name}")
                .Add<Greet>("/hello/{Name*}");
        }
    }

    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            new MyAppHost().Init();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并将以下行添加到AssemblyInfo.cs:

[assembly: ContractNamespace("http://my/custom/namespace", ClrNamespace = "TheGuest.Test")]
Run Code Online (Sandbox Code Playgroud)

它将生成以下WSDL:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="Soap12" 
    targetNamespace="http://my/custom/namespace" 
    xmlns:svc="http://my/custom/namespace" 
    xmlns:tns="http://my/custom/namespace" 

    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" 
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" 
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
    xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" 
    xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" 
    xmlns:wsa10="http://www.w3.org/2005/08/addressing" 
    xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">

    <wsdl:types>
        <xs:schema xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="anyType" nillable="true" type="xs:anyType" />
  <xs:element name="anyURI" nillable="true" type="xs:anyURI" />
  <xs:element name="base64Binary" nillable="true" type="xs:base64Binary" />
  <xs:element name="boolean" nillable="true" type="xs:boolean" />
  <xs:element name="byte" nillable="true" type="xs:byte" />
  <xs:element name="dateTime" nillable="true" type="xs:dateTime" />
  <xs:element name="decimal" nillable="true" type="xs:decimal" />
  <xs:element name="double" nillable="true" type="xs:double" />
  <xs:element name="float" nillable="true" type="xs:float" />
  <xs:element name="int" nillable="true" type="xs:int" />
  <xs:element name="long" nillable="true" type="xs:long" />
  <xs:element name="QName" nillable="true" type="xs:QName" />
  <xs:element name="short" nillable="true" type="xs:short" />
  <xs:element name="string" nillable="true" type="xs:string" />
  <xs:element name="unsignedByte" nillable="true" type="xs:unsignedByte" />
  <xs:element name="unsignedInt" nillable="true" type="xs:unsignedInt" />
  <xs:element name="unsignedLong" nillable="true" type="xs:unsignedLong" />
  <xs:element name="unsignedShort" nillable="true" type="xs:unsignedShort" />
  <xs:element name="char" nillable="true" type="tns:char" />
  <xs:simpleType name="char">
    <xs:restriction base="xs:int" />
  </xs:simpleType>
  <xs:element name="duration" nillable="true" type="tns:duration" />
  <xs:simpleType name="duration">
    <xs:restriction base="xs:duration">
      <xs:pattern value="\-?P(\d*D)?(T(\d*H)?(\d*M)?(\d*(\.\d*)?S)?)?" />
      <xs:minInclusive value="-P10675199DT2H48M5.4775808S" />
      <xs:maxInclusive value="P10675199DT2H48M5.4775807S" />
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="guid" nillable="true" type="tns:guid" />
  <xs:simpleType name="guid">
    <xs:restriction base="xs:string">
      <xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}" />
    </xs:restriction>
  </xs:simpleType>
  <xs:attribute name="FactoryType" type="xs:QName" />
  <xs:attribute name="Id" type="xs:ID" />
  <xs:attribute name="Ref" type="xs:IDREF" />
</xs:schema>
<xs:schema xmlns:tns="http://my/custom/namespace" elementFormDefault="qualified" targetNamespace="http://my/custom/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="Greet">
    <xs:sequence>
      <xs:element minOccurs="0" name="Name" nillable="true" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:element name="Greet" nillable="true" type="tns:Greet" />
</xs:schema>
    </wsdl:types>



    <wsdl:message name="GreetIn">
        <wsdl:part name="parameters" element="tns:Greet" />
    </wsdl:message>

    <wsdl:portType name="ISyncReply">

    </wsdl:portType>

    <wsdl:portType name="IOneWay">
    <wsdl:operation name="Greet">
        <wsdl:input message="svc:GreetIn" />
    </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="WSHttpBinding_ISyncReply" type="svc:ISyncReply">
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />

    </wsdl:binding>

    <wsdl:binding name="WSHttpBinding_IOneWay" type="svc:IOneWay">
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="Greet">
      <soap:operation soapAction="http://schemas.servicestack.net/types/Greet" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
    </wsdl:operation>
    </wsdl:binding>

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

    <wsdl:service name="AsyncOneWay">
        <wsdl:port name="WSHttpBinding_IOneWay" binding="svc:WSHttpBinding_IOneWay">
            <soap:address location="http://localhost:50472/test/soap12" />
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>
Run Code Online (Sandbox Code Playgroud)

当我通过Visual Studio 2010添加此服务时,我得到2个客户端.一个被称为"SyncReplyClient",它没有我可以调用的方法,另一个被称为"OneWayClient",带有"Greet"方法.但正如名称所暗示的那样,我想使用SyncReplyClient,因为我需要响应.

我该如何实现这一目标?

在旁注中,OneWayClient抛出一个ProtocolException,并显示以下消息:"单向操作返回一个非空消息,其中包含Action =''." 因为我不想使用OneWayClient,所以这并不会让我感到烦恼,但它也很奇怪.

myt*_*thz 5

在创建要由SOAP使用的服务时,请确保阅读有关SOAP限制的内容.即,您需要保留单个XSD/WSDL命名空间.例如,您可以使用以下命令更改AppConfig中的默认WSDL命名空间:

SetConfig(new EndpointHostConfig {
    WsdlServiceNamespace = "http://my.new.namespace.com/types",
});
Run Code Online (Sandbox Code Playgroud)

这将设置在生成的WSDL页面上使用的WSDL/XSD名称空间.您还需要[DataContract]通过为每个DataContract指定一个名称空间来匹配此自定义XSD名称空间与您的DTO,您可以通过在每个名称上手动指定

[DataContract(Namespace="http://my.new.namespace.com/types")]
Run Code Online (Sandbox Code Playgroud)

或者您可以使用指定

 [assembly: ContractNamespace("http://my/custom/namespace", 
            ClrNamespace = "TheGuest.Test")] 
Run Code Online (Sandbox Code Playgroud)

将它设置在共享C#名称空间下的多个DTO上.

最近还发生了一些变化,我们添加了新API并添加了不同的属性以允许您注释您的服务(将显示在/ metadata和Api Docs/Swagger页面上).考虑到这些变化,创建服务的新方法是:

[DataContract]
[Api("A sample web service.")]
public class Greet
{
    [DataMember]
    [ApiMember("The name of the person you wish to greet")]
    public string Name { get; set; }
}

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

public class GreetService : Service
{
    public GreetResponse Any(Greet request)
    {
        return new GreetResponse { Result = "Hello " + request.Name };
    }
}
Run Code Online (Sandbox Code Playgroud)

告诉ServiceStack服务响应类型是什么

为了让ServiceStack确定您的服务的响应类型,您需要提供以下任何提示:

使用强类型返回类型

您的服务可以返回一个object或现在的ResponseDto类型,例如:

public class GreetService : Service
{
    //1. Using Object
    public object Any(Greet request)
    {
        return new GreetResponse { Result = "Hello " + request.Name };
    }

    //2. Above service with a strong response type
    public GreetResponse Any(Greet request)
    {
        return new GreetResponse { Result = "Hello " + request.Name };
    }
}
Run Code Online (Sandbox Code Playgroud)

如果使用选项2)ServiceStack将采用GreetResponse类型.

使用IReturn标记界面

[DataContract]
public class Greet : IReturn<GreetResponse> { ... }
Run Code Online (Sandbox Code Playgroud)

使用Marker接口的另一个优点是它提供了更简洁的客户端API,例如:

GreetResponse response = client.Send(new Greet { Name = "World!" });
Run Code Online (Sandbox Code Playgroud)

如果您没有Marker接口,则客户端API将是:

GreetResponse response = client.Send<GreetResponse>(new Greet { Name = "World!" });
Run Code Online (Sandbox Code Playgroud)

使用typeof(RequestDto).Name +'Response'命名约定

如果您的服务具有object响应类型且没有标记接口,则可以使用名称{RequestDto}Response命名约定来告诉ServiceStack响应类型是什么.

注意:要使ServiceStack能够找到响应类型,它需要与请求DTO 位于相同的名称空间中.此外,每个请求和响应DTO都应该唯一命名,这使您可以使用请求DTO名称而不是完整名称空间来调用ServiceStack服务.