I'm studying alternatives to implement a true asynchronous communication between a server and a client using WCF. I've, of course, bumped into AsyncPattern = true.
After some fussing around I discovered that AsyncPattern is used to make the service implementation rather than the interface asynchronous, that is, the service exposed to clients still is synchronous. For instance, assume a async pair called BeginMethod and EndMethod, like below:
[ServiceContract]
interface IMyService
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginMyMethod(...);
MyComplexResult EndMyMethod(...);
}
Now, the WSDL generated from that will only expose a single method called MyMethod:
<wsdl:portType name="IMyService">
<wsdl:operation name="MyMethod">
<wsdl:input wsaw:Action="http://tempuri.org/IMyService/MyMethod" message="tns:IMyService_MyMethod_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/IMyService/MyMethodResponse" message="tns:IMyService_MyMethod_OutputMessage"/>
</wsdl:operation>
</wsdl:portType>
The question is, is there any configuration that will force WCF to actually expose the two methods of the APM to clients?
What you are trying to achieve is not what this settings is for. You could re-craft WSDL but this is not a good approach.
You can try other messaging options e.g. OneWay and Duplex to achieve async call pattern from the client. See MSDN: What You Need To Know About One-Way Calls, Callbacks, And Events by Juval Lowy.
More details about OperationContractAttribute.AsyncPattern Property:
"Clients remain unaffected because the asynchronous method pair on the server is an implementation detail that does not affect the underlying Web Services Description Language (WSDL) description of the operation. Such methods appear to clients as a single operation with and correlated messages. WCF automatically routes inbound messages to the Begin method and routes the results of the End call to the outbound message. Client channels, therefore, can represent the method pair as either a single synchronous operation or as an asynchronous operation pair. In no case does the client representation affect the asynchronous implementation on the server in any way."
"Client contracts can use the AsyncPattern property to indicate an asynchronous method pair that the client can use to invoke the operation asynchronously. Typically, client applications use the ServiceModel Metadata Utility Tool (Svcutil.exe) tool and the /async option to generate a Begin and End method pair that the client can use to invoke the operation asynchronously". [this method pair BeginXXXX/EndXXXX is generated on the client]
Related
Trying to really 'get' endpoint contracts:
I understand offering different endpoints to support different bindings, but when would one define n endpoints for a service, and use different contracts? Seems that in most cases (bar IMetadataExchange) the endpoint contract would be the same no matter the protocol, no?
If most of the time the contract would be the same across all endpoints, would it have been too simplistic (and why?) to define the service contract on the parent service instead of on each endpoint (seems cumbersome/repetitive), while alllowing an override on the endpoint for when needed (eg: IMetadataExchange).
Thanks for help with the small questions that keep me up at night ;-)
OK, well - the service that you define in the <service> tag is the actual implementation code - the actual C# or VB.NET lines that make up the service. Therefore, it's a concrete class (which might even implement multiple service contracts). This is server-side only.
The endpoint however is the communications channel between the server and the client, and between those two, you want to share only the contract - never any concrete implementation of that contract. The endpoint will only ever be used for a single service contract - if your concrete service implements multiple contracts, you need to expose multiple endpoints to the clients to provide all that functionality.
Does that make things a bit clearer?
I'm in the process of writing a duplex WCF service using NetTcpBinding, and I've run into an architecture question that I think I know the answer to, but hope that I'm wrong.
Our service is stateful, and we've selected NetTcpBinding with PerSession InstanceContextMode. For various reasons, this is something that we require. I'm trying to break up our larger interface (where large blocks of the operations would not apply to many clients) into multiple smaller interfaces with the operations logically grouped. While it's simple enough to have a single service implementation implement all of the contracts, I'm not sure if it's possible to have multiple service contracts share a single channel (or, more to my requirement, a single session), and I'd definitely need to be able to do that in order to make this work.
I could, of course, include everything on one contract and throw FaultExceptions when an invalid operation is performed, but I'd really like to be able to break these up and not even add an endpoint for inapplicable contracts. Is what I'm looking for possible?
TL;DR Version:
I need to be able to do this:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
void Foo();
}
[ServiceContract]
public interface IServiceB
{
[OperationContract]
void Bar();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service : IServiceA, IServiceB
{
...
}
And be able to establish one session from the client to the service but use both IServiceA and IServiceB.
The default instance provider over a sessionful channel will give you an instance per connection in your case. You can however extend the instance provider to pick up an existing object from your own cache and return the same object.
How you correlate instances will be upto you using some special message header etc. The underlying channel/Connection will be different for each proxy and also use differnt buffers / concurrency models but you can allow service model to use the same instance.
http://msdn.microsoft.com/en-us/magazine/cc163590.aspx
I have a service which calls back the client.
the interface has this attribute :
[ServiceContract(Namespace = "rf.services", CallbackContract = typeof (ISendBAck), SessionMode = SessionMode.Required)]
Does the SessionMode field is mandatory ?
why do i need it here ?
If i remove it , it still works. but this is a downloaded working example. and i wanted to know why it is there from the first place.
In a situation where oneway oneway operations and callbacks are used, the processing of messages may be queued. The use of sessions is not mandatory but provides assurance that messages will be processed in the order they are received.
This assurances simply has a greater value to the client in scenarios where the call to the service might return before processing is completed.
I need to create a WCF service that will emulate some third-party service. That service has very complicated messages and wrappers for them, so I will simplify them in description.
I have WSDL of that service and created proxy class. But here the first problem occurs: all methods in proxy have
[System.ServiceModel.OperationContractAttribute(Action = "", ReplyAction = "*")]
So it is impossible to create WCF service with many methods: each for one method in proxy because every method must have unique Action. I think that third-party service has one method that handles all requests. And I created such method with needed KnownType attributes on RequestTypeBase and ResponceTypeBase. All proxy-class methods have one parameter of type, derived from RequestTypeBase.
And here is the main problem and question: when WCF service tries to deserialize message body, it throws an exception saying that expected elementName is "Process" (the name of my mega-method that processes all requests) but existing elementName is "RequestType1" (the name class with data that must be passed to "Process" method as parameter). So how can I receive such message?? Is there some attribute in WCF to not require the methodName as root of Message body? And I even not understand for what does WCF need that MethodName there if he already knows what method is called? Looks like redundancy with action specification.
Maybe simple MessabeBody example that is successfully processing by WCF, will help to understand what I mean:
<s:Body>
<TestMethod xmlns="someNamespace">
<x>1</x>
<str>param2</str>
</TestMethod>
</s:Body>
You could skip WCF deserialization completely on the service side by using the "universal service contract":
[ServiceContract]
public interface IUniversalRequestResponseContract
{
[OperationContract(Action="*", ReplyAction="*")]
Message ProcessMessage(Message msg);
}
and then handle deserialization yourself working with the Message instance received.
If you are writing a stub emulation of some external service for testing purposes (I'm guessing), that is a good approach anyway because you can control exactly what is sent in the response.
From a little bit of reading around, it is my understanding that the only way to detect that a client has connected to my service is through writing my own code. I am using a Singleton service. I would like to display a message every time a client connects to my service that client x with ip xxx has connected. There is no built-in event that is generated? Am I correct?
No, I don't think there's any support in WCF for your requirement.
Not sure what you want to achieve with this, either. Your service class (in your case, just a single instance) really doesn't have any business putting up messages (on screen, I presume) - that really not it's job. The service class is used to handle a request and deliver a response - nothing more.
The ServiceHost class might be more of a candidate for this feature - but again, it's job really is to host the service, spin up the WCF runtime etc. - and it's really not a UI component, either.
What you could possibly do is this
have an Admin UI (a Winforms, console, or WPF app) running on your server alongside your service, providing an admin service to call
define a fast connection between the two services (using e.g. netNamedPipe binding which is perfect for intra-application messaging)
when your "real" service gets a call, the first thing it does is send out a message to the admin UI which can then pick up that message and handle it
That way, you could cleanly separate your real service and it's job (to provide that service) and the Admin UI stuff you want to do and build a cleanly separated system.
I have actually implemented my own connect, disconnect and ping service methods which I manually call from my client once the channel has been created. By using them as a kind of header section in all of my ServiceContract interface definitions (and their implementations, of course), they form an makeshift "base service definition" that only requires a bit of cut-n-paste.
The string-based parameters of connect and disconnect will be used to send client info to the server and return server info and (perhaps a unique connection id) to the client. In addition a set of timing reference points may make its way in also.
Note how SessionMode is required and the individual OperationContract properties IsInitiating and IsTerminating are explicitly specified for each method, the end result being what I would call a "single-session" service in that it defines connect and disconnect as the sole session bookends.
Note also that the ping command will be used as the target of a timer-based "heartbeat" call that tests the service connection state and defeats ALL connection timeouts without a single config file :-)
Note also that I haven't determined my fault-handling structure yet which may very well add a method or more and/or require other kinds of changes.
[ServiceContract( SessionMode = SessionMode.Required )]
public interface IRePropDalSvr {
[OperationContract( IsInitiating=true, IsTerminating=false )]
string connect (string pClientInfo);
[OperationContract( IsInitiating=false, IsTerminating=true, IsOneWay=true )]
void disconnect (string pClientInfo);
// ------------------------------------------------------------------------------------------
[OperationContract( IsInitiating=false, IsTerminating=false )]
string ping (string pInp);
// ------------------------------------------------------------------------------------------
// REST OF ServiceContract DEFINITION GOES HERE
One caveat: while I am currently using this code and its implemention in my service classes, I have not verified the code yet.