我需要创建一个托管在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会话的计划吗?
答案 0 :(得分:25)
您可以以非常简单的方式在内存中保存WCF会话信息。为了消除我的指示中的任何可能的外部影响,我假设你开始一个全新的项目:
WSHttpBiding
绑定的服务。转到服务合同(IService1.cs)并将ServiceContract属性更改为以下内容:
[ServiceContract(SessionMode = SessionMode.Required)]
转到服务实现(Service1.cs)并将以下ServiceBehavior属性添加到服务类(Service1
):
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
将会话数据添加为服务类(Service1
)的成员:
public class Service1 : IService1
{
...
private string UserFullName { get; set; }
...
}
使用成员显示会话特定数据(还记得将它们添加到服务合同中IService1
):
public class Service1 : IService1
{
...
public string Welcome(string fullName)
{
UserFullName = fullName ?? "Guest";
return string.Format("Welcome back, {0}!", UserFullName);
}
public string Goodbye()
{
return string.Format("Come back soon, {0}!", UserFullName ?? "Guest");
}
...
}
SessionMode.Required
可确保对您的客户进行会话跟踪
InstanceContextMode.PerSession
确保为每个会话创建服务类(Service1)的实例,以便您可以在其中保留会话数据,并且它将存储在内存中的多个调用中会话。
ConcurrencyMode.Single
确保只有一个线程可以进入每个服务类实例(Service1),并且如果您只访问服务类(和外部线程安全位置)中的数据,则可以防止可能的并发问题。
编辑:默认情况下,WSHttpBinding
仅允许安全会话。但它也支持可靠的会话,允许在没有启用安全性的情况下建立会话。以下绑定配置会禁用安全性并启用可靠会话:
<wsHttpBinding>
<binding name="wsHttpBindingConfiguration">
<security mode="None" />
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
答案 1 :(得分:1)
IMO当你使用像WCF这样的HTTP抽象不佳的技术时会发生这种情况。 WCF Web服务理论上可以在没有HTTP的情况下托管(即通过NET TCP,MSMQ等),这使得很难使用HTTP的内置功能而无需进入配置地狱并开始“猜测正确配置”的游戏通过反复试验“你在哪里尝试所有可能的配置排列,直到你找到了正确的一个有效的方式!
最终,如果您无法使用WCF并且必须从头开始实施Web服务,则只需在客户端成功通过身份验证后设置cookie。然后,每个客户端请求只需获取该cookie引用的会话信息。
如果你不得不使用WCF,一个可能的解决方案就是自己动手进行会话管理(这是我在努力工作所需的努力时所做的事情)并拥有所有需要会话/身份验证的Web服务上的显式“会话”属性(通常是在身份验证上生成的guid)。因此,对于每个后续请求,您都可以使用guid来重新水化与该客户端关联的会话信息。
如果您对尝试不同的Web服务框架感兴趣,我会使用Open Source Web Services Framework来构建免费,干燥,可测试的Web服务,其中(无需任何配置)您创建的每个Web服务都是自动的可通过REST XML,JSON,JSV,SOAP 1.1,SOAP 1.2端点访问。实际上,它允许您通过HTTP GET URL访问相同的Web服务,以便REST-ful客户端和简单的调试以及SOAP端点(一些企业仍然强制要求的流行选择)。 Hello World教程应该为您提供一些有关其功能及其工作原理的概述。