Posts Tagged 'JavaScript'

Supporting Multiple Versions of jQuery

I was in New York recently teaching my ASP.NET Web Forms class while one of my colleagues was teaching my jQuery class a couple of doors away. One of the students in the jQuery class asked an interesting question, and since another instructor – Randy Casburn – was sitting in the back of the room, he had some fun playing around with alternative answers. I thought the code he came up with might be useful to someone, so I’m posting it here – along with two other answers to the question: ranging from the officially recommended (but restrictive) to the deeply unofficial (but clever and very flexible).

Why might you want to do have multiple versions? There are all sorts of reasons:

  • You may be using a plugin that relies on an older version
  • As a developer, you may not have control over the whole page – just your portion of it – and other developers/teams may be adding their versions of jQuery elsewhere on the page. (This is particularly true if you have a complex server side set up, and your pages are built from different elements maintained by different developers/teams).
  • You may use a third party tool that relies on a particular version
  • A component may inject an older version of jQuery whether you want it to or not.

So – first, what are the official answers to the question?

Answer one: don’t do it, use the migration plugin.

The idea here is that you don’t run an older version of jQuery as well as a newer version, you use the migrate plugin to add backwards compatibility to your newer version (1.9+). First replace your old version of jQuery with the new one, then add a reference to the migrate plugin. As if by magic, the deprecated elements removed in the more recent version are restored and your existing code works:

<script src=””></script&gt;

<script src=””></script&gt;

Advantages: you only have one version of jQuery, and the plugin provides a migration path until you get around to updating.

Disadvantages: it only goes back as far as jQuery 1.6.4, so if you need to support an older version, it doesn’t help.

Answer two: use .noConflict()

The noConflict() method is designed to relinquish jQuery’s use of the $ alias so that jQuery can work alongside other JavaScript libraries. It works just as well when that ‘other’ library is an older version of jQuery, even if the jQuery team does not recommend having more than one version.

