Scott Hanselman

NuGet for the Enterprise: NuGet in a Continuous Integration Automated Build System

May 25, 2011 Comment on this post [26] Posted in NuGet | Open Source
Sponsored By

NuGet: Microsoft .NET Package Management for the EnterpriseI had the pleasure of speaking at TechEd 2011 North America last week in Atlanta. You can see ALL the videos of all the sessions on Channel 9. As an aside, you might notice that they are in the process of organizing video archives of ALL Microsoft developer events at http://channel9.msdn.com/Events. You can even see PDC 1999 if you like or see sessions by Speaker at http://channel9.msdn.com/Events/Speakers. Here are all my talks with a horrible headshot that I plan on asking Duncan to swap out ASAP.

My favorite talk was NuGet: Microsoft .NET Package Management for the Enterprise. I talked about NuGet, like I did in The Netherlands a few weeks ago, except the TechEd talk was focused much more on how NuGet fits into the software development lifecycle in a diverse Enterprise (or big boring company, if you prefer) environment.

Here's the video downloads, or you can click the slide at the right.

At my last company, we used Subversion for source control and CruiseControl for Continuous Integration (CI). I thought it'd be nice to setup a similar system using the latest free (and mostly free) tools. Note, you can do all this with TFS as well for both Source and Build. I'll do a post on that later. For now, I give you:

Setting up NuGet to build using Mercurial for Source Control and JetBrains TeamCity for Continuous Integration while pushing to a local Orchard NuGet Gallery Server

Oh yes, that's a long H3 right there but it's descriptive, right? Here's the general idea.

Progession Diagram: Source, Build, NuGet, Gallery

This of course, is not unique to NuGet, as NuGet is just a build artifact. At my last company we had several things that popped out of the build. Not just the DLLs, but also a ZIP file, MSI installer and even a complete configured and prepped Virtual Machine for sales people to pick up and give demos with our latest bits. You can setup your Continuous Integration system to be as awesome or as simple as you like. You should be thinking about which libraries and parts will create NuGet packages.

Another thing to think about is daily (or every build) packages vs. stable or release packages. There are some discussions on the NuGet site around a "-beta" switch and baked-in support for understanding stable vs. volatile builds. For now, consider two locations for your builds, one for each build and one for "blessed." For some, this might mean a folder for dailies and only blessed go to a server.

Here's the demo I did. You can change what you like and swap out for your favorite tools. I'll point out some gotchas and issues that hit me and might hit you. It's not perfect, but we're moving in the right direction.

Step 0 - Prep Stuff

Some of these steps are "make sure x is setup" type steps and can happen whenever, so don't take the ordering of the steps as totally crucial. Here's what I used and installed.

Step 1 - Make sure your project builds and you can make a NuGet package (nupkg)

I'm doing all this on one laptop, but you might have things spread out at your company. Do what makes you happy.

I made a trivial little class library called TechEdLibrary and confirmed it builds with MSBuild like this:

C:\dev\techedlibrary\TechEdLibrary>msbuild TechEdLibrary.csproj
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.225]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 5/24/2011 4:52:54 PM.
..snip...
Done Building Project "C:\dev\techedlibrary\TechEdLibrary\TechEdLibrary.csproj"

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:00.13

The most important part is to make sure that your AssemblyInfo.cs is actually filed out and not just the defaults. This is because we'll want to update the NuGet's specification file using the values from the DLL and project. Basically we want the metadata of the project to drive the NuGet package (or we have to update it all manually.)

I need a spec file. I can do this a few ways. I can do it manually with just "nuget spec," I can build it off the resulting DLL with "nuget spec -assemblyPath bin\debug\techedlibrary.dll" or off the csproject with "nuget spec techedlibrary.csproj."

If I create it off the csproj, the NuGet spec file will be created with some $tokens$ that will be filled out at packaging time:

C:\dev\techedlibrary\TechEdLibrary>nuget spec TechEdLibrary.csproj
Created 'TechEdLibrary.nuspec' successfully.

In the talk at TechEd I mistakenly build it off the DLL and ended up hard-coding the versions. In a continuous integration system you'll want to update the version in your spec as the build versions. You can either do it with tokens like I will in this post, or you can pass in the version (often from an environment variable) into the command line like "NuGet Pack -version 1.0.1.0."

