Client's method description for WCF service - wcf

I have a WCF service (hosted in windows-service) and a client for it.
They interact as follows: client sends a request, service gets it and returns HTTP 200. Also client passes its address for the answer in the WS-Addressing header. For the moment that's all
After a few hours windows-service should send a result for that request. Client has a web-method that will get the result. So the question is: where should be a description (name of the method, its parameters) for the client's method that will get the result? Should the client expose its WSDL, or should I put that description in my WSDL (if it works that way)?

As I understand your scenario, you have two services, let's call them Service A (hosted in a Windows Service) and Service B. Service B sends a request to Service A (in other words, it's acting like a client) to have Service A start a long-running task of some sort.
When the task is complete, Service A needs to send the results to Service B. Since it's a long-running task, using a duplex binding would not be ideal. However, Service A could call a method exposed by Service B to send the results.
Something like this:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
public void StartWork();
}
[ServiceContract]
public interface IServiceB
{
[OperationContract]
public void ReceiveResults(ResultData data);
}
where ResultData is some object containing the results (could be a simple type as well, this is simply for illustration). ServiceA's StartWork can return void (the response will still be sent to the client, since it's not marked as IsOneWay=true). Semi-pseduo code follows:
Start the task:
ServiceAClient client = new ServiceAClient();
client.Open();
client.StartWork();
client.Close();
Service A sends the results to Service B when the task is complete:
ResultData results = new ResultData();
ServiceBClient client = new ServiceBClient();
client.Open();
client.ReceiveResults(results);
client.Close();
In this case, the method to receive the results will be part of Service B's WSDL, as Service A will call that method.

Related

How to allow all Operations and Namespaces

