Introduction to NuGet – My Talk at Prairie Dev Con 2011

Another great session today with some good questions and some great conversation afterwards.  Thanks peeps!

Here’s some great resources to get you plugged in with NuGet and to help take those first few steps:

 

You can also follow the NuGet conversation on Twitter (#NuGet), or join in the StackOverflow.com chat room on the subject.

And as always, feel free to send me a note with any questions you may have.

Prairie Dev Con 2011 - My talk on ASP.NET MVC

Thanks!

You know a conference is going well when you the connections start happening faster than you can manage to keep up with them.  There were a lot of great people at the session today and a lot of great conversation afterwards.

Thanks to all who attended!  I’ll be doing another session tomorrow on NuGet and will post back here with all the critical links.

If you’re looking to get started, make sure you check out this post I did with a ton of material for ASP.NET MVC.

Also, for those of you who were excited about the MvcScaffolding bits, be sure to check out my Joyride post on the same.

See you tomorrow!

When Things Go Wrong During a Presentation

So what do you do when you have a room full of people and your presentation goes awry? Make sure you know your domain before you go in.

I just finished my talk on the spanky, fun Asp.Net Mvc Framework, and I thought I’d prepared well prior to going in.  Aside from a few minor snags – also called teaching opportunities Winking smile  – things ran rather smoothly and the initial feedback on the session was quite positive.  Running into errors and exceptions is okay, in my mind. We’re programmers after all and 90% of what we do is wrong ;o)  I’ve been through most scenarios, especially in this stack, and so I know how to respond.

But then it hit me: a curve ball from the audience (thanks for the questions by the way!) took me a little off course (which I love) and I tried to figure out what the problem was (which, completely topical to my talk, was scary).  And, after all, it’s important to know what color scary things are so that you can identify them easier. 

Sad face here: I hit an exception I hadn’t seen before.  On stage. In front of 50 awesomely patient folks.  sigh

image

That image reads:

Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions.

Unfortunately I was a little too nervous to tackle it beyond a couple of quick attempts, but the solution was quite simple: drop the database and let the EntityFramework recreate it.

What Went Wrong

I think the biggest issue was that I was playing with multiple changes to the model classes during the presentation.  The metadata associated with the database, stored in its own table where the db is created, got out of sync with what was in the database and what was in the classes in the project.  Not a biggy, but frustrating just the same.

I will note again that this isn’t something you’d likely run into late in a project, only early on.

Thankfully at the front end of a project we are okay with dropping data, especially when we’re working with something like EF Code First…if we really want data in those tables after we make changes we can easily create our own db initializer and add seed data.

Hopefully, when you run into this kind of error, you won’t be on stage. ;o)  At least, not without having first read this post.

Oh Yes, NuGet Can!

Update Via Twitter

I received a message from one of the awesome NuGet folks on Twitter about this post on NuGet real world scenarios:

![image[6]](http://oldblog.jameschambers.com/Media/Default/Windows-Live-Writer/Oh-Yes-NuGet-Can_9855/image%5B6%5D_2.png)

David is pointing out that if you want to upgrade a package you can first remove its dependencies, which allows you to do so without NuGet unwinding the operation. Thanks to David for this!

I responded by saying I’d still like a –ForceUpdate command that would bring all dependencies to the correct version (known as leveling) and have since discovered that such a feature is in the works for NuGet. 

More good things to come for sure.

PowerShell Script Examples for NuGet Packages

Here is a list of PowerShell examples taken right from the packages you might already be using, some have more detailed explanation or examples elsewhere on the webs. This list intends to be a quick reference for common operations when building install scripts for your NuGet packages.  Keep the list handy for writing install for your own packages.

2011.06.21 Updates

Import Modules (Using External Scripts for Commands) 

    Import-Module (Join-Path $toolsPath commands.psm1)

Going forward, the recommended convention (from David Fowler) for extending the package manager console is to put your scripts into seperate files (modules) in your tools directory, and to import them with a command similar to above in your init.ps1 file.

Insert Text into Current Document at Cursor

from jQuery.Farbtastic         $dte.ActiveDocument.Selection.Insert($scriptTemplate)

Use this to write out text to the current cursor location in the active document. A little caution with this one: You might want to check the lenth of the selection first (write-host $dte.ActiveDocument.Selection.Text.Length) becuase this will overwrite any selected text. 

Copy Text to the Clipboard

from jQuery.Farbtastic
    $mystring | clip

In this snippet all we’re doing is ‘piping’ the string into the clipboard.  Be mindful that this would overwrite anything already there.

There are lots of interesting ways you can add functionality to your package and the package manager console.  I found, in exploring useful ways to get code to the user, that there may be scenarios where just pushing generated code to the clipboard may not be a bad option.

Discover IDE Manipulation and Automation Commands

    $dte | Get-Member

This ouputs the list of exposed properties and methods in the DTE object.  This is super handy for fiddling with the IDE from the Package Manager Console, even inside a test project, to figure out what is available.  Besides, self discovery is more interesting than reading the docs ;)  You can also try plugging around with the properties exposed, such as $dte.Solution | Get-Member, for example.


Read Properties from Visual Studio Objects

from SqlServerCompact     $currentPostBuildCmd = $project.Properties.Item(“PostBuildEvent”).Value

This gets the post build command from the specified project item.

 

Loop Through All Installed Packages

from NuGetPackageUpdater
    foreach ($package in get-package) {
      write-host “Package $($package.Id) is installed”
    }

