This is the point, I have a WCF service, it is working now. So I begin to work on the client side. And when the application was running, then an exception showed up: timeout. So I began to read, there are many examples about how to keep the connection alive, but, also I found that the best way, is create channel, use it, and dispose it. And honestly, I liked that. So, now reading about the best way to close the channel, there are two links that could be useful to anybody who needs them:
1. Clean up clients, the right way
2. Using Func
In the first link, this is the example:
IIdentityService _identitySvc;
...
if (_identitySvc != null)
{
((IClientChannel)_identitySvc).Close();
((IDisposable)_identitySvc).Dispose();
_identitySvc = null;
}
So, if the channel is not null, then is closed, disposed, and assign null. But I have a little question. In this example the channel has a .Close() method, but, in my case, intellisense is not showing a Close() method. It only exists in the factory object. So I believe I have to write it. But, in the interface that has the contracts or the class that implemets it??. And, what should be doing this method??.
Now, the next link, this has something I haven't try before. Func<T>. And after reading the goal, it's quite interesting. It creates a funcion that with lambdas creates the channel, uses it, closes it, and dipose it. This example implements that function like a Using() statement. It's really good, and a excellent improvement. But, I need a little help, to be honest, I can't understand the function, so, a little explanatino from an expert will be very useful. This is the function:
TReturn UseService<TChannel, TReturn>(Func<TChannel, TReturn> code)
{
var chanFactory = GetCachedFactory<TChannel>();
TChannel channel = chanFactory.CreateChannel();
bool error = true;
try {
TReturn result = code(channel);
((IClientChannel)channel).Close();
error = false;
return result;
}
finally {
if (error) {
((IClientChannel)channel).Abort();
}
}
}
And this is how is being used:
int a = 1;
int b = 2;
int sum = UseService((ICalculator calc) => calc.Add(a, b));
Console.WriteLine(sum);
Yep, I think is really, really good, I'd like to understand it to use it in the project I have.
And, like always, I hope this could be helpful to a lot of people.
the UseService method accepts a delegate, which uses the channel to send request. The delegate has a parameter and a return value. You can put the call to WCF service in the delegate.
And in the UseService, it creates the channel and pass the channel to the delegate, which should be provided by you. After finishing the call, it closes the channel.
The proxy object implements more than just your contract - it also implements IClientChannel which allows control of the proxy lifetime
The code in the first example is not reliable - it will leak if the channel is already busted (e.g. the service has gone down in a session based interaction). As you can see in the second version, in the case of an error it calls Abort on the proxy which still cleans up the client side
You can also do this with an extension method as follows:
enum OnError
{
Throw,
DontThrow
}
static class ProxyExtensions
{
public static void CleanUp(this IClientChannel proxy, OnError errorBehavior)
{
try
{
proxy.Close();
}
catch
{
proxy.Abort();
if (errorBehavior == OnError.Throw)
{
throw;
}
}
}
}
However, the usage of this is a little cumbersome
((IClientChannel)proxy).CleanUp(OnError.DontThrow);
But you can make this more elegant if you make your own proxy interface that extends both your contract and IClientChannel
interface IPingProxy : IPing, IClientChannel
{
}
To answer the question left in the comment in Jason's answer, a simple example of GetCachedFactory may look like the below. The example looks up the endpoint to create by finding the endpoint in the config file with the "Contract" attribute equal to the ConfigurationName of the service the factory is to create.
ChannelFactory<T> GetCachedFactory<T>()
{
var endPointName = EndPointNameLookUp<T>();
return new ChannelFactory<T>(endPointName);
}
// Determines the name of the endpoint the factory will create by finding the endpoint in the config file which is the same as the type of the service the factory is to create
string EndPointNameLookUp<T>()
{
var contractName = LookUpContractName<T>();
foreach (ChannelEndpointElement serviceElement in ConfigFileEndPoints)
{
if (serviceElement.Contract == contractName) return serviceElement.Name;
}
return string.Empty;
}
// Retrieves the list of endpoints in the config file
ChannelEndpointElementCollection ConfigFileEndPoints
{
get
{
return ServiceModelSectionGroup.GetSectionGroup(
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None)).Client.Endpoints;
}
}
// Retrieves the ConfigurationName of the service being created by the factory
string LookUpContractName<T>()
{
var attributeNamedArguments = typeof (T).GetCustomAttributesData()
.Select(x => x.NamedArguments.SingleOrDefault(ConfigurationNameQuery));
var contractName = attributeNamedArguments.Single(ConfigurationNameQuery).TypedValue.Value.ToString();
return contractName;
}
Func<CustomAttributeNamedArgument, bool> ConfigurationNameQuery
{
get { return x => x.MemberInfo != null && x.MemberInfo.Name == "ConfigurationName"; }
}
A better solution though is to let an IoC container manage the creation of the client for you. For example, using autofac it would like the following. First you need to register the service like so:
var builder = new ContainerBuilder();
builder.Register(c => new ChannelFactory<ICalculator>("WSHttpBinding_ICalculator"))
.SingleInstance();
builder.Register(c => c.Resolve<ChannelFactory<ICalculator>>().CreateChannel())
.UseWcfSafeRelease();
container = builder.Build();
Where "WSHttpBinding_ICalculator" is the name of the endpoint in the config file. Then later you can use the service like so:
using (var lifetime = container.BeginLifetimeScope())
{
var calc = lifetime.Resolve<IContentService>();
var sum = calc.Add(a, b);
Console.WriteLine(sum);
}
Related
I've googled a lot and none of the answers seem to be answering my question, hopefully it'll not be a duplicate.
I'm working on a service which I would not rather rebuild completely and keep it as it was and just implement my part of a deal into it.
There is a service which has an instance of a wcf gateway created by autofac, it is a SingleInstance() as such:
public static void RegisterMyService(ContainerBuilder builder)
{
builder.Register(c => new DesiredGatewayInterceptor());
builder
.Register(
c =>
{
const string BindingName = "BasicHttpBinding_My_PortType";
Uri endpointAddress = null;
ClientSection servicesSection = (ClientSection)WebConfigurationManager.GetSection("system.serviceModel/client");
foreach (ChannelEndpointElement endpoint in servicesSection.Endpoints)
{
if (endpoint.Name == BindingName)
{
endpointAddress = endpoint.Address;
break;
}
}
ChannelFactory<DesiredGateway> channel = new ChannelFactory<DesiredGateway>(
new BasicHttpBinding(BindingName),
new EndpointAddress(endpointAddress));
NameValueCollection section = (NameValueCollection)ConfigurationManager.GetSection("CredentialsConfiguration");
channel.Credentials.UserName.UserName = section["DesiredGatewayUser"];
channel.Credentials.UserName.Password = section["DesiredGatewayPassword"];
return channel;
})
.SingleInstance();
builder
.Register(c => c.Resolve<ChannelFactory<DesiredGateway>>().CreateChannel())
.InterceptTransparentProxy(typeof(DesiredGateway))
.InterceptedBy(typeof(DesiredGatewayInterceptor))
.UseWcfSafeRelease();
}
I've read about OperationContextScope() to manipulate headers but since this gateway instance is registered by autofac I am unable to cast appropriately to IContextChannel.
using (OperationContextScope scope = new OperationContextScope((IContextChannel)desiredGateway))
{
// Do some stuff with headers now
}
Such cast gives me an exception since instance of desiredGateway is wrapped in some kind of container, which is not IContextChannel, but once I create my own instance of a desiredGateway using channel.CreateChannel() I am able to cast to IContextChannel.
Target is to be able to inject a header value upon each call to desiredGateway, is there any way to achieve this without rebuilding existing implementation too much? Maybe there exists a cleaner way to achieve the above?
So I ended up removing those lines from gateway registration:
.InterceptTransparentProxy(typeof(DesiredGateway))
.InterceptedBy(typeof(DesiredGatewayInterceptor))
This allowed me to then cast to IContextChannel and I implemented interseption process within a class that owned an instance of the gateway using a generic method.
I am writing a c# console client to connect to SignalR service of a server. Using a bit of Wiresharking, Firebugging and examining the .../signalr/hubs document on the server, I was able to connect on the default "/signalr" URL:
var connection = new HubConnection("https://www.website.com");
var defaultHub = connection.CreateHubProxy("liveOfferHub");
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Error opening the connection:" + task.Exception.GetBaseException());
}
else
{
Console.WriteLine("SignalR Connected");
}
}).Wait();
Now I need to find out
What hubs are there available on the server to connect to? (ask for a list of them)
What methods can I invoke on the hub? (ask for a list of them)
What services can I subscribe to? And what will be the names of the events I will be handling, and the classes of the objects I will be receiving?
The IHubManager interface or HubManagerExtensions class look promising, but I was not even able to find out, what classes implement it and how to use it. Asp.net/signalr offers only basic documentation and tutorials.
Thanks in advance for pointing me in the right direction!
I think what you are looking for is something like a WSDL for SignalR.
No, SignalR doesn't have something that complex. What you can get, manually, is from the SignalR proxy: ./signalr/hubs.
If you look at this code from the proxy
proxies.chatHub = this.createHubProxy('chatHub'); //hub name
proxies.chatHub.client = { };
proxies.chatHub.server = {
serverMethod: function (firstParameter, secondParameter, thridParameter) { //hub method and number of parameters
return proxies.chatHub.invoke.apply(proxies.chatHub, $.merge(["ServerMethod"], $.makeArray(arguments)));
}
};
you get only:
- hub names (chatHub)
- server methods and number of parameters (serverMethod, 3 parameters)
So, the only info is that your hub looks something like this:
[HubName("chatHub")]
public class ?? : Hub
{
public ?? ServerMethod(?? firstParameter, ?? secondParameter, ?? thridParameter)
{
??
}
}
The client methods are not really in any list and are used on the fly. You can catch them with Fiddler.
Could someone please explain to me how the request and response model works in WCF? I have a simple service that exposes a method called getRateOfExchange with a single integer parameter that returns rateOfExchange[], but the Reference.cs file that is generated from the service contains lots of classes:
getRateOfExchange (seems to be the parameters)
getRateOfExchangeRequest
getRateOfExchangeResponse
I have tried every permutation of these classes and their methods but nothing works. Intuitively you would expect to create a request object with the parameter object as a parameter, and then pass this request to the method on the response that executes the request to the sever.
But no.
It has to be painful.
Can someone please explain?
UPDATE
Thank you Gigi, but my classes don't look like that.
If I follow your model, my request would look like this:
CharterServices.charterServiceClient proxy = new CharterServices.charterServiceClient();
using (OperationContextScope scope = new OperationContextScope(proxy.InnerChannel));
{
using (proxy as IDisposable)
{
var response = proxy.getRateOfExchange()
}
}
However, my getRateOfExchange() method requires a getRateOfExchange object, so the above code doesn't compile.The getRateOfExchange class contains parameters that are the parameters to the proxy.getRateOfExchange() method. I have tried creating an instance of this class and passing it the above method, like this:
using (proxy as IDisposable)
{
var rateOfExchange = new Service.getRateOfExchange()
{
charterEnquiryId = 1550003668
};
using (OperationContextScope scope = new OperationContextScope(proxy.InnerChannel));
{
using (proxy as IDisposable)
{
var response = proxy.getRateOfExchange(rateOfExchange);
foreach (var rateOfExcchange in response)
{
Debug.WriteLine(rateOfExcchange.fromCurrencyName);
}
}
}
}
but it hangs when trying to call getRateOfExchange().
Aaargh! I know the service is working because I can execute a request in SoapUI to the same WSDL.
Can you help?
It's actually not painful at all. Once you generate the proxy/client classes, you just create an instance of the client and then call the methods as if they were local method calls.
I can't explain the whole process here, but I'll instead refer you to the intro I wrote over a year ago which explains the whole process in terms of a simple example.
You can test the service using the WCF Test Client even before you've written your own client. Writing the client is very easy if you use the Service References.
Here's an excerpt from the code from that blog post illustrating how to use client code, modified to have a using block and use the var keyword for brevity:
static void Main(string[] args)
{
using (var service = new ServiceReference1.Service1Client())
{
var response = service.GetData(5);
Console.WriteLine(response);
Console.ReadLine();
}
}
The system was throwing an exception which was not being caught, so the component model decided to hang! Fixed it now.
Suppose rateOfExchange is a List of integers, I have just added 10 numbers to it, from 1 to 10.
Then this list is sent as a parameter to the getRateOfExchange method of the service client object.
List<int> rateOfExchange=new List<int>();
for(int i=0;i<10;i++)
{
rateOfExchange.Add(i);
}
//Service Call
ServiceClient obj=new ServiceClient();
var response=obj.getRateOfExchange(rateOfExchange);
foreach(var item in response)
{
Console.WriteLine(item);
}
Console.ReadLine();
Hope it helps.
The scenario is RPC over message queues - since the underlying mechanism is asynchronous, clients should specify how long they want to wait for a response before timing out. As the client, which of these two code snippets would you rather use?
Most importantly: as a user of the GetResponseTo() method, why would you prefer one over the other? How does your choice make your code more extensible, more readable, more testable, etc?
try
{
IEvent response = _eventMgr.GetResponseTo(myRequest, myTimeSpan);
// I have my response!
}
catch(TimeoutException te)
{
// I didn't get a response to 'myRequest' within 'myTimeSpan'
}
OR
IEvent myResponse = null;
if (_eventMgr.GetResponseTo(myRequest, myTimeSpan, out myResponse)
{
// I got a response!
}
else
{
// I didn't get a response... :(
}
For your information, here's the current implementation of GetResponseTo():
public IEvent GetResponseTo(IEvent request, TimeSpan timeout)
{
if (null == request) { throw new ArgumentNullException("request"); }
// create an interceptor for the request
IEventInterceptor interceptor = new EventInterceptor(request, timeout);
// tell the dispatcher to watch for a response to this request
_eventDispatcher.AddInterceptor(interceptor);
// send the request
_queueManager.SendRequest(request);
// block this thread while we wait for a response. If the timeout elapses,
// this will throw a TimeoutException
interceptor.WaitForResponse();
// return the intercepted response
return interceptor.Response;
}
Neither first nor second, I would like to use the Task Parallel Library, which is the recommended way of doing all things asynchronous beginning with .NET 4.5:
Task<IEvent> task = _eventMgr.GetResponseToAsync(myRequest);
if (task.Wait(myTimeSpan))
{
// I got a response!
}
else
{
// I didn't get a response... :(
}
You could look to use AutoResetEvent class this will handle the plumbing for second one.
Try to avoid your first code snippet as exceptions are expensive
Personally i would prefer the exception Version. If i specify some timeout my opinion is that this IS a exception then if i couldn't get a result within the specified timespan. I don't think event based notification is the best decision here. The following Logic depends on the result so it doesn't make Sense for me.
But if you want to provide asynchronous Methods too, the Task thing is a good idea like stated by dtb
Exceptions are heavy and messy, each API method call should be wrapped by try/catch/finally to hanle custom exception. This approach is not developer-friendly so I do not like it.
Considering that GetResponse() call itself is synchronous for API consumer - it is pretty normal to return a value of operation, but I would suggest introducing something more abstract and informative rather than simple bool state, so you can return any state provided by the underlying messaging system, this could be a custom error code, message, or even object. So since this is API - put interface as well:
enum OperationStatus
{
Unknown,
Timeout,
Ok
}
// pretty simple, only message and status code
interface IOperationResult<T>
{
OperationStatus Status { get; }
string Message { get; }
T Item { get; }
}
class GetResponseResult : IOperationResult<IEvent>
{
...
}
class EventManager
{
public IOperationResult<IEvent> GetResponseTo(
IRequest request,
TimeSpan timeInterval)
{
GetResponseResult result;
// wait for async request
// ...
if (timeout)
{
result = new GetResponseResult
{
Status = OperationStatus.Timeout,
Message = underlyingMessagingLib.ErrorMessage
};
}
else
{
result = new GetResponseResult
{
Status = OperationStatus.Ok,
Item = response
};
}
return result;
}
}
I have elected to use the out parameter.
I wanted to mark someone else as the answer, but I am not able to do so. I attempted to implement the TPL-based approach, but was unable to do so, based on the question/answer that I linked in my comments.
I do not want to muddy my event model by introducing even more concepts, as #sll suggests.
And even though #dasheddot prefers the exception Version, #sll has a good point that someone trying to send a bunch of requests and get a bunch of responses in a loop might have to deal with a lot of exceptions.
// potentially 10 exceptions? meh... let's not go down this road.
for(int i=0;i<10;i++)
{
try
{
IEvent response = _eventMgr.GetResponseTo(myRequest, myTimeSpan);
// I have my response!
}
catch(TimeoutException te)
{
// I didn't get a response to 'myRequest' within 'myTimeSpan'
}
}
I'm building a T4 template that will help people construct Azure queues in a consistent and simple manner. I'd like to make this self-documenting, and somewhat consistent.
First I made the queue name at the top of the file, the queue names have to be in lowercase so I added ToLower()
The public constructor uses the built-in StorageClient API's to access the connection strings. I've seen many different approaches to this, and would like to get something that works in almost all situations. (ideas? do share)
I dislike the unneeded HTTP requests to check if the queues have been created so I made is a static bool . I didn't implement a Lock(monitorObject) since I don't think one is needed.
Instead of using a string and parsing it with commas (like most MSDN documentation) I'm serializing the object when passing it into the queue.
For further optimization I'm using a JSON serializer extension method to get the most out of the 8k limit. Not sure if an encoding will help optimize this any more
Added retry logic to handle certain scenarios that occur with the queue (see html link)
Q: Is "DataContext" appropriate name for this class?
Q: Is it a poor practice to name the Queue Action Name in the manner I have done?
What additional changes do you think I should make?
public class AgentQueueDataContext
{
// Queue names must always be in lowercase
// Is named like a const, but isn't one because .ToLower won't compile...
static string AGENT_QUEUE_ACTION_NAME = "AgentQueueActions".ToLower();
static bool QueuesWereCreated { get; set; }
DataModel.SecretDataSource secDataSource = null;
CloudStorageAccount cloudStorageAccount = null;
CloudQueueClient cloudQueueClient = null;
CloudQueue queueAgentQueueActions = null;
static AgentQueueDataContext()
{
QueuesWereCreated = false;
}
public AgentQueueDataContext() : this(false)
{
}
public AgentQueueDataContext(bool CreateQueues)
{
// This pattern of setting up queues is from:
// ttp://convective.wordpress.com/2009/11/15/queues-azure-storage-client-v1-0/
//
this.cloudStorageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
this.cloudQueueClient = cloudStorageAccount.CreateCloudQueueClient();
this.secDataSource = new DataModel.SecretDataSource();
queueAgentQueueActions = cloudQueueClient.GetQueueReference(AGENT_QUEUE_ACTION_NAME);
if (QueuesWereCreated == false || CreateQueues)
{
queueAgentQueueActions.CreateIfNotExist();
QueuesWereCreated = true;
}
}
// This is the method that will be spawned using ThreadStart
public void CheckQueue()
{
while (true)
{
try
{
CloudQueueMessage msg = queueAgentQueueActions.GetMessage();
bool DoRetryDelayLogic = false;
if (msg != null)
{
// Deserialize using JSON (allows more data to be stored)
AgentQueueEntry actionableMessage = msg.AsString.FromJSONString<AgentQueueEntry>();
switch (actionableMessage.ActionType)
{
case AgentQueueActionEnum.EnrollNew:
{
// Add to
break;
}
case AgentQueueActionEnum.LinkToSite:
{
// Link within Agent itself
// Link within Site
break;
}
case AgentQueueActionEnum.DisableKey:
{
// Disable key in site
// Disable key in AgentTable (update modification time)
break;
}
default:
{
break;
}
}
//
// Only delete the message if the requested agent has been missing for
// at least 10 minutes
//
if (DoRetryDelayLogic)
{
if (msg.InsertionTime != null)
if (msg.InsertionTime < DateTime.UtcNow + new TimeSpan(0, 10, 10))
continue;
// ToDo: Log error: AgentID xxx has not been found in table for xxx minutes.
// It is likely the result of a the registratoin host crashing.
// Data is still consistent. Deleting queued message.
}
//
// If execution made it to this point, then we are either fully processed, or
// there is sufficent reason to discard the message.
//
try
{
queueAgentQueueActions.DeleteMessage(msg);
}
catch (StorageClientException ex)
{
// As of July 2010, this is the best way to detect this class of exception
// Description: ttp://blog.smarx.com/posts/deleting-windows-azure-queue-messages-handling-exceptions
if (ex.ExtendedErrorInformation.ErrorCode == "MessageNotFound")
{
// pop receipt must be invalid
// ignore or log (so we can tune the visibility timeout)
}
else
{
// not the error we were expecting
throw;
}
}
}
else
{
// allow control to fall to the bottom, where the sleep timer is...
}
}
catch (Exception e)
{
// Justification: Thread must not fail.
//Todo: Log this exception
// allow control to fall to the bottom, where the sleep timer is...
// Rationale: not doing so may cause queue thrashing on a specific corrupt entry
}
// todo: Thread.Sleep() is bad
// Replace with something better...
Thread.Sleep(9000);
}
Q: Is "DataContext" appropriate name for this class?
In .NET we have a lot of DataContext classes, so in the sense that you want names to appropriately communicate what the class does, I think XyzQueueDataContext properly communicates what the class does - although you can't query from it.
If you want to stay more aligned to accepted pattern languages, Patterns of Enterprise Application Architecture calls any class that encapsulates access to an external system for a Gateway, while more specifically you may want to use the term Channel in the language of Enterprise Integration Patterns - that's what I would do.
Q: Is it a poor practice to name the Queue Action Name in the manner I have done?
Well, it certainly tightly couples the queue name to the class. This means that if you later decide that you want to decouple those, you can't.
As a general comment I think this class might benefit from trying to do less. Using the queue is not the same thing as managing it, so instead of having all of that queue management code there, I'd suggest injecting a CloudQueue into the instance. Here's how I implement my AzureChannel constructor:
private readonly CloudQueue queue;
public AzureChannel(CloudQueue queue)
{
if (queue == null)
{
throw new ArgumentNullException("queue");
}
this.queue = queue;
}
This better fits the Single Responsibility Principle and you can now implement queue management in its own (reusable) class.