我正在尝试以编程方式执行控制器的Action方法,但我不确定如何。
方案: 当我的ControllerFactory无法找到控制器时,我希望它能够在一个简单的自定义控制器上手动执行一个动作方法。我不想依赖于使用任何路由数据确定控制器/方法..因为该路由可能没有连线。
例如
// NOTE: Error handling removed from this example.
public class MyControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(Type controllerType)
{
IController result = null;
// Try and load the controller, based on the controllerType argument.
// ... snip
// Did we retrieve a controller?
if (controller == null)
{
result = new MyCustomController();
((MyCustomController)result).Execute404NotFound(); // <-- HERE!
}
return result;
}
}
..那个方法是......
public static void Execute404NotFound(this Controller controller)
{
result = new 404NotFound();
// Setup any ViewData.Model stuff.
result.ExecuteResult(controller.ControllerContext); // <-- RUNTIME
// ERROR's HERE
}
现在,当我运行控制器工厂找不到控制器时,我然后手动创建自己的基本控制器。然后,我在此控制器实例上调用扩展方法“Execute404NotFound
”。那很好..直到它运行ExecuteResult(..)
方法。为什么?控制器没有ControllerContext
数据。因此,ExecuteResult
崩溃,因为它需要一些ControllerContext
。
那么 - 有人可以帮我吗?看看我做错了什么。
记住 - &gt;我试图让我的控制器工厂手动/编程调用控制器上的方法,当然这将返回一个ActionResult。
请帮忙!
我也试图避免使用catchall或抛出在Application_Exception部分中处理的异常的更常见的解决方案。我不相信它们应该是处理这个问题的正确方法。考虑到我们知道问题是什么,因此我们应该在那里处理它。
答案 0 :(得分:1)
如果您手动创建控制器,则还必须手动为控制器提供上下文。
你走在正确的轨道上,但是你需要更多的代码来完成它。我自己经历了一段时间,并在thread on how to instantiate and fake a request to a controller上有一堆相当完整的代码。
如果您所做的只是想在404上运行一些代码,那么您的方法似乎有些过分。你不能做something like this吗?
答案 1 :(得分:1)
您可以从自定义控制器实例中抛出new HttpException(404, "Not found")
,该实例可以在global.asax中的Application_Error
中捕获并重定向到正确的页面:
protected void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
Response.Clear();
var httpException = exception as HttpException;
var routeData = new RouteData();
routeData.Values.Add("controller", "Error");
if(httpException != null )
{
switch( httpException.GetHttpCode() )
{
case 404:
// Page not found.
routeData.Values.Add("action", "HttpError404" );
break;
case 500:
// Server error.
routeData.Values.Add("action", "HttpError500" );
break;
default:
routeData.Values.Add("action", "General" );
break;
}
}
routeData.Values.Add("error", exception);
Server.ClearError();
var errorController = new ErrorController();
errorController.Execute(new RequestContext(
new HttpContextWrapper(Context), routeData ) );
}
答案 2 :(得分:0)
这里的问题是调用操作方法不是控制器工厂的工作。
除了Application_Error之外,我可以想到两种处理方法:
覆盖System.Web.Mvc.MvcHandler的ProcessRequest方法。在我看来,这是一个核选择。
如果找不到控制器,则返回404控制器,并且有多种方法可以直接执行此操作,覆盖控制器ExecuteCore方法,以便您的操作方法始终是一个名为。< / p>
答案 3 :(得分:0)
一个简单的简单
RedirectToAction("ActionName");
希望这有帮助吗?
答案 4 :(得分:0)
修改路线怎么样:
public class MyControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(Type controllerType)
{
IController result = null;
// Try and load the controller, based on the controllerType argument.
// ... snip
// Did we retrieve a controller?
if (controller == null)
{
result = new MyCustomController();
requestContext.RouteData.Values["action"] = "My404Action";
}
return result;
}
}