Thanks to everyone who came out for my presentation at the Jacksonville Developer User Group tonight.
Razor-based view templates are a much cleaner way to construct MVC views in ASP.NET. However, they were only released fairly recently with MVC3.
If you still have some ASPX-based templates that you'd like to upgrade, Telerik has released a free tool to do just that.
In my recent posts on scalability, I've mentioned the Web Farm Framework (WFF) as a solution for managing a farm of IIS servers. It adds a nice management Server Farm management UI into the IIS Manager.

It is a nice tool, but is only accessible via the windows interface. To make the farm more accessible, I've created a basic farm monitor MVC web site using the WFF .NET API.
Here are a couple of screen shots of it in action:

It uses a few cool features of the API:
- Getting a list of nodes in the farm & their status
Microsoft.Web.Farm.WebFarmManager manager = new Microsoft.Web.Farm.WebFarmManager();
foreach (var farm in manager.WebFarms)
{
foreach (var node in farm.Servers)
{
}
}
- CPU/Memory monitoring. See my sparkline post to learn how to create these kinds of infographics.
PercentageCPU = node.Counters.ProcessorTime/100;
MemoryAvailableKBytes = node.Counters.MemoryAvailableKBytes;
PercentageMemoryAvailable = 1.0f - node.Counters.PercentageMemoryAvailable
- Getting a list of running processes
private static ServerProcess[] GetNodeProcesses(string farmName, string nodeName)
{
var manager = new Microsoft.Web.Farm.WebFarmManager();
var farm = manager.WebFarms[farmName];
var server = farm.Servers[nodeName];
var processes = server.RunOperation(farm.CreateRunOperationOptions("GetProcesses")) as ServerProcess[];
return processes;
}
Download the
source for the project if you'd like to take it for a spin. Make sure the web site's application pool has enough permissions to access the web farm.
In my last post, I introduced sparklines and showed you how to generate them using the Google Chart API. Using an external API may not be appropriate for all applications, so here is a way to generate the sparkline using the .NET Chart API.
Over at the Better Dashboards Blog, they provide some sample code for calling the chart API. The following shows how to make it reusable for your MVC application.
First, we'll create a custom ActionResult to return the image for our sparkline:
public class SparklineResult : FileResult
{
IEnumerable<float> samples;
int SparklineWidth;
int SparklineHeight;
public SparklineResult(int width, int height, IEnumerable<float> samples) : base("image/png")
{
this.samples = samples;
this.SparklineHeight = height;
this.SparklineWidth = width;
}
protected override void WriteFile(HttpResponseBase response)
{
var sparklineImage = GetSparkLineImage(samples, SparklineWidth, SparklineHeight);
response.ContentType = "image/png";
response.BinaryWrite(sparklineImage);
}
private static byte[] GetSparkLineImage(IEnumerable<float> samples, int width, int height)
{
var chart = new Chart();
var series = new Series();
chart.Series.Add(series);
// Sparklines use the 'Spline' chart type to show a smoother trend with a line chart
series.ChartType = SeriesChartType.Spline;
// Since the line is the only thing you see on the chart, you might want to
// increase its width. Interestingly, you need to set the BorderWidth property
// in order to accomplish that.
series.BorderWidth = 2;
// Add samples to the series
int i = 0;
foreach (var sample in samples)
{
i++;
// Add 5 to the sample so line does not get cut off at the bottom of the image
chart.Series[0].Points.AddXY(DateTime.Now.AddDays(i), sample + 5);
}
// Start hiding both sets of axes, labels, gridlines and tick marks
var chartArea = new ChartArea();
chart.ChartAreas.Add(chartArea);
chartArea.AxisX.LabelStyle.Enabled = false;
chartArea.AxisY.LabelStyle.Enabled = false;
chartArea.AxisX.MajorGrid.Enabled = false;
chartArea.AxisY.MajorGrid.Enabled = false;
chartArea.AxisX.MajorTickMark.Enabled = false;
chartArea.AxisY.MajorTickMark.Enabled = false;
chartArea.AxisX.LineWidth = 0;
chartArea.AxisY.LineWidth = 0;
chartArea.AxisY.Minimum = 0;
// Add an extra 5 pixels since the samples were adjusted up by 5
// this prevents the line from being truncated
chartArea.AxisY.Maximum = 105;
// Re-adjust the size of the chart to reduce unnecessary white space
chart.Width = width;
chart.Height = height;
// Get bytes of PNG image
var s = new MemoryStream();
chart.SaveImage(s, ChartImageFormat.Png);
s.Position = 0;
return s.ToArray();
}
}
Next, we'll utilize the SparklineResult in a controller. The controller will serve the image data for the sparkline back to the calling page.
public class ChartController : Controller
{
public ActionResult Sparkline(int width, int height, string samples)
{
return new SparklineResult(width, height, (from s in samples.Split(',') select float.Parse(s)).ToArray());
}
}
Next, we'll create a HTML helper method to generate the img tag which will fetch the image from our controller.
public static MvcHtmlString DrawSparkline(this HtmlHelper helper, int width, int height, IEnumerable<int> plotData)
{
string sparkUrl = "<img src='/chart/sparkline?width={0}&height={1}&samples={2}'/>";
string sparkLine = String.Format(sparkUrl, width, height, String.Join(",", plotData));
return MvcHtmlString.Create(sparkLine);
}
Now we can call the helper method from our Razor template:
@Html.DrawSparkline(70, 20, new int[14] { 1, 4, 2, 6, 20, 30, 1, 23, 14, 2, 41, 2, 33, 21 })
Which produces the following sparkline:

