Showing posts with label ASP.NET MVC. Show all posts
Showing posts with label ASP.NET MVC. Show all posts

Wednesday, February 15, 2012

Passing variables from your Controller to your JavaScript in ASP.NET MVC

GitHub link to NGon: https://github.com/brooklynDev/NGon

Last night I was watching the latest RailCast screen cast, where Ryan showed a cool technique in Ruby on Rails on how to pass data from your Controller straight to your JavaScript:

http://railscasts.com/episodes/324-passing-data-to-javascript

Essentially, it involved using a gem called Gon which enabled you to do this in your controller:



I thought that was pretty cool, and it'd be awesome to have the same thing in ASP.NET MVC. Enter NGon. The code is actually very simple, but I think the usage is quite elegant (It's up on GitHub here, complete with Unit Tests and a sample app).

Usage:


The first step is to register the NGonActionFilterAttribute in the global filters in your Global.asax.cs page:



Then, in your Controller, you do this:



Next, in your HTML page (probably in your Layout.cshtml page so it's available everywhere) you add this line:


@Html.IncludeNGon()


At this point, you'll now have access to the values in your javascript:



The cool thing is that it works on more than just simple types. It works on any object which in turn gets serialized into JSON (using the JavascriptSerializer). This allows you to do something like this:



and in your javascript:



Under the hood:



It's actually all quite simple. The first thing that happpens, is when an action gets called, the NGonActionFilterAttribute fires, and it creates a new ExpandoObject called NGon on the Controllers ViewBag property:



Then, as you keep adding items to the ViewBag.NGon property, you're adding it to this underlying ExpandoObject. Finally, when you call the IncludeNGon in the HTML, this is where all the magic happens:



What it does is, it first creates an empty javascript object on the window object. Then, for each property in the ViewBag.NGon property, it adds the serialized version of it to that javascript object on the window object. What you end up with, is something like this:



Cool huh? Drop me a comment, let me know what you think!

Friday, March 11, 2011

Master Page Model in ASP.NET MVC 3 using Dependency Injection (Unity)

Link to source code: http://www.box.net/shared/ujfbu1ig9z

A common problem many developers face when creating ASP.NET MVC applications, is when you need some data in your Master Page (I know they're called "Layout" pages in Razor, but from here on out I'll be referring to them as Master Pages). The problem comes up when you need to have some dynamic data in the Master Page itself (think of a Shopping Cart example, where you want to display the current count of items in the cart) but since we ever only send data from the Controllers to the Views themselves, how does the Master Page get the data that it needs.

I know there are many solutions out there, and I'm not saying any of them are good or bad, I'm just here to show another way of doing it, using Dependency Injection. For this example, I'll be demoing a use case of where we want to display my last 5 tweets on the Master Page. This is the final result:



The right hand side under Index is the Index View, but on the left hand side, the "left nav" is where the twitter feed sits, and that data we want to display on every page, and will therefore come from the master page.

In ASP.NET MVC 3, Dependency Injection has become very easy. Now all you need to do is to implement your own IDependencyResolver, and let the framework know to use your custom resolver when it needs to build up Controllers and such. Here's a typical implementation using Unity:



public class UnityDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer _unityContainer;

public UnityDependencyResolver(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}

public object GetService(Type serviceType)
{
if (!_unityContainer.IsRegistered(serviceType))
{
if (serviceType.IsAbstract || serviceType.IsInterface)
{
return null;
}
}

return _unityContainer.Resolve(serviceType);
}

public IEnumerable<object> GetServices(Type serviceType)
{
return _unityContainer.ResolveAll(serviceType);
}
}


Not much to explain on this one, except that with Unity there's no "TryResolve" (actually there is in the Prism Codeplex project, but all that does is wrap a try/catch) so therefore we need to make sure we can resolve the type before we actually call Resolve.

Now let's start building on top of that. I created an interface called IMasterPageDataRetriever. It's responsibility is simply to get data that the Master Page needs. In this case, it'll call out to a Service that calls Twitter to retrieve my last 5 tweets (incidentally, NuGet is AWESOME for this kind of stuff. I just typed in "Twitter" in the Search box in Nuget, and picked the one that looked the most popular "TweetSharp". Cool stuff).