You can also  use the UpdateVersion.exe that Matt Griffith and I updated SO many years ago to change your AssemblyInfo.cs, then the NuGet package can pick it up. Again, there is no right answer, the point is to have a strategy. What drives the version and how does NuGet find out about it?

My TechEdLibrary.nuspec I just made looks like this:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$author$</authors>
<owners>$author$</owners>
<iconUrl>http://www.hanselman.com/images/nugeticon.png
</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
</metadata>
</package>

And my AssemblyInfo.cs (abridged) is like this. The attributes from the DLL will get copied into the $tokens$ and packaged.

[assembly: AssemblyTitle("TechEdLibrary")]
[assembly: AssemblyDescription("This is my cool library")]
[assembly: AssemblyCompany("Scott Hanselman")]
[assembly: AssemblyProduct("TechEdLibrary")]
[assembly: AssemblyVersion("0.9.*")] //The * means I'll get an automatic version bump
//and more...

Now I can pack it up with NuGet Pack TechEdLibrary.csproj. Note the command line output find the spec and does the token/metadata replacement?

C:\dev\techedlibrary\TechEdLibrary>nuget pack TechEdLibrary.csproj
Attempting to build package from 'TechEdLibrary.csproj'.
Building project for target framework '.NETFramework,Version=v4.0'.
Packing files from 'C:\dev\techedlibrary\TechEdLibrary\bin\Release'.
Using 'TechEdLibrary.nuspec' for metadata.
Successfully created package 'C:\dev\techedlibrary\TechEdLibrary\TechEdLibrary.0.9.4161.28882.nupkg'.

Now I can just open the .nupkg into the NuGet Package Explorer and see the version, author, ID (from Title) description and version are all there, brought in from the attributes and combined with my NuSpec. I can edit the NuSpec to taste as long as I maintain the $tokens$ I want.

My package in the NuGet Package Explorer

Now if I build the library again I'll get a new version from the .NET build system and that will cause a new NuPkg to be built with a new version. I make a change to my application's source, build again, then pack again. Note the results in my directory after I make a small change, build and pack.

C:\dev\techedlibrary\TechEdLibrary>msbuild TechEdLibrary.csproj 
Microsoft (R) Build Engine Version 4.0.30319.1
Build started 5/24/2011 5:07:58 PM.
blah build blah
Done Building Project "C:\dev\techedlibrary\TechEdLibrary\TechEdLibrary.csproj" (rebuild target(s))

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:00.32

C:\dev\techedlibrary\TechEdLibrary>nuget pack TechEdLibrary.csproj
Attempting to build package from 'TechEdLibrary.csproj'.
Building project for target framework '.NETFramework,Version=v4.0'.
Packing files from 'C:\dev\techedlibrary\TechEdLibrary\bin\Release'.
Using 'TechEdLibrary.nuspec' for metadata.
Successfully created package 'C:\dev\techedlibrary\TechEdLibrary\TechEdLibrary.0.9.4161.29041.nupkg'
.

C:\dev\techedlibrary\TechEdLibrary>dir *.nupkg

05/24/2011 05:07 PM 4,770 TechEdLibrary.0.9.4161.28882.nupkg
05/24/2011 05:08 PM 4,763 TechEdLibrary.0.9.4161.29041.nupkg
2 File(s) 9,533 bytes

Without settings really anything up but the versioning plan, spec file and checking if packing works, I've got a little system here and hopefully you can see how it'll work.

WEIRDNESS NOTE: We do have a double-build going on. NuGet.exe, for some weird reason, is running MSBuild again for us. That's lame, and a known bug. Surprisingly in a large number of CI systems in both the .NET and Java worlds "double builds" are common. Weaksauce, but common. Still, no excuse. That'll be fixed in NuGet.exe soon.

Step 2 - Initial Source Check-in

I like using BitBucket for small private projects and CodePlex for public Open Source projects. Both support Hg (the elemental symbol for "Mercury" as in Mercurial) and CodePlex supports TFS for both Source and Work Items. Since my demo is private and BitBucket supports unlimited private projects it was a good fit.

I cloned my project URL from BitBucket into a folder, then added, commited and pushed my bits to the BitBucket Site:

C:\dev\something>hg clone https://shanselman@bitbucket.org/shanselman/techedlibrary
...move my files in...
C:\dev\something>hg add
...yada yada yada...
C:\dev\something>hg commit
...yada yada yada...
C:\dev\something>hg push
...yada yada yada...