You can download my sample project that puts it all together. This includes both the Google API & .NET API methods.
Sparklines present trends and variations associated with some measurement in a very compact form. The term & concept was proposed by Ed Tufte. This form of information graphic has become very popular for dashboards. In this post, I'll show how add sparklines to your site using a custom HTML Helper method to generate code accessing the Google Chart API. In my next post, I'll show you how to add sparklines using the .NET charting API.
The folks over at Data Driven wrote a post about using the Google Chart API to render a sparkline. The following shows how to take this concept & make it reusable by your MVC application.
Code for the extension method:
public static MvcHtmlString DrawSparkline(this HtmlHelper helper, int width, int height, IEnumerable<int> plotData,
string bgColor, string lineColor, string labelColor)
{
int? max = plotData.Max();
int? min = plotData.Min();
string list = String.Join(",", plotData);
string sparkUrl = "<img src='http://chart.apis.google.com/" +
"chart?cht=lc&chf=bg,s,{6}&cgh=0,50,1,0&chds={0},{1}&chs={2}x{3}&chd=t:{4}&chco={8}" +
"&chls=1,1,0&chm=o,{7},0,20,4&chxt=r,x,y&chxs=0,{7},11,0,_|1,{7},1,0,_|2,{7},1,0,_&chxl=0:|{5}|1:||2:||'/>";
string sparkLine = String.Format(sparkUrl, min, max, width, height, list, plotData.Last(), bgColor, labelColor, lineColor);
return MvcHtmlString.Create(sparkLine);
}
And here is an example of calling the HTML helper from a MVC Razor template:
@Html.DrawSparkline(70, 20, new int[14] { 1, 4, 2, 6, 20, 30, 1, 23, 14, 2, 41, 2, 33, 21 }, "ffffff", "999999", "990000")
Which produces the following sparkline:
Today at the Jax Code Camp I gave a presentation on scaling out your .NET applications by leveraging IIS7, AppFabric, Web Farm Framework, and Web Deploy. Thanks to everyone how come out to the session.
I've posted the presentation over at SlideShare and here are some related blog posts that I mentioned during the talk:

