First time here? Check out the site's "greatest hits" or read a post from the archives. Feel free to leave a comment or ask a question, and consider subscribing to the latest posts via RSS or e-mail. Thanks for visiting!
Do you Tweet? Follow me on Twitter @shanselman or learn how to use Twitter!
Page 1 of 1 in the NerdDinner category

blogging

Are you in King County/Seattle/Redmond/Bellevue and surrounding areas? Are you a huge nerd? Perhaps a geek? No? Maybe a, dork, dweeb or wonk. Maybe you're in town for an SDR (Software Design Review) or just hanging out. Quite possibly you're just a normal person.

Regardless, why not join us for some Mall Food at the Crossroads Bellevue Mall Food Court on July 7th around 6:00pm?

All the details are at http://www.nerddinner.com/717

Also, please Tweet This!

If you want to come and share something with the group, please do! We're language and technology agnostic and always eager to learn about new stuff.

It'd be great if Microsoft Employees came also - everyone loves to put a face to a blog and sometimes Microsoft folks get tunnel vision and don't learn about what's going on in other groups! All are welcome...Please spread the word!

Hope to see you there. If not, I shall eat my Spicy Chicken alone in peace.



UPDATE: David's put the T4 template with some nice updates on CodePlex - It's the last download here.

I really advocate folks reading as much source as they can because you become a better writer by reading as much as writing. That's the whole point of the Weekly Source Code - reading code to be a better developer.

Reading code in Open Source projects is a good way to learn, especially if the project has been around a while and been successful, or if you already respect the team of people working on it. Less reliably, you can find snippets of code by searching and sharing code.

David Ebbo is scary clever. You know someone is smart when they come up with something you don't think you yourself could come up with on your own, but you still kick yourself for not thinking of it in the first place.

David's been experimenting with ways to make ASP.NET MVC better, specifically in the area of strongly-typed helpers. He's trying to get rid of strings, magic or otherwise.

