0

I have my web app, that builds reports. Web app on mvc3. And the builder is a WCF service.
I use thread pools to make my report generate automatically.
Base model looks like:
-- Web app sends request on report generation.
-- WCF service creates worker thread and send response to web app that service accepted work.
-- Web app continue to work.

What I need: when WCF worker thread will finish the job, I need to notify Web app that job is done.

So how to catch that callback with my web app.(I use mvc 3)

Can you suggest the simplest method to implement this logic?

StNickolas
  • 576
  • 7
  • 20

5 Answers5

0

There are ways using Comet or Reverse-Ajax. This has been answered previously here: Is there some way to PUSH data from web server to browser?

Community
  • 1
  • 1
Mike Parkhill
  • 5,511
  • 1
  • 28
  • 38
0

Interesting problem. If I understand your requirements, you need to allow the user to continue about their business while the report is being generated in the background, then finally send notification to the user that the report is ready via AJAX.

I believe you are heading in the right direction. What I'd suggest is to leverage WCF asynchronous callback. A good starter article on MSDN is available here. The callback event handler should set a cached status of the report using a unique cache key created when the report request is initially sent to the WCF operation.

Client-side notification can be achieved using a report status polling mechanism which periodically checks the status of the report using the same unique cache key enabled by AJAX.

A simple example of the asynchronous WCF callback could do something such as the following:

ReportServiceClient reportSvcClient = new ReportServiceClient();
Guid reportStatusKey = Guid.NewGuid();
reportSvcClient.GenerateReportCompleted += new EventHandler<GenerateReportCompletedEventArgs>(ReportStatusCallback);
reportSvcClient.GenerateReportAsync(reportStatusKey, <other operation paramters>);

// Set initial report status to False
// (recommend setting an appropriate expiration period)
Cache.Insert(reportStatusKey.ToString(), false);

// WCF callback static method which sets the report status in cache 
static void ReportStatusCallback(object sender, GenerateReportCompletedEventArgs e)
{
    Cache[e.ReportStatusKey.ToString()] = e.IsComplete;
}
...
public partial class GenerateReportCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
    private object[] results;

    public GenerateReportCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : 
        base(exception, cancelled, userState)
    {       this.results = results;         }

    public Guid ReportStatusKey
    {
        get            {
            base.RaiseExceptionIfNecessary();
            return ((Guid)(this.results[0]));
        }
    }
    public bool IsComplete
    {
        get {
            base.RaiseExceptionIfNecessary();
            return ((bool)(this.results[1]));
        }
    }
}

The client-side AJAX implementation can check the cached status of the report at whatever frequency you believe is appropriate by using the same ReportStatusKey.

Capps
  • 182
  • 7
0

Why not generate an async proxy for your wcf service using svcutil /async. That way you wont need your own worker thread within your service and clients simply register for the callback.

Rustin
  • 89
  • 3
0

This can help you: WCF Service with callbacks coming from background thread?

If isn't enought you must implement push notification to your webapp.

Community
  • 1
  • 1
0

WCF contains something called Completion Callbacks. Here, your client has a method which it asks WCF to call for you, only once the asynchronous operation is complete.

For example:

public class MyClient : IDisposable
{
    BuilderClient _proxy = new BuilderClient();

    public void CallAsync(object input)
    {
        _proxy.BeginBuildReport(input, Oncompletion, null);
    }

    void OnCompletion(IAsyncResult result)
    {
        object output = _proxy.EndBuildReport(result);
        //Do whatever you want with your output here.
    }

    public void Dispose()
    {
        _proxy.Close();
    }
}

This will allow you to use a simple event driven model.

Buh Buh
  • 7,443
  • 1
  • 34
  • 61