It's useful then to make sure I can get my source code into another folder and still build it. It's common to miss a file or two. Since the CI Server will be getting the code into a temporary folder you really need to make sure the source will build as it is, retrieved fresh from your SCM.

Step 3 - Setup your Build Server

I'm running TeamCity locally on http://localhost:8111/ with a "build agent" (there can be many) on the same machine. Visit Administration and make a new project, then a new Build Configuration (like Debug or Release).

You'll need to make a VCS root (Version Control System - there are like 60 different acronyms for version control systems. If you see a TLA (Three Letter Acronym) out there that you don't recognize, it's probably something that means "Source Control.") in TeamCity. Note that I selected Mercurial and set the HG Command Path with the full path to HG.EXE as the CI will call that to check out the code from BitBucket. Note also that I put the path without my name and password for the "pull changes from" as I put the name and password lower down.

Editing a VCS Root in TeamCity

Back in Administration, select Edit under your project. Note the nice lists of steps on the right.

The 7 steps in TeamCity

We want two steps, one for the MSBuild and one "custom command line" for the NuGet package step. The first step is easy, we call MSBuild on our TechEdLibrary.csproj.

The second step is a temporary hack. It's temporary because JetBrains TeamCity is building NuGet support in directly (screenshots of their internal build below!)

TeamCity Custom Scripts

The custom script is basically a BATCH file that looks like this:

del *.nupkg 

NuGet pack techedlibrary.csproj
forfiles /m *.nupkg /c "cmd /c NuGet.exe push @FILE yourapikey -source http://localhost:81/

There's a few interesting things going on here.

First, I delete all the nupkg files in the CI folder as it's all temporary and we don't want to accidentally push old stuff.

Second, I pack up the NuGet package like we saw before.

Finally, I don't know the name of the newly created *.nupkg file, so I cheat by making a DOS BATCH "for loop" that has only one item in it, the newly created .nupkg file! Then I call cmd.exe execute NuGet.exe pack with that new file as a parameter. Make sure you have the trailing backslash.

NOTE: You can also save the API Key in local storage with NuGet SetApiKey yourapikey -source http://localhost:81 and it'll be saved on a per-source basis.

Because I have an Orchard NuGet Gallery running locally, I have an API key for that server. I'm running my gallery server (it holds the packages and serves the OData Feed) locally on port 81 and the Orchard Site itself is on port 80.

My personal NuGet Gallery

I set the build to check Source Control every 60 seconds, if a change is detected, the source is retrieved, build, then NuGet packed, and published to my local server (or the public one).

TeamCity is something I like to have running on extra hardware I've got lying around. You can have up to 20 projects with their free version, so when combined with BitBucket and CodePlex where I keep my projects I can setup my own Continuous Integration System in just a few hours and have better confidence in my code. You can even use Amazon EC2 images to run your builds or just be a build agent.

Sneak Peak - TeamCity with NuGet Integration

I'm continuing to talk to companies and software vendors who are jazzed about NuGet. If you are one, watch my talk for ideas on what you can do as a commercial software entity and get into the discussion on CodePlex.

Here's some mockups of what JetBrains is planning for TeamCity. These are just ideas, and they aren't available, so don't stress or pressure them. ;)

This is a mockup of NuGet as a possible Build Step within TeamCity.

This is a mockup of NuGet as a possible Build Step within TeamCity.

Here's a mockup of a Build Feature where TeamCity downloads specific packages that will be needed by the build.

Here's a mockup of a Build Feature where TeamCity downloads specific packages that will be needed by the build.

Here's a screenshot of some early work that Martin Woodward from the TFS team is doing to make sure NuGet and Team Foundation Server work well together in a Continuous Integration environment. Feel free to contact Martin via his blog and continue the discussion on http://nuget.codeplex.com.

TFS and NuGet

Hope this helps you integrate NuGet into your company, however you like it.

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

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

May 24, 2011 Comment on this post [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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

This Developer's Life 2.0.2 - Pressure

May 17, 2011 Comment on this post [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 bluesky subscribe
      About   Newsletter
      Hosting By
      Hosted on Linux using .NET in an Azure App Service

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

      May 17, 2011 Comment on this post [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 bluesky subscribe
      About   Newsletter
      Hosting By
      Hosted on Linux using .NET in an Azure App Service

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

      May 13, 2011 Comment on this post [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 bluesky subscribe
      About   Newsletter
      Hosting By
      Hosted on Linux using .NET in an Azure App Service

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