He started with a BuildProvider (not a lot of folks know about BuildProviders...it's a powerful secret.) David didn't like these kinds of links in ASP.NET MVC:

<%= Html.ActionLink("Home", "Index", "Home")%>

So his BuildProvider would get added to the web.config:

<buildProviders>
<add extension=".actions" type="MvcActionLinkHelper.MvcActionLinkBuildProvider" />
</buildProviders>

And it would give you better methods like this, by poking around in your project and dynamically generating helper methods for you:

<%= Html.ActionLinkToHomeIndex("Home")%>

image_7Then, just days later, David got the T4 religion (I've argued we are doing a poor job of promoting this, so I'm telling everyone I know) and you should too. David explored the pros and cons of CodeDom vs. T4 for CodeGen then recreated his ASP.NET MVC Helpers using T4.

He's enabling not only better ActionLinks, but also Action Url Helpers, Constants for View Names, and a very clever thing, helpers for View Models, courtesy of David Fowler.

I thought this was particular cool, because it's a really visceral example of what you can do with Code Generation when you start exploring what you know at compile time with what you wish you knew at Design Time. It also reminds us that it's more than just Compile/Test/Run - your projects become more "meta" when you've got Inspect/CodeGen/Compile/Test/Run.

For example, if you have a ViewModel that say, has a string, rather than:

<label for="Name">Name:</label>
<%= Html.TextBox("Name", Model.Name) %>
<%= Html.ValidationMessage("Name", "*") %>

Why not this instead:

<%= ViewModel.Name.Label() %>
<%= ViewModel.Name.TextBox() %>
<%= ViewModel.Name.Validation() %>

This ViewModel stuff is in the earlier CodeDom templates, but not (yet?) the T4 templates. I hope we see it again, don't you? What do you think, Dear Reader, of this approach vs. the "Opinionated Input Builder" approach?

Just recently David put out his "new and improved" MVC T4 template, which is the one you should check out. I'm gently pushing him to put it on CodePlex somewhere and bake this goodness in. (Go tell him and Phil!)

He was doing some stuff at runtime, but has since moved to a pure design-time approach.

David Ebbo's ASP.NET MVC T4 Template applied to Nerd Dinner

image_d417b977-3d4c-4d3c-88e6-438b7a32582c David took the NerdDinner app as his base, and installed his T4 template. Just drop it in, and magic gets generated. How does it work, though?

Before he was using reflection but since this is a Design Time Code Generation process he had to delve into the *gasp* COM-based VS File Code Model API. However, this does really show off the power and flexibility of T4 itself. Kudos to David for looking COM in the face and not blinking!

Go download his template (direct ZIP here) and open it up.

T4 files can be scary to view in a text editor as they are constantly switching between <% code blocks %> and the code that's being generated. I use Notepad2 to view them, using the (interestingly enough) XML Document option that gives me rudimentary syntax highlighting.

If you're serious about T4, go get the Visual T4 Community Edition from Clarius for half-way syntax highlighting, or pay for the Professional Edition. They'll register themselves with Visual Studio and give you a better experience than just all-black text.

The first line in David's T4 template that made me chuckle was the the first line that's executed:

<# PrepareDataToRender(this); #>

As they say, it's funny because it's true. This is typical of code generation templates of all kinds. It's the "DoIt()" method that takes the left-hand's code (the COM crap) and prepares it for the right-hand (the template itself).

In order for David to make his template tidy and enable this nice clean level of abstraction:

<#  foreach (var controller in Controllers.Where(c=>c.IsPartialClass)) { #>
namespace <#= controller.Namespace #> {
public partial class <#= controller.ClassName #> {
protected RedirectToRouteResult RedirectToAction(ControllerActionCallInfo callInfo) {
return RedirectToAction(callInfo.Action, callInfo.Controller, callInfo.RouteValues);
}
...snip...

...he has to prepare an object model, and that's what PrepareDataToRender does. It's funny also because it's buried at the end, as it should be. It's really a pleasure to read and does a LOT considering it's only a 415 line template.

He has a number of cute gems like this one-line helper function that combines a little COM a little LINQ and a little magic to a list of methods to his template using the Visual Studio API. I laughed at the "functionFunction" enum. "Do you like her? or do you like her like her?"

// Return all the CodeFunction2 in the CodeElements collection
public static IEnumerable<CodeFunction2> GetMethods(CodeClass2 codeClass) {
// Only look at regular method (e.g. ignore things like contructors)
return codeClass.Members.OfType<CodeFunction2>()
.Where(f => f.FunctionKind == vsCMFunction.vsCMFunctionFunction);
}

David is clearly deep into this exploration right now, and is asking your opinion about the design. I would encourage you to flood him with feedback, or leave it hear and I'll tell him. ;)



Joe Lowrance said, er tweeted, it best when he said,

"the amount of attention ELMAH hasn't got is shocking."

ELMAH is one of those largely unknown and deeply awesome .NET Open Source projects that should be part of ASP.NET proper.

What is ELMAH?

I like to say that ELMAH is Tivo for your ASP.NET Errors. You can get your Yellow Screens of Death, with full call-stack back and analyze what's really happening. It's Exception Driven Development. What's it really do?

Once ELMAH has been dropped into a running web application and configured appropriately, you get the following facilites without changing a single line of your code:

  • Logging of nearly all unhandled exceptions.
  • A web page to remotely view the entire log of recoded exceptions.
  • A web page to remotely view the full details of any one logged exception.
  • In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with customErrors mode turned off.
  • An e-mail notification of each error at the time it occurs.
  • An RSS feed of the last 15 errors from the log.
  • A number of backing storage implementations for the log, including in-memory, Microsoft SQL Server and several contributed by the community.

Created by Atif Aziz (@raboof on Twitter) and Scott Mitchell, ELMAH means is "Error Logging Modules and Handlers" and has been rocking my world since, well, September of 2004.

(Small Correction, Scott Mitchell helped writing the original MSDN article. ELMAH is 100% conceived of by Atif.)

From the project site:

ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.

ELMAH is wonderful for many reasons. First, because it just works. Second, because it's a fantastic example of effective use of HttpModules and HttpHandlers working together. Third, because it's been design with enough thought that nearly anything you'd want from it for use in a production site is there.

I'm sitting here in a cafe and I'm going to add ELMAH to the ASP.NET MVC-based NerdDinner.com Source Code. Actually, the site, as I don't need to recompile the source if I'm not doing anything tricky. ;)

Implementing ELMAH on your ASP.NET (MVC or otherwise) Site 

I download ELMAH, and I put its DLL in my /bin folder (or wherever you like to put libraries). ELMAH doesn't need to be referenced by your project directly if you don't want to. Ultimately it just needs to be in your bin folder so it can be found. You can put it in /lib and make a build event if you like, as long as it ends up in /bin.

Then I open up two instances of notepad and copy over a few HttpHandlers and HttpModules into my existing web.config. Tedious, but straightforward.

Where you put these depends on if you're using IIS6 or IIS7, but the general idea is the handlers looks like this:

<handlers>
....
<add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" preCondition="integratedMode" type="Elmah.ErrorLogPageFactory, Elmah"/>
....
</handlers>

and the modules looks like this:

<modules runAllManagedModulesForAllRequests="true">
...
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
...
</modules>

