我需要创建一个托管在IIS中的WCF服务,使用http传输并在服务器的内存中保存状态.虽然我知道有状态服务并不是一个好主意,但最后的约束对于使服务与传统客户端一起工作是必要的.
我的第一个想法是asp.net的会话来存储值.我在我的服务中激活了asp.net兼容模式,这使我可以访问HttpContext,但是放在会话对象中的值没有被保存在内存中.我认为这是因为处理会话状态的http模块没有正确配置,但是当我在网上搜索答案时,WCF会话并认为使用它们可能更好.
但是,WCF会话似乎是在文档下面并在服务上放置了一组奇怪的先决条件,而且我无法找到适合我需要的配置:必须在IIS中托管,必须使用http或https传输并且可以不回复Windows身份验证,因为客户端和服务器不属于同一个域.我试图使用wsHttpBinding来实现这一点,我听说过WCF会话需要安全性或可靠的消息,但是: - 使用标准绑定,当服务器不属于同一个域时,它会失败并出现"SecurityNegotiationException调用者没有通过服务"例外验证.这是相当合理的,因为它使用的是Windows安全性.
如果我禁用安全性完成,它将失败并显示"合同需要会话,但绑定'WSHttpBinding'不支持它或未正确配置以支持它."
如果在保持安全性被禁用的同时启用可靠消息,我会收到异常"绑定验证失败,因为WSHttpBinding不支持基于传输安全性的可靠会话(HTTPS).无法打开通道工厂或服务主机.使用消息安全性实现HTTP上安全可靠的消息传递."
我已经尝试启用传输级安全性,但这似乎对生成的错误没有任何影响
有没有可能对我有用的配置?或者我应该回到使用asp.net会话的计划?
我有使用SOAP 1.2的AJAX客户端使用的WCF服务
Web.config文件:
<endpoint address="" binding="wsHttpBinding"
contract="WcfService1.IService1" bindingConfiguration="wsHttpBin">
<wsHttpBinding>
<binding name="wsHttpBin">
<security mode="None"/>
</binding>
</wsHttpBinding>
Run Code Online (Sandbox Code Playgroud)
根据我的阅读,我必须使用,<security mode="None"/>
因为使用"wsHttpBinding"绑定公开的服务实现了WS-*Web服务规范系列的WS-Security.由于绑定使用安全性,因此请求将被拒绝,因为AJAX不支持安全上下文.
我的WCF服务行为定义为InstanceContextMode.PerSession
:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerSession)]
Run Code Online (Sandbox Code Playgroud)
但是当我使用它时,该服务表现为PerCall,并且每次调用都会启动一个新的WCF实例,而不是使用当前实例.
使用wsHttpBinding时,为什么InstanceContextMode.PerSession的行为与PerCall类似?
我能做什么?
我目前使用basicHttpBindings和SSL启用了WCF服务.但现在我需要启用wcf会话(而不是asp会话)所以我将服务转移到wsHttpBidnings但是会话未启用
我已经设定
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
Run Code Online (Sandbox Code Playgroud)
但是当我设定的时候
SessionMode=SessionMode.Required
Run Code Online (Sandbox Code Playgroud)
在服务合同上,它说
合同需要Session,但Binding'WSHttpBinding'不支持它,或者没有正确配置以支持它.
以下是WSHttpBinding的定义
<wsHttpBinding>
<binding name="wsHttpBinding">
<readerQuotas maxStringContentLength="10240" />
<reliableSession enabled="false" />
<security mode="Transport">
<transport clientCredentialType="None">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
</security>
</binding>
</wsHttpBinding>
Run Code Online (Sandbox Code Playgroud)
请在这件事上给予我帮助
我正在使用NetTcpBinding编写双工WCF服务,我遇到了一个架构问题,我想我知道答案,但希望我错了.
我们的服务是有状态的,我们选择了NetTcpBinding PerSession
InstanceContextMode
.由于各种原因,这是我们需要的.我正在尝试将我们更大的接口(其中大块操作不适用于许多客户端)分解为多个较小的接口,并将操作逻辑分组.虽然简单到足以让单个服务实现实现所有合同,但我不确定是否可以让多个服务合同共享一个通道(或者,更符合我的要求,单个会话),而且我会肯定需要能够做到这一点,以使这项工作.
当然,我可以在一个合同中包含所有内容,并FaultException
在执行无效操作时抛出s,但我真的希望能够打破这些并且甚至不为不适用的合同添加端点.我正在寻找什么?
TL; DR版本:
我需要能够做到这一点:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
void Foo();
}
[ServiceContract]
public interface IServiceB
{
[OperationContract]
void Bar();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service : IServiceA, IServiceB
{
...
}
Run Code Online (Sandbox Code Playgroud)
并且能够建立从客户端到服务的一个会话,但同时使用IServiceA
和IServiceB
.
我正在做一些单元测试,并在 WCF 中遇到了一个有趣的问题。我有一个使用wsHttpBinding
, 配置的服务:
<bindings>
<wsHttpBinding>
<binding name="wsHttpUnsecured">
<security mode="None">
<transport clientCredentialType="None" />
<message clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
Run Code Online (Sandbox Code Playgroud)
服务的实现是:
public void DoWork()
{
OperationContext o = OperationContext.Current;
if (o == null) return;
if (o.ServiceSecurityContext.AuthorizationContext.Properties.ContainsKey("x"))
throw new ApplicationException();
o.ServiceSecurityContext.AuthorizationContext.Properties.Add("x", "x");
}
Run Code Online (Sandbox Code Playgroud)
它在这里所做的只是检查操作上下文,如果 AuthorizationContext 中没有“X”,则添加一个。如果已经有一个“X”,则例外。(这严格设置为一个简单的测试。在正常使用中,这将发生在自定义 AuthorizationManager 和 Token Authenticator 中)。
所以基本上,如果我们在同一个 operationContext 和 AuthorizationContext 中多次调用该方法,那么我们会看到一个异常。
现在,这是我的测试夹具。
[Test]
public void CallTwice()
{
using (var cli1 = new TestBusinessClient())
{
cli1.DoWork();
cli1.Close();
}
using (var cli2 = new TestBusinessClient())
{
cli2.DoWork(); …
Run Code Online (Sandbox Code Playgroud)