May 232011
 

At the recently concluded I/O developer conference, Google made an much awaited announcement – The Google Places API has been opened to everyone (was in beta testing for some time). For the uninitiated, Google Places is a Google application for searching local businesses like hotels, ATMs etc. Places fits in beautifully with Google maps both on the web and the Android.

Now with the API being opened up, Its also possible for any location aware tools and websites to make uses of Places search option to add the functionality to your own sites. Check out the documentation here. I integrated the Places API search in my previous geolocation example explained in a blog post here. The application returns 20 places near the user’s current location and adds markers to the map for each.

Web Workers

Web workers are one of the most interesting concepts of HTML5. They are a standard based on running JS scripts on a background thread rather than the main UI thread. This is extremely important since the more time consuming scripts (like complex mathematical calculations) can be offloaded to a secondary thread rather than freezing up your application, having huge applications in graphics intensive work. I used Web Workers in the current application to work call a server side method which in turn calls the Google places API to search for a list of places near the user’s application.

Here are some limitations of Web Workers in their current implementation:-

  • Not supported on all browsers (Most notably Internet Explorer).
  • We cannot access any DOM object in the Web Worker script. All communication needs to be to the main thread using the postMessage function.
  • Because we cannot access DOM objects, it also doesn’t allow any script to be loaded which refers to DOM, which renders most JS libraries like JQuery and Prototype unusable.

In this example, I following components.

  • An ASP.NET MVC server side in order to call the Google places API. Its a controller method which calls the API url and a method which holds the data. On client side we have a similar method in JSON with same properties. The ASP.NET MVC Model binder converts the JSON object to a CLR object and passes it to the Action method. Client Side Javascript cannot call the Google places API directly because it would be a cross site request and not allowed by Google. Hence the Server’s broker method becomes necessary here
  • Client side main script which uses Geolocation to determine the user’s location. It then passes this location to the MVC Action. Before calling the action, it checks whether the browser supports Web Workers – If so they are offloaded to secondary thread. Else called on the main thread itself.
  • Worker script which makes the AJAX call to the Server using xmlHttpRequest object (Jquery cannot be used here) 🙁

Here is the code.

ASP.NET Server Side

        public ActionResult GoogleSearchAPI(SearchQuery query)
        {
            //Base URL for calling the Google Places API
            string BaseAPIURL = String.Format("https://maps.googleapis.com/maps/api/place/search/xml?location={0},{1}&radius={2}", query.Latitude, query.Longitude, query.Radius);
            if (!string.IsNullOrEmpty(query.Name))
                //Append the name parameter only if data is sent from Client side.
                BaseAPIURL = String.Concat(BaseAPIURL, String.Format("&name={0}", query.Name));
            //Include the API Key which is necessary
            BaseAPIURL = String.Concat(BaseAPIURL, String.Format("&sensor=false&key={0}", GetAPIKey()));
            //Get the XML result data from Google Places using a helper method whichc makes the call.
            string _response = MakeHttpRequestAndGetResponse(BaseAPIURL);
            //Wrap XML in a ContentResult and pass it back the Javascript
            return Content(_response);
        }

        //Helper method to call the URL and send the response back.
        private string MakeHttpRequestAndGetResponse(string BaseAPIURL)
        {
            var request = (HttpWebRequest)WebRequest.Create(BaseAPIURL);
            request.Method = WebRequestMethods.Http.Get;
            request.Accept = "application/json";
            string text;
            var response = (HttpWebResponse)request.GetResponse();

            using (var sr = new StreamReader(response.GetResponseStream()))
            {
                text = sr.ReadToEnd();
            }

            return text;
        }

    ///
    /// Our data object  which sends the object with data from client side to
    /// server. The Model binder takes care of conversion between JSON and
    /// CLR objects.
    ///
    public class SearchQuery
    {
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string Radius { get; set; }
        public string Type { get; set; }
        public string Name { get; set; }
    }

Client Side Main script

Most of the Geolocation code is the same as my previous example. This is the additional code written after the geolocation data is found and the coordinates is passed on to another method which uses it to retrieive places data and mark it on map

var spawnWorkerThread = function (position) {
    //This is executed if the getPosition is successfull. Moving the map to the user's location
    map.panTo(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
    var coordinates = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
    //Create a JSON object with the details of search query.
    var placesQuery = { Latitude: position.coords.latitude, Longitude: position.coords.longitude, Type: "establishment", Radius: "500" };
    //Check if the browser supports WEbWorkers
    if (Modernizr.webworkers) {
        printMsg("Web Workers are supported on your browser. Searching for places nearby your location");
        //Load the Worker Script
        var myWorker = new Worker("/files/webworkersmvc/Scripts/worker.js");
        //Send the JSON object to the Worker thread after serializing it to string
        myWorker.postMessage(JSON.stringify(placesQuery));
        // receive a message from the worker
        myWorker.onmessage = function (event) {
            //Send the returned data to the processPlacesData method
            processPlacesData(event.data);
        };
    }
    else {
    //Make the call in a standard way and not using Web Workers
        printMsg("Web Workers isnt supported on your browser.Calling Places API the conventional way");
        var xhr = new XMLHttpRequest();
        //Calling the controller method.
        xhr.open("POST", "http://www.ganeshran.com/Files/webworkersmvc/Home/GoogleSearchAPI");
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 0)) {
                processPlacesData(xhr.responseText);
            }
        }
        xhr.send(JSON.stringify(placesQuery));
    }

};