You can pare it down a bit if you don't need ErrorMail, for example. Then, I hit my site at http://localhost:xxxx/elmah.axd and I get this Error log, similar to what you'd see via Trace.axd.

Error log for  on HANSELMAN-T60P (Page #1) - Windows Internet Explorer

Ok, no errors. Let's make some. I'll visit some messed up URLs and intentionally cause trouble...here's what ELMAH says now:

Error log for  on HANSELMAN-T60P (Page #1) - Windows Internet Explorer (2)

And I can drill down and see the Yellow Screen of Death (YSOD) as it "would have been."

Error System.ArgumentException [5] - Windows Internet Explorer

Now, this assumes my ASP.NET MVC site has no error handling to speak of. ELMAH is watching for unhandled exceptions and recording them, holding them in memory. I can also setup logs to SQL Server or VistaDB or SQLLite so they'll live beyond application recycles.

You can certainly secure access to the ELMAH pages. You can also pull the errors into your favorite RSS Reader, which is a killer feature, IMHO.

Making ELMAH work with ASP.NET MVC's "HandleError" Attribute

In ASP.NET MVC there's an attribute called [HandleError] that will grab anything that goes wrong inside your controllers and show the ~\Shared\Error.aspx View. However, because it "handles" the error, it hides it from ELMAH. Remember that [HandleError] is a declarative try/catch. In my case, I want to have ELMAH handle it.

There's two ways around this.

One, I made a method in my Controller like this:

public ActionResult Trouble()
{
return View("Error");
}

In my web.config, I have a customErrors section like this:

<customErrors mode="On" defaultRedirect="/Dinners/Trouble">
<error statusCode="404" redirect="/Dinners/Confused" />
</customErrors>

This sends folks to /Dinners/Trouble which shows the Error page, after ELMAH takes care of it.

Second, as an advanced technique, I could write my own derived HandleErrorWithELMAHAttribute that logs the error using ELMAH's API, then passes the exception up to the default handler with ASP.NET MVC.

UPDATE: Looks like Dan Swatik was coincidentally doing a similar thing error this morning! What's nice about the solution on Dan's Blog, is that it was written with the help of Atif Aziz himself! (Remember, Atif's The primary author of ELMAH!) Here's the StackOverflow question.

My naive solution is below, but Atif's is better as it signals the error to ELMAH's pipeline rather that logging directly as mine does. Here's the more correct version:

namespace MvcDemo
{
using System;
using System.Web;
using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
base.OnException(context);

var e = context.Exception;
if (!context.ExceptionHandled // if unhandled, will be logged anyhow
|| RaiseErrorSignal(e) // prefer signaling, if possible
|| IsFiltered(context)) // filtered?
return;

LogException(e);
}

private static bool RaiseErrorSignal(Exception e)
{
var context = HttpContext.Current;
if (context == null)
return false;
var signal = ErrorSignal.FromContext(context);
if (signal == null)
return false;
signal.Raise(e, context);
return true;
}

private static bool IsFiltered(ExceptionContext context)
{
var config = context.HttpContext.GetSection("elmah/errorFilter")
as ErrorFilterConfiguration;

if (config == null)
return false;

var testContext = new ErrorFilterModule.AssertionHelperContext(
context.Exception, HttpContext.Current);

return config.Assertion.Test(testContext);
}

private static void LogException(Exception e)
{
var context = HttpContext.Current;
ErrorLog.GetDefault(context).Log(new Error(e, context));
}
}
}

Below is my naive version.

I made this HandleErrorWithELMAHAttribute:

public class HandleErrorWithELMAHAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
try
{
var context = HttpContext.Current;
Error error = new Error(filterContext.Exception, context);
ErrorLog log = ErrorLog.GetDefault(context);
string id = log.Log(error);
}
catch (Exception localException)
{
//
// IMPORTANT! We swallow any exception raised during the
// logging and send them out to the trace . The idea
// here is that logging of exceptions by itself should not
// be critical to the overall operation of the application.
// The bad thing is that we catch ANY kind of exception,
// even system ones and potentially let them slip by.
//

Trace.WriteLine(localException);
}

base.OnException(filterContext);
}
}

Then I put the attribute on my ASP.NET MVC Controller like this:

[HandleErrorWithELMAHAttribute]
public class DinnersController : Controller {
...

Either way works, I actually kind of prefer the first one, although it requires a controller to have an essentially empty method to send folks to the shared error page. I keep the /Confused and /Trouble methods in there as I think it makes the site more personal.

Anyway, ELMAH rocks and you should use it today. Phil Haack loves ELMAH too! Jeff and the guys at StackOverflow use ELMAH also, albeit a "custom fork." (Release your code, Jeff!)

Time for me to to donate some money to the ELMAH Open Source efforts.

Related



imageToday is a pretty cool day. It's the culmination of a bunch of little stuff and a lot of hard work by some really nice dudes. Here's a few surprises.

Rob, Phil, and I have been working on the ASP.NET MVC book for a while. One (poorly kept) surprise is the inclusion of ScottGu as an author on the book. Between the four of us, we got enough forehead space for like six guys.

Here's where it gets cool.

Free ASP.NET MVC eBook

Today we're releasing the first 185 pages of the book as a FREE PDF download.

Not only that, it's licensed as Creative Commons Attribution No Derivatives. You can share, distribute, hand out, transmit it all you like. You can even include it in your own book if you'd like. ;)

We worked really hard on this chapter, but the real applause goes to ScottGu who closed down Starbucks a number of times, working late into the night. If you enjoy ScottGu's Epic Blog Posts, here's 185 pages of Epic. This chapter will be Chapter 1 in the book; kind of a book within a book.

The book itself is deep in production but this should hold you off for a while, I hope. ;)

Free ASP.NET MVC Sample Application - NerdDinner

Next, we're releasing the NerdDinner sample application at http://nerddinner.codeplex.com as MS-Pl. It's not nearly as sophisticated as the MVC Storefront, but it's pretty cool and does some nice stuff in a very clean way, in our opinion.

There's also more Full Application Samples to be had at http://www.asp.net/mvc with more to come soon!

Big thanks also to the NerdDinner style designer Michael Dorian Bach and to Dave Ward for his jQuery ninja skills. Thanks also to Steve Harman for his peer review. (I'm getting there! Soon...)

I'll be maintaining the application with all these folks, and you're welcome to join in! I'm hoping to add features like RSS, iCal, Blog Badges, jQuery UI controls, OpenID and more in the coming weeks. Wanna help?

Mix 09

I'll be presenting NerdDinner and the code at Mix 09 next week on Thursday at 2:30pm in session "T49F" called

"File|New -> Company: Creating NerdDinner.com with Microsoft ASP.NET MVC "

You can sign up for my talk by going to the Mix Session Builder, entering "T49F" and clicking on the "Green Plus Sign" next to the title.

Enjoy!



Page 1 of 1 in the NerdDinner category

Contact

Sponsors

Hosting By

Hot Topics

Tags

Calendar

<November 2009>
SunMonTueWedThuFriSat
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

Archives

November, 2009 (5)
October, 2009 (19)
September, 2009 (11)
August, 2009 (12)
July, 2009 (21)
June, 2009 (26)
May, 2009 (16)
April, 2009 (13)
March, 2009 (17)
February, 2009 (17)
January, 2009 (18)
December, 2008 (32)
November, 2008 (17)
October, 2008 (22)
September, 2008 (16)
August, 2008 (14)
July, 2008 (25)
June, 2008 (19)
May, 2008 (17)
April, 2008 (17)
March, 2008 (26)
February, 2008 (21)
January, 2008 (28)
December, 2007 (19)
November, 2007 (17)
October, 2007 (31)
September, 2007 (39)
August, 2007 (37)
July, 2007 (43)
June, 2007 (37)
May, 2007 (32)
April, 2007 (38)
March, 2007 (29)
February, 2007 (46)
January, 2007 (31)
December, 2006 (27)
November, 2006 (31)
October, 2006 (32)
September, 2006 (39)
August, 2006 (34)
July, 2006 (40)
June, 2006 (18)
May, 2006 (31)
April, 2006 (34)
March, 2006 (30)
February, 2006 (38)
January, 2006 (44)
December, 2005 (19)
November, 2005 (34)
October, 2005 (24)
September, 2005 (37)
August, 2005 (20)
July, 2005 (24)
June, 2005 (33)
May, 2005 (16)
April, 2005 (22)
March, 2005 (34)
February, 2005 (15)
January, 2005 (37)
December, 2004 (28)
November, 2004 (30)
October, 2004 (34)
September, 2004 (22)
August, 2004 (34)
July, 2004 (18)
June, 2004 (64)
May, 2004 (49)
April, 2004 (21)
March, 2004 (29)
February, 2004 (29)
January, 2004 (36)
December, 2003 (25)
November, 2003 (24)
October, 2003 (59)
September, 2003 (42)
August, 2003 (24)
July, 2003 (44)
June, 2003 (29)
May, 2003 (21)
April, 2003 (30)
March, 2003 (27)
February, 2003 (47)
January, 2003 (50)
December, 2002 (31)
November, 2002 (38)
October, 2002 (44)
September, 2002 (15)
May, 2002 (2)
April, 2002 (4)

Google Ads