在控制器上找不到捕捉动作方法

时间:2016-06-01 16:07:02

标签: c# asp.net-mvc

在我的MVC应用程序中,我正在尝试处理Application_Error HttpApplication方法中的错误。在那个处理程序中我这样做:

Exception exc = Server.GetLastError();

我正在使用Ninject,它提供了自己的DefaultControllerFactory,这将为不存在的控制器抛出一个异常,我可以很容易地抓住它:

if (exc is MyApp.Web.App_Start.ControllerNotFoundException)
{
    Response.Clear();
    Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
    Server.ClearError();
    log = false;
}

哪个效果很好。我不想记录这些。

问题在于控制器确实存在,但操作不存在。例如,我有人打了:admin/config.php。我实际上有一个AdminController因此不会导致ControllerNotFoundException,它会给我一个HttpException的文字:

"A public action method 'config.php' was not found on controller 'MyApp.Web.Controllers.AdminController'."

但我不是解析文本以检测它是HttpException这种类型而不是其他类型,有没有办法告诉这是一个未找到的动作而不是其他的动作?

1 个答案:

答案 0 :(得分:4)

我相信这会做你想要的。您可以继承默认的AsyncControllerActionInvoker类,然后将其注入。

public class DependencyResolverForControllerActionInvoker : IDependencyResolver
{
    private readonly IDependencyResolver innerDependencyResolver;

    public DependencyResolverForControllerActionInvoker(IDependencyResolver innerDependencyResolver)
    {
        if (innerDependencyResolver == null)
            throw new ArgumentNullException("innerDependencyResolver");

        this.innerDependencyResolver = innerDependencyResolver;
    }

    public object GetService(Type serviceType)
    {
        if (typeof(IAsyncActionInvoker).Equals(serviceType) || typeof(IActionInvoker).Equals(serviceType))
        {
            return new MyAsyncControllerActionInvoker();
        }

        return this.innerDependencyResolver.GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.innerDependencyResolver.GetServices(serviceType);
    }
}

public class MyAsyncControllerActionInvoker : AsyncControllerActionInvoker
{
    public override bool InvokeAction(ControllerContext controllerContext, string actionName)
    {
        try
        {
            return base.InvokeAction(controllerContext, actionName);
        }
        catch (HttpException ex)
        {
            // Handle unknown action error
        }
    }

    public override bool EndInvokeAction(IAsyncResult asyncResult)
    {
        try
        {
            return base.EndInvokeAction(asyncResult);
        }
        catch (HttpException ex)
        {
            // Handle unknown action error
        }
    }
}

以下是InvokeActionEndInvokeAction方法的链接,因此您可以尝试确定如何最好地处理它引发的任何错误。

用法

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        // Decorate the current dependency resolver 
        // (make sure to do this last if using a DI container - 
        // or alternatively register your type with the DI container)
        DependencyResolver.SetResolver(
            new DependencyResolverForControllerActionInvoker(DependencyResolver.Current));
    }
}

替代

您可以创建一个基本控制器并覆盖HandleUnknownAction方法以获得类似(但更紧密耦合)的结果。