Implementing Callback on WCF DICOM Proxy Service - vb.net

I am trying to implement a DICOM proxy server using WCF. That it is DICOM isn't really important, except that it forces me to use a particular process for getting image files: Under DICOM, you set up a listener on a well known IPAddress/Port which is registered with an ID (AETITLE) on a server. You then send a query to that server, and at some time in the future (or maybe never) the server sends the image file directly to your listener.
My listener will be a method on the proxy, that will receive the DICOM file.
The proxy will work using WCF, receiving requests from the desktop client. In this case, the desktop client will send a request to the proxy using WCF, for a particular study UID (a GUID for the file from the actual server), I am then happy to have that thread block for a reply from the proxy until the file arrives at the listener, I might also, eventually, use callbacks - but the same problem applies.
So:
Client Proxy DICOM Server
|RegisterListener--------->|
|
|Request(StudyID)------->|
| |Request StudyID---------->|
| |
| |<--------------Send(DICOM)|
|<----------Return(DICOM)|
Is there a pattern or example I can use to implement this? I assume I need to register a pointer (delegate??) to the client making the request, so the proxy knows which client to return the image to when the listener gets the file from the DICOM server? Can I make a dictionary of (StudyUID, List(Of Delegate)) or some similar structure to get this to work (will be List(Of Delegate) as their could be multiple clients requesting the same study)?
Or is it better to just have the proxy thread watch a shared dictionary and wait until that entry is populated with the file? ie: have a shared dictionary of (StudyID, DICOMFile) that is monitored by the clients requesting thread and populated by the proxy listener? This would preclude me from using Async Callbacks though.
Any suggestions welcome. Hopefully this isn't too vague...

I solved this by implementing a nettcp WCF service. The service accepts a DICOM UID from the client and then stores this and the client session in a shared dictionary. It then registers a DICOM listener and queries the PACS server for an image.
Once the image is returned to the listener, the service looks for the UID from the image in the shared dictionary, serializes the image and triggers a callback on the client returning the image.
I still have a couple of issues to iron out, but overall this works effectively.
This tutorial got me started:
http://www.codeproject.com/Articles/596287/Broadcasting-Events-with-a-Duplex-WCF-Service

Related

Is there a way to listen to the upload events in the EMC's Documentum via .NET API?

i need to implement a windows service that connects to EMC's Documentum and receives an event every time a document is loaded.
The event should contain the reference to the document itself.
Is there a way to do it via API or do i have to do polling using a web service?
Quickest would be to implement this via polling.
Your Windows service can either
access DFS exposed service (that you need implement on DCTM side)
access docbase directly using DFC/.NET
But the question here is what is that you want to check?
Document loaded - If you are referring to dm_document object created (e.g. by a user/system or some sort of upload functionality) - you will need to register dm_audittrail for that event. Once that is in place your service or API call can check for dm_audittrail entries.
Alternatively you could use Documentum BOF (Business Object Framework) to write custom code that would be triggered every time for instance new document is being crated (or updated) - i.e. on specific predefined event.
This custom code could do whatever you like, like for instance broadcast JMS message to a queue that your Windows Service is listening. You see to implement the thing that you want (event based notification) you need some communication channel between your application and a content server.
Or simply just poll Docbase it every x seconds.
Guess you already know this but a lot of info can be found on:
https://community.emc.com/community/edn
Also BOF Guide (older version): https://developer-content.emc.com/developer/downloads/BusinessObjectsDevelopersGuide.pdf
I think you can use Rest Service. Documentum whole functionality exposed in rest service. https://community.emc.com/community/labs/archivedprojects/dctm_rest

WCF Proxy Caching + runtime endpoint modification

The project I am currently working in, we have over 30 wcf services, which are called a lot in our web application, we ran into performance issues and once of the solutions was to cache the proxy. So what we did is create a dictionary object and using the endpoint name as key, cached the channel factory object so that subsequent calls will pull from the cache rather than re-instantiating the channel factory object at every call. There are many implementations over on other forums.
But we ran into one issue, the way our system is setup is that our services reside on one or more servers, of which only one is active at any one time, if a server fails then another is used as a fail safe. When creating the channel factory before putting into the cache, we can get the latest endpoint address for a given service and then instantiate it. However in this scenario, if a server fails and we pull a channel factory object from the cache, it'll refer to an old endpoint address.
I was checking on forums whether it was possible to update the endpoint address in channel factory object, if this was doable I could update the channel factory object in the cache and use it from then, I don't think this is possible.
The only thing I came up with recently is, that we check for a possible 404 fault exception which will happen when an old endpoint address is hit, then get the latest endpoint address and recreate the channel factory, and update that in the cache.
If you guys have any other ideas, would be helpful. Kinda stuck at this point.
You can create the channel factory without specifying an endpoint address and pass it to the method CreateChannel later:
public TChannel CreateChannel(EndpointAddress address)

Using WCF to wrap an existing connected stream

I have both ends of a bi-directional connected Stream, which I want to do some communication over. The underlying implementation behind the stream isn't important, I want to work at the Stream level...
Rather than implement my own communications protocol for the stream, I want to use all of the existing WCF goodness to wrap the existing stream with with a bi-directional (request/response + callback) WCF communications channel.
My question is, how can I go about doing this...?
UPDATE:
I've gone down the path of implementing a custom transport. I've got this working, but I'm still not totally happy with it...
I've implemented an IDuplexSessionChannel to wrap the stream, along with appropriate IChannelFactory and IChannelListener, and a Binding Element for creating the channel factories. Now, I just pass through the connected stream, and eventually pass these into the transport channel when it is created.
So, I can create the client proxy for accessing the service via the stream as follows:
var callback = new MyCallback();
var instanceContext = new InstanceContext( callback );
var pipeFactory = new DuplexChannelFactory<IMyService>( instanceContext, new StreamBinding(clientStream),
new EndpointAddress("stream://localhost/MyService"));
var serviceProxy = pipeFactory.CreateChannel();
The problem I have is, it seems WCF is set on using a ServiceHost to create the server end of the channel, via a IChannelListener. In my case, I already have a connected stream, and I won't be able to listen for any more incoming connections. I can work around this, but I'd much rather not use a ServiceHost to create the server end of the channel, because I end up with a lot of obscure boilerplate and hacks to make it work.
Questions
I'm looking, therefore, for a better way to take the IDuplexSessionChannels, and wrap these into a Channel proxy at both the server and client ends.
Or maybe a different ServiceHost implementation that doesn't require a IChannelListener.
Really, the problem here is I don't want a single server, multiple client arrangement, I have a 1-1 relationship between my WCF Service and the client. Is there a correct way to instantiate one of these?
To put it yet another way, I want to create the Server-side service instance without using a ServiceHost.
Any suggestions would be appreciated at this stage.
Use a client at both ends. You will need to define your contracts carefully though. If you have ClientA and ClientB at either end of the stream, when ClientA sends a request, ClientB will expect it to look like what it sees as it's defined callback contract and vice versa.

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.