我在開發IIS上有兩個應用程序。第一個WCF應用程序,包含所有與數據庫的邏輯和通信(我們稱之爲服務器)。另一個引用WCF應用程序的ASP.NET MVC 3應用程序(我們稱之爲客戶端)。Unity IoC + WCF + wsHTTPBinding +證書授權
我有問題與混合WCF web.config配置與Unity IoC定製服務主機和自定義行爲相關聯。
當所有配置由Unity完成時,它會創建簡單的BasicHttpBinding,但我的要求是使用證書授權來保護它,所以我需要wsHTTPBinding。
-------------配置basicHttpBinding的------------
在開始的時候看看常見的統一實施WCF:
internal class UnityInstanceProvider : IInstanceProvider
{
private readonly IUnityContainer container;
private readonly Type contractType;
public UnityInstanceProvider(
[NotNull] IUnityContainer container,
[NotNull] Type contractType)
{
this.container = container;
this.contractType = contractType;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return container.Resolve(contractType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
container.Teardown(instance);
}
}
internal class UnityServiceBehavior : IServiceBehavior
{
private readonly IUnityContainer container;
public UnityServiceBehavior(
[NotNull] IUnityContainer container)
{
this.container = container;
}
#region IServiceBehavior Members
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
{
if (endpointDispatcher.ContractName != "IMetadataExchange")
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(container, serviceDescription.ServiceType);
}
}
}
}
#endregion
}
public class UnityServiceHost : ServiceHost
{
private readonly IUnityContainer container;
public UnityServiceHost(
[NotNull] IUnityContainer container,
[NotNull] Type serviceType,
Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
this.container = container;
}
protected override void OnOpening()
{
base.OnOpening();
if (Description.Behaviors.Find<UnityServiceBehavior>() == null)
{
Description.Behaviors.Add(new UnityServiceBehavior(container));
}
}
}
public class UnityServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
IUnityContainer container = new UnityContainer();
UnityContainerConfigurator.Configure(container);
return new UnityServiceHost(container, serviceType, baseAddresses);
}
}
WCF應用程序web.config僅包含基本信息: 無端點,無服務定義。
現在,假設我們有SecurityService與定義:
<%@ ServiceHost Language="C#" Debug="true"
Service="myNamespace.SecurityService"
Factory="myNamespace.UnityServiceHostFactory" %>
現在,我可以添加服務引用SecurityService到我的客戶。 一個該步驟中,生成客戶端的web.config:
<basicHttpBinding>
<binding name="BasicHttpBinding_ISecurityService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
<endpoint address="http://localhost/wcf-app/SecurityService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISecurityService"
contract="SecurityServiceReference.ISecurityService" name="BasicHttpBinding_ISecurityService" />
在這一點上我這個配置對於統一:
container.RegisterType<SecurityServiceClient>(new InjectionConstructor());
而在客戶端應用程序,我可以用它(我在這裏不提及構造注入):
var securityService = DependencyResolver.Current.GetService<SecurityServiceClient>();
而這一切都有效!但是這不,如果我想使用的WSHttpBinding ...
-------------配置的WSHttpBinding ------------
爲了啓用wsHTTPBinding,我在WCF應用程序的web.config中配置了它。作爲BasicHttpBinding的其餘部分,它沒有包含關於綁定,終止等的任何信息。
但現在我的wsHttpBinding說:
<bindings>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceBehavior" name="myNamespace.SecurityService">
<endpoint address="" binding="wsHttpBinding"
bindingConfiguration="wsHttpEndpointBinding"
name="wsHttpEndpoint" contract="myNamespace.ISecurityService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<serviceCertificate findValue="CN=myClientCert" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
並添加服務參考客戶端應用程序後,它會產生:
<wsHttpBinding>
<binding name="wsHttpEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
我手動添加behaviorConfiguration = 「CertBehavior」,那就是:
<behaviors>
<endpointBehaviors>
<behavior name="CertBehavior">
<clientCredentials>
<clientCertificate findValue="CN=myClientCert"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
,現在當我想用團結來解決它:
var securityService = DependencyResolver.Current.GetService<SecurityServiceClient>();
我總是得到空...
什麼是有趣的,當我創建簡單實例:
var client = new SecurityServiceReference.SecurityServiceClient();
它工作正常...所以肯定問題不是用錯的wsHttpBinding配置連接,而是從web.config中結合團結+的wsHttpBinding ...
任何一個可以幫助我解決這個問題?
丹尼爾
它看起來更像是你自己的代碼中的問題。如果Unity無法創建實例,並且它嘗試創建它調用構造函數的實例,則Unity會觸發異常 - 這種調用不會導致「null」。 –