I'm new to WCF, but not new to C# and .Net. and am using Visual Studio 2008 and .Net 3.5.
I'm trying to build a Web Service that can receive any inbound Request XML and any namespaces. It would behave like a transparent receiver and simply intake the inbound request XML.
Once I get the request I'm going to pass it to some custom .Net C# Project to invoke a MQPUT to IBM MQ Series.
Right now I have the WCF Web Service Application receiving a generic inbound operation called RunTest(). I consume the WSDL into SoapUI, build a sample request and breakpoint and it works. But, when I try to pass our company request XML it doesn't land on the breakpoint.
Here is the ServiceContract and Operation:
[ServiceContract(Name="IService1",Namespace="cfg-env=http://www.co.com/schemas/cfg- env/")]
//[ServiceContract]
public interface IService1
{
[OperationContract]
void RunTest();
[OperationContract]
void CFX();
Here is the Method for the Operation:
public void RunTest()
{ <<<it does break here using the request from the WSDL
string serviceName;
string queueManager;
string queue;
string requestMessage;
//Capture the Service Name
serviceName = "";
//Save the QueueManager
queueManager = "";
//Save the Request Queue
queue = "";
//Save the Message
requestMessage = "";
//Call MQ Put
Engine eng = new Engine();
try
{
eng.Put(serviceName, queue, requestMessage, queueManager);
}
The main thing I need to do is receive the inbound XML, interogate it for a few pieces of information and call this Method to do the MQPUT function on MQ.
The inbound namespace will look like the above but I'd like to ensure I can receive and interogate any XPATH that may be namespace qualified. If I have to I can work with the cfg-env namespace prefix exclusively as our services do use that as a standard.
What are my key hurdles in doing this in VS 2008 WCF? If you have any links please pass them along if you can.
I believe you specify the name property on the OperationContract attribute as "*" to accept all requests. To make the parameter itself schema agnostic, it should be of type System.ServiceModel.Channels.Message.
What you are building is a "WCF router".
Included in the latest .NET release is a configurable Routing Service.
If the routing service doesn't meet your needs, building your own router is possible but can get really complicated when secure messages are a requirement. This set of MSDN articles is the best resource. They answer your question of how to have a service accept any message, and then continue on into addressing and security issues.
Building a WCF Router, Part 1
Building a WCF Router, Part 2

Time Consuming WCF service call blocks the other WCF service calls.

I am using a WCF service with my Silverlight 5 Application.
In one of my service calls I am doing a time consuming job. It takes 1 or 2 minutes to complete the event. I am not blocking the UI with busy indicators, so the user can still interact with the application.
The problem is when I do my first service call, it performs some time consuming operation. When the user loads some other, my second service call is not being processed until the first service is completed.
How can I perform the time consuming service call in separate thread to avoid other
calls waiting for this service completion?
WebService Code
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TestService
{[OperationContract]
public bool PerformFileScan(int fileID)
{
//Time Consuming Process
}
}
cs
client.PerformFileScanAsnc(docId);
client.PerformFileScanCompleted += new EventHandler<.PerformFileScanCompletedEventArgs>(client_PerformFileScanCompleted);
You have two options:
Make your call asynchronous on the server side. You can use the TPL and just write something like Task.Factory.StartNew(...)
You can decorate your service implementation with the ServiceBehavior attribute and set the ConcurrencyMode to Multiple:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class YourService
{
}
Then wcf will schedule calls to your service in parallel. But then you have to ensure that your service code is threadsafe!

What operation contract can I put for my WCF service?

I am currently developing a C# Windows Form Application that I intend to let it interact with a server. The server will receive posting from a mobile application that I have developed and whenever a posting is received, my Windows Form Application should be notified and give me a notification. And for now I am starting to create a WCF service for it.
This is a sample scenario of what I meant,
E.g. My mobile application sends an message over to my server. Once my server receives the message, my windows form application should display a new notification showing the content of the message received.
so for the operationcontract of the service, what type of methods should i put in in order for me to receive the posting?
e.g.
[OperationContract]
bool receivePosting(int n);
I'm not quite clear as to which direction you want to communicate:
your "server" needs to notify the Winforms app of a new posting that's been saved?
or:
your Winforms app asks the "server" about new postings??
I put "server" in quotes because in WCF world, that's a term being used for a specific role.
Assuming the first option, you need to do this:
your Winforms app needs to be the WCF server - e.g. it needs to define a service contract, operation contract and data contract - and implement those
your "posting server" would be the WCF client in this case; whenever a posting is received/stored, then you would call the WCF service in your Winforms app to send a notification (so really, in this setup, your roles are reserved - the Winforms app is the WCF server)
As for the operation contract - what does your Winforms app need to know about the new posting? Just the fact a new posting has been received? The whole contents of the posting, or just parts of it??
In any case, you need to define a method on your WCF service that the "posting server" can call and pass all relevant info to the Winforms WCF Server - you don't want to have to make two or more calls just for one notification.
So you Service Contract might be:
[ServiceContract]
public interface IPostingService
{
[OperationContract]
void NotifyAboutPosting(Posting post);
}
and your Posting class would be the data contract:
[DataContract]
public class Posting
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public DateTime PostingTimestamp { get; set; }
}
Whatever you need to send between those two parties - define it in your data contract which is the argument to your service call

How can I callback the client and expose a new Channel with instance context

I'm making a WCF service with netTcpBinding which has a main lobby with multiple chatrooms which the clients can enter. The Lobby class implements ILobby as the service contract.
When a client wishes to enter a room I want to callback the client exposing a new Channel containing the InstanceContext for the room he just entered but after much searching I am doubting that this is possible.
For example on the Service side I might have
class Lobby : ILobby
{
Dictionary<string, Chatroom> rooms;
public void JoinRoom(string roomname)
{
if (rooms[roomname].TryEnter()) {}
}
}
class ChatRoom : IChatRoom
{
public bool TryEnter(string username)
{
ILobbyCallback callback =
OperationContext.Current.GetCallbackChannel<ILobbyCallback>();
// How do I do this next bit?
callback.JoinedRoom(pass some instance context here);
return true;
}
}
On the client side callback method I want
public void JoinedRoom(InstanceContext for the room on the service side)
{
// Create a new WCF proxy using above InstanceContext
// Create a WPF UI for the new room passing the proxy so it can communicate
// with the room class directly without going via the root service
}
Is this possible? What's the best practice for spawning new classes with their own contracts on the service side? Or do I just have to bundle everything into one massive MyService class and handle everything myself?
You cannot pass instance context as parameter to any operation contract. It doesn't make sense because that context has local scope. It is called "instance context" = it is context of current service instance. In duplex scenario both client and server has its own service:
Clients calls server's service through its proxy
Server calls client' service through received callback channel
Server's service instance context has meaning only on the server. It is not clear what you are trying to achieve (except very complex architecture).
If you want to share context on client you can try to pass around the instance context used for the very first proxy you created - I'm not sure if it will work but you can try it
If you want to share service instance context between multiple proxies you must develop your own IInstanceContextProvider and perhaps also your own IInstanceProvider (depending on what you want to achieve), wrap them in behavior and add them to the service. That will put whole complexity of session handling and correct instance releasing under your control (it obviously has its pros and cons).
But is it really needed? When I look at your code I see that one service and one proxy is enough. Also your JoinRoom operation doesn't need to use callback at all, it can be just request response method.

How can I check connection is still valid for Silverlight client using net.tcp for duplex?

I'm putting together a WCF service using net.tcp and netTcpBinding to get duplex comms with my Silverlight client. I call into the service from the Silverlight app and the service calls out to another server, passing it a callback method in the WCF service class. The remote server calls back several times and each time it does, the WCF service uses the callbackchannel to send the data to the Silverlight client. It all works nicely most of the time.
If the user puts in a big request, I get a TimeoutException after a large number of callbacks have already worked. (Clearly, there's some work to do elsewhere to prevent this but I'd like to robustify the service, first.)
I was expecting to do some kind of 'if (client.ConnectionState == faulted)' check before trying to call back to the Silverlight client but I can't seem to find the object that holds the state of the connection. Is there one? Am I approaching this from the wrong side?
This is my first venture into a service net.tcp and duplex. I just moved house and my WCF bible is still in a box. Somewhere. :-) So, I can't do my usual background reading.
Any pointers would be gratefully received. Here's some bare code in case my description is too soupy:
private IActiveDirectoryClient client;
private AsyncSearchRunner runner;
public void Search(Request request)
{
this.client = OperationContext.Current.GetCallbackChannel<IActiveDirectoryClient>();
runner = new AsyncSearchRunner();
runner.Run(request.SearchRoot, request.SearchFilter, request.PageSize,
System.DirectoryServices.Protocols.SearchScope.Subtree, SendObjects);
}
private void SendObjects(List<DirectoryObject> items)
{
Response response = new Response();
response.DirectoryObjects = items.ToArray();
client.SendResponse(response);
}
Yes, there is a State property that is defined in the ClientBase<> class (all the proxy classes are derived from ClientBase<>).
There are some proxy wrappers out there that handle fault states of the connection and re-establish connections as needed. Google for "wcf proxy wrapper".
You can also home-brew something if you use some kind of ServiceLocator pattern.