为此,我们创建了一个 ServiceFactory 类,该类连接到给定端点和适当的IClientChannel
派生接口的服务。这假设您直接使用 WCF 服务,例如,不是通过 VS 生成的代理,因为您需要在每个客户端通道创建时设置用户名和密码值。
客户端通道接口与服务工厂一起位于外部“服务库”中,因此它们可以与 WCF 服务实现和客户端共享。我们将凭据存储在静态字典中(尽管您也将其放入主资源字典中),密码保存在 aSecuredString
中以提供一点额外的安全性。
我已经通过博客描述了创建这样一个服务工厂的基本过程:
http://blog.kutulu.org/2012/03/proxy-free-wcf-ditching-proxy.html
在我们的例子中,我们执行一个设置例程App.xaml.cs
,提示输入凭据并尝试调用我们的服务之一,循环直到我们成功登录。该代码要复杂得多,但基本上是:
while (true)
{
var factory = new ChannelFactory<ITestChannel>(new WSHttpBinding("SecuredBinding"));
ITestChannel client = null;
try
{
factory.Credentials.UserName.UserName = logOnModel.UserName;
factory.Credentials.UserName.Password = logOnModel.Password;
var address = Settings.Default.TestServiceUrlBase));
client = factory.CreateChannel(address);
break;
}
// Catch various exceptions here.
}
这里的诀窍是,如果您的登录名或密码错误并且您UsernamePasswordValidator
的登录失败,您将得到一个会导致您的频道出错MessageSecurityException
的频道,因此您需要关闭它并打开一个新频道。但是一旦打开第一个通道,您就无法更改凭据ChannelFactory
,因此您每次都需要处理并重新创建新工厂和新客户端通道。
如果 URL 错误,我们还会在此处检查CommunicationException
和检查。ArgumentException
完成后,您可以在服务工厂类中使用类似的代码来构造客户端,给定其通道接口,并为每个调用设置凭据。(我们实际上为每个不同的接口缓存了服务工厂,因为我们经常创建和销毁通道,但这取决于你。)