Thursday, July 30, 2009

Passing objects using the ref keyword...Wait, aren't objects *always* passed by reference???

4 comments:
For the past month I've been on the job market and have been exposed to all kinds of technical questions. Most of them were run of the mill, but every once and a while I'd get asked a question that made me stop and think. Perfect for a guy with a blog, because now you have tons more stuff to blog about right?

P.S. For those interested, I accepted an offer earlier this week at a company called BIA. They are a computer forensics firm and I'm real excited to start!

So one question that I really liked, was the point of this blog post. The interviewer actually informed me that I was only one out of one hundred that got this question right. Not believing that these numbers were true, I asked everyone on my team at my old job, and only one of them sort of half knew. The others were completely stumped. I guess it is something that many developers just glance over.

OK, so what is this question already?? Well it goes something like this: "What's the difference between passing an object to a method the standard way, and passing an object to a method using the ref keyword?"

Let's break it down. Let's first talk about what the ref keyword does when it comes to value types. Simple example:



static void Main(string[] args)
{
int number = 10;

Add5(number);
Console.WriteLine(number);

Add5(ref number);
Console.WriteLine(number);

Console.ReadKey(true);
}

public static void Add5(int x)
{
x += 5;
}

public static void Add5(ref int x)
{
x += 5;
}


Before trying to run this, see if you can guess what the output would be.....


Answer: The first Console.Writline outputs 10 and the second one outputs 15. Why? Well, the definition of a "value type" is that when passing it to a method, it's passed by value. Meaning, not the actual variable itself is passed to the method, rather a copy of the value is passed to the method. Therefore, when calling the first method, just adding 5 to the variable that was passed in, does NOT affect the variable in the main method, because we only added 5 to the COPY of the x variable not the actual one.

In the second method call though, we're passing the variable using the ref keyword. This changes the behavior and actually DOES pass the actual variable itself to the method. Therefore, in the second method, when adding 5 to the value being passed in, you're actually messing with the same exact variable that's in the main method. Therefore, it outputs 15 showing the changes DID take effect.

So now we have an understanding of how value types work, and how ref changes the behavior. Let's talk about objects now, which are passed by reference. I'll start with another example:

First a simple Person class:



public class Person
{
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}

public override string ToString()
{
return String.Format("{0} is {1} years old.", this.Name, this.Age);
}

public string Name { get; set; }
public int Age { get; set; }

}


Simple class with two properties. Name and Age. Also, the ToString is overridden to make it easier to demonstrate.

Now, let's say we had something like this in our Program.cs:



static void Main(string[] args)
{
var alex = new Person("Alex", 27);

ChangePerson(alex);
Console.WriteLine(alex);

Console.ReadKey(true);
}


public static void ChangePerson(Person p)
{
p.Age += 5;
}


Try guessing what the output would be for this program.

Answer: Alex is 32 years old.

If you're paying attention you'll notice that this is different than how it was with value types. The change in the method DID affect the one in the main method! That's because objects are passed by reference, meaning that a reference (pointer) to the SAME object is being passed to the method. So in the method itself, you still have a reference to the same object that exists in the main method. Therefore, when you make changes, it does show up back in the main.

So back to the original question: If all objects are passed by reference, what's the point of the ref keyword when passing an object to a method??

So here's the deal. Let's talk in terms of the stack and the heap. In the current version of the CLR value types are stored on the stack, and reference types are stored on the heap. However, and this is key, for reference types, a *pointer* to that object is ALSO stored on the stack! Ok, so why is this so important? Well, I sort of mispoke earlier when I said objects are passed by refernece. I didn't give you the whole picture. What's actually happening is that a copy of the pointer is being passed to the the method. So while you are referencing the same object in memory in the method and the one in the main, the POINTER variable on the stack, is NOT the same. HOWEVER, when using the ref keyword, the pointer itself is passed to the method, not a copy of it! So when you're inside the method itself, you're dealing with the exact same pointer variable that's in the main.

The only way to explain is with an example:



static void Main(string[] args)
{
var alex = new Person("Alex", 27);

ChangePerson(alex);
Console.WriteLine(alex);

ChangePerson(ref alex);
Console.WriteLine(alex);

Console.ReadKey(true);
}


public static void ChangePerson(Person p)
{
p = new Person("Alex", 35);
}

