March 2011 - Posts - Jon Galloway

March 2011 - Posts

Hear me talk about MVC 3 on Jesse Liberty's Yet Another Podcast

Jesse Liberty interviewed me about ASP.NET MVC 3 recently on Yet Another Podcast. It was a lot of fun being a guest on a podcast for a change. Here are some of the highlights:

  • Some introductory chatter about Herding Code and whatnot (skip to 3:50 if you're not interested)
  • Jon's history of MVC releases (and Jesse's reminder that MVC is an old pattern that predates ASP.NET by decades)
  • An overview of what's in new in MVC 3
    • Razor
    • Javascript / jQuery
    • Model Validation
    • Advanced features like Dependency Injection
  • Links to some of the top MVC information on the ASP.NET website: http://asp.net/mvc and http://asp.net/mvc/mvc3
  • Razor view engine - why another view engine, what it's like, why Jon loves working with it
  • Support for Javascript / jQuery, incl. change in validation to jQuery validate
  • Jesse asks Jon if all ASP.NET developers should learn MVC, and if there are cases where you'd want to stay with Web Forms
  • Jesse asks Jon about how to learn about MVC 3 since the MVC books out now all focus on MVC 2
    • Jon mentions that MVC 3 builds on MVC 2 so the "old" books are still of use
    • Jon mentions some additional additional places to learn about MVC 3 (previously blogged here)
    • Jon mentions mvcConf
  • Jesse asks about the current release status of MVC, how to install it, etc.

It's a quick 30 minute show, check it out - and don't forget to subscribe to YapCast.

Download / Listen

Yet Another Podcast #29 Jon Galloway on MVC 3

Posted by Jon Galloway | 1 comment(s)
Filed under: ,

Comparing MVC 3 Helpers: Using Extension Methods and Declarative Razor @helper Syntax

HTML Helpers provide a clean way to encapsulate view code so you can keep your views simple and markup focused. There are lots of built in HTML Helpers in the System.Web.Mvc.HtmlHelper class, but one of the best features is that you can easily create your own helpers. While you've been able to create your own helpers since MVC 1 using extension methods, the Razor view engine gives you a new option to create helpers using the @helper keyword.

Extension Method helpers

Previous versions of ASP.NET MVC allowed you to do that by writing extension methods on the HtmlHelper class, and that's still available in MVC 3. Helpers are just methods which return strings, so they're pretty easy to set up. Let's look at an example from the MVC Music Store - a helper which which truncates a string to make sure it's smaller than a specified length.

2011-03-23 13h31_39

The extension method needs to be in a static class, and I generally like to create a separate folder for organization.

2011-03-23 12h56_37

The code is standard extension method syntax - the first parameter uses the this keyword to indicate that it's extending an HtmlHelper, and the rest is just a simple method that returns a string. The method takes a string and a max length, chops the string if needed, and returns the result.

using System.Web.Mvc;
 
namespace MvcMusicStore.Helpers
{
    public static class HtmlHelpers
    {
        public static string Truncate(this HtmlHelper helper, string input, int length)
        {
            if (input.Length <= length)
            {
                return input;
            }
            else
            {
                return input.Substring(0, length) + "...";
            }
        }
    }
}

Note: Make sure you're extending the HtmlHelper defined in System.Web.Mvc and not System.Web.WebPages. The using statement is important.

Our views can make use of this by either importing the namespace with the @using keyword to the views or by adding the helper's namespace to the pages/namespaces element in the web.config.

We could use this in the default Home / Index.cshtml view as below:

@{
    ViewBag.Title = "Home Page";
}
@using RazorHelpers.Helpers

<h2>@Html.Truncate(ViewBag.Message as string, 8)</h2>

Notice that we need to cast the ViewBag.Message as a string, or we'll get a compiler error when the page is rendered: CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'Truncate' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.

2011-03-23 14h08_55

Alternative, if we wanted to add the namespace to the web.config in the Views folder, we could use the helper class in all our views without a @using statement. That would look like this:

<system.web.webPages.razor>
  <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <pages pageBaseType="System.Web.Mvc.WebViewPage">
    <namespaces>
      <add namespace="System.Web.Mvc" />
      <add namespace="System.Web.Mvc.Ajax" />
      <add namespace="System.Web.Mvc.Html" />
      <add namespace="System.Web.Routing" />
      <add namespace="RazorHelpers.Helpers" />
    </namespaces>
  </pages>
</system.web.webPages.razor>

Razor Declarative Helpers

Razor allows us to implement this using either an in-page code block or in another file, using a more declarative syntax using an @helper block.

Razor helpers inline

To implement this helper inline, we'd just add the @helper block in the page as shown below.

@{
    ViewBag.Title = "Home Page";
}

@helper TruncateString(string input, int length)
{
    if (input.Length <= length) {
        @input
    } else {
        @input.Substring(0, length)<text>...</text>
    }
}

<h2>@Truncate(ViewBag.Message, 8)</h2>

