NuGet 1.6 and RouteMagic and Html.ActionLink

Dec 15, 2011 at 2:35 PM
Edited Dec 16, 2011 at 8:46 AM

Dear Team,

I downloaded the new NuGet (615413f0cd03) and rebuild my ASP.NET MVC based NuGet Server and got some errors in URLs where I use ActionLink.
If I comment out the MapDelegate("CreatePackage" ... MapDelegate("DownloadPackage" in src\Server\DataServices\Routes.cs the ActionLink working well.
What caused the problem?

Thanks,
Attila.
Html.ActionLink("List NuGet-Packages", "Packages", "nuget")

RESULThttp://localhost:29047/api/v2/package?action=packages&controller=nuget
REQUIRED RESULThttp://localhost:29047/nuget/Packages

 

I made a simple test solution for represent this problem,:

europa.webfiok.hu/Content/Download/Solution23.zip

 

 

Here is Global.asax.cs:

 

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Linq;
using System.ServiceModel.Activation;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

using Ninject;
using NuGet.Server.Infrastructure;
using NuGet.Server.DataServices;
using NuGet.Server;
using RouteMagic.HttpHandlers;
using RouteMagic.RouteHandlers;
using RouteMagic;


namespace MvcApplication1
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            // Route to create a new package
            // -- NuGet.exe push RB.Program.Foci.Client.1.0.1.nupkg b31c4f99-c01e-4266-8de8-4c19e42d1a52 -s http://localhost:1768 -CreateOnly
            routes.MapDelegate("CreatePackage",
                "api/v2/package",
                new { httpMethod = new HttpMethodConstraint("PUT") },
                context => CreatePackageService().CreatePackage(context.HttpContext));
            // Route to delete packages
            // -- NuGet.exe delete RB.Program.Foci.Client 1.0.1 b31c4f99-c01e-4266-8de8-4c19e42d1a52 -s http://localhost:1768
            routes.MapDelegate("DeletePackage",
                "api/v2/package/{packageId}/{version}",
                new { httpMethod = new HttpMethodConstraint("DELETE") },
                context => CreatePackageService().DeletePackage(context.HttpContext));
            // Route to get packages
            routes.MapDelegate("DownloadPackage",
                "api/v2/package/{packageId}/{version}",
                new { httpMethod = new HttpMethodConstraint("GET") },
                context => CreatePackageService().DownloadPackage(context.HttpContext));
            //
            // The default route is http://{root}/nuget/Packages
            // -- NuGet.exe list /Source http://localhost:1768/nuget
            // -- NuGet.exe install RBExtraDll /Version 1.0.1 /Source http://localhost:1768/nuget /OutputDirectory Packages
            var factory = new DataServiceHostFactory();
            var serviceRoute = new ServiceRoute("nuget", factory, typeof(Packages));
            serviceRoute.Defaults = new RouteValueDictionary { { "serviceType", "odata" } };
            serviceRoute.Constraints = new RouteValueDictionary { { "serviceType", "odata" } };
            RouteTable.Routes.Add("nuget", serviceRoute);
            //
            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

        private static PackageService CreatePackageService()
        {
            return NinjectBootstrapper.Kernel.Get<PackageService>();
        }
    }
}

 

How to NuGet was builded:

 

0, Download
  http://nuget.codeplex.com/SourceControl/list/changesets/615413f0cd03

1, Unzip

2, Modify
 src\CommandLine\CommandLine.csproj
  

    

 src\VsExtension\VsExtension.csproj
    $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets

    $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets.notfound 

 src\Server\DataServices\Routes.cs
    // [assembly: WebActivator.PreApplicationStartMethod(typeof(NuGet.Server.NuGetRoutes), "Start")]
    namespace NuGet.Server {
        public static class NuGetRoutes {
            public static void Start() {
                // MapRoutes(RouteTable.Routes);
            }

3, build
 build.cmd

4, copy server items into Solution23\MvcApplication1\Lib\
 - src\Server\bin\Elmah.dll
 - src\Server\bin\Microsoft.Web.Infrastructure.dll
 - src\Server\bin\Ninject.dll
 - src\Server\bin\NuGet.Core.dll
 - src\Server\bin\NuGet.Server.dll
 - src\Server\bin\RouteMagic.dll
 - src\Server\bin\WebActivator.dll

 

Site.Master:

 

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="<%: Url.Content("~/Scripts/jquery-1.5.1.min.js") %>" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <div id="header">
            <div id="title">
                <h1>My MVC Application</h1>
            </div>
            <div id="logindisplay">
                <% Html.RenderPartial("LogOnUserControl"); %>
            </div> 
            <div id="menucontainer">
                <ul id="menu">
                    <li><%: Html.ActionLink("Home", "Index", "Home")%></li>
                    <li><%: Html.ActionLink("About", "About", "Home")%></li>
                    <li><%= Html.ActionLink("Packages", "Packages", "nuget")%></li>
                </ul>
            </div>
        </div>
        <div id="main">
            <asp:ContentPlaceHolder ID="MainContent" runat="server" />
            <div id="footer">
            </div>
        </div>
    </div>
</body>
</html>

Dec 16, 2011 at 8:50 AM

The demo solution is downloadable from:

http://europa.webfiok.hu/Content/Download/Solution23.zip

Dec 21, 2011 at 7:35 AM

Dear Team,

There is no a member who known an answer this serious behaviour of NuGet 1.6 server ?

Why the routes changed ?

e.g. Html.ActionLink("List NuGet-Packages", "Packages", "nuget")

THE RESULT

http://localhost:29047/api/v2/package?action=packages&controller=nuget


THE REQUIRED RESULT

http://localhost:29047/nuget/Package

See it in the demo solution http://europa.webfiok.hu/Content/Download/Solution23.zip

Thanks any answer (an "you are stupid" is more than as nothiong ),

Attila.

Dec 22, 2011 at 5:37 PM
Edited Dec 22, 2011 at 5:38 PM

Dear Team,

I tried the newest "4039c34901be" nightly build the result was changed  but not that which expected.

e.g. Html.ActionLink("List NuGet-Packages", "Packages", "nuget")

THE RESULT

http://localhost:29047/?action=packages&controller=nuget


THE REQUIRED RESULT

http://localhost:29047/nuget/Packages

the new Global.asax.cs is:

 

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Linq;
using System.ServiceModel.Activation;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

using Ninject;
using NuGet.Server.Infrastructure;
using NuGet.Server.DataServices;
using NuGet.Server;
using RouteMagic.HttpHandlers;
using RouteMagic.RouteHandlers;
using RouteMagic;


namespace MvcApplication1
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            // Route to create a new package
            // -- NuGet.exe push RB.Program.Foci.Client.1.0.1.nupkg b31c4f99-c01e-4266-8de8-4c19e42d1a52 -s http://localhost:1768 -CreateOnly
            routes.MapDelegate("CreatePackage-Root",
                "",
                new { httpMethod = new HttpMethodConstraint("PUT") },
                context => CreatePackageService().CreatePackage(context.HttpContext));
            routes.MapDelegate("CreatePackage",
                "api/v2/package",
                new { httpMethod = new HttpMethodConstraint("PUT") },
                context => CreatePackageService().CreatePackage(context.HttpContext));
            // Route to delete packages
            // -- NuGet.exe delete RB.Program.Foci.Client 1.0.1 b31c4f99-c01e-4266-8de8-4c19e42d1a52 -s http://localhost:1768
            routes.MapDelegate("DeletePackage-Root",
                "{packageId}/{version}",
                new { httpMethod = new HttpMethodConstraint("DELETE") },
                context => CreatePackageService().DeletePackage(context.HttpContext));
            routes.MapDelegate("DeletePackage",
                "api/v2/package/{packageId}/{version}",
                new { httpMethod = new HttpMethodConstraint("DELETE") },
                context => CreatePackageService().DeletePackage(context.HttpContext));
            // Route to get packages
            // -- NuGet.exe install RBExtraDll /Version 1.0.1 /Source http://localhost:1768/nuget /OutputDirectory Packages
            routes.MapDelegate("DownloadPackage",
                "api/v2/package/{packageId}/{version}",
                new { httpMethod = new HttpMethodConstraint("GET") },
                context => CreatePackageService().DownloadPackage(context.HttpContext));
            //
            // The default route is http://{root}/nuget/Packages
            // -- NuGet.exe list /Source http://localhost:1768/nuget
            var factory = new DataServiceHostFactory();
            var serviceRoute = new ServiceRoute("nuget", factory, typeof(Packages));
            serviceRoute.Defaults = new RouteValueDictionary { { "serviceType", "odata" } };
            serviceRoute.Constraints = new RouteValueDictionary { { "serviceType", "odata" } };
            RouteTable.Routes.Add("nuget", serviceRoute);
            //
            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

        private static PackageService CreatePackageService()
        {
            return NinjectBootstrapper.Kernel.Get<PackageService>();
        }
    }
}
Developer
Dec 22, 2011 at 6:39 PM
Edited Dec 22, 2011 at 6:39 PM

Does using a RouteLink instead of an ActionLink help?

Html.RouteLink("List NuGet-Packages", "nuget")

Coordinator
Dec 22, 2011 at 10:13 PM

The behavior is probably due to having a route that has a parameterless URL. See http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx

Having said that, if we're using RouteMagic, I've posted a fix to the latest version which addresses this issue for routes registered using RouteMagic. We simply need to update NuGet.Server to the latest route magic and that should (hopefully) fix it. Do test though! :)

Dec 24, 2011 at 2:17 PM

Dear Haacked,

I downloaded the "c195fcdd0069" source and changed the RouteMagic from 1.1.3 to 1.2 after I builded it the test solution worked well I got "THE REQUIRED RESULT".

Thanks a lot your fix.

Attila.