In the previous post of this serie, I introduced NuPack package manager:
Dissecting NuPack (Part 1) Introduction
I would like to explore NuPack internal process. First, to run using the source code, I installed:
Visual Studio 2010 SDK
PowerShell 2.0
Then, this is the current solution (October 11th):
NuPack.Server project is a web server, written using ASP.NET MVC:
First, note the MVC mapping in global.asax.cs:
// Map a feed route at the root routes.MapRoute("feed", "feed", new { controller = "Packages", action = "Feed" } );The Package controller is in charge of producing the list of package to expose in the server. Its address is /feed. The output:
![]()
The source code of Package controller is in Controllers\PackageController.cs. The Feed action will be deprecated in NuPack CPT 2:
//TODO: This method is deprecated. Need to keep it around till we release NuPack CTP 2. public ActionResult Feed() { // Add the response header Response.AddHeader(PackageUtility.FeedVersionHeader, PackageUtility.AtomFeedVersion); if (Request.Headers[PackageUtility.FeedVersionHeader] != null) { return new HttpStatusCodeResult(304); } // Get the last modified of the package directory DateTime lastModified = Directory.GetLastWriteTimeUtc(PackageUtility.PackagePhysicalPath); return ConditionalGet(lastModified, () => { SyndicationFeed packageFeed = PackageSyndicationFeed.Create( PackageUtility.PackagePhysicalPath, package => PackageUtility.GetPackageUrl(package.Id, package.Version.ToString(), Request.Url)); packageFeed.Title = new TextSyndicationContent("Demo Feed"); packageFeed.Description = new TextSyndicationContent("Demo package feed"); SyndicationPerson sp = new SyndicationPerson("person@demofeed.com", "Demo", "http://www.demofeed.com"); packageFeed.Authors.Add(sp); packageFeed.Copyright = new TextSyndicationContent("Copyright " + DateTime.Now.Year); packageFeed.Description = new TextSyndicationContent("ASP.NET package feed"); packageFeed.Language = "en-us"; packageFeed.LastUpdatedTime = lastModified; return new SyndicationFeedResult(packageFeed, feed => new Atom10FeedFormatter(feed)); }); }The packages are retrieved from PackageUtility.PackagePhysicalPath:
public class PackageUtility { internal static string PackagePhysicalPath = HostingEnvironment.MapPath("~/Packages"); internal static string AtomFeedVersion = "1.0"; internal static string ODataFeedVersion = "2.0"; internal static string FeedVersionHeader = "NuPackVersion";I copied NuPack packages files (with .nupkg extension) from package directory (included in the download) (In previous versions, the Server contained a complete list of .nupkg files, but now, we should add the package to the /Packages INSIDE web server).
There is a new OData service, in /DataServices/Packages.svc. The initialization code:
protected override void OnStartProcessingRequest(ProcessRequestArgs args) { base.OnStartProcessingRequest(args); // HACK: Exceptions for control flow yay! Only way to stop the request from completing // right now HttpRequestBase request = new HttpRequestWrapper(HttpContext.Current.Request); DateTime lastModified = Directory.GetLastWriteTimeUtc(PackageUtility.PackagePhysicalPath); if (request.IsUnmodified(lastModified)) { throw new DataServiceException(304, null); } // Stick the version header in the response args.OperationContext.ResponseHeaders[PackageUtility.FeedVersionHeader] = PackageUtility.ODataFeedVersion; // Try to determine if this is a request for the feed version if(args.OperationContext.RequestHeaders[PackageUtility.FeedVersionHeader] != null) { throw new DataServiceException(200, null); } HttpCachePolicy cachePolicy = HttpContext.Current.Response.Cache; cachePolicy.SetCacheability(HttpCacheability.Public); cachePolicy.SetLastModified(Directory.GetLastWriteTimeUtc(PackageUtility.PackagePhysicalPath)); }The PackageContext is the key class to get an IQueryable over existing packages:
namespace NuPack.Server.DataServices { public class PackageContext { private IPackageRepository _repository; public PackageContext(IPackageRepository repository) { _repository = repository; } public IQueryable<Package> Packages { get { return from package in _repository.GetPackages() select new Package(package); } } } }More about WCF DataServices and OData:
http://msdn.microsoft.com/en-us/data/ee720180.aspx
http://www.odata.org/developers/protocols/uri-conventions
You can obtain the list of packages entering /DataServices/Packages.svc/Packages in browser:
![]()
I should explore the NuPack.Core, the way a package is created and installed.
Keep tuned!
Angel “Java” Lopez
http://www.ajlopez.com