I have declared field "_accessToken" in my service implementation and initializing it inside a method call GetToken(). GetToken is the first method called by client. When client first time calls GetEmployees method which annotated with transaction, it returns the data. It checks _accesstoken value inside GetEmployees method which is not null in during first call However becomes null in subsequent calls!
What is the problem? Can anyone tell me.
Service Contract:
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IEmployeeService
{
[OperationContract]
LoginResponse Getoken(LoginRequest request);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
EmployeeResponse GetEmployees(EmployeeRequest request);
}
Service Implementation
private string _accessToken;
public TokenResponse GetToken(TokenRequest request)
{
_accessToken = new Guid();
}
[OperationBehavior(TransactionScopeRequired = true,TransactionAutoComplete = true)]
public EmployeeResponse GetEmployees(EmployeeRequest request)
{
if (_accessToken != null)
{
// Do processing
}
}
I'm not sure this has anything to do with transactions, rather your services instance management. I suspect you're using percall, in which case all calls get their own service instance. Try using per session, this should resolve your problem.
Here is some reading material: http://msdn.microsoft.com/en-us/magazine/cc163590.aspx
HTH,
Steve
The problem is in ServiceBehaviorAttribute ReleaseServiceInstanceOnTransactionComplete, which is set to true by default. While the attribute is enabled service instance will be destroyed after any transaction.
You can set the attribute to false, however it will make very complex solution and is bad architecture.
For example your service have two methods:
public void Method1()
{
//transaction
//use data base resources table1;
}
public void Method2()
{
//transaction
//use data base resources table1;
}
If the client calls Method1, then calls Method2 there can be in some cases deadlock, or Method2 will be waiting for releasing table1 by Method1.
Better use default settings. Or use PerCall session when session instance is recreated for every call.
Related
What I'm trying to do is the following:
1) I have the following WCF service contract:
[ServiceContract]
public interface IUploadService
{
[OperationContract]
ServiceData Upload(Request request);
}
[DataContract]
public class Request
{
[DataMember]
public long AbnNumber;
[DataMember]
public string Email;
}
2) This contract is implemented like this.
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
// Some code
}
}
In the "Some code" section I would like to call a validation class to validate the clients request, so something like this:
var result = validation.ValidateRequest(request);
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method? Like this:
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
var validation = new Validation();
var result = validation.ValidateRequest(request);
}
}
I know you can get around this by creating a constructor but as far as I know you can't create a constructor inside a WCF service implementation class, or am I wrong?
I'm new to WCF so if I'm totally heading the wrong direction please let me know.
Thanks
Personally I like as little as possible in my service methods. I would have a separate project to handle the Upload. This then allows you to reuse this code more easily, and to test the functionality without creating the service.
As to whether you should create your Validation like this it really depends on what it does, but generally I would make sure the Validation class implements an interface containing ValidateRequest(Request) and then inject that. You can then mock it in your tests if you need to.
So your service code would look like
public class UploadService : IUploadService
{
private readonly IUploadHandler _uploadHandler;
public UploadService(IUploadHandler uploadHandler)
{
_uploadHandler = uploadHandler;
}
public bool Upload(Request request)
{
//would possibly do some mapping here to create a different type of object to pass to the handler
_uploadHandler.Upload(request);
}
}
and the handler in a different project would look like
public class UploadHandler : IUploadHandler
{
private readonly IValidation _validator;
public UploadHandler(IValidation validator)
{
_validator = validator;
}
public bool Upload(Request request)
{
return _validator.ValidateRequest(request);
}
}
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method?
It comes down to whether you will be using Singleton or Per Call services. Usually it is better to have new instance of Service created for every request, and in that case it is OK to create all instances in your operation.
Interesting discussion on this topic Should WCF service typically be singleton or not?
If you decide to not to create Validation class for each then request there are two options:
Make it singleton
Create custom ServiceHostFactory for your service and initialize your Service in it (with constructor). Useful links on this topic:Extending Hosting Using ServiceHostFactory, Integrating StructureMap with WCF
Problem:
getting a deadlock exception message in the WCF client.
Scenario:
Service calls a client callback (this call is completely independent and is initiated by some condition on the server).
While inside the client callback function, the client calls a function in the service and that's when the deadlock exception is thrown:
This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute.
I tried to simplify the code as much as I can. I did read this article but still I cant find where the problem is: http://msdn.microsoft.com/en-us/library/cc294424.aspx
I'd appreciate any suggestions....
SERVICE:
[ServiceContract(Namespace = "http://abc.com/Core", SessionMode = SessionMode.Required, CallbackContract = typeof(ISvcCallback))]
public interface ISvc
{
// One way only - does not wait until operation completes and returns
// Can initiate session
[OperationContract(IsOneWay = true)]
void Initialize(string appId);
[OperationContract(IsInitiating = false)]
Account GetCurrentAccount();
}
public interface ISvcCallback
{
/// <summary>
/// Report status of the account
/// </summary>
/// <param name="acct"></param>
[OperationContract(IsOneWay=true)]
void AccountStatus(Account acct);
}
Service Implementation
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public class Svc : ISvc
{
public Account GetCurrentAccount()
{
SipAccount sipAcct = null;
try
{
Account acct = m_MyBusinessObject.GetCurrentAccount();
}
catch (Exception ex)
{
}
return Acct;
}
}
}
CLIENT:
public class CallbackHandler : WcfSipItfService.IWinSipItfCallback
{
public void AccountStatus(Account Acct)
{
try
{
// display accout status in UI by delegate-wrapped event
// delegate and event declarations are somewhere else
// and work fine...
if (DisplayAccountStatusEvent != null)
DisplayAccountStatusEvent(Acct);
}
catch (Exception ex)
{
....
}
}
private void OnDisplayAccountStatusEvent(Account acct)
{
// call service function results in deadlock
Account acct = GetCurrentAccount();
}
}
The service is Duplex - uses WSDualHttpBinding.
The deadlock appears to be due to you making a new out bound call while processing a callback from the previous call.
The error message states that you may be able to solve it by "specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute".
Edit
I missed the code that was off the screen. Couple of things to check:
Why do you need instance mode single?
Did you updated the service references after changing the concurrency mode?
What's your client? Is it a UI client? if so, you need to add callbackBehavior UseSynchronizationContext=false to client that implements callback contract.
Lets say I have 3 assemblies, Example.Core, Example.Contracts, Example.WcfServices. In my contracts assembly I define an interface and add some operation, e.g. ICalculator, which has operation Add(double a, double b). In my WcfServices assembly I have an implementation of ICalculator explosed as a Wcf service.
Now my question is this....in my Example.Core assembly how do I program against that interface while keeping everything decoupled (to allow me to have an alternative implementation of the interface). If I have a class that needs an ICalculator I can create one from say a ChannelFactory and use it, or I can inject an instance in the constructor. If I create one in the class then I am putting dependencies in my class on ChannelFactory/Wcf and I really don't want to do that. If I inject an instance in my constructor then how will the injecting class manage and tidy up the wcf service? It seems that although I have an interface I have no clean way of using it. I have looked at something like NInject, but I am not convinced that it would clean up the ChannelFactory if it faults (at least I haven't found any documentation that shows it knows when to call Abort rather than Close on the channel).
What I have ended up doing is implmenting my interface again and using the method described in this question: creating WCF ChannelFactory<T> and just recalling the methods on the service. This "smells" a bit to me as I am wrapping all my calls again just to ensure the channel is properly closed/aborted.
Has anyone any patterns/methods that cleanly have two implmentations of an interface, one of which is a Wcf service?
Thanks,
Mike.
I have used a variation of the answer linked in Mark's comment and this article here to come up with a solution that has worked for me.
Given the service contract you defined, step 1 will be to define an interface implementing your service and IClientChannel.
// Service Contract
public interface ICalculator
{
Add(double a, double b);
}
// Interface to expose Close and Abort
public interface ICalculatorChannel : ICalculator, IClientChannel { }
Step 2 involves creating reusable code that will handle creating the proxies and implementing the code to close or abort connections.
public class ServiceClient<T> where T : class, IClientChannel
{
private ProxyGenerator _generator = new ProxyGenerator();
public T CreateProxy(string endpointConfigurationName)
{
return _generator.CreateInterfaceProxyWithoutTarget<T>
(new WcfInterceptor<T>(endpointConfigurationName));
}
}
The T in ServiceClient<T> will take the ICalculatorChannel defined in step 1. The ProxyGenerator is part of the Castle project. Its usage here is to allow us to intercept the calls to the WCF service and perform pre and post actions.
public class WcfInterceptor<T> : IInterceptor where T : IClientChannel
{
private ChannelFactory<T> _factory = null;
public WcfInterceptor(string endpointConfigurationName)
{
_factory = new ChannelFactory<T>(endpointConfigurationName);
}
public void Intercept(IInvocation invocation)
{
T channel = _factory.CreateChannel();
try
{
invocation.ReturnValue = invocation.Method.Invoke
(channel, invocation.Arguments);
}
finally
{
closeChannel(channel);
}
}
}
As you can see, the Intercept method encapsulates the channel and the call to close the channel. The closeChannel method will handle the decision to call Close() or Abort().
private void closeChannel(T channel)
{
if (channel != null)
{
try
{
if (channel.State != CommunicationState.Faulted)
{
channel.Close();
}
else
{
channel.Abort();
}
}
catch
{
channel.Abort();
}
}
}
Now we create a class to wrap up the usage of this ServiceClient.
public class Calculator : ICalculator
{
private var _calcualtor = new ServiceClient<ICalculatorChannel>();
public void Add(double a, double b)
{
var proxy = _calculator.CreateProxy("endpointConfigGoesHere");
return proxy.Add(a, b);
}
}
Notice that the implementation of add no longer has to deal with the WCF connection concerns. The consuming class only has to know about the Service Contract. The ugliness of of dealing with faulted connections is now taken care of for us by the ServiceClient class.
The client need only take on one dependency now.
public class MyClient
{
private ICalculator _calculator;
public MyClient(ICalculator calculator)
{
_calculator = calculator;
}
}
And IOC can populate the client:
Bind<ICalculator>().To<Calculator>();
I want to know is there way of Event Handling in WCF.
I came across Callbacks in WCF, but i want to do Event Handling in WCF.
My requirement is like i want to raise event to particular clients not to all the clients using Event Handling in WCF and i also want to maintain session.
I have seen Publisher/Subscriber model in WCF which deals with Callback , but this model publish to all the clients who have subscribed but i want to publish only to selected clients.
I think that can be done using Events in WCF.
Client side :
public class Callbacks : IServiceCallback
{
public void CallToMyClient(string name)
{
this.CallToMyClient(name);
}
}
protected void Page_Load(object sender, EventArgs e)
{
Callbacks callback = new Callbacks();
ServiceClient client = new ServiceClient(new InstanceContext(callback));
client.SubscribeClient();
client.DoSomeWork();
}
There is no Event in WCF to notify it's client but there is a callback channel, the purpose of the callback channel is same as event though the working principle is totally different in both cases.
To notify a particular client what you could do is store callback channel of that client while subscribing to somewhere, (I prefer Dictionary in this case). Later you can pick the instance and invoke your callback method over that channel, doing so only one client will get notified.
UPDATE
If you are interested here is the code:
public interface IClientCallback
{
//Your callback method
[OperationContract(IsOneWay = true)]
void CallToMyClient(string name);
}
[ServiceContract(CallbackContract = typeof(IClientCallback))]
public interface ITestService
{
[OperationContract(IsOneWay = true)]
void SubscribeClient();
[OperationContract(IsOneWay = true)]
void DoSomeWork();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class ServiceImplementation : ITestService
{
private static readonly List<IClientCallback> CallbackChannels = new List<IClientCallback>();
/// <summary>
/// client should call this method before being notified to some event
/// </summary>
public void SubscribeClient()
{
var channel = OperationContext.Current.GetCallbackChannel<IClientCallback>();
if (!CallbackChannels.Contains(channel)) //if CallbackChannels not contain current one.
{
CallbackChannels.Add(channel);
}
}
public void DoSomeWork()
{
//Here write your code to do some actual work
//After you done with your work notify client
//here you are calling only the first client that is registered
IClientCallback callbackChannel = CallbackChannels[0];
callbackChannel.CallToMyClient("You are the only one receving this message");
}
}
WCF Duple Operation and UI Threads By jeff.barnes
Perhaps this can help you.
The WCF doesn't support event handler. Callback channel is the way for it
If you are using WCF for RPC(as apposed to web service or rest) you can use .Net Remoting to perfrom event invocation cross process.
You cannot use events. You can use callbacks to simulate events.
So I'm hosting WCF service in a WinForms application. I have the following
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerCall)]
public class Test : ITest
{
public string TestIt(string input)
{
Thread.Sleep(5000);
return "test";
}
}
I'm using Named Pipes and have two instances of another application that act as clients to the above WCF service (running in a WinForms application). I thought based on the ConcurrencyMode setting of Multiple that when Client1 calls the Test Service, Client2 doesn't have to wait till the first call is complete. However, when Client1 calls TestIt, Client2 blocks until the call from Client1 is complete!?!?! Shouldn't it make a new instance each time based on the above settings?
Also, is the best way to keep a WinForms application that is hosting a WCF service responsive is by running the WCF service on a separate thread?
NOTE: Setting [CallbackBehavior(UseSynchronizationContext = false)] on the Test class does not alleviate the problem. The service still only responds to one request at a time.
Sounds like you want to set this
http://msdn.microsoft.com/en-us/library/system.servicemodel.servicebehaviorattribute.usesynchronizationcontext.aspx
to false. By default, if there is a synchronization context when service.Open() happens, WCF will pick it up and use it. But if you don't want that feature, this flag is how to turn it off.
After digging into this a bit more the only way I was able to get this to work properly was to start the ServiceHost on a separate thread in the WinForms application. If you don't do that setting the ConcurrencyMode and InstanceContextMode attributes does nothing.
I had the same problem.
My class that implemented Callback also contained methods for wcf client, so when I was calling some method from remote service and service was calling Callback method, I was creating a deadlock.
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class AppContext : ICustomerOrderCallback
{
//WCF Proxy client
private CustomerOrderClient _client = null;
public AppContext()
{
InstanceContext context = new InstanceContext(this);
_client = new CustomerOrderClient(context);
_client.Subscribe(); //Remote method for subscribing callback
}
public void SendMessage(string message)
{
//Calling Remote method
_client.SendMessage(message);
}
//....code
//callback method
public void OnMessageReceived(string message)
{
//.....code
}
}
So I created a separate class for callback, added attribute CallBehavior to it and everything worked OK.
public class AppContext
{
private CustomerOrderClient _client = null;
private MyCallbackClass _myCallback = null;
public AppContext()
{
_myCallback = new MyCallbackClass();
InstanceContext context = new InstanceContext(_myCallback);
_client = new CustomerOrderClient(context);
_client.Subscribe();
}
public void SendMessage(string message)
{
_client.SendMessage(message);
}
}
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyCallbackClass : ICustomerOrderCallback
{
public void OnMessageReceived(string message)
{
//.....code
}
}