var processPlacesData = function (data) {
    //Parse the XML result into an xml obect
    var places = $.parseXML($.trim(data));
    var xmldoc = $(places);
    var resultstring = "";
    //Iterate through each result object
    $("result", places).each(function () {
        var typestring = "";
        $("type", this).each(function () {
            typestring += $(this).text() + " , ";
        });
        //Create a MapResult object for each result.
        var resObj = new mapResult($("name", this).text(),
                                      $('vicinity', this).text(),
                                      typestring,
                                      $('lat', this).text(),
                                      $('lng', this).text(),
                                      $('icon', this).text());
        //Create a Google Maps Marker and use the result object's latitude and
        //longitude.
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(resObj.latitude, resObj.longitude),
            title: resObj.name,
            animation: google.maps.Animation.DROP
        });
        //If the screen is smaller then zoom lesser else zoom more closer.
        //This is to make the markers visible
        if (screen.width < 1000) {
            map.setZoom(12);
        }
        else {
            map.setZoom(15);
        }
        //Set each marker on the map
        marker.setMap(map);
        //this is for the window to show information when the marker is clicked.
        //A single infowindow is reused in order to display only one
        google.maps.event.addListener(marker, 'click', function () {
            infowindow.setContent(resObj.getMarkerHTML());
            infowindow.open(map, marker);
        });
    });

};

//Javascript object to hold the map data and the get the HTML required for the marker.
function mapResult (name, vicinty, types, latitude, longitude, icon) {
    this.name = name;
    this.vicinity= vicinty;
    this.types = types;
    this.latitude = latitude;
    this.longitude = longitude;
    this.iconpath = icon;
}
//Prototype method to avoid creating seperate copies of the method
//for each object
mapResult.prototype.getMarkerHTML = function () {
var htmlstring = "
<div style="color: blue; font-weight: bold;">";
    htmlstring += "Name: " + this.name + "";
    htmlstring += "Types: " + this.types + "";
    htmlstring += "Location: " + this.latitude + "," + this.longitude + "";
    htmlstring += "Vicinity: " + this.vicinity +"</div>";
    return htmlstring;
};

Worker Side Script

The worker side script is pretty straightforward. Just calls the controller and passes on the data to the main thread using the PostMessage function

// receive a message from the main JavaScript thread
onmessage = function (event) {
    // do something in this worker
    var info = event.data;
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "http://www.ganeshran.com/Files/webworkersmvc/Home/GoogleSearchAPI");
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 0)) {
            //Send message back to Main thread
            postMessage(xhr.responseText);
        }
    }
    xhr.send(info);
};

Demo Page

http://www.ganeshran.com/files/webworkersmvc/

Demo Pics

On PC

On Android

Jan 102010
 

Here are the steps to deploy MVC applications to servers with shared hosting providers.

  • In your Hosting provider’s IIS management panel, create a sub directory and configure it as an appplication- root, so that it is recognized as an asp.net application.
  • Set your MVC dll’s Copy To Local property to true, so that they are copied to the bin directory of the project.
  • Edit your web.config file and update the debug property to false. This holds true for all web applications.
  • Update the connection strings to your hosting provider’s connection strings.

Thats it. Your MVC application should run fine. Mine does.

Jan 092010
 

Though MVC is an age old architectural style that has existed since the 70s, its a relatively new entrant in the .NET world. I had written a general introduction about MVC earlier. That post is available here. While Java, Ruby, Python all had their MVC frameworks for quite some time, ASP.NET was quite comfortable with the Webform based architecture till recently. And Webforms arent really a bad way to code at all, you work with almost a Windows style of programming, dragging dropping controls. Double clicking them to code their event handlers. In fact due to this Rapid application development, ASP.NET was amazingly simple to work with. However, like with all other simple ways, ASP.NET webforms also take a lot of control away from the developer.

MVC seeks to give developers an alternative, where they have complete control over the application including the viewstate of the controls. My first look was at ASP.NET MVC was a training session given by an architect from Microsoft, and I absolutely didn’t like the complexity it brought to a simple demo application that was showed. I found that we were writing too much code, again bringing back spaghetti code that died with ASP. But over time, after digging into MVC, I found that it made a lot of sense. If my need is just to display a set of data, why should I sacrifice performance over all of the gridview’s bulky viewstate. Rather, it makes sense to use a HTML table and apply CSS to style it.  That is exactly the flexibility that MVC gives you, instead of relying on built in abstraction done by Webform architecture, you get to control every detail of your application.