public static void ChangePerson(ref Person p)
{
p = new Person("Alex", 45);
}


Here we have two methods that look the same. The only difference is the ref keyword. What the method is doing, is it's assigning a NEW person object to the Person p (the pointer) that was passed in to the method. However, if you run this program you'll see that the first Console.Writeline still outputs 27 years old, even though we assigned it to a person object that's 35 years old! The reason for this is because the pointer itself was passed by VALUE so when you're assigning a new person object, you're not assigning it to the same pointer referenced in the main.

In the second case however, since we're using the ref keyword, the pointer in the method is the SAME one that's in the main method. Therefore, the second Console.Writeline outputs 45 years old, because the pointer in the main, is now pointing to the object that was assigned to it in the method.

Personally I've never used this yet in production code, but if you understand this, then that means you understand the nitty gritty details of how parameters are passed around. Very impressive on interviews :-)

Tuesday, July 14, 2009

Using JQuery to post a Form with ASP.NET MVC with AJAX

No comments:
Source code:http://www.box.net/shared/2to3vfajqp In order for this sample to work on your machine, you need to have the Northwind database, and you need to configure the connection string in the HomeController.

When you install ASP.NET MVC, you'll notice that when you create a new project, the latest jQuery libraries get added for you as well. For those of you who don't know what jQuery is, think of it as a layer of abstraction for common tasks you would do with javascript. Instead of having to rewrite tons of javascript to let's say, do some animation, or post to a server with AJAX, jQuery makes it all extremely simple. I've found that there aren't that many tutorials online for getting started with jQuery and AJAX when using ASP.NET MVC, so I figured I'll share what I've learned so far in the hopes that maybe others can get some insight.

The premise here will be simple. We'll be using the Northwind database (specifically the Products table) to display a list of Products and some of their attributes. Then, there will be a textbox on top of the list. When the user enters some text into the textbox, it will post back to the server via AJAX and find any products that match what the user entered. Here's what it will look like:




So first I started with a simple ASP.NET MVC application. I'll be using the standard project for this tutorial. I then added a NorthwindDataContext to the Models folder with only the Products table from the Northwind database. Then, I added a repository that will help us retrieve the items from the database. Here's the code for the repository:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MVCJqueryDemo.Models
{
public class NorthwindRepository : IDisposable
{
#region Members

private NorthwindDataContext dataContext;

#endregion

#region Constructors

public NorthwindRepository()
: this(null)
{
}

public NorthwindRepository(string connectionString)
{
dataContext = String.IsNullOrEmpty(connectionString) ? new NorthwindDataContext()
: new NorthwindDataContext(connectionString);
}

#endregion

#region Methods

public IEnumerable<Product> GetAllProducts()
{
return this.dataContext.Products.ToList();
}

public IEnumerable<Product> GetProductsByName(string name)
{
return this.dataContext.Products.Where(p => p.ProductName.Contains(name)).ToList();
}

#endregion

#region IDisposable

public void Dispose()
{
this.dataContext.Dispose();
}

#endregion
}
}


So this class will help us retrieve what we need from the db. Now, over in the Home controller, I've added two actions:



