One way web service still returns a response - wcf

I aplogise if my terminology is inaccurate, still deep in learning.
I am creating a web service to act as an intermediary between Silverlight and XMPP. To start all of this I have created a web service call to enable me to ask the server to log on on my behalf and the idea is that the server will log on and then push back to my client once complete.
I have based the idea on the code form this site: http://weblogs.asp.net/dwahlin/archive/2011/02/06/syncing-data-with-a-server-using-silverlight-and-http-polling-duplex.aspx
Now the problem I have is that the Register call I have created will use an asynchronous call to log into XMPP. But the register call itself is also asychronous. So I don't know the best way for a web service call to wait for another service's async call
What I thought of doing was making the Register a one way call with the idea being that my server will log into XMPP then push the client once logged in (or fileld etc)
[OperationContract(IsOneWay = true)]
void Register(string name, string password, string nickname);
But when I imported the Service Reference the class generated appears to have a RegisterCompleted() call which debug shows is invoked. But I thought one-way meant no response is called so why is it?

One Way means No Response Data. Internet protocols are a request-response model where there is an acknowledgement for the receipt of the request. Your Register service returns no data (void) so RegisterCompleted really did "completed accepting three string parameters and returned no data".
This is a good thing - now you know if you had a problem starting the registration or everything is good so business as usual until you hear back from the server. You don't know yet if you're actually registered yet so that's why your client continues to Poll the server until the server responds - good or bad.
His previous article references an good MSDN example on using the PollingDuplexHttpBinding.

Related

Turn off WCF SOAP Service for Maintenance and provide friendly message

I'm hosting some SOAP services with WCF. How can I turn off these services via config for the purposes of maintenance, etc., and provide a friendly message to the service consumer with something like "The service you've requested is down for maintenance."?
You would have to have a second service, that offered the same interface, same methods etc., that would all return that friendly message instead of a real result.
That might get a bit trickier when those service methods don't just return a string but a complex data object - where do you put that "friendly" message??
In reality I think this cannot really be done - since your services typically aren't "seen" by actual people, you cannot just put up an app_offline.htm file or anything like that.
Try to have as little downtime as possible, by e.g. setting up your new version of the service on a new port and testing it there, until you're confident enough to switch over.
With WCF, it's mostly an exercise of updating / copying around the appropriate config, so your service should never really be unavailable for any extended period of time (hopefully!).
If you really must, what you could do, is just have a replacement service that will always throw a FaultContract<ServiceDownForMaintenance> - but then all the clients calling your service would have to know about this and they would have to handle this case and present an error or information message. Your service can't really provide that...
How about this: create a custom ServiceBehavior to intercept my incoming requests to the service. Then, have the custom behavior check a user-defined flag in my config file, something like <add key="IsMyServiceUp" value="true" /> and if that value returns as false then throw a ServiceException with my friendly message and HTTP code of 503 - Service Unavailable.
Does that sound reasonable? Then all I have to do is change the flag in my config file to specify where the service is up or down.
Okay, so I've created a new Custom Behavior that implements IOperationBehavior. In the Validate method, I've got
public void Validate(OperationDescription operationDescription)
{
bool isServiceUp = Boolean.Parse(ConfigurationManager.AppSettings["IsOrderServiceUp"].ToString());
if (!isServiceUp)
{
throw new ServiceException(ServiceErrorCode.Generic_Server_Exception,
ServiceErrors.Generic_Server_Exception,
SoapFaultCode.Server);
}
}
The other implemented methods ApplyClientBehavior, ApplyDispatchBehavior and AddBindingParameters are all empty.
I have decorated one of my service operations with [ServiceStatusValidation] which is the class name of my custom behavior.
When I start the service and navigate to the operation with this decoration, I do NOT get the exception I've thrown. SOAP UI shows nothing as returned in the response pane, and my consuming REST facade gives a generic 400 error with The exception message is 'The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.'.
Any ideas? Should I be doing this logic in one of the other methods that I didn't implement instead of the Validate method?

Detect when client connected to wcf service

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.

WCF using Enterprise Library Validation Application Block - how to get hold of invalid messages?

