PDA

View Full Version : WCF - ProxyFactory


jjarrel
11-24-2007, 04:17 AM
I am trying to work out the pattern for instantiating my client side, svcUtil generated proxys.

When a proxy is to be created, I need to create an create an EndPointAddress (service locator type thing) to pass to the ctor of the proxy. Then after the proxy is created, I need to adjust various settings on it like security, buffer size, etc. Then I can send it out, for use.

I don't want the ProxyFactory itself to have any specific reference to the service being instantiated.

Excerpt from ProxyFactory...

public Object Create(String shortName)
{
IApplicationContext context = ContextRegistry.GetContext();
object o = context.GetObject(shortName);

// how to do get this cast
ClientBase<TChannel> proxy = (ClientBase<TChannel>)o;

ResolveCertificate(proxy, "http://jjarrel:8080/someservice");
}

public static void ResolveCertificate<TChannel>(ClientBase<TChannel> proxy, Uri targetService) where TChannel : class
{snip}

Here is where I thought I was going...
<!-- the proxyFactor, which contains an instance method called 'CreateInstance' -->
<object id="proxyFactory"
type="whi.pw.core.webutil.ProxyFactory, whi.pw.core"
lazy-init="true"/>

<object id="eventLog" type="whi.pw.utilscreens.servicereferences.EventLogSvcCl ient, whi.pw.UtilScreens"
singleton="false"
factory-object="proxyFactory"
factory-method ="Create"
>
<constructor-arg name="shortName" value="eventLog"/>
</object>

It appears to me that when I use *my* proxyFactory then the ProxyFactory has to actually instantiate the proxyObject. I'd like to push this back into Spring.

I'd appreciate any suggestions.

Thanks.
jeff

Bruno Baia
11-26-2007, 04:21 PM
Hi,

I don't get it.
Are you trying to make you ProxyFactory class generic to be used with any client type ?

- Bruno

jjarrel
11-27-2007, 03:15 AM
Yes, any svcutil generated proxy.

In my configuration,the service is instantiated with an Endpoint address, with a DnsIdentity. Then after creating the proxy, a certificate is applied, a username, password is applied, and some http binding elements are adjusted.

I have found it a tough road to 'generally' instantiate a generic type like ClientBase<T>. I had hoped to push some of this wiring into Spring managed factory.

Here is what I have now..
public class EventLogDao : IDisposable
{
EventLogSvcClient _proxy;

public EventLogDao()
{
createProxy();
}

private void createProxy()
{
ServiceLocator serviceLocator = (ServiceLocator)Globals.Factory.GetObject("serviceLocator");
ServiceItem serviceItem = serviceLocator.GetService("EventLog");

_proxy = new EventLogSvcClient(serviceItem.EndpointName, serviceItem.EndPointAddress);
WCFProxyHelper.Prepare(_proxy, serviceItem);
}
<snip>



And then the proxyHelper.
public class WCFProxyHelper
{
private const string const_CertificateName = "xwssecurityserver";

public static void Prepare<TChannel>(ClientBase<TChannel> proxy, ServiceItem serviceItem) where TChannel : class
{
if (proxy.State == CommunicationState.Opened)
{
throw new InvalidOperationException("Proxy channel is already opened");
}

// use the .Uri from the endPoint
applyCertificate(proxy,serviceItem.EndPointAddress .Uri);

// apply the password
proxy.ClientCredentials.UserName.UserName = serviceItem.UserName;
proxy.ClientCredentials.UserName.Password = serviceItem.Password;

adjustHttpElements(proxy);
}

/// <summary>
/// Applies the certificate to the incoming wcf proxy (byref).
/// </summary>
/// <typeparam name="TChannel">The type of the channel.</typeparam>
/// <param name="proxy">The proxy.</param>
/// <param name="targetService">The URL of the target service.</param>
private static void applyCertificate<TChannel>(ClientBase<TChannel> proxy, Uri targetService) where TChannel : class
{

StoreLocation certLoc = StoreLocation.LocalMachine;
StoreName certNameRoot = StoreName.TrustedPublisher;
X509FindType certType = X509FindType.FindBySubjectName;

X509CertificateRecipientClientCredential clientCredential;
clientCredential = proxy.ClientCredentials.ServiceCertificate;

clientCredential.SetScopedCertificate(certLoc, certNameRoot, certType, const_CertificateName, targetService);

proxy.ClientCredentials.ServiceCertificate.SetDefa ultCertificate(certLoc, certNameRoot, certType, const_CertificateName);

return;
}

private static void adjustHttpElements<TChannel>(ClientBase<TChannel> proxy) where TChannel : class
{
HttpTransportBindingElement httpElement;
httpElement = (HttpTransportBindingElement)getBindingElement(pro xy, typeof(HttpTransportBindingElement));

httpElement.MaxReceivedMessageSize = 524288;
httpElement.MaxBufferSize = 524288;
}

private static BindingElement getBindingElement<TChannel>(ClientBase<TChannel> proxy, Type bindingType) where TChannel : class
{
CustomBinding binding = (CustomBinding)proxy.Endpoint.Binding;
foreach (BindingElement item in binding.Elements)
{
if (item.GetType().Name == bindingType.Name)
{
return item;
}
}
return null;
}
}