错误500而不是404

9 浏览
0 Comments

错误500而不是404

我有一个asp.net MVC 5项目,我想抛出404错误而不是500错误。

错误信息如下:

控制器'ProjetX.Controllers.HomeController'上找不到公共操作方法'something'

路径'/something'上找不到控制器或者控制器没有实现IController接口

我理解为什么是500错误,但我希望抛出404错误,这对于SEO更好。

我无法弄清楚如何做到这一点。

以下是我的代码:

我的Elmah的ExceptionHandler类

public class HandleCustomError : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            //如果异常已经处理,我们什么也不做
            if (filterContext.ExceptionHandled)
            {
                return;
            }
            else
            {
                //使用Elmah记录异常
                Log(filterContext);
                Type exceptionType = filterContext.Exception.GetType();
                //如果是ajax调用时的异常
                if (exceptionType == typeof(ExceptionForAjax))
                {
                    filterContext.HttpContext.Response.Clear();
                    filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8;
                    filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8;
                    filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
                    filterContext.HttpContext.Response.StatusCode = 500;
                    filterContext.HttpContext.Response.StatusDescription = filterContext.Exception.Message;
                }
                else
                {
                    base.OnException(filterContext);
                }
            }
            //确保将异常标记为已处理
            filterContext.ExceptionHandled = true;
        }
        private void Log(ExceptionContext context)
        {
            //获取此请求的当前HttpContext实例
            HttpContext httpContext = context.HttpContext.ApplicationInstance.Context;
            if (httpContext == null)
            {
                return;
            }
            //将异常包装在HttpUnhandledException中,以便ELMAH可以捕获原始错误页面
            Exception exceptionToRaise = new HttpUnhandledException(message: null, innerException: context.Exception);
            //将异常发送给ELMAH(用于记录、发送邮件、过滤等)
            ErrorSignal signal = ErrorSignal.FromContext(httpContext);
            signal.Raise(exceptionToRaise, httpContext);
        }
    }

我如何添加自定义错误

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleCustomError());
        }

路由配置

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute("Robots.txt",
                "robots.txt",
                new { controller = "robot", action = "index" });
            routes.MapRoute(
                name: "Localization",
                url: "{lang}/{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                constraints: new { lang = @"^[a-zA-Z]{2}$" }
            );
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
       routes.MapRoute(
        "NotFound",
        "{*url}",
        new { controller = "Error", action = "Error404" }
        );
            routes.MapMvcAttributeRoutes();
        }

我的webconfig


    
    
    
    
    
      
      
      
    
    
    
      
      
      
    
  
  
    
      
      
      
      
      
      
    
    
      
      
      
      
    
    
    
      
      
      
      
      
    
    
    
  

我希望在HandleCustomError类中处理错误,但问题是它直接进入我的错误控制器中的Error500操作。

奇怪的是错误仍然在elmah中记录。

它没有触发HandleCustomError类中的任何断点,错误是如何记录的?

谢谢

0
0 Comments

问题出现的原因是在路由配置中,没有正确处理404错误的情况。解决方法是添加一个名为"NotFound"的路由,将所有无法匹配的URL重定向到Error控制器的Error404动作。

具体代码如下:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        
        routes.MapRoute(
            name: "Localization",
            url: "{lang}/{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            constraints: new { lang = @"^[a-zA-Z]{2}$", controller = GetAllControllersAsRegex(), action = GetAllActionsAsRegex }
        );
        
        routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new { controller = GetAllControllersAsRegex(), action = GetAllActionsAsRegex() }
        );
        
        routes.MapRoute(
            "NotFound",
            "{*url}",
            new { controller = "Error", action = "Error404" }
        );
        
        routes.MapMvcAttributeRoutes();
    }
    
    private static string GetAllControllersAsRegex() 
    { 
        var controllers = typeof(MvcApplication).Assembly.GetTypes()
            .Where(t => t.IsSubclassOf(typeof(Controller))); 
        var controllerNames = controllers
            .Select(c => c.Name.Replace("Controller", "")); 
        return string.Format("({0})", string.Join("|", controllerNames)); 
    }
    
    private static string GetAllActionsAsRegex()
    {
        Assembly asm = Assembly.GetExecutingAssembly();
        var actions = asm.GetTypes()
                        .Where(type => typeof(Controller).IsAssignableFrom(type)) //filter controllers
                        .SelectMany(type => type.GetMethods())
                        .Where(method => method.IsPublic && !method.IsDefined(typeof(NonActionAttribute)))
                        .Select(x=>x.Name);
        return string.Format("({0})", string.Join("|", actions)); 
    }
}

以上是该问题的解决方案,可以从这个地址查看更多详情:https://stackoverflow.com/a/4668252

0