This loops through all packages that are installed on the currently targetted project.

 

Loop Through All Projects in the Solution

from NuGetPackageUpdater
    foreach ($proj in get-project -all) {
      write-host “Project $($proj.Name) is in this solution.”
    }

This outputs the name of each project in the solution in the package manager console. You can use get-project to retrieve the name of the currently targetted project.

 

Delete an Item in a Project

from MvcScaffolding
    Get-ProjectItem “foo.txt” | %{ $.Delete() }
 or
    Get-ProjectItem “InstallationDummyFile.txt” -Project $projectName | %{ $.Delete() }

This gets the specified file from the current project and ‘pipes’ it into the next command, which is a call to delete.  The “$_” is a token representing the passed-in object.  If you have the name of the project and want to target that project you can also use the -Project argument as in the second example.

Note: Get-ProjectItem was available when I tried this out because MvcScaffolding has a dependency on T4Scaffolding, which exposes a PowerShell cmdlet of the same name.  I will post on this later to show you how to get this to work in your own packages, but if you intend to use scaffolding anyways there’s no reason your package can’t depend on T4 for now.

 

Remove a Reference from a Project

from Machine.Specifications

    $project.Object.References | Where-Object { $_.Name -eq 'NameOfReference' } | ForEach-Object { $_.Remove() }

If you’re looking to purge references that you know are safe to do so when you’re uninstalling, you can do so as above. This uses a filter to selectively remove a reference from the project in question.  You could also use a foreach at the project level and remove the reference from each project (rather than using the $project param that NuGet feeds you when uninstall is executed).

Alternatively, rather than assuming your user hasn’t taken on the dependency in another fashion in their project, you could simply use Write-Host and let them know that if they aren’t using the references you’ve added (during your install) that it is now safe to remove them from the project in question.

 

Loop Through All Project Items

from MisterJames

    ForEach ($item in $project.ProjectItems) { Write-Host $item.Name } 

This will print out the list of all items in the specified project. You can use $item for project item operations per the VS automation docs (see link at bottom), here, I’ve just output the name.

 

Open a File from the Tools Folder

from EfCodeFirst (note that this is a legacy package no longer used)

    $dte.ItemOperations.OpenFile($toolsPath + ‘\EFCodeFirstReadMe.txt’)

This one is pretty straightforward.  $toolsPath is passed into our script and is available as a parameter throughout.  Here, we’re simply calling $dte.ItemOperations.OpenFile to open the file specified.

 

Opening a File from the Content Folder

from Glimpse.Mvc3
    $path = [System.IO.Path]
    $readmefile = $path::Combine($path::GetDirectoryName($project.FileName), “App_Readme\glimpse.mvc3.readme.txt”)
    $DTE.ExecuteCommand(“File.OpenFile”, $readmefile)

In this example there are two variables at play, an System.IO.Path reference  and a string being built to open a file.  In the final line, $DTE.ExecuteCommand is called to invoke Visual Studio’s “open file” command in a different way from EFCodeFirst, with the filename passed in as a parameter.  Note that you could also use [System.IO.Path]::Combine directly; $path is just a reference/alias to access the static method in a more readible manner.

 

 

Calling Other Scripts in the Current Scope

 from SqlServerCompact     . (Join-Path $toolsPath “GetSqlCEPostBuildCmd.ps1”)

PowerShell will execute the specified file in the context of the current script when you do a “dot-space-brackets”.  In this example, we need to concatenate the name of our script, which is located in the package tools directory, to the tools path and then make the call.  At this point, any vars you set up will be available to you in the current script.  If you want to break out and build a list of files or - in this case - set up a variable with post-build information, this is your vehicle.

 

Exploring On Your Own

If you want to accomplish something that you don’t see here but have seen in another package it’s pretty easy to see what they’ve done.  You need to get yourself a copy of the NuGet Package Explorer – also a great tool for building your own packages – and just start pulling down the work that’s out there.

image

The best part about using this for exploratory purposes is that it can connect directly to a repository feed.  Just pull up File –> Open from Feed… to search or browse packages. The NuGet.org package repository load by default, but you can specify your own.

image

References

You can dive much deeper, of course, as you have PowerShell in your hands here, controlling the IDE.  If you want more information on specifics of any of the ideas at play here, check out the following links:

 

Wrapping Up

Know any other good samples?  A more straight-forward way to pull something off? Feel free to send me a note so I can add them here, or send questions my way.

CodeProject

Naming the Database Created by EF Code First

If you don’t want to have a database name like:
holy.crap.this.is.a.long.name.with.my.whole.namespace.contextname
…then you simply need to name the database.  To do this, we need to create the class that inherits from DbContext and call the base constructor to pass in the name.
    public class FamilyContext :

DbContext        {        public FamilyContext (): base(“FamilyContext”) {}        }

 

Sweet.  So, one other thing to pay attention to then, especially if you’re using MvcScaffolding or other similar tools.  If you’ve named your context you’ll need to tell it where you want your entity collections to manifest.  For MvcScaffolding in particular, you can use the –DbContext switch and pass in your context name.  That looks something like this:
Scaffold Controller Family -DbContext Family

The result is that MvcScaffolding will now look for that type in the target project and add the appropriate code.


    public class FamilyContext : DbContext
{
public FamilyContext (): base(“FamilyContext”) {}
public DbSet<MyProject.Models.Family> Families { get; set; }
}


Hope this helps!