Scott Hanselman

NuGet Package of the Week #7 - ELMAH (Error Logging Modules and Handlers) with SQL Server Compact

May 23, '11 Comments [13] Posted in ASP.NET | ASP.NET MVC | NuGet | NuGetPOW
Sponsored By

Hey, have you implemented the NuGet Action Plan? Get on it, it'll take only 5 minutes: NuGet Action Plan - Upgrade to 1.3, Setup Automatic Updates, Get NuGet Package Explorer. NuGet 1.3 is out, so make sure you're set to automatically update!

The Backstory: I was thinking since the NuGet .NET package management site is starting to fill up that I should start looking for gems (no pun intended) in there. You know, really useful stuff that folks might otherwise not find. I'll look for mostly open source projects, ones I think are really useful. I'll look at how they built their NuGet packages, if there's anything interesting about the way the designed the out of the box experience (and anything they could do to make it better) as well as what the package itself does.

This week's Package of the Week is "ELMAH 1.2 with SQL Compact."

image

You may already use ELMAH. Don't stop reading now, because you're going to need this information!

Now, I've been blogging and promoting ELMAH (Error Logging Modules and Handlers) for years. It's the first thing I add to any ASP.NET project of any importance. It's one of the great little gems of ASP.NET open source.

I've shown "install-package elmah" in a number of talks and videos as my go-to demo for how NuGet and a well structured OSS package get you started quickly. Recently the ELMAH team has started to do some restructuring of their packages, and I wanted to showcase their work so you can not only learn from it, but also implement similar structures in your own packages.

First, spend a few minutes checking out how ELMAH works and how it can add to your ASP.NET project. Now, let's look at the (currently three, soon to be more) ELMAH packages that are up on NuGet.org.

There's currently:

  • ELMAH Core Library (no config) - "Core library for ELMAH (Error Logging Modules and Handlers) without any configuration"
    • This one includes just the library. If you already have a custom ELMAH configuration or you want to create a new one, you can use and depend on this "core" package.
  • ELMAH - "ELMAH with initial configuration for getting started quickly. 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."
    • This one includes the basics you'll need to for a drop-in/just-works configuration. This isn't the "core" library, but rather one that depends on the core. It's the "getting started" one.
  • ELMAH on MS SQL Server Compact - "ELMAH with configuration for getting started quickly on a Microsoft SQL Server Compact database as the error log."
    • This package depends on the Elmah library and Elmah.CoreLibrary package as well as SqlServerCompact and adds configuration for using them together.
    • Dependency chain: elmah.sqlservercompact -> elmah -> elmah.corelibrary

Here's the web.config.transform that elmah.sqlservercompact adds to your base ELMAH web.config:

<configuration>
<elmah>
<errorLogtype="Elmah.SqlServerCompactErrorLog, Elmah"connectionStringName="elmah-sqlservercompact"/>
</elmah>
<connectionStrings>
<addname="elmah-sqlservercompact"connectionString="Data Source=|DataDirectory|\Elmah.sdf"/>
</connectionStrings>
</configuration>

ELMAH Database Column StructureGive it a try, it's easy, just install-package elmah.sqlservercompact. This basic package dependency structure will enable the Elmah guys to create "quick starts" with different configurations that each depend on elmah, which depends on the elmah.corelibrary. 

ELMAH supports many formats for storing errors, but I think that SQL Server Compact is a great choice for small to medium size applications.

  • Everything in one place and queryable.
  • No mess of text files or XML files
  • Database survives application restarts/recycles

If you're using a WebFarm, you might want to use a central SQL Server instance, but I know a number of folks who run WebFarms and still prefer their errors on a per WebServer basis.

When your application starts up, ELMAH will put the Elmah.sdf in your ~\App_Data folder. The database is structured like this image at right. With the SQL Server Compact tooling that's added with Visual Studio 2010 SP1 you can open the SDF file right in VS and query it if you like.

If you prefer a different backend for your logs, we should soon see NuGet "quick start" packages for many of the supported ELMAH storage solutions. You can even get your errors as RSS or JSON!

Also, be aware that Elmah has just be updated to version 1.2 with a number of new features and fixes. ELMAH works in .NET 1.1 and .NET 2, so there's no excuse for not checking it out!

Screenshot of an ELMAH log

Enjoy, and thanks to the ELMAH team for putting up with my nagging, bug reports and reviews over the last few months! It's only because I love the project so much!

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