public interface IMasterPageDataRetriever
{
object GetMasterPageData();
}


Here's the implementation:



public class MasterPageDataSetter : IMasterPageDataRetriever
{
private readonly ITweetRetriever _tweetRetriever;

public MasterPageDataSetter(ITweetRetriever tweetRetriever)
{
_tweetRetriever = tweetRetriever;
}

public object GetMasterPageData()
{
return new TweetViewModel(_tweetRetriever.GetTweets("@brooklynDev", 5));
}
}

public class Tweet
{
public string UserName { get; set; }
public string Message { get; set; }
public DateTime Timestamp { get; set; }
}

public interface ITweetRetriever
{
IEnumerable<Tweet> GetTweets(string userName, int maxAmount);
}

public class TweetRetriever : ITweetRetriever
{
public IEnumerable<Tweet> GetTweets(string userName, int maxAmount)
{
var service = new TwitterService();
var result = service.ListTweetsOnSpecifiedUserTimeline(userName, maxAmount);
return result.Select(r => new Tweet
{
Message = r.TextAsHtml,
Timestamp = r.CreatedDate,
UserName = userName
});
}
}

public class TweetViewModel
{
public TweetViewModel(IEnumerable<Tweet> tweets)
{
this.Tweets = tweets.Select(t => t.Message);
this.UserName = tweets.First().UserName;
}

public string UserName { get; set; }
public IEnumerable<string> Tweets { get; set; }

}


Not much code, but the point here is, I have an implementation of an IMasterPageDataRetriever that gets injected with an ITweetRetriever, calls that TweetRetriever and that returns a ViewModel that has the tweets in it. So far this is all pretty straight forward, very common stuff that you see in all apps that use loose coupling.

The questions now however, is how does the Master Page get a hold of this TweetViewModel? The trick is in the Dependency Resolver. Here's the updated code, I'll do my best to explain:



public class UnityDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer _unityContainer;

public UnityDependencyResolver(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}

public object GetService(Type serviceType)
{
if(!_unityContainer.IsRegistered(serviceType))
{
if(serviceType.IsAbstract || serviceType.IsInterface)
{
return null;
}
}

var result = _unityContainer.Resolve(serviceType);
var controller = result as ControllerBase;
if(controller == null)
{
return result;
}
try
{
var masterPageDataSetter = _unityContainer.Resolve<IMasterPageDataRetriever>();
controller.ViewBag.MasterPageModel = masterPageDataSetter.GetMasterPageData();
return controller;
}
catch
{
return result;
}
}

public IEnumerable<object> GetServices(Type serviceType)
{
return _unityContainer.ResolveAll(serviceType);
}
}


What's happening here is that instead of just returning what we got out of the container, we first check if it's a Controller (if it can be assigned to a ControllerBase). If it is, we cast it to a ControllerBase, at which point we use the ViewBag property, and set the data we get from our IMasterPageDataRetriever (pulled out of the container) to a (dynamic) property on the ViewBag called "MasterPageModel". In order for this to work, you need to make sure you're correctly configuring your container:

In my Global.asax I have this:



protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

DependencyResolver.SetResolver(new UnityDependencyResolver(GetConfiguredContainer()));
}

private IUnityContainer GetConfiguredContainer()
{
var container = new UnityContainer();
container.RegisterType<ITweetRetriever, TweetRetriever>();
container.RegisterType<IMasterPageDataRetriever, MasterPageDataSetter>();
return container;
}


I'm registering all the dependencies I need, including the IMasterPageDataRetriever.

Now, in order to use this data, here's what we do in our Master Page (I'm using the Razor view engine, but this can obviously be applied to any View Engine):

First, I created a Partial View that will actually display the Tweets. It's strongly typed to the TweetViewModel type:



@model MasterPageModelDemo.Web.Models.TweetViewModel

<h4>@this.Model.UserName</h4>
<ul>
@foreach(var tweet in this.Model.Tweets)
{
<li>@Html.Raw(tweet)</li>
}
</ul>