The code is very similar, but there are a few differences:

  • I've tightened it up a bit since it's able to take advantage of Razor syntax to directly write out the value rather than return a string
  • We also don't need to bother with the this HtmlHelper business because it's not an extension method.
  • We don't need to cast the input as a string, since the Razor engine can figure that out for us on the fly
  • Since it's not an extension method, we directly call @Truncate() rather than @Html.Truncate()

Reusable helpers within your project: Use App_Code

You can move Razor helpers to another file within your project, but you'll need it to be in the App_Code folder. Right-click on the project and select "Add / New Folder" and call the folder "App_Code".

2011-03-23 14h22_50

You'll see that the App_Code folder gets a special icon:

2011-03-23 14h27_27

Now we can add a new Razor view to that folder using "Add / New Item / MVC 3 View Page (Razor)". You can name it what you want, but you'll be using the filename when you call the helper. I called mine CustomHelpers.cshtml.

Replace the generated code in the new CSHTML file with the @helper block we just used above, so the entire source of the new CustomHelpers.cshtml file will read as follows.

@helper TruncateString(string input, int length)
{
    if (input.Length <= length) {
        @input
    } else {
        @input.Substring(0, length)<text>...</text>
    }
}

In order to use that in a view, we call the helper using the name we gave the view page, like this:

@{
    ViewBag.Title = "Home Page";
}

<h2>@CustomHelpers.Truncate(ViewBag.Message, 8)</h2>

Notice that we don't need a @using statement to pull it in, we just call into the CustomHelpers class.

Turning Razor Helpers in reusable libraries

David Ebbo posted about how to turn your Razor helpers into libraries using the Single File Generator. This uses a custom build tool create a .cs or .vb file based on the view, which means you can move it wherever you'd like. Running that generator on the CustomHelpers.cshtml file would create CustomHelpers.cs, which could be used within my project, in a code library, etc.

Summary

Extension method based Custom HTML Helpers still have some benefits. They're code files, they can live in any directory, and since they're extension methods off the HtmlHelper class they're very discoverable - just type @Html. and see them in the list with all the other built in helpers.

Razor declarative helpers have some nice benefits, though:

  • You can easily whip one up inline in a view, then upsize it to a separate files in App_Code, then to a reusable library. I like the low barrier to entry - it removes any thought from writing helpers whenever possible.
  • The syntax is a little simpler - rather than thinking about writing an extension method, you just write some Razor code that writes out values and it all works.
  • Razor helpers are a little more dynamic due to the later compile - e.g. I didn't need to cast the ViewBag.Message to a string.
  • You don't need to worry about namespaces. That's one of the most common problems beginners run into in using the helpers in the MVC Music Store sample.
Posted by Jon Galloway | 2 comment(s)
Filed under:

ASP.NET MVC 3 Roundup of Tutorials, Videos, Labs, and other Assorted Training Materials

I've answered the "Where can I learn about MVC 3" question enough that it's time for a blog post.

Tutorials

You can find a lot of good MVC training resources listed at http://www.asp.net/mvc, including:

Scott Hanselman's Getting Started With MVC tutorial is a great place to start if you're looking for a beginner level introduction. It's a very introductory level sample covering MVC 3, Nuget, and EF Code First, and the code is available in both C# and VB.NET. I'm guessing this is something that a beginner could complete in a few hours.

I've previously blogged about MVC Music Store. In addition to the mechanics of MVC 3 / NuGet / Razor views and layouts / EF Code First, it covers some slightly more advanced features, such as authentication, administration, and AJAX. It's available online and in downloadable source + 150pg PDF eBook at http://mvcmusicstore.codeplex.com. The goal is to cover an end-to-end app building scenario - it's not p&p style code, but it goes a little beyond Hello World. I've worked with developers who had web development experience but were new to ASP.NET MVC who completed this in a day of focused effort.

Videos

My top two recommendations here are the free Pluralsight series and the mvcConf session videos on Channel 9.

Pluralsight - Right now there’s a fantastic MVC 3 training series from Pluralsight - presented by K. Scott Allen - which is free for a limited time. This covers some of the more advanced features of MVC 3 with downloadable code samples. Don't miss this!

mvcConf - There are also 27 high quality videos from the recent mvcConf virtual ASP.NET conference, including a keynote by Scott Guthrie and presentations by MVC product team members. There's a wide variety of content there, from high level overviews and introductions all the way to Brad Wilson's Advanced MVC 3 talk.

Labs

The Web Camps Training Kits include a lot of hands on labs which build on the MVC Music Store tutorial with some intermediate to advanced concepts, like Unit Testing and Dependency Injection.

Note: The Web Camps Training Kits also include some fantastic labs for IE9 & HTML 5, OData, jQuery, WebApps, and WebMatrix as well as ASP.NET MVC 3.

What's in MVC 3

Phil and I put some extra effort into the MVC 3 release content to make sure you wouldn't have to outdated scour blog posts to find out what's going on. I've been converting the release notes to HTML (and if you've converted long Word docs to HTML before, you know how much I must love you to have volunteered to do that) for all the Beta / RC / RTM releases of MVC 3, and we've compiled and updated top links which are posted at http://asp.net/mvc/mvc3. I got the /mvc/mvc3 page going because having to datamine obsolete blog posts was annoying to me, and I figured I wasn't alone there.