I've got some WCF services (hosted in IIS 6) which use the Enterprise Library (4.0) Validation Application Block. If a client submits a message which fails validation (i.e. gets thrown back in a ValidationFault exception), I'd quite like to be able to log the message XML somewhere (using code, no IIS logs). All the validation happens before the service implementation code kicks in.
I'm sure it's possible to set up some class to get run before the service implementation (presumably this is how the Validation Application Block works), but I can't remember how, or work out exactly what to search for.
Is it possible to create a class and associated configuration that will give me access to either the whole SOAP request message, or at least the message body?
Take a look at using the Policy Injection Application Block...
I'm currently developing an application in which I intercept (using PIAB) all requests incoming to the server and based on the type of request I apply different validation behavior using the VAB.
Here's an article about integrating PIAB with WCF:
http://msdn.microsoft.com/en-us/magazine/cc136759.aspx
You can create different inteception mechanisms such as attributes applied to exposed operations.
You could log the whole WCF Message:
http://msdn.microsoft.com/en-us/library/ms730064.aspx
Or you could combine it with Enterprise Library Logging Application Block.
I found a blog post which seems to do what I want - you create a class that implements IDispatchMessageInspector. In the AfterReceiveRequest method, you have access to the whole incoming message, so can log away. This occurs after authentication, so you also have access to the user name - handy for logging. You can create supporting classes that let you assign this behaviour to services via attributes and/or configuration.
IDispatchMessageInspector also gives you a BeforeSendReply method, so you could log (or alter) your response message.
Now when customers attempt to literally hand-craft SOAP request messages (not even using some kind of DOM object) to our services, we have easy-to-access proof that they are sending rubbish!

wcf - transfer context into the headers

I am using wcf 4 and trying to transparently transfer context information between client and server.
I was looking at behaviors and was able to pass things around. My problem is how to flow the context received in the incoming headers to the other services that might be called by a service.
In the service behavior I intercept the the message and read the headers but don't know where to put that data to be accessible to the next service call that the current service might make.
What I am looking for is something like:
public void DoWork()
{
var someId = MyContext.SomeId;
//do something with it here and call another service
using(var proxy = GetProxy<IAnotherService>())
proxy.CallSomeOtherMethodThatShouldGetAccessTo_ MyContextualObject();
}
If I store the headers in thread local storage I might have problems due to thread agility(not sure this happens outside ASP.NET, aka custom service hosts). How would you implement the MyContext in the code above.
I chose the MyContext instead of accessing the headers directly because the initiator of the service call might not be a service in which case the MyContext is backed by HttpContext for example for storage.
In the service behavior I intercept
the the message and read the headers
but don't know where to put that data
to be accessible to the next service
call.
Typically, you don't have any state between calls. Each call is totally autonomous, each call gets a brand new instance of your service class created from scratch. That's the recommended best practice.
If you need to pass that piece of information (language, settings, whatever) to a second, third, fourth call, do so by passing it in their headers, too. Do not start to put state into the WCF server side! WCF services should always be totally autonomous and not retain any state, if at ever possible.
UPDATE: ok, after your comments: what might be of interest to you is the new RoutingService base class that will be shipped with WCF 4. It allows scenarios like you describe - getting a message from the outside and forwarding it to another service somewhere in the background. Google for "WCF4 RoutingService" - you should find a number of articles. I couldn't find antyhing in specific about headers, but I guess those would be transparently transported along.
There's also a two-part article series Building a WCF Router Part 1 (and part 2 here) in MSDN Magazine that accomplishes more or less the same in WCF 3.5 - again, not sure about headers, but maybe that could give you an idea.

View underlying SOAP message using vb.net

I have a VB.NET web service that calls a third party web service. How can I view the SOAP message generated by .NET before it is sent to the third party web service and how can I see the SOAP response before it is serialized by .NET.
When creating a standalone EXE, I see the Reference.vb file that is automatically generated, but don't see a similar file when my project is a web service. I have found lots of C# code to do this, but none in VB.NET.
Edit - Fiddler and TCP loggers are great, but will not work for my purposes. I need to be able to access the raw SOAP messages from within the application so I can log them or modify them. I need to do more than just see the messages going back and forth.
You can use fiddler or a tcp sniffer to filter and identify all outgoing and incoming traffic on your host.
This is if you want to see the xml request and response.
How about using an extension to allow you to examine the SOAP message?
Accessing Raw SOAP Messages in ASP.NET Web Services
http://msdn.microsoft.com/en-us/magazine/cc188761.aspx
I was trying to do the same thing and this seems to work for me:
Dim message As String = OperationContext.Current.RequestContext.RequestMessage.ToString()
I didn't think it would be that easy since most of the time ToString() returns the name of the class, but I tried it out and low and behold.
I know you asked this back in January so if since then you've figured out a better way let me know.
Please note that if you're catching the exception in a class that implements IErrorHandler then you have to perform this operation from within the ProvideFault() method instead of the HandleError() method because the context is closed before it gets to call the HandleError() method.
Hope this helps.