我试图让我的WCF服务具有可以通过代理客户端和REST调用调用的操作,我使用以下配置:
<services>
<service behaviorConfiguration="SecureBehavior" name="Payment">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="secureWS" contract="IPayment"/>
<endpoint address="rest" binding="webHttpBinding" behaviorConfiguration="webBehavior" contract="IPayment"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
<bindings>
<mexHttpBinding>
<binding name="userMex"/>
</mexHttpBinding>
<wsHttpBinding>
<binding name="secureWS">
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true"/>
</security>
</binding>
<binding name="publicWS">
<security mode="None"/>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SecureBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<windowsAuthentication allowAnonymousLogons="false"/>
</serviceCredentials>
</behavior>
<behavior name="PublicBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<windowsAuthentication allowAnonymousLogons="true"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</services>
这是我的代码:
[ServiceContract]
public interface IPayment
{
[OperationContract]
PaymentResult Finalize(string TransactionID, string CertificatePath);
[OperationContract]
[WebGet(UriTemplate = "rest")]
System.IO.Stream GetPayment();
}
现在每当我运行我的服务时,我都会收到此错误:
合同'IPayment'的操作'Finalize'指定要序列化的多个请求体参数,而不包含任何包装元素。最多可以在没有包装元素的情况下序列化一个body参数。删除额外的body参数或将WebGetAttribute / WebInvokeAttribute上的BodyStyle属性设置为Wrapped。
在这里我想保持Finalize操作只能通过.NET客户端调用,并且GetPayment操作可以通过任何浏览器调用。
答案 0 :(得分:0)
如果您不希望从通过webhttp端点连接的客户端调用Finalize方法,并且您不希望从通过wshttp连接的客户端调用GetPayments,则可以简单地将合同分成两部分。
假设您在IIS中托管,您可能需要做一些小技巧以确保它有效。让我举一个使用问题细节的例子......
首先,这里是两个服务的代码......
[ServiceContract]
public interface IPayment
{
[OperationContract]
[WebGet(UriTemplate = "rest")]
System.IO.Stream GetPayment();
}
[DataContract]
public class PaymentResult
{
}
[ServiceContract]
public interface IMakePayment
{
[OperationContract]
PaymentResult Finalize(string TransactionID, string CertificatePath);
}
// Maybe you really should have the two services separate but if you do
// want to implement them both in a single class you can do this
public abstract class PaymentBase : IMakePayment, IPayment
{
// ... Implement both interfaces here
public PaymentResult Finalize(string TransactionID, string CertificatePath)
{
return null;
}
public System.IO.Stream GetPayment()
{
return null;
}
}
public class MakePayment : PaymentBase
{
// Empty
}
public class Payment : PaymentBase
{
// Empty
}
现在创建两个.svc文件,如下所示:
<强> MakePayment.svc 强>
<%@ ServiceHost Language="C#" Debug="true" Service="WebApplication1.MakePayment" %>
<强> Payment.svc 强>
<%@ ServiceHost Language="C#" Debug="true" Service="WebApplication1.Payment" %>
最后这里是system.servicemodel配置:
<system.serviceModel>
<services>
<service behaviorConfiguration="SecureBehavior" name="WebApplication1.MakePayment">
<endpoint binding="wsHttpBinding" bindingConfiguration="secureWS" contract="WebApplication1.IMakePayment"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" bindingConfiguration="userMex"/>
</service>
<service behaviorConfiguration="PublicBehavior" name="WebApplication1.Payment">
<endpoint binding="webHttpBinding" behaviorConfiguration="webBehavior" bindingConfiguration="publicWS" contract="WebApplication1.IPayment"/>
</service>
</services>
<bindings>
<mexHttpBinding>
<binding name="userMex"/>
</mexHttpBinding>
<wsHttpBinding>
<binding name="secureWS">
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true"/>
</security>
</binding>
</wsHttpBinding>
<webHttpBinding>
<binding name="publicWS">
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SecureBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<windowsAuthentication allowAnonymousLogons="false"/>
</serviceCredentials>
</behavior>
<behavior name="PublicBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<windowsAuthentication allowAnonymousLogons="true"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
你去 - 如果你连接到/MakePayment.svc你将通过WSHTTP连接并能够调用FinalizePayment,如果你去/Payments.svc/rest它会调用GetPayment方法返回一个流。