The documentation team worked really hard on an MVC 3 overview which features top links to relavent blog posts, available here: http://www.asp.net/mvc/mvc3#overview

MVC Content Map

The MSDN Content Map for ASP.NET MVC 3 includes a lot of great links to a variety of content sources, including tutorials, blog posts, etc.

Application Building Videos

A lot of training videos focus on features, and that's often a great help. However, I find that presentations which build a working sample while you watch are indispensible for seeing the bigger context, understanding why features are important, and seeing how the different parts fit together.

I really like Scott Hanselman's PDC 2010 session, PDC10: Building a Blog with Microsoft "Unnamed Package of Web Love". Scott showed off MVC 3 features, but also showed how fundamentally MVC development - and all .NET development, really - is changed by using NuGet. It's great stuff.

If you don't mind a more informal tone, you might like The Full Stack series on Channel 9. It's a series that Jesse Liberty and I are working on, and we're aiming to go beyond the product-centric approach to show how to integrate multiple pieces in the dev stack. We're using ASP.NET MVC 3, NuGet, EF Code First, WCF Data Services / OData, and Windows Phone 7. As part of hooking these things together, we're trying to document things that don't show up in product level documentation.

Recommendations?

Please recommend any others you think are worthwhile in the comments!

Posted by Jon Galloway | 14 comment(s)
Filed under:

Web Platform Installer bundles for Visual Studio 2010 SP1 - and how you can build your own WebPI bundles

Visual Studio SP1 is  now available via the Web Platform Installer, which means you've got three options:

  • Download the 1.5 GB ISO image
  • Run the 750KB Web Installer (which figures out what you need to download)
  • Install via Web PI

Note: I covered some tips for installing VS2010 SP1 last week - including some that apply to all of these, such as removing options you don't use prior to installing the service pack to decrease the installation time and download size.

Two Visual Studio 2010 SP1 Web PI packages

There are actually two WebPI packages for VS2010 SP1. There's the standard Visual Studio 2010 SP1 package [Web PI link], which includes (quoting ScottGu's post):

  • VS2010 2010 SP1
  • ASP.NET MVC 3 (runtime + tools support)
  • IIS 7.5 Express
  • SQL Server Compact Edition 4.0 (runtime + tools support)
  • Web Deployment 2.0

The notes on that package sum it up pretty well:

Looking for the latest everything? Look no further. This will get you Visual Studio 2010 Service Pack 1 and the RTM releases of ASP.NET MVC 3, IIS 7.5 Express, SQL Server Compact 4.0 with tooling, and Web Deploy 2.0. It's the value meal of Microsoft products. Tell your friends! Note: This bundle includes the Visual Studio 2010 SP1 web installer, which will dynamically determine the appropriate service pack components to download and install. This is typically in the range of 200-500 MB and will take 30-60 minutes to install, depending on your machine configuration.

There is also a Visual Studio 2010 SP1 Core package [Web PI link], which only includes only the SP without any of the other goodies (MVC3, IIS Express, etc.). If you're doing any web development, I'd highly recommend the main pack since it the other installs are small, simple installs, but if you're working in another space, you might want the core package.

Installing via the Web Platform Installer

I generally like to go with the Web PI when possible since it simplifies most software installations due to things like:

  • Smart dependency management - installing apps or tools which have software dependencies will automatically figure out which dependencies you don't have and add them to the list (which you can review before install)
  • Simultaneous download and install - if your install includes more than one package, it will automatically pull the dependencies first and begin installing them while downloading the others
  • Lists the latest downloads - no need to search around, as they're all listed based on a live feed
  • Includes open source applications - a lot of popular open source applications are included as well as Microsoft software and tools
  • No worries about reinstallation - WebPI installations detect what you've got installed, so for instance if you've got MVC 3 installed you don't need to worry about the VS2010 SP1 package install messing anything up

In addition to the links I included above, you can install the WebPI from http://www.microsoft.com/web/downloads/platform.aspx, and if you have Web PI installed you can just tap the Windows key and type "Web Platform" to bring it up in the Start search list. You'll see Visual Studio SP1 listed in the spotlight list as shown below.

2011-03-17 13h56_18

That's the standard package, which includes MVC 3 / IIS 7.5 Express / SQL Compact / Web Deploy. If you just want the core install, you can use the search box in the upper right corner, typing in "Visual Studio SP1" as shown.

2011-03-16 16h09_43

Core Install: Use Web PI or the Visual Studio Web Installer?

I think the big advantage of using Web PI to install VS 2010 SP1 is that it includes the other new bits. If you're going to install the SP1 core, I don't think there's as much advantage to using Web PI, as the Web PI Core install just downloads the Visual Studio Web Installer anyways. I think Web PI makes it a little easier to find the download, but not a lot. The Visual Studio Web Installer checks dependencies, so there's no big advantage there.

If you do happen to hit any problems installing Visual Studio SP1 via Web PI, I'd recommend running the Visual Studio Web Installer, then running the Web PI VS 2010 SP1 package to get all the other goodies. I talked to one person who hit some random snag, recommended that, and it worked out.

Custom Web Platform Installer bundles

