有没有一种方法可以区分特定的System.Web.HttpException?
有没有一种方法可以区分特定的System.Web.HttpException?
我有一些“坏孩子”用户,他们使用不存在的控制器调用我的网站。
例如www.myapp.com/.svn/
或www.myapp.com/wp-admin/
。
该应用程序基本上会抛出一个System.Web.HttpException
,该异常的ExceptionMessage
为:路径“...”的控制器未找到或未实现IController。
有没有一种稳定的方法来准确捕获这个“子”System.Web.HttpException
?(当然不能仅仅比较ExceptionMessage
的字符串)。
是否有任何子InnerException类型和/或一些指示确切异常的“代码”?
有时候我们想要在ASP.NET MVC应用程序中处理特定的System.Web.HttpException异常。下面的内容提供了一个解决方案:
我们可以创建一个自定义的IControllerFactory,可以通过继承DefaultControllerFactory来实现。该工厂的GetControllerInstance方法将在无法解析匹配的控制器时,使用null值作为controllerType参数进行调用。
在这一点上,我们已经超越了异常。
在这里,我们可以决定如何处理请求,例如记录和/或通过特定的控制器处理请求。
以下示例显示了如何使用ErrorController作为备用控制器,执行其Index操作方法。
class CustomControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { if (controllerType == null) { var routeData = requestContext.RouteData; routeData.Values["controller"] = "Error"; routeData.Values["action"] = "Index"; controllerType = typeof(ErrorController); } return base.GetControllerInstance(requestContext, controllerType); } }
可以在Global.asax.cs的Application_Start方法中安装自定义控制器工厂,如下所示:
ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
需要注意的是,这种方法无法防止在控制器存在但操作不存在的情况下出现相关异常。
例如,给定一个没有Ufo操作方法的HomeController,在URL“www.myapp.com/home/ufo”中将引发异常“A public action method 'ufo' was not found on controller '...HomeController'”。
解决这种情况的简单方法是在自定义基础控制器中重写HandleUnknownAction方法,所有的控制器都继承自该基础控制器。
以下示例显示了如何执行共享的Error视图(Shared\Error.cshtml)。
public abstract class BaseController : Controller { protected override void HandleUnknownAction(string actionName) { View("Error").ExecuteResult(ControllerContext); } }
问题原因:路由问题,没有匹配到指定的路由路径。
解决方法:尝试使用“catch all”路由,即当没有其他路由与请求的路径匹配时执行的路由。将“catch all”路由定义在最后,如下所示:
.NET Core MVC的配置如下:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapControllerRoute( name: "catch-all", pattern: "{*controller}", defaults: new { controller = "Home", action = "Index" }); });
在ASP.NET MVC中也可以参考这个讨论。
如果仍然无法加载Home/Index页面,可以考虑重定向到404页面。
在使用.net 4.6框架时,可以在Global.asax文件中使用全局异常捕获,代码如下:
protected void Application_Error(object sender, EventArgs e) { var ex = Server.GetLastError(); Debug.WriteLine(ex); var httpEx = ex as HttpException; var statusCode = httpEx?.GetHttpCode() ?? 500; Server.ClearError(); ... }
另外,也可以通过IIS来解决这个问题。可以通过添加一个映射规则(可以在web.config中完成)或者添加一个过滤器,甚至是一个防火墙规则来解决(因为我猜测您的应用程序是托管在IIS上的)。因为根据我的判断,这种探测扫描类型的请求并不值得在应用程序中记录 - 我认为它们应该在另一个层面上处理。