Need further reading?
» Web
Farm Framework
» Windows AppFabric
» Other
Gupreet over on the IIS.NET site posted a sample for integrating an F5 load balancer with the Web Farm Framework. It works well, but isn't configurable. I started adding my own configuration, but artisticcheese posted a project to CodePlex that already has this functionality.
To install, download the extension and perform the following:
- Create pool on F5 load balanacer with exactly the same
name on WFF. Do not add any farm members yet.
- Stop WFF service
- Create folder "%programfiles%\IIS\Microsoft Web Farm Framework\extensions"
and put all files in distribution into that folder
- Modify "F5LoadBalancer.dll.config" file to point to active node of F5
loadbalancer and authentication credentials
- Copy "icontrol.dll" into "%programfiles%\IIS\Microsoft Web Farm Framework"
- Open "%systemroot%\system32\inetsrv\config\applicationHost.config" and edit
XML node below by adding attribute in bold <webFarm name="DevWebFarm"
enabled="true" primaryServer="webnode1" loadBalancerProvider="F5">
- Start WFF service
iControl.dll is an assembly provided by BigIP giving you a .NET API to control your F5 Local Traffic Balancer.
Now that you have it installed, WFF will automatically take nodes online & offline thru the F5 as needed. This supports rolling deployments and more.
Internet Explorer 9 is finally here...well almost. Microsoft is releasing their new browser on March 14, 2011.
IE9 has a number of improvements, including:
-
Faster, Faster, Faster. Did I mention it is faster? With the new browsers coming out from Mozilla, Google, and Microsoft, there have been a flood of speed test coverage. Chrome has long held the javascript speed crown. But according to
Steven J. Vaughan-Nichols over at ZDNET..."for the moment at least IE9 is actually the
fastest browser I’ve tested to date." He came to this revelation after figuring out that the 32-bit version of IE9 has the new
Chakra JIT (the 64-bit version doesn't). It also has a DirectX-based rendering engine so it can do
cool tricks once reserved for desktop applications.
-
Windows 7 Desktop Integration. Read
my post for more details. Unfortantely, they didn't integrate
my ideas...at least not yet :)
-
Hot new UI. Ok, they "borrowed" some ideas from Chrome...but that is the best form of flattery.
-
Standards Compliance. A real focus on HTML5 and CSS3. Definite goodness for developers.
So, go get yourself some IE9 on Monday and enjoy!
Microsoft has been beta testing SP1 since December of last year. Today, it was released to MSDN subscribers and will be available for public download on March 10, 2011.
The service pack includes a slew of fixes, and a number of new features:
- Silverlight 4 support
- Basic Unit Testing support for the .NET Framework 3.5
- Performance Wizard for Silverlight
- IntelliTrace for 64-bit and SharePoint
- IIS Express support
- SQL CE 4 support
- Razor support
- HTML5 and CSS3 support (IntelliSense and validation)
- WCF RIA Services V1 SP1 included
- Visual Basic Runtime embedding
- ALM Improvements
Of all the improvements, IIS Express probably has the largest impact on web developer productivity.
According to Scott Gu, it provides the following:
- It’s lightweight and easy to install (less than 10Mb download and a super quick install)
- It does not require an administrator account to run/debug applications from Visual Studio
- It enables a full web-server feature set – including SSL, URL Rewrite, Media Support, and all other IIS 7.x modules
- It supports and enables the same extensibility model and web.config file settings that IIS 7.x support
- It
can be installed side-by-side with the full IIS web server as well as
the ASP.NET Development Server (they do not conflict at all)
- It works on Windows XP and higher operating systems – giving you a full IIS 7.x developer feature-set on all OS platforms
IIS Express (like the ASP.NET Development Server) can be quickly launched to run a site from a directory on disk. It does not require any registration/configuration steps. This makes it really easy to launch and run for development scenarios.
Good stuff indeed. This will make our lives much easier. Thanks Microsoft...we're feeling the love!
There are a few different APIs for accessing Twitter from .NET. In this example, I'll use linq2twitter. Other APIs can be found on Twitter's development site.
First off, we'll use the LINQ provider to pull in the recent tweets.
1: public static Status[] GetLatestTweets(string screenName, int numTweets)
2: {
3: try
4: {
5: var twitterCtx = new LinqToTwitter.TwitterContext();
6: var list = from tweet in twitterCtx.Status
7: where tweet.Type == StatusType.User &&
8: tweet.ScreenName == screenName
9: orderby tweet.CreatedAt descending
10: select tweet;
11: // using Take() on array because it was failing against the provider
12: var recentTweets = list.ToArray().Take(numTweets).ToArray();
13: return recentTweets;
14: }
15: catch
16: {
17: return new Status[0];
18: }
19: }
Once they have been retrieved, they would be placed inside an MVC model.
Next, the tweets need to be formatted for display. I've defined an extension method to aid with date formatting:
1: public static class DateTimeExtension
2: {
3: public static string ToAgo(this DateTime date2)
4: {
5: DateTime date1 = DateTime.Now;
6: if (DateTime.Compare(date1, date2) >= 0)
7: {
8: TimeSpan ts = date1.Subtract(date2);
9: if (ts.TotalDays >= 1)
10: return string.Format("{0} days", (int)ts.TotalDays);
11: else if (ts.Hours > 2)
12: return string.Format("{0} hours", ts.Hours);
13: else if (ts.Hours > 0)
14: return string.Format("{0} hours, {1} minutes",
15: ts.Hours, ts.Minutes);
16: else if (ts.Minutes > 5)
17: return string.Format("{0} minutes", ts.Minutes);
18: else if (ts.Minutes > 0)
19: return string.Format("{0} mintutes, {1} seconds",
20: ts.Minutes, ts.Seconds);
21: else
22: return string.Format("{0} seconds", ts.Seconds);
23: }
24: else
25: return "Not valid";
26: }
27: }
Finally, here is the piece of the view used to render the tweets.
1: <ul class="tweets">
2: <%
3: foreach (var tweet in Model.Tweets)
4: {
5: %>
6: <li class="tweets">
7: <span class="tweetTime"><%=tweet.CreatedAt.ToAgo() %> ago</span>:
8: <%=tweet.Text%>
9: </li>
10: <%} %>
11: </ul>
More Posts
Next page »