Then, in my Master Page:



@{Html.RenderPartial("TweetViewPartial", (object)ViewBag.MasterPageModel);}


Make sure to cast it to an object, because if not, .Net will complain that it doesn't have an overload that takes dynamic, since the ViewBag is dynamic.

When you put it all together, we get this:



The only tricky bit here, is to unit test this so that we can make sure we never accidentally mess up our DependencyResolver and no longer setting the MasterPageModel property. The hard part about this particular unit test, is that we need a UnityContainer. The problem is, we want to mock a ControllerBase, and an IMasterPageDataRetriever. Now remember, when mocking objects, the Mocking framework (in this case I'll be using Moq) creates Proxy objects with no types at runtime. For one reason or another, Unity doesn't play nice with Proxy types, so therefore, we're stuck using our own implementation of IUnityContainer. It's not bad because there's really only two things we need to give implementations for:



public class TestContainer : IUnityContainer
{
private readonly IMasterPageDataRetriever _masterPageDataRetriever;
private readonly ControllerBase _controllerBase;

public TestContainer(IMasterPageDataRetriever masterPageDataRetriever, ControllerBase controllerBase)
{
_masterPageDataRetriever = masterPageDataRetriever;
_controllerBase = controllerBase;
}

public IUnityContainer AddExtension(UnityContainerExtension extension)
{
throw new NotImplementedException();
}

public object BuildUp(Type t, object existing, string name, params ResolverOverride[] resolverOverrides)
{
throw new NotImplementedException();
}

public object Configure(Type configurationInterface)
{
throw new NotImplementedException();
}

public IUnityContainer CreateChildContainer()
{
throw new NotImplementedException();
}

public IUnityContainer Parent
{
get
{
throw new NotImplementedException();
}
}

public IUnityContainer RegisterInstance(Type t, string name, object instance, LifetimeManager lifetime)
{
throw new NotImplementedException();
}

public IUnityContainer RegisterType(Type from, Type to, string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
{
throw new NotImplementedException();
}

public IEnumerable<ContainerRegistration> Registrations
{
get
{
return Enumerable.Empty<ContainerRegistration>();
}
}

public IUnityContainer RemoveAllExtensions()
{
throw new NotImplementedException();
}

public object Resolve(Type t, string name, params ResolverOverride[] resolverOverrides)
{
if (t == typeof(IMasterPageDataRetriever))
{
return _masterPageDataRetriever;
}
if ((typeof(ControllerBase)).IsAssignableFrom(t))
{
return _controllerBase;
}

throw new InvalidOperationException();
}

public IEnumerable<object> ResolveAll(Type t, params ResolverOverride[] resolverOverrides)
{
throw new NotImplementedException();
}

public void Teardown(object o)
{
}

public void Dispose()
{
}
}


Basically, we take in an instance of an IMasterPageDataRetriever, and a ControllerBase. In the resolve method, we just pass the correct one back, based on what's being asked from it. Here's the actual test (I'm using NUnit, again, NuGet is awesome for adding all these references!!)



[TestFixture]
public class Tests
{
[Test]
public void TestMasterPageDataGetsSetByDependencyResolver()
{
const string testData = "Test Data";

var masterDataRetrieverMoq = new Mock<IMasterPageDataRetriever>();
masterDataRetrieverMoq.Setup(m => m.GetMasterPageData()).Returns(() => testData);
var masterDataRetireverObject = masterDataRetrieverMoq.Object;

var controllerMoq = new Mock<ControllerBase>();
var controllerObject = controllerMoq.Object;
var unityDependencyResolver = new UnityDependencyResolver(new TestContainer(masterDataRetireverObject, controllerObject));
var result = unityDependencyResolver.GetService(controllerObject.GetType()) as ControllerBase;

Assert.AreEqual(result.ViewBag.MasterPageModel, testData);
}
}


Here, we're mocking out the IMasterPageDataRetriever, and making it return a string "Test Data". After registering that instance with our fake container, and then calling GetService on the UnityDependencyResolver, the Mocked ControllerBase ViewBag should have the "Test Data" set.

Like I said in the beginning, this is far from the only way of doing it, it's just that I like this approach because you don't need to force your ViewModels from inheriting some base view model, you don't need to have a custom ControllerBase, you just need to massage your Dependency Injection code a bit, and then forget it's ever there. Also, as I've shown, it's still testable, which is always a good thing! Enjoy!

Tuesday, July 14, 2009

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

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.

Wednesday, March 25, 2009

Cool IEnumberable extension method. Useful in ASP.NET MVC

So recently at work we started revamping our site and we've decided to use ASP.NET MVC. I'm not going to cover ASP.NET MVC in this blog post (hopefully in the future) but in short, it's Microsoft's new Web Framework that doesn't use WebForms. No more postbacks for every little thing! Woohoo! However, without WebForms, that means no more ASP.NET controls. Therefore, it was useful for us in a few places to be able to generate an HTML table from a collection of various different objects. So, I ended up writing a really cool extension method which I think can be beneficial since it covers generics, and reflection (two topics that wasn't explored thoroughly enough in SetFocus IMO).

So, first I'll show the code, then I'll do my best to explain:

        public static string ToHtmlTable<T>(this IEnumerable<T> list,string tableSyle, string headerStyle, string rowStyle, string alternateRowStyle)
        {
            var result = new StringBuilder();
            if (String.IsNullOrEmpty(tableSyle))
            {
                result.Append("<table id=\"" + typeof(T).Name + "Table\">");
            }
            else
            {
                result.Append("<table id=\"" + typeof(T).Name + "Table\" class=\"" + tableSyle + "\">");
            }
 
            var propertyArray = typeof(T).GetProperties();
 
            foreach (var prop in propertyArray)
            {
                if (String.IsNullOrEmpty(headerStyle))
                {
                    result.AppendFormat("<th>{0}</th>", prop.Name);
                }
                else
                {
                    result.AppendFormat("<th class=\"{0}\">{1}</th>",headerStyle, prop.Name);
                }
            }
 
 
            for (int i = 0; i < list.Count(); i++)
            {
                if (!String.IsNullOrEmpty(rowStyle) && !String.IsNullOrEmpty(alternateRowStyle))
                {
                    result.AppendFormat("<tr class=\"{0}\">", i%2==0 ? rowStyle : alternateRowStyle);
                }
 
                else
                {
                    result.AppendFormat("<tr>");
                }
                foreach (var prop in propertyArray)
                {
                    object value = prop.GetValue(list.ElementAt(i), null);
                    result.AppendFormat("<td>{0}</td>", value ?? String.Empty);
                }
                result.AppendLine("</tr>");
            }
 
            result.Append("</table>");
 
            return result.ToString();
        }


Ok, let's start with the parameters:

        public static string ToHtmlTable<T>(this IEnumerable<T> list,string tableSyle, string headerStyle, string rowStyle, string alternateRowStyle)


This will allow us to pass in the CSS class of each piece in the HTML table. The way it's coded is that you can pass in null or empty strings and it'll ignore it. Otherwise, it'll enter that as the class name. IE:

<table class="tableClass">


Also notice that the method is generic, so any collection of any kind will work with this method.

            var result = new StringBuilder();
            if (String.IsNullOrEmpty(tableSyle))
            {
                result.Append("<table id=\"" + typeof(T).Name + "Table\">");
            }
            else
            {
                result.Append("<table id=\"" + typeof(T).Name + "Table\" class=\"" + tableSyle + "\">");
            }


Here we start building up the HTML table. If a CSS class was supplied for the table, then we put that in the table tag, otherwise, we don't put any class name. I gave it an ID based on the name of the type that T represents. This may be useful if you want to apply further CSS, so it's good practice to give every element an ID, but in our example we won't actually make use of it. I just left it there for completeness.

            var propertyArray = typeof(T).GetProperties();


Here's where we reflect over T to get an array of PropertyInfo objects. GetProperties returns a PropertyInfo[] array.

            foreach (var prop in propertyArray)
            {
                if (String.IsNullOrEmpty(headerStyle))
                {
                    result.AppendFormat("<th>{0}</th>", prop.Name);
                }
                else
                {
                    result.AppendFormat("<th class=\"{0}\">{1}</th>",headerStyle, prop.Name);
                }


Next, we want to set up the table headers. The headers of the HTML table will be the actual property name. So say you were passing in a List to this method, and your Car class had properties such as "Year", "Make" etc, then that's what would actually appear as the column headers. That's what the PropertyInfo.Name property represents.

            for (int i = 0; i < list.Count(); i++)
            {
                if (!String.IsNullOrEmpty(rowStyle) && !String.IsNullOrEmpty(alternateRowStyle))
                {
                    result.AppendFormat("<tr class=\"{0}\">", i%2==0 ? rowStyle : alternateRowStyle);
                }
 
                else
                {
                    result.AppendFormat("<tr>");
                }


Here we start enumerating the actual IEnumerable that was passed in. For every element in the collection, we want to add a row to our table. Thefore, we first open the tag. However, if the styles for rows are set (both rowStyle and alternateRowStyle) then we need to apply the appropriate class to the row. We can simply check if i is currently an even number (i % 2 == 0). If it is, then we're on a regular row, if it's odd, then we're on an alternate row. If no style is specified, just do a regular tag.

                foreach (var prop in propertyArray)
                {
                    object value = prop.GetValue(list.ElementAt(i), null);
                    result.AppendFormat("<td>{0}</td>", value ?? String.Empty);
                }
                result.AppendLine("</tr>");
            }


Now, we go back to using our PropertyInfo array. For each item in our collection, we want to enumerate over all of it's properties, and get the value for that property. Therefore, first we call the GetValue method on the current PropertyInfo. The first parameter to GetValue, is the object of whose value you want to get. The second one, is if parameters are neccessary to access that property like an indexer. We won't be dealing with that here so we just pass null.

Then, if value isn't null, we append that to the table, else we append a String.Empty. You'll notice the syntax is value ?? String.Empty. That's actually called the "null coalescing operator" It's basically a shorthand way of saying "If value isn't null, use value, else use String.Empty".

            result.Append("</table>");
 
            return result.ToString();
        }


Finally, we just close up the tag and then the tag. Then, we return the result. Now, let's actually test this!

Create a winforms project and add a button to the form, and a WebBrowser control. Then, create a simple Person class like this:

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }


No big deal, simple class with three properties. Then, in the button click, create a new List and add a few Person objects to that list:
        private void button1_Click(object sender, EventArgs e)
        {
            var personList = new List<Person>();
            personList.Add(new Person
            {
                FirstName = "Alex",
                LastName = "Friedman",
                Age = 27
            });
 
            personList.Add(new Person
            {
                FirstName = "Jack",
                LastName = "Bauer",
                Age = 45
            });
 
            personList.Add(new Person
            {
                FirstName = "Cloe",
                LastName = "O'Brien",
                Age = 35
            });
 
            personList.Add(new Person
            {
                FirstName = "John",
                LastName = "Doe",
                Age = 30
            });
 
            string html = @"<style type = ""text/css""> .tableStyle{border: solid 5 green;} 
th.header{ background-color:#FF3300} tr.rowStyle { background-color:#33FFFF; 
border: solid 1 black; } tr.alternate { background-color:#99FF66; 
border: solid 1 black;}</style>";
            html += personList.ToHtmlTable("tableStyle", "header", "rowStyle", "alternate");
            this.webBrowser1.DocumentText = html;
        }


Then, I created an html string with all the different CSS styles to simulate a real life scenario where you'll actually have those classes in your CSS file. Finally, call the ToHtmlTable method, and set the webBrowser's DocumentText to the HTML. This is the result:





FirstNameLastNameAge
AlexFriedman27
JackBauer45
CloeO'Brien35
JohnDoe30


Yuck, those colors are nasty! But you get the idea. The nice thing is, since it's generic, and on IEnumerable, any collection of objects that you have can now be turned into an HTML table by calling this one method. Gotta love generics and reflection.