根据某些条件动态重新路由所有请求

Re-route all requests dynamically based on some condition

我有一个 ASP.Net MVC 5 网站,需要在某些情况下将所有传入请求动态重新路由到特定控制器和操作。

例如,如果数据库不存在,我想将所有传入的请求重新路由到特定的 Action,例如 SetupController.MissingDatabase:

public class SetupController : Controller
{
    public ActionResult MissingDatabase()
    {
        return View();
    }
}

我想为每个请求检查此条件(数据库是否存在)。最好在管道的早期执行检查,而不是在每个 Action 的顶部或在每个 Contoller 中执行检查。当然,如果传入请求被路由到 SetupController.MissingDatabase 我不需要执行检查或重新路由请求。

完成此任务的最佳方法是什么?

具体来说,ASP.Net MVC 5 管道中的哪个位置是执行此类检查的最佳位置,我将如何重新路由传入请求?

您可以创建一个操作过滤器来执行此操作并将其注册到应用程序级别,以便为所有传入请求执行它。

public class VerifySetupIsGood : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var dbExists=VerifyDataBaseExists();
        if ( ! dbExists)
        {
            var values = new Dictionary<string, string> {{"action", "MissingDatabase"}, 
                                                         {"controller", "Setup"}};

            var routeValDict = new RouteValueDictionary(values);
            //redirect the request to MissingDatabase action method.
            context.Result = new RedirectToRouteResult(routeValDict);
        }
    }
}

假设 VerifyDataBaseExists() 执行您的代码以检查数据库是否存在并且 return 一个布尔值。现在在 global.asax.cs

Application_Start 事件中注册这个动作过滤器
protected void Application_Start()
{      
    //Existing code goes here

    GlobalFilters.Filters.Add(new VerifySetupIsGood());
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

    //Existing code goes here
}

如果需要,您也可以更新操作过滤器以检查请求的子集。您可以从 ActionExecutingContext 的对象获取请求 url 并使用它来进行检查。