Reflection ASP.NET MVC-使用反射查找控制器是否存在

Reflection ASP.NET MVC-使用反射查找控制器是否存在,reflection,asp.net-mvc-2,routing,constraints,Reflection,Asp.net Mvc 2,Routing,Constraints,我花了很长时间才弄明白如何正确实现404重定向 如果我使用下面的 <HandleError()> _ Public Class BaseController : Inherits System.Web.Mvc.Controller ''# do stuff End Class 请注意控制器存在约束?我需要做的是使用反射来发现控制器是否存在 谁能帮我填空吗 Public Class ControllerExistsConstraint : Implements IRouteConst

我花了很长时间才弄明白如何正确实现404重定向

如果我使用下面的

<HandleError()> _
Public Class BaseController : Inherits System.Web.Mvc.Controller
''# do stuff
End Class
请注意
控制器存在约束
?我需要做的是使用反射来发现控制器是否存在

谁能帮我填空吗

Public Class ControllerExistsConstraint : Implements IRouteConstraint

    Public Sub New()
    End Sub

    Public Function Match(ByVal httpContext As System.Web.HttpContextBase, ByVal route As System.Web.Routing.Route, ByVal parameterName As String, ByVal values As System.Web.Routing.RouteValueDictionary, ByVal routeDirection As System.Web.Routing.RouteDirection) As Boolean Implements System.Web.Routing.IRouteConstraint.Match


        ''# Bah, I can't figure out how to find if the controller exists


End Class

我也想知道这对性能的影响。。。反思有多重?如果太多,有更好的方法吗?

为什么不在web.config文件中用自定义错误捕获它们,并避免一系列反射

<customErrors mode="On">   
    <error statusCode="404" redirect="/Error/NotFound" />
</customErrors>

我有一个C#解决方案,希望能有所帮助。我剽窃了其中的一些代码,尽管就我个人而言,我找不到它的来源。如果有人知道,请让我知道,这样我可以添加到我的评论

此解决方案不使用反射,但它查看所有应用程序错误(异常)并检查是否为404错误。如果是,那么它只是将当前请求路由到另一个控制器。尽管我在任何方面都不是专家,但我认为这个解决方案可能比反思更快。不管怎样,这是解决方案,它将进入您的Global.asax.cs

    protected void Application_Error(object sender, EventArgs e)
    {
        Exception exception = Server.GetLastError();

        // A good location for any error logging, otherwise, do it inside of the error controller.

        Response.Clear();
        HttpException httpException = exception as HttpException;
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "YourErrorController");

        if (httpException != null)
        {
            if (httpException.GetHttpCode() == 404)
            {
                routeData.Values.Add("action", "YourErrorAction");

                // We can pass the exception to the Action as well, something like
                // routeData.Values.Add("error", exception);

                // Clear the error, otherwise, we will always get the default error page.
                Server.ClearError();

                // Call the controller with the route
                IController errorController = new ApplicationName.Controllers.YourErrorController();
                errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
            }
        }
    }
那么控制器应该是

public class YourErrorController : Controller
{
    public ActionResult YourErrorAction()
    {
        return View();
    }
}

这是一个非常相似的问题,但我喜欢你的替代方法

我认为作为动态过滤器的反射可能会对性能造成太大影响,但我认为我有一个更好的方法-您可以通过正则表达式过滤允许的操作:

// build up a list of known controllers, so that we don't let users hit ones that don't exist
var allMvcControllers = 
    from t in typeof(Global).Assembly.GetTypes()
    where t != null &&
        t.IsPublic &&
        !t.IsAbstract &&
        t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
        typeof(IController).IsAssignableFrom(t)
    select t.Name.Substring(0, t.Name.Length - 10);

// create a route constraint that requires the controller to be one of the reflected class names
var controllerConstraint = new
{
    controller = "(" + string.Join("|", allMvcControllers.ToArray()) + ")"
};

// default MVC route
routes.MapRoute(
    "MVC",
    "{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional },
    controllerConstraint);

// fall back route for unmatched patterns or invalid controller names
routes.MapRoute(
    "Catch All", 
    "{*url}",
    new { controller = "System", action = "NotFound" });
然后,我在我的基础
控制器上添加了一个额外的方法:

protected override void HandleUnknownAction(string actionName)
{
    this.NotFound(actionName).ExecuteResult(this.ControllerContext);
}
在本例中,
BaseController.NotFound
处理有效控制器上缺少的操作

因此,最后:

  • {site}/无效
    -由新的基于反射的筛选器找到
  • {site}/valid/notAnAction
    -由
    HandleUnknownAction
  • {site}/valid/action/id
    -由id的签入代码找到(与前面一样)
  • {site}/valid/action/id/extraPath
    -通过不匹配任何路由而找到,但与catch all匹配

我想这就是404场景的全部内容:-)

因为在我的问题中我说“原始URL保持不变,“NotFound”控制器被加载。”。我不想重定向到找不到的页面,尽管这不是问题的答案。这确实解决了我的问题。我会奖励赏金,但不是马克作为答案。关于“比反射更快”这一点,你可能是对的。这很好,因为我不必一直打电话给我的
控制器resistsconstraint
。我没有注意到你还有关于这个问题的帖子。我应该回答那个问题。也许你可以把另一个的解决方案链接到这里。你对赏金积分太好了:)。你说得对。。。我确实先问了另一个问题,但出于某种原因,我问这个问题的方式导致了最少的活动。我想我应该更好地描述这个问题,问一个更直接的问题。好的,我用你的答案回答了我的另一个问题。信用到期时给予信用;-)-如果你想在那里编辑它,我会给你+10复选标记。
protected override void HandleUnknownAction(string actionName)
{
    this.NotFound(actionName).ExecuteResult(this.ControllerContext);
}