I have an application in WCF that runs in all machines on my customer. But just one works like a server in the net.
In this model, every time the WCF "client" is called, he call your WCF "server" to obtain your response.
So, I have this configuration on my Interface:
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
MyObjectReturn CheckUpdate(string foo1, string foo2, string foo3);
In my code, this:
MyObjectReturn myObjReturn = new MyObjectReturn();
if (this.Master)
{
myObjReturn.Code = 15000;
myObjReturn.Message = "New Update found";
return myObjReturn;
}
else
{
var myTask = Task<MyObjectReturn >.Factory.StartNew(() =>
{
ServerContractClient server = new ServerContractClient(master.Url);
return server.CheckUpdate(foo1, foo2, foo3);
}
return myTask.Result;
}
When the WCF "client" calls his "server", the return is always null! If I do not use the "Task . Factory.StartNew", I get a Bad Request error
Any tip?
Uh, first, "server" and "client" are the preferred nomenclatures.
Second, Servy has a point that if you want the data back immediately, there's no real point in starting a thread. That said, threads are fun! Who doesn't want to thread? To do it properly you'll have to revise your application a bit, but for now you'll at least have to design the WCF method to be asynchronous, and the client making the call needs to know it's asynchronous; otherwise the result is null, as you experienced. Best starting point is here.
I'm ashamed to say it, but the problem was not what I thought. I noticed that when I called the WCF Server via browser, my return was not null. It was then that I realized that my Binding was the real problem. I noticed that there were two errors:
1) My Bindding is created via code. As noted in my interface, I declared my WebMessageBodyStyle as WrappedRequest. But when creating the Binding Client, I was using Wrapped;
2) The namespace of my ServiceBehavior and DataContract were different, which also caused confusion in WCF.
This link helped me clarify this last point:
WCF Web Service Call to Another WCF Web Service returns no data
Anyway, thank you all who gave me very valuable tips on this problem.
Related
I have access to WSDL file of a specific .asmx web service that contains a SendDataAsync method - basically I specify the TimeStamp and Value to be send. I uploaded the WSDL file to my project in Visual Studio 2019 as a connected service (Add->Connected Service->Microsoft WCF Web Service Reference Provider->Browse->I added location of the WSDL file and specified the service that included SendDataAsync method). After that I created a new client and tried to use my method like that:
ServiceSoapClient client = new ServiceSoapClient(ServiceSoapClient.EndpointConfiguration.ServiceSoap);
client.SampleData sd = new client.SampleData();
sd.TStamp = DateTime.Now;
sd.Value = 10;
client.SendDataAsync(sd);
Unfortunately, it doesn't work. I don't receive any errors or exceptions so I tried to check the response from the web service via Fiddler. I found out that actually nothing is being transmitted. No connection is being made, nothing. Now I try to understand what I'm doing wrong. Is my way of using the method defined on the web service wrong? Or maybe the method doesn't actually do what the name suggests? Or could the problem be related to the fact that the method is Async? Any suggestions are welcome! :)
According your description,I made a demo.The asynchronous method in demo is automatically generated by the client-side according to SendData, that is, the server-side has no SendDataAsync method, and the server-side only has SendData.
public void SendData(SampleData data)
{
Console.WriteLine(data.TStamp);
Console.WriteLine(data.value);
Console.WriteLine("success");
}
This is the SendData method of the server-side.
public System.Threading.Tasks.Task SendDataAsync(Client_SOAP.ServiceReference1.SampleData data) {
return base.Channel.SendDataAsync(data);
}
This is an asynchronous method automatically generated by the client-side.
ServiceReference1.Service1Client service1Client = new Service1Client();
SampleData sampleData = new SampleData();
sampleData.value = 10;
sampleData.TStamp = DateTime.Now;
service1Client.SendDataAsync(sampleData);
service1Client.Close();
Console.ReadLine();
This is the client-side calling asynchronous methods.
This is the execution result of the server-side after the client-side calls.
In another case,if your asynchronous method is implemented by the server-side, there are three ways for the server to implement asynchronous operation: the task-based asynchronous pattern, the Event-based Asynchronous Pattern, the IAsyncResult asynchronous pattern.For the different asynchronous model used by the server-side, the client calls in different ways.
The following link details the asynchronous invocation of the client-side:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/synchronous-and-asynchronous-operations
Okay, thanks to both the comment from Paulo Morgado and the answer from Ding peng I managed to solve my problem. The proper way of using asynchronous method, such as SendDataAsync in my case, is with the await operator. I changed the method invocation from:
client.SendDataAsync(sd);
to:
response = await client.SendDataAsync(sd);
I also had to change void Main to async Main and the method works now :)
I have desktop application, that uses WCF services. I have got great usability improve when I implemented async WCF calls.
My question is: what is the best practice to initialize service client?
In previous realization there was single static object with credentials and a public method GetClient(), that was creating new ServiceClient before every call. In application there was commonly used such construction:
using (var svc = ServiceClientFactory.GetClient()) {
var data = svc.CallMethod(...);
some_application_context.specific_attribute = data;
}
so, before any call, was created new client, that was destroyed immediately after operation was finished and received data was used.
My question is: is it the best practice to call client constructor before every call?
I've tried to create single static client object, that is initialized once at startup and destroyed once on application closing, but I haven't got any notional performance gain.
Seems like it works fine, but I wonder if there any not very obvious obstacles in using single client? And what is recommended?
It's kind of a broad question, it depens on a lot of factors and also on style I guess.
When using reliable sessions or sessions in general you have to store the reference of course.
When calling the service many times it might be better to store the reference, or it might not. Better profile it then and there.
I always store a reference and create a property which check if the client is null or in the Faulted State.
Service.ServiceClient ShippingService
{
get
{
if (mService == null || mService.State == CommunicationState.Faulted)
{
mService = new Service.ServiceClient("netTcpService");
mShippingService.Open();
}
return mService;
}
}
You should look at dependency injection for getting your service references. Effectively it would be similar if not the same performance to what your doing now but it would make long term management easier and allow easier unit testing.
Most of the WCF overhead is connection negotiation so singleton vs new on each call won't really end up making a huge difference.
I have a client application that consumes a number of services. It's not always immediately obvious when a service is down or incorrectly configured. I own the service side code and hosting for most of the services, but not all of them. It's a real mixed bag of client proxies - different bindings (basichttp/wshttp/nettcp), some have been generated using svcutil.exe, while others are made programatically with ChannelFactory where the contract is in a common assembly. However, I always have access to the address, binding and contract.
I would like to have a single component in my client application that could perform a basic check of the binding/endpoint config and the service availability (to show in some diagnostic panel in the client). As a minimum I just want to know that there is an endpoint at the configured address, even better would be to find out if the endpoint is responsive and supports the binding the client is trying to use.
I tried googling and was surprised that I didn't find an example (already a bad sign perhaps) but I figured that it couldn't be that hard, all I had to do was to create a clientchannel and try to open() and close() catch any exceptions that occur and abort() if necessary.
I was wrong - in particular, with clients using BasicHttpBinding where I can specify any endpoint address and am able to open and close without any exceptions.
Here's a trimmed down version of my implementation, in reality I'm returning slightly more detailed info about the type of exception and the endpoint address but this is the basic structure.
public class GenericClientStatusChecker<TChannel> : ICanCheckServiceStatus where TChannel : class
{
public GenericClientStatusChecker(Binding binding, EndpointAddress endpoint)
{
_endpoint = endpoint;
_binding = binding;
}
public bool CheckServiceStatus()
{
bool isOk = false;
ChannelFactory<TChannel> clientChannelFactory = null;
IClientChannel clientChannel = null;
try
{
clientChannelFactory = new ChannelFactory<TChannel>(_binding, _endpoint);
}
catch
{
return isOk;
}
try
{
clientChannel = clientChannelFactory.CreateChannel() as IClientChannel;
clientChannel.Open();
clientChannel.Close();
isOk = true;
}
catch
{
if (clientChannel != null)
clientChannel.Abort();
}
return isOk;
}
}
[Test]
public void CheckServiceAtNonexistentEndpoint_ExpectFalse()
{
var checker = new GenericClientStatusChecker<IDateTimeService>(new BasicHttpBinding(), new Endpointaddress("http://nonexistenturl"));
// This assert fails, because according to my implementation, everything's ok
Assert.IsFalse(checker.CheckServiceStatus());
}
I also tried a similar technique with a dummy testclient class that implemented ClientBase with the same result. I suppose it might be possible if I knew that all my service contracts implemented a common CheckHealth() method, but because some of the services are outside my control, I can't even do that.
So, is it even possible to write such a simple general purpose generic service checker as this? And if so how? (And if not, why not?)
Thanks!
Have you looked at WCF Discovery?
WCF Discovery allows a client to search for a service based on
different criteria including contract types, binding elements,
namespace, scope, and keywords or version numbers. WCF Discovery
enables runtime and design time discovery. Adding discovery to your
application can be used to enable other scenarios such as fault
tolerance and auto configuration.
For a first attempt, you could query the endpoint to see if it supports the expected contract.
The big benefit is that you can have the client “discover” which service it wants to talk to at runtime. Which removes a lot of the client side configuration errors that you are likely used to seeing.
You need to check out SO-AWARE. It is a web service management tool that can manage SOAP or REST WCF-based service across your organization. Further it has a Test Workbench!
Here are a couple of videos that show it off too:
Part 1
Part 2
To put it in perspective, this is so complex that these people make a living doing it, I don't think it's something you want to realistically build on your own.
I have a question regarding Task. I have a WCF app which has a method ReceiveEmpInfo which will be called from a client app.
WCF Server app:
public void ReceiveEmpInfo(string EmpName, string EmpId)
{
DifferentClass.SaveEmpToDB(string EmpName, string EmpId);
return;
}
My requirement is I want to return this method call (ReceiveEmpInfo()) once I call the method SaveEmpToDB(), I don’t want to hold the client call until the SaveEmpToDB() method saves the data to the database. I’m thinking of using Task, but I’m not sure whether it will solve my requirement.
Please give me your suggestions.
Thanks,
Joe
Yes, it will. Once you call Task.Start() your WCF method can return and the task will run in the "background". You have to be very careful, especially if you're running this WCF service inside of IIS. If these tasks are very long running and the IIS application pool shuts down (or gets restarted) your task is going to get whacked [potentially] in the middle of its work.
BTW: I'm assuming you're referring to: System.Threading.Tasks.Task
Use callbacks, and do async calls to db or whatever,
see example http://msdn.microsoft.com/en-us/library/ca56w9se.aspx
This is a lot like this post:
How to make a call to my WCF service asynchronous?
I think the links in the popular answer should help.
If this is a one-way fire-and-forget operation you can simply make the operation one-way. This will not block the client for the duration of the method execution.
[ServiceContract]
interface ISomeContract
{
[OperationContract(IsOneWay = true)]
void ReceiveEmpInfo(string EmpName, string EmpId)
}
I call a WCF service from multiple threads at the same time, but the response comes empty. If i have like 10 threads working in parallel calling the service, only 1 returs the data, the rest of them return all properties with null value. The service is consumed by another project in the same solution in VS. The service refference is obtained by discovery(so the service is not hosted in IIS).
Why do you think I get this behaviour?
If I only allow one thread at a time with:
myList.AsParallel().WithDegreeOfParallelism(1).ForAll(x => Worker(x));
all is fine, but I need at least 5 to speed things up. Worker method calls the WCF service.
public void Worker(object cui)
{
MyData mf = null;
mf = (new AnalyseService.AnalyseServiceClient()).GetDataFromWCFService((string)cui, true);
}
On the server the response is always correct, but when it reaches the client it may have it's properties equl null
It turned out that VS was having some problems with this.