How to set the leaseTimeout setting programmaticaly? - wcf

We have a WCF service (NetTcpBinding) that sits behind a load balancer. I've read that in order to avoid "stickyniss" I have lower the LeaseTime the channels get in the channel pool.
I've only found samples how to set this value using the config file, but I would like to set it programmaticaly, any pointers?

You can access the LeaseTimeout property via the TcpTransportBindingElement, through the ConnectionPoolSettings property:
TcpTransportBindingElement tcpBE = new TcpTransportBindingElement();
tcpBE.ConnectionPoolSettings.LeaseTimeout = TimeSpan.FromSeconds(1);
If you have a NetTcpBinding object, you'll need to first convert it into a CustomBinding, then access the binding element. The example below shows one way of doing this.
NetTcpBinding myOriginalBinding = CreateBinding();
CustomBinding newBinding = new CustomBinding(myOriginalBinding);
TcpTransportBindingElement tcpBE = newBinding.Elements.Find<TcpTransportBindingElement>();
tcpBE.ConnectionPoolSettings.LeaseTimeout = TimeSpan.FromSeconds(1);

Related

Using WS2007FederationHttpBinding with SOAP 1.1

Is there a way to use WS2007FederationHttpBinding binding, but generate SOAP 1.1 request envelop? I need to use WS2007FederationHttpBinding to authenticate using a bearer token acquired from an STS service. Here is my bindings:
private static Binding GetWS2007FederationHttpBinding()
{
var binding = new WS2007FederationHttpBinding(
WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
//binding.MessageVersion.Addressing = AddressingVersion.WSAddressingAugust2004;
//binding.MessageVersion.Envelope = EnvelopeVersion.Soap11;
// or
//binding.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;
return binding;
}
But I can't change binding.MessageVersion because it's a read-only property?
You would need a custom binding for that. One way would be to statically declare a custom binding equivalent to WS2007FederationHttpBinding - could take a while to fine tune it. Or you could create WS2007FederationHttpBinding in code (like you do), clone it into a custom binding:
CustomBinding outputBinding = new CustomBinding(federationBinding.CreateBindingElements());
and then find the text message encoding channel and change its soap version.

Resolve a URI to an EndpointAddress

I currently have a WCF client that is able to do ad-hoc service discovery to find (unknown) services running on the local subnet. I would like to implement a way for the user to specify a service endpoint to use by entering a URI into a text box, and for the client to resolve this URI to an EndpointAddress, and in the process gather additional metadata about the service. Namely, I need to gather the EndpointIdentity and additional data exposed in the Extensions property of the EndpointDiscoveryBehavior.
I am trying to achieve this by using DiscoveryClient.Resolve(), but I am only receiving null for the ResolveResponse.EndpointDiscoveryMetadata property.
String Address = "net.tcp://machine-name:12345/MyService"
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = new ResolveCriteria()
{
Address = new EndpointAddress(Address)
};
var result = discoveryClient.Resolve(criteria);
//scv is null here.....
var svc = result.EndpointDiscoveryMetadata;
I've found a lot of information out there regarding DiscoveryClient.Find(), but not so much about DiscoveryClient.Resolve().
So my questions are:
Is this the intended use of DiscoveryClient.Resolve()?
Is MetadataResolver more appropriate here?
How does one resolve an URI to a EndpointAddress and obtain other metadata?
I think you are trying to replicate functionality of svcutil.exe. In that case you may have to resolve the mex endpoint first and query service metadata from that endpoint (IMetaDataExchange). The SPN identity should be in the metadata.
Also see reference http://msdn.microsoft.com/en-us/library/ms733130.aspx
I achieved what I wanted to do like so:
String Address = "net.tcp://machine-name:12345/MyService"
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var endpoint = new EndpointAddress(new Uri(Address));
var criteria = new ResolveCriteria()
{
Address = endpoint
};
var result = discoveryClient.Resolve(criteria);
var mexClient = new MetadataExchangeClient(MetadataExchangeBindings.CreateMexTcpBinding());
var contracts = new List<ContractDescription>() { ContractDescription.GetContract(typeof(RuntimeService.Services.IWorkflowService)) };
var metaResult = MetadataResolver.Resolve(contracts, endpoint, mexClient);
var svc = metaResult.First();
I am able to get to the extension data through result and svc provides me with the correct EndpointAddress complete with the correct identity.
Thanks to #YK1 for pushing me in the right direction.

How to set the MaxReceivedMessageSize programmatically when using a WCF Client?

I want to set the MaxReceivedMessageSize property to some higher limit (Due to (400) Bad Request error) in my client programmatically.
This is the code I am using...
WCFServiceTestClient wcfClient =
new WCFServiceTestClient(new wsHttpBinding(), strServiceURL);
My service url is dynamic and hence cannot use the web.config.
//The following code doesn't seem to take effect
((WSHttpBinding)wcfClient.ChannelFactory.Endpoint.Binding)
.MaxReceivedMessageSize = 2147483647;
What am I doing wrong?
Have you tried re-ordering the calls so that you set the MaxReceivedMessageSize before instantiating the client? eg,
var binding = new wsHttpBinding();
binding.MaxReceivedMessageSize = Int32.MaxValue;
var wcfClient = new WCFServiceTestClient(binding, strServiceURL);
This may or may not help your 400 error, though.
I had similar problems in my wcf-service and I solved it with:
CustomBinding binding = (CustomBinding)PDAServiceContractClient.CreateDefaultBinding();
HttpTransportBindingElement httpBindingElement = new HttpTransportBindingElement();
httpBindingElement.MaxBufferSize = Int32.MaxValue;
httpBindingElement.MaxReceivedMessageSize = Int32.MaxValue;
binding.Elements.Add(httpBindingElement);
string address = PDAServiceContractClient.EndpointAddress.Uri.ToString();
m_proxy = new PDAServiceContractClient(binding, new EndpointAddress(address));
This works well, though it's not that obvious. It retains all the existing binding properties and only adjusts the MaxReceivedMessageSize (which, incidentally, also increases MaxBufferSize to the same size).
Dim oClient as WcfClient = New WcfClient
CType(oClient.Endpoint.Binding, ServiceModel.BasicHttpBinding).MaxReceivedMessageSize = Int32.MaxValue

WCF - Passing CurrentPrincipal in the Header

I have a WCF service that needs to know the Principal of the calling user.
In the constructor of the service I have:
Principal = OperationContext.Current.IncomingMessageHeaders.GetHeader<MyPrincipal>("myPrincipal", "ns");
and in the calling code I have something like:
using (var factory = new ChannelFactory<IMyService>(localBinding, endpoint))
{
var proxy = factory.CreateChannel();
using (var scope = new OperationContextScope((IContextChannel)proxy))
{
var customHeader = MessageHeader.CreateHeader("myPrincipal", "ns", Thread.CurrentPrincipal);
OperationContext.Current.OutgoingMessageHeaders.Add(customHeader);
newList = proxy.CreateList();
}
}
This all works fine.
My question is, how can I avoid having to wrap all proxy method calls in the using (var scope...{ [create header and add to OperationContext]?
Could I create a custom ChannelFactory that will handle adding the myPrincipal header to the operation context? Something like that would save a whole load of copy/paste which I'd rather not do but I'm not sure how to achieve it:)
Thanks
The correct time to set a WCF principal is via IAuthorizationPolicy, by specifying a custom policy in configuration. This covered in full here. If you try setting the principal at other points (an inspector, perhaps) it can get reset by the system.

How can I set the maxItemsInObjectGraph property programmatically from a Silverlight Application?

I have a Silverlight 3.0 application that is using a WCF service to communicate with the database, and when I have large amounts of data being returned from the service methods I get Service Not Found errors. I am fairly confident that the solution to it is to simply update the maxItemsInObjectGraph property, but I am creating the service client progrogrammatically and cannot find where to set this property. Here is what I am doing right now:
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
{
MaxReceivedMessageSize = int.MaxValue,
MaxBufferSize = int.MaxValue
};
MyService.MyServiceServiceClient client = new MyService.MyServiceProxyServiceClient(binding, new EndpointAddress(new Uri(Application.Current.Host.Source, "../MyService.svc")));
It's not defined in binding, but in Service Behavior.
In Silveright, maxItemsInObjectGraph defaults to int.MaxValue.
Here is an article on how to change it for .NET application, but not Silverlight: Programattically setting the MaxItemsInObjectGraph property in client
A snippet of the code:
protected ISecurityAdministrationService GetSecAdminClient()
{
ChannelFactory<ISecurityAdministrationService> factory = new ChannelFactory<ISecurityAdministrationService>(wsSecAdminBinding, SecAdminEndpointAddress);
foreach (OperationDescription op in factory.Endpoint.Contract.Operations)
{
DataContractSerializerOperationBehavior dataContractBehavior =op.Behaviors.Find<DataContractSerializerOperationBehavior>() as DataContractSerializerOperationBehavior;
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = 2147483647;
}
}
ISecurityAdministrationService client = factory.CreateChannel();
return client;
}
The following is a function that I've used inside a client object that inherits from
System.ServiceModel.ClientBase(Of IServiceName)
The purpose of the method is to programatically set the MaxItemsInObjectGraph value for each operation. This allows me to have much more complex structures.
Private Sub IncreaseObjectCount()
For Each op As System.ServiceModel.Description.OperationDescription In Me.Endpoint.Contract.Operations
For Each dscob As System.ServiceModel.Description.DataContractSerializerOperationBehavior In op.Behaviors.FindAll(Of System.ServiceModel.Description.DataContractSerializerOperationBehavior)()
dcsob.MaxItemsInObjectGraph = Integer.MaxValue
Next dcsob
Next op
End Sub
I usually call it in the constructors of the object.
Change the maxItemsInObjectGraph in your WCF service for each endpoint, changing it in Silverlight means the client will be able to support the behavior, but the service must support it aswell.
After changing it in your service, regenerate the proxy/update web service, and you will get a new ServiceReference.config, that will include the new maxItemsInObjectGraph value