You can create links that will launch the Web Platform Installer with a custom list of tools. You can see an example of this by clicking through on the install button at http://asp.net/downloads (cancelling the installation dialog). You'll see this in the address bar: http://www.microsoft.com/web/gallery/install.aspx?appsxml=&appid=MVC3;ASPNET;NETFramework4;SQLExpress;VWD

Notice that the appid querystring parameter includes a semicolon delimited list, and you can make your own custom Web PI links with your own desired app list. I can think of a lot of cases where that would be handy: linking to a recommended software configuration from a software project or product, setting up a recommended / documented / supported install list for a software development team or IT shop, etc.

For instance, here's a link that installs just VS2010 SP1 Core and the SQL CE tools: http://www.microsoft.com/web/gallery/install.aspx?appsxml=&appid=VS2010SP1Core;SQLCETools

Note: If you've already got all or some of the products installed, the display will reflect that. On my dev box which has the full SP1 package, here's what the above link gives me:

2011-03-17 14h30_10

Here's another example - on a fresh box I created a link to install MVC 3 and the Web Farm Framework (http://www.microsoft.com/web/gallery/install.aspx?appsxml=&appid=MVC3;WebFarmFramework) and got the following items added to the cart:

Web PI Cart

But where do I get the App ID's?

Aha, that's the trick. You can link to a list of cool packages, but you need to know the App ID's to link to them. To figure that out, I turned on tracing in Web Platform Installer  (also handy if you're ever having trouble with a WebPI install) and from the trace logs saw that the list of packages is pulled from an XML file:

DownloadManager Information: 0 : Loading product xml from: https://go.microsoft.com/?linkid=9763242
DownloadManager Verbose: 0 : Connecting to https://go.microsoft.com/?linkid=9763242 with (partial) headers:
Referer: wpi://2.1.0.0/Microsoft Windows NT 6.1.7601 Service Pack 1
If-Modified-Since: Wed, 09 Mar 2011 14:15:27 GMT
User-Agent:Platform-Installer/3.0.3.0(Microsoft Windows NT 6.1.7601 Service Pack 1)

DownloadManager Information: 0 : https://go.microsoft.com/?linkid=9763242 responded with 302
DownloadManager Information: 0 : Response headers:
HTTP/1.1 302 Found
Cache-Control: private
Content-Length: 175
Content-Type: text/html; charset=utf-8
Expires: Wed, 09 Mar 2011 22:52:28 GMT
Location: https://www.microsoft.com/web/webpi/3.0/webproductlist.xml
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Wed, 09 Mar 2011 22:53:27 GMT

Browsing to https://www.microsoft.com/web/webpi/3.0/webproductlist.xml shows the full list.

You can search through that in your browser / text editor if you'd like, open it in Excel as an XML table, etc. Here's a list of the App ID's as of today:

SMO
SMO32
PHP52ForIISExpress
PHP53ForIISExpress
StaticContent
DefaultDocument
DirectoryBrowse
HTTPErrors
HTTPRedirection
ASPNET
NETExtensibility
ASP
CGI
ISAPIExtensions
ISAPIFilters
ServerSideIncludes
HTTPLogging
LoggingTools
RequestMonitor
Tracing
CustomLogging
ODBCLogging
BasicAuthentication
WindowsAuthentication
DigestAuthentication
ClientCertificateMappingAuthentication
IISClientCertificateMappingAuthentication
URLAuthorization
RequestFiltering
IPSecurity
StaticContentCompression
DynamicContentCompression
IISManagementConsole
IISManagementScriptsAndTools
ManagementService
MetabaseAndIIS6Compatibility
WASProcessModel
WASNetFxEnvironment
WASConfigurationAPI
IIS6WPICompatibility
IIS6ScriptingTools
IIS6ManagementConsole
LegacyFTPServer
FTPServer
WebDAV
LegacyFTPManagementConsole
FTPExtensibility
AdminPack
AdvancedLogging
WebFarmFrameworkNonLoc
ExternalCacheNonLoc
WebFarmFramework
WebFarmFrameworkv2
WebFarmFrameworkv2_beta
ExternalCache
ECacheUpdate
ARRv1
ARRv2Beta1
ARRv2Beta2
ARRv2RC
ARRv2NonLoc
ARRv2
ARRv2Update
MVC
MVCBeta
MVCRC1
MVCRC2
DBManager
DbManagerUpdate
DynamicIPRestrictions
DynamicIPRestrictionsUpdate
DynamicIPRestrictionsLegacy
DynamicIPRestrictionsBeta2
FTPOOB
IISPowershellSnapin
RemoteManager
SEOToolkit
VS2008RTM
MySQL
SQLDriverPHP52IIS
SQLDriverPHP53IIS
SQLDriverPHP52IISExpress
SQLDriverPHP53IISExpress
SQLExpress
SQLManagementStudio
SQLExpressAdv
SQLExpressTools
UrlRewrite
UrlRewrite2
UrlRewrite2NonLoc
UrlRewrite2RC
UrlRewrite2Beta
UrlRewrite10
UrlScan
MVC3Installer
MVC3
MVC3LocInstaller
MVC3Loc
MVC2
VWD
VWD2010SP1Pack
NETFramework4
WebMatrix
WebMatrix_v1Refresh
IISExpress
IISExpress_v1
IIS7
AspWebPagesVS
AspWebPagesVS_1_0
Plan9
Plan9Loc
WebMatrix_WHP
SQLCE
SQLCETools
SQLCEVSTools
SQLCEVSTools_4_0
SQLCEVSToolsInstaller_4_0
SQLCEVSToolsInstallerNew_4_0
SQLCEVSToolsInstallerRepair_EN_4_0
SQLCEVSToolsInstallerRepair_JA_4_0
SQLCEVSToolsInstallerRepair_FR_4_0
SQLCEVSToolsInstallerRepair_DE_4_0
SQLCEVSToolsInstallerRepair_ES_4_0
SQLCEVSToolsInstallerRepair_IT_4_0
SQLCEVSToolsInstallerRepair_RU_4_0
SQLCEVSToolsInstallerRepair_KO_4_0
SQLCEVSToolsInstallerRepair_ZH_CN_4_0
SQLCEVSToolsInstallerRepair_ZH_TW_4_0
VWD2008
WebDAVOOB
WDeploy
WDeploy_v2
WDeployNoSMO
WDeploy11
WinCache52
WinCache53
NETFramework35
WindowsImagingComponent
VC9Redist
NETFramework20SP2
WindowsInstaller31
PowerShell
PowerShellMsu
PowerShell2
WindowsInstaller45
FastCGIUpdate
FastCGIBackport
FastCGIIIS6
IIS51
IIS60
SQLNativeClient
SQLNativeClient2008
SQLNativeClient2005
SQLCLRTypes
SQLCLRTypes32
SMO_10_1
MySQLConnector
PHP52
PHP53
PHPManager
VSVWD2010Feature
VWD2010WebFeature_0
VWD2010WebFeature_1
VWD2010WebFeature_2
VS2010SP1Prerequisite
RIAServicesToolkitMay2010
Silverlight4Toolkit
Silverlight4Tools
VSLS
SSMAMySQL
WebsitePanel
VS2010SP1Core
VS2010SP1Installer
VS2010SP1Pack
MissingVWDOrVSVWD2010Feature
VB2010Beta2Express
VCS2010Beta2Express
VC2010Beta2Express
RIAServicesToolkitApr2010
VS2010Beta1
VS2010RC
VS2010Beta2
VS2010Beta2Express
VS2k8RTM
VSCPP2k8RTM
VSVB2k8RTM
VSCS2k8RTM
VSVWDFeature
LegacyWinCache
SQLExpress2005
SSMS2005

Converting a Powershell script to a NuGet command

Last week I posted about the NuGet.Downloader package, which had begun life as a Powershell script. If you've got a Powershell commands that you'd like to make available in NuGet packages, here's how.

Write Powershell scripts that are easy to convert to NuGet packages

I've been looking at the contents of NuGet packages for a while. Since a .nupkg file is really just a zip file, you can extract them if you want, but it's just gotten even easier with the new NuGet Package Explorer. Download the Package Explorer, open the MvcScaffolding package (File / Open From NuGet Feed) and browse through the Powershell scripts in the tools folder.

2011-03-10 17h32_28

The main lesson I'd learned from reading other peoples' scripts was that you add Package Manager commands by writing functions in the global namespace with parameters, like this:

function global:Verb-Noun {  
 param (
    [string] $question = "Can I kick it?",
    [string] $affirmativeResponse = "Yes you can!"
    )

    # actual code goes here
} 

I'd written the original script with settings at the top so that they could easily be turned into parameters. Here's the structure of the original Powershell script:

# --- settings ---
$feedUrlBase = "http://go.microsoft.com/fwlink/?LinkID=206669"
# the rest will be params when converting to funclet
$latest = $true
$overwrite = $false
$top = 500 #use $top = $null to grab all
$destinationDirectory = join-path ([Environment]::GetFolderPath("MyDocuments")) "LocalNuGet"
# --- locals ---
$webClient = New-Object System.Net.WebClient
# --- functions ---
# download entries on a page, recursively called for page continuations
function DownloadEntries {
 #code here
}  
function GetPackageUrl {
 # code here
}

# --- do the actual work ---
# one line of code to create the directory if not existing
# a few lines of code to change feed based on settings

DownloadEntries 

Adding the function to the Init script

Adding that as a command that can be run from the Package Manager console is pretty simple (especially if you can get Eric to do most of the work - PROTIP!).

NuGet has conventions for a few specific Powershell scripts. From the "Creating a Package" docs on CodePlex:

  • Init.ps1 runs the first time a package is installed in a solution. If the same package is installed into additional projects in the solution, the script is not run during those installations. The script also runs every time the solution is opened. For example, if you install a package, close Visual Studio, and then start Visual Studio and open the solution, the Init.ps1 script runs again
  • Install.ps1 runs when a package is installed in a project. If the same package is installed in multiple projects in a solution, the script runs each time the package is installed. If a package is not installed into a project (such as the MvcScaffold package), the script runs when the package is installed into the solution. The package must have content/dll that will be added to the project for this to run. Just having something in the tools folder will not kick this off.
  • Uninstall.ps1 runs every time a package is uninstalled.

The init script is where you add Package Manager commands to a package – although it can load scripts in other directories as well - you can really see this in action in the MvcScaffolding package, which adds a lot of commands to create scaffolds.

Adding a command in init.ps1 just requires wrapping it in a global function using parameters with default values, as shown below:

function global:Download-Packages {  
 param (
    [string] $feedUrlBase = "http://go.microsoft.com/fwlink/?LinkID=206669",
    [bool] $latest = $true,
     [bool] $overwrite = $false,
     $top = 500, #use $null to download all  
     [string] $destinationDirectory = (join-path ([Environment]::GetFolderPath("MyDocuments")) "NuGetLocal"  )    
    )
 
 # --- locals --- 
 $webClient = New-Object System.Net.WebClient   
 $feedUrl = ""
 
function DownloadEntries {  
#### code excerpted ###
    }   
    
    DownloadEntries $feedUrl
    "Complete. Local packages saved to $destinationDirectory"
}        

Getting an API key

Before you can publish a package on the NuGet feed, you'll need an API key. That's a very simple process:

  1. Go to http://nuget.org/Users/Account/Register and get an account
  2. Copy your API key from your account page

2011-03-11 17h20_12

Build the package

The next step is to build a package. Honestly, the best thing to do here is just look at Scott Hansleman’s detailed post titled Creating a NuGet Package in 7 easy steps - Plus watch me drop Thusly in mid-post like it was Your Average Everyday Adverb. There's also plenty of documentation on the CodePlex, and you can watch Phil create and deploy packages in his mvcConf video. I'll tell you what I did for completeness, but I'm not going to take it to the Thusly level. No, sir.

There are two ways to go here - you can use the NuGet Package Explorer or you can go the manual way. I wanted experience with the manual approach first, so that's what I did. In the future, I think I'd probably just use the Package Explorer.

A .nupkg is just a zip file which contains some standard things:

  • /lib contains binaries that you'll be adding as references
  • /content contains code, configuration, and other non-dll files that you'll be adding to the project
  • /tools contains command-line programs and scripts to support the package

This bundle also includes a manifest which is built from a simple XML specification file (.nuspec).

In this case, it looks like this:

2011-03-11 16h54_13

Creating the nuspec file is pretty simple. You can just build one based on the specification, or you can create a shell nuspec file by running the NuGet.exe with the spec option:

C:\path\>nuget spec
Created 'Package.nuspec' successfully.

That creates an empty Package.nuspec file in the same directory with the following contents:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>Package</id>
    <version>1.0</version>
    <authors>Author here</authors>
    <owners>Owner here</owners>
    <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <tags>Tag1 Tag2</tags>
    <dependencies>
      <dependency id="SampleDependency" version="1.0" />
    </dependencies>
  </metadata>
</package>

From there, it's just fill in the blanks. Here's the nuspec file for the NuGet.Downloader package:

<?xml version="1.0"?>
<package>
 <metadata>
   <id>Nuget.Downloader</id>
   <version>1.0.0.5</version>
   <authors>Jon Galloway,Eric Hexter</authors>
   <requireLicenseAcceptance>false</requireLicenseAcceptance>
   <description>Download packages from a remote feed to a local directory</description>
   <summary>Download packages from a remote feed to a local directory. Adds one command: Download-Packages By default, only pulls the top 100 packages by download count. Inspired by Steve Michelotti's local repository PowerShell script.</summary>
   <language>en-US</language>
   <projectUrl>http://weblogs.asp.net/jgalloway/archive/2011/02/02/downloading-a-local-nuget-repository-with-powershell.aspx</projectUrl>
   <tags>nuget</tags>
 </metadata>
</package>

One important thing to notice here is the version - you'll need to update that when you build. There are all kinds of smart ways to automate this - e.g. adding this to you build process - but, hey, this is a one file package so I will mark that as Closed - Won't Fix for now.

Now it's time to build the package. With everything in place, we can just run NuGet.exe with the pack command. I'd recommend - at least as you're getting started - to pack test the package locally (adding it to your local repository), then do a push.

C:\my\crazy\file\structure\is\of\no\concern\here>..\nuget pack
Attempting to build package from 'Nuget.Downloader.nuspec'.
Successfully created package 'C:\Users\Jon\Documents\Visual Studio 2010\Projects\download-nugets\Package\Nuget.Downloader.1.0.0.5.nupkg'.

Once we're tested out, we can push this out to the feed. Since I want to make updates easy, I put everything in a folder and wrote a short batch file for the build. Here's how that looked:

2011-03-11 17h13_53

The build.cmd is just 3 lines:

cd Package
..\Nuget.exe pack
..\Nuget.exe push nuget.downloader.1.0.0.5.nupkg APIKEYGOESHERE

Yes, I should probably use pushd and popd instead of cd. Running that builds and pushes the package, though:

C:\what\are\you\looking\at>..\Nuget.exe pack
Attempting to build package from 'Nuget.Downloader.nuspec'.
Successfully created package 'C:\path\Nuget.Downloader.1.0.0.5.nupkg'.

C:\stop\looking\at\the\path\>..\Nuget.exe push nuget.downloader.1.0.0.6.nupkg APIKEYGOESHERE
Publishing Nuget.Downloader 1.0.0.6 to the live feed...
Your package was published to the feed.

And just like that, your Powershell command has become a NuGet package that's published for all the world to use.

Posted by Jon Galloway | 1 comment(s)
Filed under:

Nuget.Downloader package - Download a local NuGet repository using Nuget

NuGet supports multiple feeds, running against either a server or a simple folder / fileshare. See Phil Haack's post explaining both options for more information. I'm a big believer in running your own local NuGet feed for a lot of reasons - offline access, control over updates, and as an absolute must-have for demonstrations and training. I previously wrote up a NuGet Powershell script which pages through the NuGet OData feed and downloads local copies of the packages. It's a little more complex than you'd guess, since the script needs to follow redirections and page links, plus I added in some options to skip downloads for features you've got, only grab the most popular X packages, etc.

I'd always assumed this would end up as a NuGet package, although the use case is a little out of the ordinary. The primary use case of NuGet is to add things (libraries, code, and content) to an existing application, and this NuGet package doesn't work at the project level at all. But, it's just so handy - and there had been enough requests for it - that I couldn't help myself.

I'd actually started on this when Eric Hexter mentioned that he was working on it as well, so I merged what he'd done, removed all the affiliate ad codes he'd snuck in, and uploaded it yesterday. So, here's NuGet.Downloader.

2011-03-10 15h46_44

How to use it

  1. Open a project in Visual Studio (it doesn't matter which - if you try to install a package outside of a solution, you'll get slapped down with "The current environment doesn't have a solution open").
  2. Open the Package Manager console (View / Other Windows / Package Manager Console).
  3. Type "install-package NuGet.Downloader" - you should see "Successfully installed 'Nuget.Downloader 1.0.0.5'." (with whatever the current version number is).
  4. This adds a new commend to the Package Manager console, Download-Packages. You can run it without any parameters, which will grab the top 500 most popular NuGet packages and drop them in a new LocalNuGet folder inside your My Documents folder.
  5. If desired, uninstall the package using Uninstall-Package.

Parameter options:

  • feedBaseUrl (default: official NuGet package feed, following redirections) - you can point this at a corporate NuGet server or some other location
  • latest (default: $true) - when true, only grabs the latest version of each package
  • overwrite (default: $false) - when true, downloads and overwrites all packages regardless of whether you already have a copy
  • top (default: 500) - number of packages to download, ordered by package popularity. If $null, downloads all packages; if 1 it would download the most popular package
  • destinationDirectory - (default: %HOMEPATH%\Documents\NuGetLocal) full path to the directory you'd like the packages downloaded to. Note: I changed this from LocalNuGet in the Powershell to NuGetLocal in the package, as I thought it made more sense

Example - downloading the top 10 most popular packages with overwrite option, then removing the package:

PM> Install-Package NuGet.Downloader
Successfully installed 'Nuget.Downloader 1.0.0.5'.   PM> Download-Packages -top 10 -overwrite $true
Downloading latest 10 packages (by download count)
downloading from http://packages.nuget.org/v1/FeedService.svc/Packages?$filter=IsLatestVersion eq true&$orderby=DownloadCount desc&$top=10
Complete. Local packages saved to C:\Users\Jon\Documents\NuGetLocal
PM> Uninstall-Package NuGet.Downloader
Successfully uninstalled 'Nuget.Downloader 1.0.0.5'.
 
PM> 

Hope it helps you out, and please let me know how I can make it better.

Posted by Jon Galloway | 1 comment(s)
Filed under:

Tips on installing Visual Studio 2010 SP1

UPDATED 3/14/2011 with Web Platform Installer links

Visual Studio SP1 went up on MSDN downloads (here) on March 8, was released publicly March 10 here, and is available via the Web Platform Installer in two flavors:

You can find out more about Visual Studio 2010 SP1 via the release announcements:

There's a lot of info on what's in Visual Studio 2010 SP1 in Scott Hanselman's post when the beta was released here: Visual Studio Explosion! - VS2010 SP1 *BETA* Released and Context

I started on this post with tips on installing VS2010 SP1 when I realized I’ve been writing these up for Visual Studio and .NET framework SP releases for a while (e.g. VS2008 / .NET 3.5 SP1 post, VS2005 SP1 post). Looking back the years of Visual Studio SP installs (and remembering when we’d get up to SP6 for a Visual Studio release), I’m happy to see that it just keeps getting easier. Service Packs are a lot less finicky about requiring beta software to be uninstalled, install more quickly, and are just generally a lot less scary. If I can’t have a jetpack, at least my future provided me faster, easier service packs.

Disclaimer: These tips are just general things I've picked up over the years. I don't have any inside knowledge here. If you see anything wrong, be sure to let me know in the comments. You may want to check the readme file before installing - it's short, and it's in that new-fangled HTML format.

On with the tips!

Before starting, uninstall Visual Studio features you don't use

Visual Studio service packs (and other Microsoft service packs as well) install patches for the specific features you’ve got installed. This is a big reason to always do a custom install when you first install Visual Studio, but it’s not difficult to update your existing installation. Here’s the quick way to do that:

Tap the windows key and type “add or remove programs” and press enter (or click on the “Add or remove programs” link if you must).
Modifying Visual Studio 2010 Installation

 

Type “Visual Studio 2010” in the search box in the upper right corner, click on the Visual Studio program (the one with the VS infinity looking logo) and click on Uninstall/Change.
2011-03-09 10h59_46

Click on Add or Remove Features

Modifying Visual Studio 2010 Installation

The next part’s up to you – what features do you actually use? I’ve been doing primarily ASP.NET MVC development in C# lately, so I selected Visual C# and Visual Web Developer.

Remember that you can install features later if needed, and can also install the express versions if you want. Selecting everything just because it’s there - or you paid for it – means that you install updates for everything, every time.

When you’ve made your changes, click on the Update button to uninstall unused features.

VS2010 - Small Install

Shut down all instances of Visual Studio

It probably goes without saying that you should close a program down before installing it, partly to avoid the file-in-use-reboot-after-install horror.

Additional "hunch / works on my machine" quality tip: On one computer I saw a note in the setup log about Visual Studio a prompt for user input to close Visual Studio, although I never saw the prompt. Just to  be sure, I'd personally open up Task Manager and kill any devenv.exe processes I saw running, as it couldn't hurt.

Use the web installer

I use the Web Installers whenever possible. There’s no point in downloading the DVD unless you’re doing multiple installs or won’t have internet access. The DVD IS is 1.5GB, since it needs to be able to service every possible supported installation option on both x86 and x64.

The web installer is 776 KB (smaller than calc.exe), so you can start the installation right away. Like other web installers, the real benefit is that it only installs the updates you need (hence the reason for step 1 – uninstalling unused components). Instead of 1.5GB, my download was roughly 530MB.

If you’re installing from MSDN (this link takes you right to the Visual Studio installs), select the first one on the list:

2011-03-09 12h43_34

The first step in the installation process is to analyze the machine configuration and tell you what needs to be installed. Since I've trimmed down my features, that's a pretty short list. The time's not far off where I may not install SQL Server on my dev machines, just using SQL Server Compact - that would shorten the list further.

2011-03-09 13h06_20

When I hit next, you can see that the download size has shrunk considerably.

2011-03-09 13h07_20

When I start the install, note that the installation begins while other components are downloading - another benefit of the web install.

2011-03-09 13h09_26

On my mid-range desktop machine, the install took 25 minutes.

What if it takes longer?

According to Heath Stewart (Visual Studio installer guru), average SP1 installs take roughly 45 minutes. An installation which takes hours to complete may be a sign of a problem: see his post Visual Studio 2010 Service Pack 1 installing for over 2 hours could be a sign of a problem.

Why so long?

Yes, even 25 minutes is a while. Heath's got another blog post explaining why the update can take longer than the initial install (see: A patch may take as long or longer to install than the target product) which explains all the additional steps and complexities a patch needs to deal with, as well as some mitigation steps that deployment authors can take to mitigate the impact.

Other things to know about Visual Studio 2010 SP1

Installs over Visual Studio 2010 SP1 Beta

That's nice. Previous Visual Studio versions did a number of annoying things when you installed SP's over beta's - fail with weird errors, get part way through and tell you needed to cancel and uninstall first, etc. I've installed this on two machines that had random beta stuff installed without tears.

That Readme file you didn't read

I mentioned the readme file earlier (http://go.microsoft.com/fwlink/?LinkId=210711 ). Some interesting things I picked up in there:

2.1.3. Visual Studio 2010 Service Pack 1 installation may fail when a USB drive or other removeable drive is connected

2.1.4. Visual Studio must be restarted after Visual Studio 2010 SP1 tooling for SQL Server Compact (Compact) 4.0 is installed

2.2.1. If Visual Studio 2010 Service Pack 1 is uninstalled, Visual Studio 2010 must be reinstalled to restore certain components

2.2.2. If Visual Studio 2010 Service Pack 1 is uninstalled, Visual Studio 2010 must be reinstalled before SP1 can be installed again

2.4.3.1. Async CTP If you installed the pre-SP1 version of Async CTP but did not uninstall it before you installed Visual Studio 2010 SP1, then your computer will be in a state in which the version of the C# compiler in the .NET Framework does not match the C# compiler in Visual Studio. To resolve this issue: After you install Visual Studio 2010 SP1, reinstall the SP1 version of the Async CTP from here.

Description of what's in Visual Studio 2010 SP1

There's a KB article which describes Visual Studio 2010 SP1, including the issues that are fixed and the technology improvements that are added in Visual Studio 2010 SP1: http://support.microsoft.com/kb/983509

Hardware acceleration for Visual Studio is disabled on Windows XP

Visual Studio 2010 SP1 disables hardware acceleration when running on Windows XP (only on XP). You can turn it back on in the Visual Studio options, under Environment / General, as shown below. See Jason Zander's post titled Performance Troubleshooting Article and VS2010 SP1 Change.

More Posts