aspnet / Routing

[Archived] Middleware for routing requests to application logic. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
272 stars 122 forks source link

Support IgnoreRoute #47

Closed yishaigalatzer closed 7 years ago

yishaigalatzer commented 10 years ago
rynowak commented 10 years ago

Interesting design question in the k-world.. does ignore route mean that routing stops processing and allows another middleware to handle the request?

For instance today if no route matches, then the middleware invokes next(). An 'ignore route' needs a way to signal to the routing system that other routes should not run. Currently this mechanism is entangled with 'call next()'. Does this become trinary logic?

yishaigalatzer commented 10 years ago

Yeah that's the idea. Isn't that what we do today if none of the routes match?

rynowak commented 10 years ago

Yes. So IgnoreRoute isn't just a new IRouter implementation, we need a special semantic for it that we don't currently support because it gets to 'handle' the request (preventing other routes from running) but also cause the middleware to call next().

Current API does not have a way to do this.

Eilon commented 10 years ago

Yes, it would be new. In ASP.NET (MVC) / Web API this was done by having a token route handler called the StopRoutingHandler that the route collection would interpret as "stop doing what you're doing and return to the host."

lodejard commented 10 years ago

I wonder if the next delegate should be part of the route context? that way the "stop routing" handler could also be implemented as calling next() and returning as completed.

Even if that's not how it's done in the end, passing the next delegate on the context might be useful for other reasons.

danroth27 commented 9 years ago

Scenario is to have a way to indicate that the request should not be handled by routing - it should be handled by other middleware instead.

kscott5 commented 9 years ago

So, I've looked and could not find MapMvcAttributeRoutes or IgnoreRoutes as it relates to ASP.NET vNext. Is it implement? If not, how do I use the conventional base routing as it relates to Microsoft.AspNet.Mvc?

k web produced the following error message:

G:\apps\web\GreenShelter\k web 
System.IO.FileLoadException: Could not load file or assembly 'GreenShelter, Cult
ure=neutral, PublicKeyToken=null' or one of its dependencies. General Exception
(Exception from HRESULT: 0x80131500)
File name: 'GreenShelter, Culture=neutral, PublicKeyToken=null' ---> Microsoft.F
ramework.Runtime.Roslyn.RoslynCompilationException: G:\apps\web\GreenShelter\Rou
teConfig.cs(11,20): error CS1061: 'RouteCollection' does not contain a definitio
n for 'IgnoreRoute' and no extension method 'IgnoreRoute' accepting a first argu
ment of type 'RouteCollection' could be found (are you missing a using directive
 or an assembly reference?)
RouteConfig.cs(17,77): error CS0103: The name 'UrlParam
eter' does not exist in the current context
   at Microsoft.Framework.Runtime.Roslyn.RoslynProjectReference.Load(IAssemblyLo
adContext loadContext)
   at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name,
 IAssemblyLoadContext loadContext)
   at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name)

   at klr.host.LoaderContainer.Load(String name)
   at klr.hosting.RuntimeBootstrapper.<>c__DisplayClass0.<ExecuteAsync>b__8(Asse
mblyName assemblyName)
   at klr.hosting.DelegateAssemblyLoadContext.Load(AssemblyName assemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(AssemblyNam
e assemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.Resolve(IntPtr gchManagedAssembl
yLoadContext, AssemblyName assemblyName)
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String cod
eBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark&
stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntro
spection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String code
Base, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& s
tackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntros
pection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName as
semblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMar
k& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIn
trospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName as
semblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMar
k& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean sup
pressSecurityChecks)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
   at Microsoft.AspNet.Hosting.Startup.StartupLoader.LoadStartup(String applicat
ionName, String environmentName, IList`1 diagnosticMessages)
   at Microsoft.AspNet.Hosting.Startup.StartupManager.LoadStartup(String applica
tionName, String environmentName)
   at Microsoft.AspNet.Hosting.HostingEngine.EnsureApplicationStartup(HostingCon
text context)
   at Microsoft.AspNet.Hosting.HostingEngine.EnsureApplicationDelegate(HostingCo
ntext context)
   at Microsoft.AspNet.Hosting.HostingEngine.Start(HostingContext context)
   at Microsoft.AspNet.Hosting.Program.Main(String[] args)
Microsoft.Framework.Runtime.Roslyn.RoslynCompilationException: G:\apps\web\Green
Shelter\RouteConfig.cs(11,20): error CS1061: 'RouteCollection' does not contain
a definition for 'IgnoreRoute' and no extension method 'IgnoreRoute' accepting a
 first argument of type 'RouteCollection' could be found (are you missing a usin
g directive or an assembly reference?)
G:\apps\web\GreenShelter\RouteConfig.cs(17,77): error CS0103: The name 'UrlParam
eter' does not exist in the current context
   at Microsoft.Framework.Runtime.Roslyn.RoslynProjectReference.Load(IAssemblyLo
adContext loadContext)
   at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name,
 IAssemblyLoadContext loadContext)
   at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name)

   at klr.host.LoaderContainer.Load(String name)
   at klr.hosting.RuntimeBootstrapper.<>c__DisplayClass0.<ExecuteAsync>b__8(Asse
mblyName assemblyName)
   at klr.hosting.DelegateAssemblyLoadContext.Load(AssemblyName assemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyName(AssemblyNam
e assemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.Resolve(IntPtr gchManagedAssembl
yLoadContext, AssemblyName assemblyName)

project.json

{
  "version": "1.0.0.0",
  "authors": [
    "Karega Scott - PCSC"
  ],
  "description": "Green Shelter Project for Not-for-Profit",
  "compilationOptions": {
    "warningsAsErrors": true
  },
  "code": "*.cs",
  "exclude": "*.bk",
  "dependencies": {
    "Microsoft.Framework.Logging": "1.0.0-beta1",
    "Microsoft.Framework.Logging.Console": "1.0.0-beta1",
    "Kestrel": "1.0.0-beta1",
    "Microsoft.AspNet.Diagnostics": "1.0.0-beta1",
    "Microsoft.AspNet.Hosting": "1.0.0-beta1",
    "Microsoft.AspNet.Mvc": "6.0.0-beta1",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta1",
    "Microsoft.AspNet.Routing": "1.0.0-beta1",
    "Microsoft.AspNet.Mvc.WebApiCompatShim": "6.0.0-beta1"
  },
  "commands": {
    "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:8080",
    "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:8181",
    "test": "Xunit.KRunner"
  },
  "frameworks": {
    "aspnetcore50": {
        "System.Console": "4.0.0-beta-*"
        //"System.Web.Http": "4.0.0"
    }
  },
  "configurations": {
    "Debug": {
      "compilationOptions": {
        "define": [
          "DEBUG",
          "TRACE"
        ]
      }
    },
    "Release": {
      "compilationOptions": {
        "define": [
          "RELEASE",
          "TRACE"
        ],
        "optimize": true
      }
    }
  }
}

RouteConfig.cs

using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;

namespace PCSC.GreenShelter.AppStart
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
        // Can't find IgnoreRoute
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapMvcAttributeRoutes();

            routes.MapRoute(
                name: "Default",
// This appears to be changed to template
//                url: "{controller}/{action}/{id}",
                  template: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new []{ "PCSC.GreenShelter.Controllers" }
            );
        }
    }
}

WebApiConfig.cs

using System.Web.Http;
using Microsoft.AspNet.Mvc.WebApiCompatShim;

namespace PCSC.GreenShelter.AppStart
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes (Attribute based - Not available yet)
            //config.MapHttpAttributeRoutes(); 

            // Convention-based routing.
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );          
        }
    }
}
yishaigalatzer commented 9 years ago

@kscott5 IgnoreRoute was not yet implemented (as indicated by this issue being open), so you need to remove the routes.IgnoreRoute for now.

MapMvcAttributesRoutes is no longer necessary, and you can safely remove the line. Attribute routes just work by default.

ChrisFelstead commented 8 years ago

My issue has been moved and I've been ask to supply a case. In short, I can a wildcard route in order to allow for views without a controller (these are static pages but with the same design template). The issue is that I need to exclude common extensions (images, css, JavaScript, documents etc...) and cant without IgnoreRoutes.

Eilon commented 8 years ago

@ChrisFelstead one thing to note about ASP.NET Core MVC (the new MVC) is that if the incoming URL matches a route that is intended for MVC, but MVC can't find a matching controller/action, MVC ignores it, and the request will continue to the next middleware. Also, generally the Static Files middleware should be registered before the MVC middleware (that is, call UseStaticFiles() before UseMvc()).

I'm curious - did you try this and it didn't work? And if so, what exactly happened?

ChrisFelstead commented 8 years ago

I had this is my startup. I expected it to run the wildcard route if no appropriate route found but ignore static files like images, js, css and documents. It's applying to everything so I wanted to use ignore routes to exclude them extensions.

Basically, Im to achieve the ability to have views without a controller for static pages. But I need the ability to use the layout (hence why I dont make html pages)

app.UseStaticFiles();

app.UseMvc(routes =>
{
//routes.MapRoute(
// name: "RP",
// template: "RP/{controller=Home}/{action=Index}/{id?}",
// defaults: new { area = "RP" });

routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

routes.MapRoute("Wildcard Routing",
"{*anything}",
new { controller = "Wildcard", action = "Get" },
new { anything = @"^(.*)?$" });
Eilon commented 8 years ago

Hmm that looks like it should work for this scenario:

  1. If the incoming request matches a file that exists on disk, serve it (static file middleware should catch all these)
  2. If the incoming request matches an existing MVC controller/action, run that
  3. Send all other requests to WildcardController.Get()

But that's not what's happening?

ChrisFelstead commented 8 years ago

Nope. I thought it should too. All requests (including the js and css) are going to the controller. I'll do some more investing tomorrow and get back to you with specific cases and a sample project if you would like.

On 29 Feb 2016, at 17:09, Eilon Lipton notifications@github.com<mailto:notifications@github.com> wrote:

Hmm that looks like it should work for this scenario:

  1. If the incoming request matches a file that exists on disk, serve it (static file middleware should catch all these)
  2. If the incoming request matches an existing MVC controller/action, run that
  3. Send all other requests to WildcardController.Get()

But that's not what's happening?

Reply to this email directly or view it on GitHubhttps://github.com/aspnet/Routing/issues/47#issuecomment-190293567.

Eilon commented 8 years ago

Is this on a machine with a case-sensitive file system (e.g. Linux), and the requests are coming in with the wrong casing?

ChrisFelstead commented 8 years ago

No. Its running on Windows. And Im using the default project template.

rynowak commented 8 years ago

You should be able to see some relevant information in the debug output window from logging if you're using VS and the default template.

Eilon commented 8 years ago

An the webroot property in project.json is pointing at the correct folder (usually wwwroot)?

Does the plain old regular default project template (without any modifications) serve static files correctly?

ChrisFelstead commented 8 years ago

Interesting. Got a colleague to open and run (as Im out of the office) the project and it works as expected. Getting 200 and 302s. The problems must be on my machine. Sorry to both you guys.

Eilon commented 8 years ago

@ChrisFelstead have your colleague join this program: http://blog.codinghorror.com/the-works-on-my-machine-certification-program/

You, on the other hand, cannot yet join this program :smile:

dlebedynskyi commented 8 years ago

@Eilon we have same issues. dnx core rc1, Window 7 x64. Both on IIS and kestrel. Static files if not found are passed to controller and are return an home/index page with text/plain.

I had to put attribute routing on home/index and remove all routing from ConfigureMvc. Something like

[Route("~/")] // required to server root 
[Route("~/{controller}/{action}")] / any controller action etc

PS not at work machine now so code may be a bit wrong. but hope shows the idea. I with we had ignore route

Eilon commented 8 years ago

@dlebedynskyi can you log a new issue in this repo with precise repro steps? IgnoreRoute still shouldn't be needed for this scenario, so unless I'm missing something, this could just be a bug.

dlebedynskyi commented 7 years ago

@Eilon great resolution. good job. too a lot of work I assume