ASP.NET MVC JQuery EventAggregator (Decoupled Event Handling)

The concept of Event Aggregation was first introduced to me as I read through the PRISM toolkit (Composite Application Guidance) from the Microsoft Patterns and Practises team.

It allows you to modularise your code and reduce dependencies between modules, I love it.
An example of how it benefits web applications would be:

Consider a simple 2 column web page layout where I have a div with content on the left (LeftBarRegion) and a div for the more content (MainContentRegion) on the right. Lets say that these two regions are defined in a Layout page (or Master Page) and the inner content of the MainContentRegion is changed by a JQuery ajax call. I have a LeftView and RightView which would fill the appropriate regions in my layout.

Now how do I get the view in the LeftBarRegion to talk to the view in the MainContentRegion and vice versa without knowing anything about the implementation details of each view? What if I also want to notify the parent layout page from either of the inner containers?

Welcome to the power of EventAggregator. We could have any content we like in either of the regions above and they can still talk to each other in a de-coupled fashion.

Enough talking lets watch it in action.


// Very simple - JQuery awesomeness
var EventAggregator = {

    // Ensure you are using the jquery data from the parent document so that everything goes
    // through the same EventAggregator.
    publish: function (event, args) {
        window.top.document.$(window.top.document).trigger(event, args);
    },

    subscribe: function (event, delegate) {
        window.top.document.$(window.top.document).bind(event, delegate)
    }
}

Now I can do this:


// In left content page
EventAggregator.publish(Events.SomeEventThatNeedsToBeHandled, { ID = 1 });

// In content page
EventAggregator.subscribe(Events.SomeEventThatNeedsToBeHandled, function (args) {
    // Do stuff in the main content page when this event occurs
});

// In layout page
EventAggregator.subscribe(Events.SomeEventThatNeedsToBeHandled, function (args) {
    // Do stuff in the layout page when this event occurs.
});

Advertisements

Jquery AJAX call to WCF Service returning custom objects

As the web gets faster and ajax becomes more and more used you will find clients are expecting a web experience close to that of a desktop application. JQuery together with Ajax make this task a whole lot easier. I’m currently writing a control to make room bookings via calender (you can see alot of these if you search for jquery plugins) our needs are a little different so I’m rolling my own and I thought I’d show just how easy it is to add ajax functionality to your page.

We all know the update panel is a horrible control. Sure it makes life easy but it is slow, has massive viewstate issues and not very developer friendly since it doesn’t allow for much customisation.

If you haven’t had a look at JQuery yet I suggest you should head over to jquery.com and have a look. This library makes our lives as developers a whole lot easier, and is great for AJAX calls which is what I’ll be talking about today.

I’m assuming you have basic experience with WCF and JQuery, and of course you know what ajax is (if not have a look a gmail. Notice how the page doesn’t refresh when you change folders, and mail is added to your html inbox automatically.. great user experience.)

Lets set up a simple web service. Add a new item to your web project and choose WCF Service. Create a contract as shown below:


    [Serializable]
    public class BookingViewModel
    {
        public int bookingID;
        public string description;
    }

    [ServiceContract(Name = "TestBookings", Namespace = "MyNamespace")]
    public interface ITestBookings
    {
        [OperationContract]
        [WebInvoke(Method="POST",
            BodyStyle=WebMessageBodyStyle.Wrapped,
            ResponseFormat=WebMessageFormat.Json)]
        List<BookingViewModel> SearchBookings();
    }

Now above I’ve created an interface which will be my WCF contract. I’ve declared my method as Web Invokable (can be called from javascript) and will be returning values encoded in Json.

At this point we have our contract, you should create a simple class to test that we have wcf set up correctly.

    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
    public class TestBookings: ITestBookings
    {
          public List<BookingViewModel> SearchBookings()
         {
               return new List<BookingViewModel>
               {
                     new BookingViewModel
                     {
                            bookingID = 100,
                            description = "bob booked hotel"
                     },
                     new BookingViewModel
                     {
                            bookingID = 101,
                            description = "tim booked hotel"
                     }
               };
         }
    }

You’ll need to set up your serviceModel and endpoints in your web.config file. Heres a sample one:


    <system.serviceModel>
        <services>
            <clear />
            <service name="Namespace.TestBookings">
                <endpoint address="" binding="webHttpBinding" behaviorConfiguration="TestBehaviour"  contract="Namepsace.ITestBookings"/>
            </service>
        </services>

        <behaviors>
            <endpointBehaviors>
                <behavior name="TestBehaviour">
                    <webHttp/>
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior>
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>

Basically the important parts are the binding=”webHttpBinding” and the behaviour config for .

Now right click on your svc file, choose set as start page and then run your app. You should see the default svc page generated by .NET. If not you will have to troubleshoot I won’t go into debugging the service here as its out of scope but a quick google of the error should find what you need. Otherwise comment and I’ll see if I can help.

At this point we can use JQuery to call the WCF service


<script>
    $(document).ready(function () {
            $.ajax({
                type: "POST",
                url: "YOUR-URL/TestBookings.svc/SearchBookings",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (data) {
                    var bookings = data.SearchBookingsResult;
                    alert(bookings[0].description);
                },
                error: function (xhr) {
                    alert(xhr.responseText);
                    return;
                }
            });
});

</script>

If everything worked correctly you should get an alert stating the description of booking number 1. This is so easy, however there is so much going on in the backend for your c# objects to be projected onto javascript. The .NET team have done amazing work here. And JQuery is the icing on the cake.

Jquery Visual Studio 2010 Intellisense in Javascript (JS) file

Hey guys,
Just a little trick I came along today, If you’re after Jquery Intellisense in your js file your going to need the jquery-x.x.x-vsdoc.js file which comes with the jquery package.

Simply add this to the top of your JS file

/// <reference path="jquery-x.x.x-vsdoc.js" />

Then Ctrl+Shift+J will reset Intellisense for javascript. Now ctrl+space and you should get the usual intellisense.

You should automatically get the intellisense in your aspx file (for script tags) if referencing your normal jquery file (and the vsdoc file is in the same directory as that reference) as automatic support for that is inbuilt.

Cheers!