public class HomeController : Controller
{
#region Members

//CHANGE THIS CONNECTION STRING IF YOUR NORTHWIND IS IN A DIFFERENT LOCATION!!!!
private const string CONNECTIONSTRING = "Data Source=.;Initial Catalog=Northwind;Integrated Security=True";

#endregion

public ActionResult Products()
{
using (var repository = new NorthwindRepository(CONNECTIONSTRING))
{
var allProducts = repository.GetAllProducts();
return View(allProducts);
}
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(string name)
{
using (var repository = new NorthwindRepository(CONNECTIONSTRING))
{
var result = repository.GetProductsByName(name);
return View("ProductsPartial", result);
}
}
}


So there are two methods here. Once will be ../Home/Products and the other will be a url where we'll post to ../Home/Search.

The first one is straight forward. It just hits the repository for all the products, and passes it on to the View. We can see from this, that there's a Products View. Here's the code for the Products View:



<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Product>>" %>

<%@ Import Namespace="MVCJqueryDemo.Models" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">

Products
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Products</h2>
<form id="searchForm" action="javascript:void();">
<input type="text" name="name" id="searchBox" />
</form>
<div id="products" class="productsDiv">
<%Html.RenderPartial("ProductsPartial", this.Model); %>
</div>
</asp:Content>


It has a form with a textbox, and then it has a div where we call RenderPartial to render a partial view called: ProductsPartial. Here's the code for the ProductsPartial.ascx:



<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Product>>" %>
<%@ Import Namespace="MVCJqueryDemo.Models" %>


<table id="productsTable">
<tr>
<th>Product ID</th>
<th>Product Name</th>
<th>Units in Stock</th>
<th>Unit Price</th>
<th>Being Produced</th>
<th>Units on Order</th>
</tr>
<%foreach (var product in this.Model)%>
<%{%>
<tr>
<td><%=product.ProductID %></td>
<td><%=product.ProductName %></td>
<td><%=product.UnitsInStock %></td>
<td><%=product.UnitPrice.Value.ToString("$#0.00")%></td>
<td><img class="inStockImages" src="<%=product.Discontinued ? "../../Content/x.png" : "../../Content/check.png" %>" /></td>
<td><%=product.UnitsOnOrder %></td>
</tr>
<%}%>
</table>


So basically, what's happening is this. When you go to ../Home/Products, the Products Action gets called on the Home controller. Then, we get a list of Products from the database, and pass that on to the Products View. The Products View then passes that on to the ProductsPartial which actually renders the products in a nice HTML table.

At this point, we haven't done anything fancy yet. If we were to run it at this point, you'd see a list of all the products displayed. If you were to type anything in the textbox, nothing would happen. Here's where we want to start using some AJAX. The idea will be, that whenever the keyup event will be triggered in the textbox, we'll fire off an AJAX call to the server, and display the results. So first, let's look at the second Action in the Home Controller:



[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(string name)
{
using (var repository = new NorthwindRepository(CONNECTIONSTRING))
{
var result = repository.GetProductsByName(name);
return View("ProductsPartial", result);
}
}
}


As you can see, this Action only accepts HTTP POST requests. Again, we call our repository, and get back a list of Products that match the search criteria. We then call return View to display the ProductsPartial, and we pass in the list of products.

That's all very nice, but how do we call this method? How do we hook up an event to our textbox to trigger this method to be called? This is where we'll use jQuery to make the AJAX call. First, in the head section of your master page, you need to add these lines:



<script src="../../Scripts/jquery-1.3.2.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>


This will include the jQuery libraries in your page. Then, I've added another file called ProductScripts.js into the Scripts folder. Then, I added this line to the head of my page:



<script src="../../Scripts/ProductScripts.js" type="text/javascript"></script>


Here's what the ProductScripts.js file looks like:



$(document).ready(function() {
$("#searchBox").keyup(function(item) {
var textValue = $("#searchBox")[0].value;
var form = $("#searchForm").serialize();
$.post("/Home/Search", form, function(returnHtml) {
$("#products").html(returnHtml);
});

});
});


Looks a little weird at first, but I'll try to explain. First we call $(document.ready(..)). In here is where we hook up all of our jQuery events. This ready function gets called as soon as the DOM is loaded. Then, we get a reference to the searchBox using $("#searchBox"). This is the equivalent of document.getElementById(..) in JavaScript. We then hook into the keyup event and whenever that event is triggered we call this function:



var textValue = $("#searchBox")[0].value;
var form = $("#searchForm").serialize();
$.post("/Home/Search", form, function(returnHtml) {
$("#products").html(returnHtml);


First, we get the text that was typed into the textbox. Then, we get the entire form (which in this case is just the textbox itself). We then serialize the form and call the post method. This is where the actual AJAX call is happening. The parameters that are passed into the post method are as follows:

URL : in our case it's /Home/Search
Data: in our case it's the serialized form, which will then get sent as a parameter to our Search Action on the Home Controller
Callback: in our case it's a function that we use to set the inner HTML of the products div. Remember, the Search Action in our controller renders the ProductsPartial View. So basically it send HTML back to the browesr as a result of the AJAX request. We take that HTML, and stick it into the Products div.

The full source code is available at the link posted at the top, download it and mess with it. It's actually real simple, and real powerful.

In this post I only demonstrated how to send back HTML. Another very common way of sending data is through JSON. I'll cover that in another post. ASP.NET MVC makes it EXTREMELY easy to send JSON across the wire.