WebForms

ASP.NET Webforms are radically different from any other server side scripting technology. For one, its event driven. Just like Windows programming, you assign an event handler to an element, like a button and it calls the handler when the button is clicked. No longer, do you have to keep on submitting the form to handle click events and write bulky code to do simple stuff. ASP.NET made the server side code clean – in fact a helluva lot cleaner than ASP.

But all this ignores the age old truth about the web/HTTP – that it is stateless. The server forgets about the page the minute its sent to the client and thats the end of it. So how is context maintained in WebForms? The answer is Viewstate. All of the control states are Base64 encoded and recreated on the server again where the request is executed. There is a lot of built-in plumbing to achieve this level of abstraction.

The main problem with webforms is that though it cleans up your code and markup and seperates them neatly in your Visual studio solution, it horribly clutters the rendered markup to the browser. Every control takes up more and more viewstate and the nested control names which are really long, make the markup bulky, and since this does a round trip on every request, it starts impacting performance and eventually scalability.

One more concern is the Testability, due to the event driven approach, the GUI is tighly coupled with your business layer and there isnt any effective way to test your web page. Automating such testing could be an tedious effort and you would most probably end up doing manual testing.

Despite all of these problems, Webforms are not a bad architecture. It is extremely mature and extensible. A lot of good documentation exists for it and it still makes sense for quite a few scenarios.

MVC

With MVC, it was love at first byte. In fact I never realized how inefficient webforms were, until i worked with MVC. Instead of a page receiving the request, its the Controller which lives at the heart of MVC. Once it gets the request, it decides which view to render and may use models.

One great thing about MVC is the clean Seperation of Concerns (SoC ) which you are able to achieve out of the box. Both the Controllers and the Views can be tested separately using testing tools like NUnit or MBUnit. So that means no longer. Manual testing doesn’t really make any sense for most scenarios, because the effort is not repeatable and when you want to try with a different input, you would need to start all over again.

Also, you have complete control over the HTML that your controls generate. No more grappling with heavy Viewstate and decreased performance. Also there is no concept of a postback in MVC. Hence although, we can make use of ASP.NET server controls, we cant use either ViewState or Postback in them. Microsoft is working to create a library of MVC aware server controls that would be more suitable for this architectural style. Also, you have complete control over the HTML that your controls generate. No more grappling with heavy Viewstate and decreased performance. Also there is no concept of a postback in MVC. Hence although, we can make use of ASP.NET server controls, we cant use either ViewState or Postback in them. Microsoft is working to create a library of MVC aware server controls that would be more suitable for this architectural style.

One major point that is oft repeated is that we shouldn’t jump the gun to convert every existing webforms applications into MVC just because its the in thing. You would have to rewrite your application completely, and the benefit derived would often not be worth the effort. But I would certainly  recommend that  you use MVC for any new applications you create. Its certainly the smarter way.

Nov 172009
 

MVC or Model View Controller is an architectural style that separates the business from the presentation layer to enable independent development and testing of each. MVC is not a new concept, It has existed right from the nascent days of software development with the first implementation being in SmallTalk in 1979 done by Trygve Reenskaug.

It is relatively new to the Microsoft World though, with the ASP.NET MVC framework being shipped in 2008 compatible with Visual Studio 2008 – .NET Framework 3.5. So what is MVC? MVC divides the application into three parts – The model, View and the controller.

  • Controller:- The controller is the heart of the MVC application. It recieves each and every request that is made by the user and responds to it accordingly. It controls the flow of the application.
  • Views:- This is the actual UI of the application. The controller controls how the view should be rendered to the browser. Views contain markup, scripts just like an .aspx page
  • Model:- Apart from the View and the controller, all the other parts in the application are collective called as the Model. These components are the business and data logic of the application.

A huge advantage of the MVC architecture is that it separates all these three components and makes them completely independent of each other. Hence all of them can be tested separately rather than the case with the webform architecture where testing each component is a pain and mostly we end up doing functional testing for the whole application. This also means modifying one component is far more easy without disturbing the whole application.

Since all the requests are now handled by the controller, we cannot use the postback feature of the web controls like the webform architecture. One of the drawback (or advantage) of MVC is the level of control over HTML rendering that we have. Since we can exactly control how the page will be rendered, we have to write more code to do so. Also you will see more code mixed with Markup, something that ASP.NET eliminated with the help of code behind.

MVC and WebForms are to be seen as two distinct styles which are advantageous to use depending on the scenario, rather than being pitted against each other. If you have a small standalone application to develop with fewer programming resources, a webform based application makes more sense since there is less coding involved. However if you are looking to build an application that would be used and extended by a large number of users, MVC is certainly the way to go.

To download the ASP.NET MVC framework, use this link.

Once done, you should get the options to create a new ASP.NET MVC project in the Visual Web Developer window.

newProject

The solution explorer has an organized directory structure that must be followed while developing the application.

solutionexp

A simple application is already created for us.

sampleApplication