This Developer's Life 2.0.2 - Pressure

May 17, '11 Comments [9] Posted in Podcast
Sponsored By

clampIn this second episode of the second season of This Developer's Life we talk to a group of Top Gun developers: the StackOverflow team, about the day their database melted - and how the team responded.

      Also, please visit the new site at http://thisdeveloperslife.com. We've got sixteen episodes so far, and we are pretty proud of them. Don't listen to podcasts? Don't commute? Surely you have a long plane flight coming up? Maybe a cross country drive? Load up. It's all free.

      You can download the MP3 here (53 minutes) and visit our site at http://thisdeveloperslife.com.

      Please consider subscribing with iTunes, or Zune. If you enjoy it, take a moment and please do REVIEW our show on iTunes.

      Or if you have a BitTorrent client and would like to help save us bandwidth money, as well as the bragging rights of downloading legal torrents via RSS, get our Torrent Feed at ClearBits.

      The bandwidth and other costs for this week's show were picked up DevExpress and CodeRush! Visit them and thank them on Twitter.

      This Developer's Life is brought to you by CodeRush for Visual Studio.

      This Developer's Life is brought to you by CodeRush for Visual Studio.

      Announcing our listener contest...This Developer's Life - Crowdsourced

      Oh yes. We want to hear your stories. Record your best developer stories and send them to us and if we think they rock, we'll include them in the next episode of This Developer's Life.

      What we need from you:

      • Your story. We don't want interviews, we want stories. Tell us about your passion, or something crazy that happened at work while solving some technical problem.
      • Keep your audio clean. Use a decent microphone or at least make sure you don't "overdrive" your microphone by talking to close or two loudly. Don't record while mowing the lawn and don't record in a giant echo chamber.
      • Be passionate. Talk to us like you're talking to a friend.
      • Don't worry about editing or music. Just share. We'll handle the Lady Gaga mashups.
      • Note we may move your audio around or change the order of stuff to make it more listenable or interesting or both.
      • Change the names of companies and people to protect the innocent (or guilty)
      • Know that by giving us your audio you're releasing it the Creative Commons and that we may or may not use it for a future show.

      Send us a link to your audio file and what you're talking about and we'll do the rest. See you next time!

      About Scott

      Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

      facebook twitter subscribe
      About   Newsletter
      Sponsored By
      Hosting By
      Dedicated Windows Server Hosting by SherWeb

      Hanselminutes Podcast 266 - Open Source vs. Making Money vs. Freaking Lasers - Are we all Evil? With Chris Sells

      May 17, '11 Comments [2] Posted in Open Source | Podcast
      Sponsored By

      sharkswithlasersScott chats with Chris Sells about the pressure to release software as Open Source versus pressure to make money as a business. How are Google, Microsoft and Apple evolving over the years and what should we as developers do about it?

      Download: MP3 Full Show

      NOTE: If you want to download our complete archives as a feed - that's all 266 shows, subscribe to the Complete MP3 Feed here.

      Also, please do take a moment and review the show on iTunes.

      Subscribe: Subscribe to Hanselminutes or Subscribe to my Podcast in iTunes or Zune

      Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

      Telerik is our sponsor for this show.

      Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface and developer tools, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET AJAX, MVC, Silverlight, Windows Forms and WPF. Enjoy developer tools like .NET Reporting, ORM, Automated Testing Tools, Agile Project Management Tools, and Content Management Solution. And now you can increase your productivity with JustCode, Telerik’s new productivity tool for code analysis and refactoring. Visit www.telerik.com.

      As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

      Enjoy. Who knows what'll happen in the next show?

      About Scott

      Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

      facebook twitter subscribe
      About   Newsletter
      Sponsored By
      Hosting By
      Dedicated Windows Server Hosting by SherWeb

      How to add Tweets to your blog and debugging basic JavaScript: Why did Twitter.com/JavaScript/Blogger JSONP Widget stop working?

      May 13, '11 Comments [13] Posted in Javascript
      Sponsored By

      I have a little yellow bar at the top of my blog that is supposed to show my latest Tweet. It's a nice unobtrusive way to show that I'm out there and I'm active, and maybe if the tweet is interesting to you, you'll stop by Twitter and follow me.

      However, I noticed it stopped working recently. It was blank:

      image

      Static picture of a list of tweetsWeird. It'd worked great for years, plural. I searched around and found a few posts on GetSatisfaction asking about it, some recent, some not recent at all. Some people are having the code work on some accounts and not others.

      Unfortunately, Twitter seems to have quietly deprecated the code I was using. It's still there but there are no pages on Twitter on how to add tweets to your blog in a low-level controlled way.

      Twitter wants you to visit http://twitter.com/badges and use their existing Twitter Widgets. These are very typical of other sites, in that they are boxes with your tweets in them.

      For example, here's a box of Tweets to the right, however, that's a little garish for my tastes.

      Here's the code I was using to show just the very first tweet on the top of page. First at the top of the page I have a div that will hold my most recent tweet.

      <div id="twitter_div">
      <a href="http://twitter.com/shanselman" id="twitter-link" >Latest Tweet: </a>
      <span id="twitter_update_list"></span>
      </div>

      Then later at the bottom I have these two scripts. These are what appear to be either not supported or not advertised by Twitter anymore.

      <script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></script>
      <script type="text/javascript" src="http://twitter.com/statuses/user_timeline/shanselman.json?callback=twitterCallback2&count=1"></script>

      Now, don't use it just like that if you want to get only 1 original tweet as I do. Because it's this very code that stopped working recently. Except it stopped working sometimes. But did it?

      To figure it out quickly, first I visited this URL in my browser. It returns JSON of all my tweets.

      http://twitter.com/statuses/user_timeline/shanselman.json?count=1

      However sometimes I get this:

      []

      Yes, really. An empty JSON array. But why? Well at this moment in time my "most recent tweet" is actually a native retweet. It's not a tweet from me, it's a retweet of a YouTube video. See below?

      A native REtweet next to a real tweet

      Perhaps this JSON Twitter API was created before the Native Retweet was invented. But, if I tweet something fresh, at hit http://twitter.com/statuses/user_timeline/shanselman.json?count=1 again, I'll see this minimized JSON:

      [{"in_reply_to_status_id":null,"text":"Testing for a blog post. Move along. This tweet never happened.","created_at":"Thu May 12 23:44:13 +0000 2011","favorited":false,"retweet_count":0,"source":"web","in_reply_to_screen_name":null,"in_reply_to_status_id_str":null,"id_str":"68823826439487488","contributors":null,"retweeted":false,"in_reply_to_user_id_str":null,"place":null,"coordinates":null,"geo":null,"in_reply_to_user_id":null,"truncated":false,"user":{"is_translator":false,"notifications":false,"created_at":"Tue May 01 05:55:26 +0000 2007","profile_sidebar_border_color":"b8aa9c","listed_count":3909,"following":true,"description":"Tech, Diabetes, Parenting, Race, Linguistics, Fashion, Podcasting, Media, Culture, Code, Ratchet.","show_all_inline_media":true,"geo_enabled":true,"profile_use_background_image":true,"profile_image_url":"http:\/\/a1.twimg.com\/profile_images\/1344567304\/image_normal.jpg","contributors_enabled":false,"verified":false,"profile_background_color":"d1cdc1","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/157325454\/twilk_background_4ca8e4832a970.jpg","screen_name":"shanselman","default_profile_image":false,"statuses_count":40900,"id_str":"5676102","default_profile":false,"friends_count":2616,"profile_text_color":"696969","lang":"en","profile_sidebar_fill_color":"b8aa9c","followers_count":36994,"protected":false,"location":"Portland, Oregon","follow_request_sent":false,"profile_background_tile":true,"favourites_count":2089,"name":"Scott Hanselman","url":"http:\/\/hanselman.com","id":5676102,"time_zone":"Pacific Time (US & Canada)","utc_offset":-28800,"profile_link_color":"72412c"},"id":68823826439487488}]

      I can run it by the http://jsbeautifier.org and it looks lovely...

      [{
      "in_reply_to_status_id": null,
      "text": "Testing for a blog post. Move along. This tweet never happened.",
      "created_at": "Thu May 12 23:44:13 +0000 2011",
      "favorited": false,
      "retweet_count": 0,
      "source": "web",
      "in_reply_to_screen_name": null,
      "in_reply_to_status_id_str": null,
      "id_str": "68823826439487488",
      "contributors": null,
      "retweeted": false,
      "in_reply_to_user_id_str": null,
      "place": null,
      "coordinates": null,
      "geo": null,
      "in_reply_to_user_id": null,
      "truncated": false,
      "user": { ..... SNIP! .....
      }
      }]

      So, Twitter has a nice JSON API that is old and doesn't support Native Retweets but I want the most recent tweet, my way.

      Bam. http://twitter.com/statuses/user_timeline/shanselman.json?count=5

      Of course, if my last five tweets are all Native Retweets then it all falls part, but you get the idea.

      image

      If I was really serious, I could even remove @replies, only showing original tweets, remembering that this JSON API doesn't include Native Retweets in its results.

      I found some code on BarneyB's blog that is a modification of Twitter's original code. He mentions in the comments that he's removing replies in his code. I just took his code and stop the code as soon as a valid original non-replied tweet is found. In this case, I search the 5 tweets I requested that were returned from Twitter. If it turns out I reply a lot and get an empty payload, maybe I'll increase that number.

      The conclusion here is that this code still "works," it just doesn't see Native Retweets:

      <div id="twitter_div">
      <a href="http://twitter.com/shanselman" id="twitter-link" >Latest Tweet: </a>
      <span id="twitter_update_list"></span>
      </div>

      Then later...

      <script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></script>
      <script type="text/javascript" src="http://twitter.com/statuses/user_timeline/shanselman.json?callback=twitterCallback2&count=1"></script>

      My issue was that I want a single tweet, specifically the first original, non-native-retweet, non-reply tweet. I solved it by taking BarneyB's @reply-filtering code and adding a check that breaks out of the loop. I ask Twitter for 5 tweets, but as soon as I find one from that lists of candidates, that's the one. Feel free to View Source if you like, or just be aware of the limitation of Twitter's (possibly deprecated) JSONP API.

      It was a trivial but fun lunch hour, indeed.

      UPDATE: Great comment below from Dave Ward. He points out that I could have my cake and eat it too by using the new API and a "include_rts" flag like this:

      https://api.twitter.com/1/statuses/user_timeline.json?screen_name=shanselman&include_rts=true&count=10&callback=twitterCallback2

      Thanks Dave!

      About Scott

      Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

      facebook twitter subscribe
      About   Newsletter
      Sponsored By
      Hosting By
      Dedicated Windows Server Hosting by SherWeb

      NuGet Package of the Week #6 - Dynamic, Malleable, Enjoyable Expando Objects with Clay

      May 6, '11 Comments [26] Posted in Learning .NET | NuGet | NuGetPOW
      Sponsored By

      Hey, have you implemented the NuGet Action Plan? Get on it, it'll take only 5 minutes: NuGet Action Plan - Upgrade to 1.2, Setup Automatic Updates, Get NuGet Package Explorer. NuGet 1.3 is out, so make sure you're set to automatically update!

      The Backstory: I was thinking since the NuGet .NET package management site is starting to fill up that I should start looking for gems (no pun intended) in there. You know, really useful stuff that folks might otherwise not find. I'll look for mostly open source projects, ones I think are really useful. I'll look at how they built their NuGet packages, if there's anything interesting about the way the designed the out of the box experience (and anything they could do to make it better) as well as what the package itself does.

      This weeks Package of the Week is "Clay." It makes working with dynamic objects even more fun. It was written for the open source Orchard Project by Louis DeJardin with an assist from Bertrand LeRoy.

      image

      Enjoyable Dynamics in a Static Language

      Here's a little copy/paste from a post two years ago I did on the dynamic keyword in C#. I thought it was good, so I'll include it again here.

      So I asked this guy, what's up with the dynamic keyword, and what type was it exactly? I mean, C# isn't dynamic, right? He says:

      "Oh, well it's statically-typed as a dynamic type."

      Then my brain exploded and began to leak out my ears. Honestly, though, it took a second. Here's a good example from some of Anders' slides:

      Calculator calc = GetCalculator();
      int sum = calc.Add(10, 20);

      That's the creation of an object, invokation of a method, and the collection of a return value. This is the exact same code, as the "var" type is figured out at compile time.

      var calc = GetCalculator();
      int sum = calc.Add(10, 20);

      If you wanted to do the exact same thing, except with Reflection (like if it were some other class, maybe old-COM interop, or something where the compiler didn't know a priori that Add() was available, etc) you'd do this:

      object calc = GetCalculator();
      Type calcType = calc.GetType();
      object res = calcType.InvokeMember("Add",
      BindingFlags.InvokeMethod, null,
      new object[] { 10, 20 });
      int sum = Convert.ToInt32(res);

      It's pretty horrible to look at, of course. If the object is some dynamic thing (from any number of sources), we can do this:

      dynamic calc = GetCalculator();
      int sum = calc.Add(10, 20);

      And get the dynamic method invocation and conversion of the return type. Basically it looks just like we're calling any other object.

      My buddy Rob Conery and I love dynamic languages, but we also love the .NET CLR. If we had our way, there'd be a lot more support for the Dynamic Language Runtime and the Iron.NET languages. We wrote the http://thisdeveloperslife.com website using ASP.NET Web Pages largely because it uses the Razor template engine - which feels very dynamic - and we used dynamics throughout the code.

      Some folks think that static languages have no business dipping their toes into the dynamic pool, but I disagree. Successful compilation is just the first unit test, as they say, and I like the ability to pick and choose between static and dyanamic.

      Expandos and Dynamic

      In .NET, the Expando object is a dynamic type that lets you add and remove members to it, ahem, dynamically. It's great for dealing with dynamic data. You might do this:

      dynamic myObject = new ExpandoObject();
      myObject.WhateverMakesMeHappy = "Scott";

      And boom, I've got a new property. You can even "cast" Expandos as other types and start using them like that type. It's crazy. Play with it.

      Anonymous objects via object initalizers are nice, but once you've made one, it's stuck that way. For example, from Bertrand Le Roy's blog

      Html.TextBoxFor(m => m.CurrentUser, new {
      title = "User Name",
      style = "float:left;"
      })

      See the object intializer? It makes an anonymous object, but it'll have that shape with title and style, forever.

      Why is Clay needed?

      In Bertrand's words:

      In terms of API usability [ExpandoObject is] not very daring and in particular it does not do much to help you build deep dynamic object graphs. Its behavior is also fixed and can’t be extended.

      Clay on the other hand is highly extensible and focuses on creation and consumption of deep graphs.

      Clay has a clever naming convention (although you may hate it. Relax, it's a convention) where you name the ClayFactory instance "New." Yes, capital-N "New." *brain explodes again*

      You can do the usual stuff with Clay that you can also do with Expando, of course. But, you can use several different techniques depending on the situation you're in, and that's where it gets interesting. Here's some examples from Bertrand and Lou, starting with the ClayFactory creation:

      dynamic New = new ClayFactory();

      Now this “New” object will help us create new Clay objects, as the name implies (although this name is just a convention). Then:

      var person = New.Person();
      person.FirstName = "Louis";
      person.LastName = "Dejardin";

      For instance in Clay, indexer syntax and property accessors are equivalent, just as they are in JavaScript. This is very useful when you are writing code that accesses a property by name without knowing that name at compile-time:

      var person = New.Person();
      person["FirstName"] = "Louis";
      person["LastName"] = "Dejardin";

      You can also use properties as chainable setters, jQuery-style:

      var person = New.Person()
          .FirstName("Louis")
          .LastName("Dejardin");

      Or you can pass an anonymous object and it will become a Clay object:

      var person = New.Person(new {
          FirstName = "Louis",
          LastName = "Dejardin"
      });

      Even better, Clay also understands named arguments, which enables us to write this:

      var person = New.Person(
          FirstName: "Louis",
          LastName: "Dejardin"
      );

      Or even this as an array:

      var people = New.Array(
      New.Person().FirstName("Louis").LastName("Dejardin"),
      New.Person().FirstName("Bertrand").LastName("Le Roy")
      );

      All of this also means that these are all equivalent:

      person.FirstName
      person["FirstName"]
      person.FirstName()

      To get started, rather than using NuGet to "install-package Clay," I'd recommend you install Clay.Sample. This is a common convention for open source projects to include sample packages that have a dependency on the project itself. Install the sample and you'll get both packages.

      Here's some other cool samples that really give you an idea of how you can move like clay between the dynamic and static worlds:

      public interface IPerson {
      string FirstName { get; set; }
      string LastName { get; set; }
      }

      public static void CastToCLRInterface() {
      dynamic New = new ClayFactory();

      var person = New.Person();
      person.FirstName = "Louis";
      person.LastName = "Dejardin";

      // Concrete interface implementation gets magically created!
      IPerson lou = person;

      // You get intellisense and compile time check here
      Console.WriteLine("{0} {1}", lou.FirstName, lou.LastName);
      }

      I'd like the see folks in power *cough* Anders *cough* check out things like Clay and make them built in. Yum.

      Related Links

      About Scott

      Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

      facebook twitter subscribe
      About   Newsletter
      Sponsored By
      Hosting By
      Dedicated Windows Server Hosting by SherWeb

      Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.