I am using WCF DataService I have a method:
[OperationContract]
public List<string> GetAges()
{
return _registrationData.GetAges();
}
on my client side, I instantiate it this way:
_registrationDataServices = new RegistrationDataServiceClient();
it now exposes a delegate
_registrationDataServices.GetAgesCompleted += GetAgesCompleted;
and a function call:
_registrationDataServices.GetAgesAsync()
the problem with this is that the call to the service will be asynchronous and the results comes in the delegate function, I want to be able to call the service and wait (block) until the results come back, how can this be done using WCF ?
I have to use a wcf, because I have a silverlight application that needs data from a database, the WCF is being called from a .NET assembly as my data access layer.
It is a very bad practice to call web service from a Silverlight/WPF application synchronously. The sync call would hang your UI until the web service call has ended, which will cause bad user experience.
However, if you're still up for it, here is a very helpful link.
Don't call it synchronously -- you will block the UI thread. Users usually think their software has crashed if the UI is frozen.
Ideally you would make a modal busy indicator that animates and shows 'progress' while you wait for the call to come back, and it goes away when you receive the Completed event.
Even if you were still convinced that blocking the UI thread was OK in your case, you can't actually call it synchronously! It was designed this way for a reason - go with the flow.
Related
Someone else created a WSDL service for me in Java. There is so far only one simple method to call. We tested this method in a C# console app by adding a service reference with the service's url. If I make a call to the generated method that has 'Async' at the end, I get an error. However, since the synchronous method is available, making calls to that work perfectly.
The trouble is, when I add a service reference to the same service from within a Silverlight project, the synchronous method is not available. A call to the async method also errors out.
Is there a different way I can do this so I can call the synchronous method from Silverlight?
I am currently developing a windows form application as the subscriber for my WCF service and a asp.net application as the publisher for the service.
Whenever I launch the service or the client, and attempt to "Connect" (AKA subscribe) to the service, it would take awhile to load before it displays a successful message or exception handling. And while the thing "loads", the windows form sort of "hangs" temporary until the thing loads finish.
Is it possible to create a loading effect while they are "loading" to feedback to the user? Anyone can guide me on how to actually start developing this effect.
Thanks!
You can use asynchronous service calls. Before calling the asynchronous call you can show graphical representation of this and in the completion of the asynchronous call you can stop displaying the progress of the call.
Refer to this link to know how you can call the wcf service asynchronously.
I have WPF application that needs to access WCF service at start ( login window ). Each time application runs on Windows 7 it freezes on login until gets a responce from WCF. Is there any way to design this process differently?
It sounds like you need to make your calls asynchronously. Either start the call on a new thread (preferably using a Task), or call the WCF service using an asynchronous design pattern.
Put the WCF call in a background thread
There are two causes for something perceived as "freezing" when carrying out WCF Service Calls:
Calling the service in a synchronous fashion will block your UI thread until the call has completed. This bad and the reason why Silverlight forbids synchronous calls and forces you to follow the Begin/End Async pattern for any kind of RPC - be it WebRequest or WCF Layer. By default the async methods are not generated when adding a service reference to your WPF project but you can turn it on using Configure Service Reference.
The second cause is less obvious. The initial service client instantiation can take almost 3 seconds - even on fast machines. That's why you are well advised to QueueWorkUserItem the proxy instantiation and the BeginXXX call even when using the async pattern.
If you need the response from this service call to start the application, you can use a background thread to call this service and handle the return value. While this thread is consuming the service you can display your window or a splash screen.
If you don't need the retrun value from this service method you can use [OperationContract(IsOneWay=true)] on your service. So that you don't need to worry about threading and stuff.
You're calling a WCF call on the main thread, Therefore it will appear to crash.
You can either, put it in a thread and call it at the start of your app.
Put it in a background process ( if you're in visual studio you can drag this off the tool bar)
You can do threads quite easily by defining a Thread, then defining a threadstart, passing in your login WCF call, and the call thread.start(); and pass in your threadstart you defined.
A background worker is pretty similar, you can put your code in the backgroundWorker1_DoWork() method
Or make your WCF call Async, so it will send off the login response, and your login code will call on the "OnTaskCompleted" method( you could also put it on a new thread as well, but don't really have to)
Try this thread for Async WCF calls
How to make a call to my WCF service asynchronous?
I'm not sure if I'm on the right lines but this is what I'm trying to do, I have a Silverlight application and a WCF service, the Silverlight app "subscribes" to the WCF service using PollingDuplex and the service can send data to any connected clients which works.
The service is marked with [ServiceContract(CallbackContract = typeof(IServiceCallback))] and it is single instanced
The problem is there is another service which should be able to call a standard method on this service to pass it data that will get distributed to the connected Silverlight clients, but because of the above settings it requires it to use callbacks (I can't change the other service).
Is there a way to have both types of operations, callback and standard in the same service if that makes sense?
Thanks for your time
Yes. It is possible. I guess CallbackContract parameter will not stop you from using your service as a regular request/response service (though I have not tried it).
But for the same contract, you may have to define two end points with different bindings, one with PollingDuplexHttpBinding and another one with basicHttpBinding (with silverlight this is the only other option).
You have to make sure that you are calling the right operation from the clients using duplex and basic http bindings.
I am planning to use WCF (not ria) in conjunction with Entity Framework 4 and STE (Self tracking entitites). If I understand this correctly my WCF should return an entity or collection of entities (using LIST for example and not IQueryable) to the client (in my case Silverlight).
The client then can change the entity or update it. At this point I believe it is self tracking? This is where I sort of get a bit confused as there are a lot of reported problems with STEs not tracking.
Anyway, then to update I just need to send back the entity to my WCF service on another method to do the update. I should be creating a new OBJECTCONTEXT every time? In every method?
If I am creating a new objectcontext every time in every method on my WCF then don't I need to re-attach the STE to the objectcontext?
So basically this alone wouldn't work??
using(var ctx = new MyContext())
{
ctx.Orders.ApplyChanges(order);
ctx.SaveChanges();
}
Or should I be creating the object context once in the constructor of the WCF service so that 1 call and every additional call using the same WCF instance uses the same objectcontext?
I could create and destroy the WCF service in each method call from the client - hence creating in effect a new objectcontext each time.
I understand that it isn't a good idea to keep the objectcontext alive for very long.
You are asking several questions so I will try to answer them separately:
Returning IQueryable:
You can't return IQueryalbe. IQueryable describes query which should be executed. When you try to return IQueryable from service it is being executed during serialization of service response. It usually causes exception because ObjectContext is already closed.
Tracking on client:
Yes STEs can track changes on a client if client uses STEs! Assembly with STEs should be shared between service and client.
Sharing ObjectContext:
Never share ObjectContext in server environment which updates data. Always create new ObjectContext instance for every call. I described reasons here.
Attaching STE
You don't need to attach STE. ApplyChanges will do everything for you. Also if you want to returen order back from your service operation you should call AcceptChanges on it.
Creating object context in service constructor:
Be aware that WCF has its own rules how to work with service instances. These rules are based on InstanceContextMode and used binding (and you can implement your own rules by implement IInstanceProvider). For example if you use BasicHttpBinding, default instancing will be PerCall which means that WCF will create new service instance for each request. But if you use NetTcpBinding instead, default instancing will be PerSession and WCF will reuse single service instance for all request comming from single client (single client proxy instance).
Reusing service proxy on a client:
This also depends on used binding and service instancing. When session oriented binding is used client proxy is related to single service instance. Calling methods on that proxy will always execute operations on the same service instance so service instance can be stateful (can contains data shared among calls). This is not generally good idea but it is possible. When using session oriented connection you have to deal with several problems which can arise (it is more complex). BasicHttpBinding does not allow sessions so even with single client proxy, each call is processed by new service instance.
You can attach an entity to a new object context, see http://msdn.microsoft.com/en-us/library/bb896271.aspx.
But, it will then have the state unchanged.
The way I would do it is:
to requery the database for the information
compare it with the object being sent in
Update the entity from the database with the changes
Then do a normal save changes
Edit
The above was for POCO, as pointed out in the comment
For STE, you create a new context each time but use "ApplyChanges", see: http://msdn.microsoft.com/en-us/library/ee789839.aspx