Derik Whittaker

Syndication

News


Using TPL to access Async WCF Endpoints in ASP.net MVC

I am in the process of building out a internal portal/dashboard for our company which will allow us to get a status of what is going on behind the scenes in our application.  I want this site to utilize our existing WCF endpoint and as much existing code as possible.  When doing this I realized pretty quickly that I needed to create Async Controller actions to hit our async endpoints which was a first for me.  Of course the first thing I did was a quick Bing search to see if I could find some existing examples to help me a long.  However, every example I found assumed that we were using the automatically generated proxy to access our endpoints rather than spinning up the connection manually via ChannelFactory and the service interface.  Because I struggled to get this working I thought I would share my experiances in case others are having the same issue.

Our WCF Endpoint Definition

    [ServiceContract]
    public interface IScheduledEventsService
    {
        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginScheduledEvents(ScheduledEventsRequest request, AsyncCallback callback, object state);
        Result<IList<ScheduledEvent>> EndScheduledEvents(IAsyncResult result);

    }

One thing to point out about the code above, the actual return value from our endpoint is a Result<T>.  The result class is a simple container envelope which provides us back some metadata, this is not something to worry about or to try to find online, you can simply ignore this for your needs

My MVC controller definition

public class ScheduledActivitiesController : AsyncController
{
        public Task<PartialViewResult> Listing()
        {            
            return Task.Factory
                .StartNew(() => GetScheduleActivitiesAsync())
                .ContinueWith(x => PartialView("_Listing", x.Result.ToList()));
        }

        private IList GetScheduleActivitiesAsync()
        {
            var baseUrl = ConfigurationManager.AppSettings["BaseWcfServerUrl"];

            var channel = ChannelHelper.CreateFor<IScheduledEventsService>(baseUrl);

            var myTask = Task.Factory
                .FromAsync(channel.BeginScheduledEvents,
                           new Func<IAsyncResult, Result<IList<ScheduledEvent>>>(channel.EndScheduledEvents),
                           new ScheduledEventsRequest(), 
                           null, 
                           TaskCreationOptions.None);

            var taskResult = myTask.Result;

            return taskResult.ResultItem;            
        }
}

The above code is our entire controller (well at least the important parts her).  Please take note of 3 things

  1. Our controller inherits off of AsyncController which is required to do async controller actions in MVC
  2. My return type is a Task<PartialView> for the action, this is required
  3. In the .ContinueWith I am returning the correct PartialView w/ the data

One thing I want to point out here is that when trying to get the .FromAsync logic to work I keep getting compiler warnings telling me about a mismatch.  This was because at first I was NOT declaring my two Func<T> and just assumed the compiler knew what I meant (guess not).  As soon as I actually defined my 2 Func<T> signatures (I have removed the first one as R# told me it was not needed and sure enough it was not) the compiler was happy.

As you can see, once you make the compiler happy (pesky compiler) this is pretty straight forward.  Hope this helps someone.

Till next time,


Posted 05-13-2012 3:07 PM by Derik Whittaker
Filed under: ,

[Advertisement]

Comments

Pedro Ferreira wrote re: Using TPL to access Async WCF Endpoints in ASP.net MVC
on 05-13-2012 5:46 PM

I have to say that I haven't played with MVC4 and it's async support, but I think you are doing one extra step that is not required.

I think you should return your Task directly from GetScheduleActivitiesAsync and use that task to add your Continuation.

The final result should be the same, but you don't need to block on GetScheduleActivitiesAsync just to create another task in Listings to wait for that block.

Also, you shouldn't need to create those Func<T> in your FromAsync. Try specifying the type directly in the Task class as: Task<YourResultType>.Factory.FromAsync(channel.Begin..., channel.End..., ...)

John wrote re: Using TPL to access Async WCF Endpoints in ASP.net MVC
on 05-14-2012 7:46 AM

I was writing the exact same comment as Pedro last night, but your Captcha is impossible to use on an iPad. Can you pass that along to the devlicio.us guys?

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)