The following code….






    Newer version code would be here

    Note: use of ‘on()’ method



        jQuery(‘#new’).on(‘click’, function(e){


            jQuery(‘body’).append(‘You clicked on the “jQuery” link. It used version: ‘+jQuery.fn.jquery+‘<br/><br/>’);




    Legacy code would be here

    Note: use of ‘bind()’ method



        $(‘#old’).bind(‘click’, function(e){


            $(‘body’).append(‘You clicked on the “$” link. It used version: ‘+$.fn.jquery+‘<br/><br/>’);






href=’#’>Execute older version (jQuery as $)</a>


href=’#’>Execute newer version (jQuery as jQuery)</a>



Leads to the following output when both buttons have been clicked:

That’s nice if you need to support two versions of jQuery, one of which is older than 1.6.4. But what if you have a situation where you absolutely have to use more than two versions of jQuery side by side? Here is Randy’s solution:

Answer three: Alias, alias, alias

The solution here is to add the version of jQuery you want to use and assign it to a variable. Then add another version, and assign it to another variable. Repeat as necessary.

Here’s the code:



    var $$$ = jQuery;




    var $$ = jQuery;







        $$$(‘body’).append(‘/————-/<br>$$$ is version: ‘+$$$.fn.jquery);

        $$$(‘body’).append(‘<p>’ + testOnSupport($$$) + ‘</p>’);



        $$(‘body’).append(‘/————-/<br>$$ is version: ‘+$$.fn.jquery);

        $$(‘body’).append(‘<p>’ + testOnSupport($$) + ‘</p>’);



        jQuery(‘body’).append(‘/————-/<br>jQuery is version: ‘+jQuery.fn.jquery);

        jQuery(‘body’).append(‘<p>’ + testOnSupport(jQuery) + ‘</p>’);



        $(‘body’).append(‘/————-/<br>$ is version: ‘+$.fn.jquery);

        $(‘body’).append(‘<p>’ + testOnSupport($) + ‘</p>’);



    function testOnSupport(x)


     if (typeof (x(‘body’).on) == ‘undefined’) nope = ‘Does not support on()’; else nope = ‘Does support on()’;

     return nope;







And here’s what the output looks like:

Do I recommend having multiple versions of jQuery side by side? Emphatically not. But if you have no choice in the matter, there are a surprising number of ways to get there. Whichever you use, do be careful of the order in which you add your references – if you’re using .noConflict() for example, you need to make sure you put your script files and the .noConflict() code AFTER any older version of jQuery injected by a component.

Kevin Rattan

For other related information, check out this course from Learning Tree:

jQuery: A Comprehensive Hands-On Introduction

Combining Google Maps with ASP.NET Web Forms – Part 2

In my last post I showed how easy it was to add a Google map to a Web page. This time, I want to look at how you can customize the map by adding markers to it, as well as using data binding to build the script dynamically.

The application I’m using provides restaurant recommendations for Learning Tree education centers. What I want to do is add a map that shows the location of the restaurant – and for that, we need to have the latitude and longitude. That’s not something users will know, so the first thing we need is a form that asks Google for the information.

Here is the form:

The user fills in the address, then clicks on the Get Coords button– this calls a retrieveCoords() function which asks Google to look up the address and give us the longitude and latitude. The key object we need is Google.maps.Geocoder. It has a geocode() method that accepts a string address argument and returns an array of results containing location information – and specifically, lat() and lng() methods that have the details we need. Here is the code:

So now we have the longitude and latitude available, we want to add a map showing the restaurant location, so the the app goes from looking something like this:

To something like this:

This is similar to what we did last time, except that now we’re going to be building the script using longitude and latitude values from the database.

The basic page is as follows:

  1. The file is referenced in a content area mapped to the header on the master
  2. A div with the id map has been added immediately above a DetailsView which displays information about a restaurant. The div has been styled to float right (as in the image above).
  3. The DetailsView is bound to a list of Restaurant objects

Now what we have to do is build a script to

  1. retrieve a map centered on the longitude and latitude of the bound restaurant, and
  2. create a marker to indicate its location.

Since we have all the data ready to hand inside the DetailsView, that’s where we’re going to build the script. The first thing we need is TemplateField, and since there’s already one there, we’re just going to reuse that – we’re only adding script, after all, so it’s not going to affect the look and feel:

Then we use the same code that we did when we were building a simple Google Map – but this time using data binding to write the values into the JavaScript:

If you look carefully at the image, you’ll see that Visual Studio isn’t entirely happy. It thinks there’s a syntax error:

Fortunately, it’s wrong. The generated code is perfectly fine:

Which means we now have a Google map driven by a script that’s built dynamically using data binding. The resulting page looks like this:

However, we’re not done yet. We want to show the user the exact location of the restaurant, not just the general area. For that we need a marker – a google.maps.Marker, to be precise – which can be added to the map using the setMap() method. Like the Map object itself, the Marker needs a google.maps.LatLng object, so this time I’m going to create one explicitly and then use it in both methods. Here is the code:

And this is the final result, complete with marker (which will display the name of the restaurant if you hover over it, thanks to the title attribute:

There’s obviously a lot more you can do with Google maps – like customizing icons, adding directions and waypoint markers and much else besides – and I may just explore some of those features in future posts. For now, though, I think that should be enough to help those former (and future) students who want to make a start on combining Google maps and ASP.NET web forms.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building ASP.NET Web Applications: Hands-On

Combining Google Maps with ASP.NET Web Forms – Part 1

One question that keeps cropping up while I’m teaching is – how do I include Google Maps in ASP.NET pages?

The short answer is – it’s incredibly easy: just go to this page, follow the steps and you’ll get code you can paste into your page. The problem with that is it only works for fixed locations. It’s great for showing a map of your office on your web page, not so great for displaying maps using data you’ve retrieved from a database. For that, you need to use JavaScript to call the Google Maps API.

In this post, I’m going to introduce the basics – how you sign up and the bare minimum JavaScript you need to get up and running. In my next post, I’ll look at building the script dynamically using data binding, and show you how to add a marker on the map.

The first thing you need to do is sign in to your Google account (you have one, right? If not, just sign up: it’s free). Then you need to go along to the API console at and get an API key. Without the key, there are limits to how much you can do with your maps and you can’t exceed the anonymous usage limit of 25000 requests per day. Passing the key to Google along with every request lets them track your usage so they don’t cut you off when the free limit is exceeded. (And if you’re going to be a heavy business user, then you need to go further, use the business API and get a client id).

Once you’re at the API console, you need a project to work with – so if you don’t have one already, it guides you through creating one. Then you need to sign up for individual services.

Just click on Services on the left….

And scroll down the page until you find maps. There are various options, but you want Google Maps API v3.

Now you need to get yourself a key. So click on API Access in the left hand menu:

Copy the key – you’re going to need it by and by. The other thing you’ll want to do is set up restrictions so that the key can only be used on domains you control (so that no-one can steal your key and use some of your quota). Click on the Edit allowed referers link on the right and then add your domains to the dialog – one line per domain, using the pattern **. (Don’t worry about adding localhost; just leave the key out altogether when you’re testing).

Click on Update and you’re ready to begin.

First, add a script reference to to the page. It’s available via both http and https, so use a relative path beginning with // so it defaults to whichever protocol is currently being used by the page. The two arguments are key (which you can omit if you want to, and should omit during testing on localhost) and sensor, which is designed to tell Google whether the device sending the request has used GPS to find its location (so if you’re not doing so, just set it to false).

With the script available, you can now call the maps API. The first thing we need is a div on the page to hold the map. I’ve given mine the id ‘map’ (not very original, I know) and styled it in an external CSS file.

Now the infrastructure is in place, all we have to do is call the map and tell it what to display. We need to do two things:

  1. Create an options object literal specifying where we want the map to be centered, what zoom level to show (0 – 21: where 0 is the whole world) and which kind of map to display – a standard road map, satellite view or a hybrid.

  2. Create a new map, telling it 1) which div to use for display and 2) how to display it – which is done by passing in the options object we just created

And that gives us a map on the page, centered on the location we specified:

That’s it for now. In my next post, I’ll cover retrieving latitude and longitude information for a given address, displaying icons on the map and building the script dynamically on an ASP.NET page using data binding.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building ASP.NET Web Applications: Hands-On

Google Coding Style Guides

Google have made their internal coding style guides publicly available. I’ve been checking out the HTML and CSS and JavaScript guides over the past couple of days, and would strongly recommend that anyone working on the client-side take a look at both.

Guides like these are full of little tips and tricks. They give you confidence that you’re doing something the right way – Hey look! Google agrees with me! – and you’ll always find some little optimization you haven’t come across before. In this case, I had a definite case of old-dog-taught-new-trick, and also an incredible sense of déjà vu: at least one of the techniques suggested in the HTML guide is a naughty little cheat from years ago (actually, last century) turned into an ultra-modern performance optimization.

Teaching an old dog new tricks

Little more than a week ago I wrote an article for this blog about the SSL features in IIS Express/Visual Studio 2012. Part of that article suggested a way to switch between http and https for images stored on a third party site using an action filter. The HTML style guide suggests a much simpler solution – a form of relative pathing I’d never come across before: simply omit the protocol from the url. Instead of a path like src=https://localhost:44301/Content/Images/1.jpg you use src=//localhost:44301/Content/Images/1.jpg. This makes the path relative and substitutes the appropriate protocol automatically. It relies on the images being available in both formats – but it is massively simpler than my original solution. Time to go back and refactor.

Teaching a new dog old tricks

Way back when the internet was a lot smaller and slower than it is nowadays and everything was in black and white (okay, I made that bit up), we sometimes used to cheat to reduce bandwidth. I remember building an online shop for a small web development company in the 1990s where we had one page with a long table listing all products. We saved more than 100kb (a massive amount of bandwidth back then) simply by omitting the closing </td> and </tr> tags. That was naughty even then, but worth it. Since then, of course, it has been completely verboten because it’s such a horrible breach of the rules. Well guess what – that’s exactly what Google recommends!

Here, for example is what they don’t recommend:

<!DOCTYPE html>



<title>Spending money, spending bytes</title>






And here is what they do:

<!DOCTYPE html>

<title>Saving money, saving bytes</title>


To be fair, they do suggest being cautious on that one – but still: wow! That’s such a sea-change in approach I find it hard believe it’s going to be accepted any time soon, if ever.

Whether you agree with everything in there or not, the guidelines are definitely worth a look. There’s plenty of food for thought in there and you never know, you might pick up a new trick or two like I did.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

Building Web Applications with ASP.NET and Ajax

Validating That At Least One TextBox Has Content

I came across an interesting little validation problem on my current project. The site is for members only – and in order to become a member, you need to be nominated. You can provide either one or two nominators, but you must provide at least one.

So how to force users to enter text in either of two TextBoxes? RequiredFieldValidators won’t do, because either one can be left empty. Yet at least one must be completed. Clearly this is a job for CustomValidators.

The client-side and server-side code are both fairly straight-forward, but I thought someone out there might find it useful, so here it is.

First of all, the CustomValidators in the ASPX page:

<asp:CustomValidator ID=”Nomination1CustomValidator” runat=”server” Display=”None” ValidateEmptyText=”true” ClientValidationFunction=”CheckNominations” ErrorMessage=”At least one nomination must be provided” ControlToValidate=”Nominated1TextBox” OnServerValidate=”Nomination2CustomValidator_ServerValidate”></asp:CustomValidator>

<asp:CustomValidator ID=”Nomination2CustomValidator” runat=”server” Display=”None” ValidateEmptyText=”true” ClientValidationFunction=”CheckNominations” ErrorMessage=”” ControlToValidate=”Nominated2TextBox” OnServerValidate=”Nomination2CustomValidator_ServerValidate”></asp:CustomValidator>

Note the empty ErrorMessage in the second validator. Combined with display=”none’, that means our ValidationSummary control is only going to display one error message to the user, making it much less confusing. Also notice that ValidateEmptyText is set to true – otherwise, our code will never run.

Then the JavaScript. We’re validating two controls, so even though we use the standard signature the validators are expecting, we’re only interested in the args. I set the TextBoxes’ ClientIDMode to static and used jQuery to get the controls.  (I use jQuery for pretty much all my client-side code).

function CheckNominations(sender, args) {
  if ($(‘#Nominated1TextBox’).val() == “”
      && $(‘#Nominated2TextBox’).val() == “”) {
        args.IsValid = false;
   else {
args.IsValid = true;



And, of course, we also need to implement the server-side code for a complete solution:

If String.IsNullOrEmpty(Me.Nominated1TextBox.Text) And
String.IsNullOrEmpty(Me.Nominated2TextBox.Text) Then
        args.IsValid = False
        args.IsValid = True
End If

So now the user must fill in one of the TextBoxes, but can pick either one.  I have been using ASP.NET MVC a lot recently, and it’s nice to go back to Web Forms and see how very easy it is to take built-in controls like the custom validator and use them to meet your specific needs.

Kevin Rattan

For related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET and Ajax

jQuery: A Comprehensive Hands-On Introduction

Retrieving Data with a JavaScript MVC Framework

This is part of series of posts on building reliable, testable Ajax-enabled applications using a JavaScript MVC framework. In my first post, I discussed why this was a key technology and set up my initial server-side resources in an ASP.NET MVC application. The second post created the test framework for the application, using QUnit for the client-side code and Visual Studio for the server-side code. My last post started to provide the pay-off for all that work: integrating the client-side ViewModel’s data and methods with HTML.

The point of this application is to have the user select a customer from a dropdown list and display the information for that customer, retrieved from the server. Using Knockout as a framework for implementing the MVVM pattern, I’ve created a client-side Customer ViewModel written in JavaScript that exposes three properties (CustId, CompanyName, and City) and the functions to retrieve a Customer (getCustomer) and delete a Customer (deleteCustomer). I’ve also wired up the properties to controls on the page.

But I’ve left out one important part: integrating the code that actually retrieves the data from the server into events in the page. In this post, I’ll take care of two topics: adding a dropdownlist that displays all the customers in the Northwind database and retrieving the appropriate customer object from my server when the user selects a customer from the list. Unlike my previous posts, however, I’ll defer showing the TDD code that proves the code works to the end of the post.

Creating the DropDown List

My first step is to define the dropdown list. In my client-side ViewModel I need a property that will expose the list of Customer objects that I retrieve. I add that to the list of properties that I defined in my ViewModel again using one of Knockout’s functions. Because I’m working with multiple objects, I use Knockout’s observableArray function:

this.Customers = ko.observableArray();

Technically speaking, I probably don’t need to use observableArray here. The observableArray function gives me two-way databinding: changes to the Customers property will be reflected in the page and changes to the array in the page would be reflected in the property. Right now, I don’t intend to let the user add or remove Customers from this property so using observableArray is probably providing more functionality than I need. However, the syntax for updating “observable” properties is different from updating a standard variable: I’m using observableArray here because it makes my life easier to use Knockout’s observable functions on all of my ViewModel’s properties instead of just some of them.

Also on the client, I need a function that uses jQuery’s getJson method to retrieve the customer objects that will populate the property. I add the following function to my client-side Customer ViewModel to do that. In the function, I use my controller variable to build the URL that retrieves the list of Customer objects from the right controller. Once I’ve retrieved the array, I update my Customers property with it:

this.getCustomers = function () {
         $.getJSON("/" + Controller + "/GetAllCustomers",
				function (custs) {

With the client-side code created, I need the server-side method in my controller that returns the JSON objects that will populate the dropdownlist. Rather than return the whole Customer object, I’ll create an anonymous object that holds just the values the dropdownlist needs—CustomerId and CompanyName:

public ActionResult GetAllCustomers()
  using (northwndEntities ne = new northwndEntities())
    var res = from c in ne.Customers
	select new  {cName = c.CompanyName, cId = c.CustomerID};
    return this.Json(res.ToArray(), JsonRequestBehavior.AllowGet);

My final step in displaying these customers is to bind a dropdownlist on the page and bind it to the Customers property I’ve created on my ViewModel. That markup looks like this:

<select data-bind="options: Customers, 
                    optionsText: 'cName', 
                    optionsValue: 'cId', 
                    optionsCaption: 'Select a  Customer'">

I’m using several of Knockout’s bindings here to tie the list to the property:

  • options: this binding is passed the name of the property on my ViewModel that holds the list of objects to be used to populate the dropdown list.
  • optionsText/optionsValue: These bindings specify which property on the object are to be used for the text and value attributes in the list. The text attribute specifies the property to be displayed to the user while the value property specifies the property to be passed to any related function
  • optionsCaption: Specifies the value to be displayed in the list when it’s first displayed

I don’t need the selectedOptions binding that lets you specify the list’s current selected value through a property on the ViewModel.

Retrieving the Customer Object

Now I need a client-side method to retrieve the customer object from the server. I write that method so that it accepts a customer Id and updates the ViewModel’s properties with the retrieved data:

this.getCustomer = function (custId) {
        $.getJSON("/" + Controller + "/CustomerById/" + custId,
		function (cust) {

I can’t however, wire this method up to my dropdown list directly. Here’s the syntax that ties the list to a function called fetchCustomer on my ViewModel that runs as soon as the user selects an item in the list:

<select data-bind="event: {change: fetchCustomer}, 
                   options: Customers, …

I’m using Knockout’s event binding which lets me specify an event (change, in this case) to a method (fetchCustomer). Unfortunately, there’s no provision in this binding to pass a parameter to the fetchCustomer function. However, when a function is called through Knockout’s binding process, the function is passed two parameters. The second paremeter includes information about the event and through that parameter’s target property I can access the element that fired the event. From there it’s just a short step to retrieving the current value on the element that invoked the function through its value property.

This code gets the currently selected value from the dropdownlist that calls the function and passes that value to my getCustomer function:

this.fetchCustomer = function (ignore, event) 

Which raises the question of why have the fetchCustomer method at all? Why not call the getCustomer function from the dropdownlist binding and just extract the selected value from the second parameter? I don’t know that I have a good answer for that question. I’m could say that I’m trying to create a testable ViewModel and the more functions that I have that are tied to my View, the harder it is to test the ViewModel. However, a test for a method like fetchCustomer isn’t hard to construct—this code would do the trick:

var eventTest = { target: { value: "ALFKI"} };
cust.fetchCustomer(null, eventTest);

Still, I’m happier isolating any code that seems to me is related to the user interface into its own methods so I’ll continue with this design.

As I said at the start of this series, Learning Tree has several excellent courses in this area. In Canada, I teach both Learning Tree’s ASP.NET MVC course (which has a chapter on TDD in ASP.NET MVC) and its Design Patterns and Best Practices course (which goes into TDD in more depth). But Learning Tree also has related courses that I don’t get to teach, including ones on JavaScript and jQuery.

There’s lots more I could do here. With Knockout it’s easy to enable and disable portions of your page by binding them to properties on your ViewModel. I also haven’t tried to create or manage multiple objects on the page. However, I have convinced myself (and, hopefully, you) that there’s at least one MVC/MVVM framework out there that lets you create applications in a testable, reliable way even when your application includes client-side code.

Test Code

And here’s the code that I used to test my code. First, the test for client-side code that returns the list of customers:

test("Get All Customers",
                  function () {
                  cust = new Customer("Test");
                  setTimeout(function () 
                             equals(cust.Customers().length, 2, 
                                        "All customers not retrieved");

Now the mock server-side method that I used to with that client-side test code:

public ActionResult GetAllCustomers()
  List<Customer> custs = new List<Customer>();
  Customer cust = Customer.CreateCustomer("PHVIS", 
              "PH&V Information Services", null);
  cust.City = "Regina";
  cust = Customer.CreateCustomer("Other", "Other one", null);
  cust.City = "Winnipeg";
  return this.Json(custs.ToArray(), JsonRequestBehavior.AllowGet);

Finally, the test code for the production version of the server-side method:

public void GetAllCustomersTest()
  HomeController hc = new HomeController();
  System.Web.Mvc.JsonResult jres = 
                (System.Web.Mvc.JsonResult) hc.GetAllCustomers();
  dynamic res = jres.Data;
  Assert.AreEqual(96, res.Length, "Unable to retrieve all customers");

How To Post To A Remote Server From An ASP.NET Web Form

I recently came an across an interesting problem: I had to post an ASP.NET Web Form to a third party Web site. It turns out to be quite a tricky thing to do – so I thought I’d share my solution with you in case you ever need to do the same thing.

First off: why did I want to post on rather than back?

I am in the process of taking over responsibility for an existing Web site. The site integrates with a bank to take credit cards – and the data needs to be posted.

So why not just use HttpWebRequest?

Because the user has to leave the site, pay and then come back – bringing return parameters back with them.

Ok – so how did the current site work?

It cheated. It’s an ASP.NET Web Forms site, but the page that does the posting is actually PHP!

So – what exactly is the problem with just switching to an ASP.NET Web Form?

Actually, there are several:

  1. ASP.NET Web Forms post back to the same page (or, at a pinch, to other pages on the same server). They don’t post on to third party web sites.
  2. The remote server requires set names for the posted fields – and ASP.NET Web Forms changes these on the client. This problem had two sub-problems:
    1. I had to use runat=”server” controls because the values were dynamic, and
    2. It turns out that ClientIDMode=”Static” fixes IDs, but not names

Q: So how did I make it work?

A: By using jQuery

Here’s what I did:

  1. Added a label telling the user that they needed JavaScript to pay by credit card (or they could pay by bank instead)
  2. Hid the label using jQuery, then showed a button (input type=”button”, not submit) and set its click event to….
  3. Rewrite the form’s action so that it posted to the remote address
  4. Rewrite the control names so that they met the remote sites requirements.
  5. Remove the unwanted form elements such as __VIEWSTATE
  6. Submit the form

Then all I had to do was test it – which I did by creating a page to echo the newly posted values back to the (which also meant I had to set EnableViewStateMac=”false” on the test page).

Here is the JavaScript:

$(function () {
$(‘#buttonSubmit’).show().click(function () {
$form = $(‘form:first’);
$form.attr(‘action’, “test.aspx”);
$(‘input:hidden’).each(function () {
var original = $(this).attr(‘name’);
var improved = original.substring(original.lastIndexOf(“$”) + 1, original.length);
$(this).attr(‘name’, improved);

So there you have it – a way to post to a remote server from an ASP.NET Web Forms Web site.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET and Ajax

jQuery: A Comprehensive Hands-On Introduction

Learning Tree International

.NET & Visual Studio Courses

Learning Tree offers over 210 IT training and Management courses, including a full curriculum of .NET training courses.

Free White Papers

Questions on current IT or Management topics? Access our Complete Online Resource Library of over 65 White Papers, Articles and Podcasts

Enter your email address to subscribe to this blog and receive notifications of new posts by e-mail.

Join 29 other followers

Follow Learning Tree on Twitter


Do you need a customized .NET training solution delivered at your facility?

Last year Learning Tree held nearly 2,500 on-site training events worldwide. To find out more about hosting one at your location, click here for a free consultation.
Live, online training

%d bloggers like this: