20

Previously, one would add something like this to Global.aspx.cs, which is gone in .NET Core:

  routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

Here's what I currently have in my Startup.cs (for .NET Core):

  app.UseDefaultFiles();

  app.UseStaticFiles();

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

      routes.MapSpaFallbackRoute(
          name: "spa-fallback",
          defaults: new { controller = "Home", action = "Index" });
  });

The problem is that in MVC (pre-Core) routes was a RouteCollection and in .NET Core it's a Microsoft.AspNetCore.Routing.IRouteBuilder so IgnoreRoute is not a valid method.

Jess
  • 23,901
  • 21
  • 124
  • 145
Jeff Guillaume
  • 1,661
  • 3
  • 17
  • 29

6 Answers6

19

You could write middleware for this.

public void Configure(IApplciationBuilder app) {
    app.UseDefaultFiles();

    // Make sure your middleware is before whatever handles 
    // the resource currently, be it MVC, static resources, etc.
    app.UseMiddleware<IgnoreRouteMiddleware>();

    app.UseStaticFiles();
    app.UseMvc();
}

public class IgnoreRouteMiddleware {

    private readonly RequestDelegate next;

    // You can inject a dependency here that gives you access
    // to your ignored route configuration.
    public IgnoreRouteMiddleware(RequestDelegate next) {
        this.next = next;
    }

    public async Task Invoke(HttpContext context) {
        if (context.Request.Path.HasValue &&
            context.Request.Path.Value.Contains("favicon.ico")) {

            context.Response.StatusCode = 404;

            Console.WriteLine("Ignored!");

            return;
        }

        await next.Invoke(context);
    }
}
Technetium
  • 5,902
  • 2
  • 43
  • 54
  • 6
    Thanks very much for this, but to boil it down: I must replace one line of code with an entire custom route? Seems kinda bloated. – Jeff Guillaume Sep 15 '16 at 20:59
  • 1
    Perhaps? There may be a way in .NET Core that more directly addresses your concern. Perhaps via the Routing middleware. I simply have not run into it. I would read this document then check out the source code to get something more definitive: https://docs.asp.net/en/latest/fundamentals/routing.html – Technetium Sep 15 '16 at 23:08
  • 1
    This solution makes sense but should be more specific, looking for a path containing the string provided means potentially paths you don't want to match will be matched, and this isn't very optimal either, it would be better in terms of performance to simply not use middleware and keep the number of routes to a minimum. – Professor of programming Jul 22 '17 at 21:44
  • In order to address Bonner's concerns `Contains(...)` should be replaced with `StartsWith("/favicon.ico")`.Otherwise, an excellent answer. – Alexei - check Codidact Dec 19 '18 at 13:01
  • This works, but **see my answer below** for a simpler solution. – Jess May 11 '20 at 20:21
9

.NET Core 3.1

For .NET Core 3.1 with endpoint routing, this seems like the easiest way. You don't need to build a middleware just for this simple case.

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/favicon.ico", async (context) =>
    {
        context.Response.StatusCode = 404;
    });
    // more routing
});

The original question is about ignoring routes. If you do want to serve a favicon, you can add HTML markup in _Layout.cshtml like this. This technique allows more control over where the icon is served from.

<link rel="icon" href="@Url.Content("~/images/favicon.ico")" />

I am using both of these techniques in my code.

Jess
  • 23,901
  • 21
  • 124
  • 145
8

If you want to make a static file accessible without the routing condition, simply use the build-in StaticFiles Middleware. Activate it with app.UseStaticFiles(); in Configure Method and put your static files in wwwroot directory. They're availible on HOST/yourStaticFile

For more information, refer here

Ky -
  • 30,724
  • 51
  • 192
  • 308
Oguzhan
  • 96
  • 1
  • 1
5

inside public void Configure

add

app.Map("/favicon.ico", delegate { });
Zam
  • 2,880
  • 1
  • 18
  • 33
  • 1
    If you're using swagger and also want to ignore the controller (still requires this answer), also add `[ApiExplorerSettings(IgnoreApi = true)]` will remove from the swagger doc – Adam Cox Mar 31 '19 at 03:04
  • This answer works, but it throws an exception `System.InvalidOperationException: The request reached the end of the pipeline without executing the endpoint: '/favicon.ico HTTP: GET'. Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if using routing.` in .NET Core 3.1. – Jess May 11 '20 at 20:13
  • @Jess Good to know. Original answer was for .NET Core 1.0.1 – Zam May 16 '20 at 20:27
3

Allow favicon requests to be parsed by the route handler, and keep your routes to a minimum. Avoid using middleware, this just adds additional complexity to your code and means all other requests must go through the middleware before the route handler, which is worse in terms of performance for busy websites. For websites that aren't busy you would just be wasting your time worrying about this.

See https://github.com/aspnet/Routing/issues/207

Professor of programming
  • 2,978
  • 3
  • 30
  • 48
0

In ASP.NET Core, you can write a constrained catch-all route template. To do so, in your ASP.NET Core example, replace the call to routes.MapSpaFallbackRoute with the following:

// Returns the home/index page for unknown files, except for
// favicon.ico, in which case a 404 error is returned.
routes.MapRoute(
    name: "spa-fallback",
    template: "{*url:regex(^(?!favicon.ico).*$)}",
    defaults: new { Controller = "Home", action = "Index" });
Marc Sigrist
  • 3,964
  • 3
  • 22
  • 23