2012-03-10 83 views
1

我有一个ActionFilterAttribute,如果请求无效,则会引发错误。如何在从属性抛出控制器时捕获错误?

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class AjaxOnlyAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if((!filterContext.HttpContext.Request.IsAjaxRequest() || 
      !filterContext.HttpContext.Request.IsXMLHttpRequest()) && 
      (!filterContext.HttpContext.Request.IsLocal)) 
     { 
      throw new InvalidOperationException("This operation can only be accessed via Ajax requests."); 
     } 
    } 
} 

现在在我的控制,我想捕捉错误,并把它传递给视图

[AjaxOnly] 
public JsonpResult List() 
{ 
    try 
    { 
    var vimeoService = new VimeoService(); 
    var videos = vimeoService.GetVideosFromChannel(this._vimeoChannelId); 

    return this.Jsonp(videos); 
    } 
    catch (Exception ex) 
    { 
     var err = new ErrorsModel() { ErrorMessage = ex.Message }; 
     return this.Jsonp(err, false); 
    } 
} 

现在因为属性控制器动作火灾之前运行,我绝不能“抓“控制器中的错误,从而我无法将错误传递给视图。

我该如何做到这一点?

回答

1

好了,所以简单的答案(TL;博士)是你需要处理在整洁有序的方式对所有的例外。这不是在每个控制器操作中单独执行,因为我(作为虚拟)最初是计划的。

取而代之,我已经连接了我的Global Application_Error方法来处理所有错误,并使用单个index操作将它们打到错误控制器。

private void Application_Error() 
    { 
     // setup the route to Send the error to 
     var routeData = new RouteData(); 
     routeData.Values.Add("action", "Index"); 

     // Execute the ErrorController instead of the intended controller 
     IController errorController = new Controllers.ErrorController(); 
     errorController.Execute(new RequestContext(new HttpContextWrapper(this.Context), routeData)); 

     // After the controller executes, clear the error. 
     this.Server.ClearError(); 
    } 

我的错误控制器是非常基本的。基本上它需要抛出最后一个错误,并将相关数据推送给客户端(在我的情况下,将其序列化为JsonP)。

public class ErrorController : Controller 
{ 
    public JsonpResult Index() 
    { 
     var lastError = Server.GetLastError(); 
     var message = lastError.Message; 
     int statusCode; 

     // If the lastError is a System.Exception, then we 
     // need to manually set the Http StatusCode. 
     if (lastError.GetType() == typeof(System.Exception)) 
     { 
      statusCode = 500; 
     } 
     else 
     { 
      var httpException = (HttpException)this.Server.GetLastError(); 
      statusCode = httpException.GetHttpCode(); 
     } 

     // Set the status code header. 
     this.Response.StatusCode = statusCode; 

     // create a new ErrorsModel that can be past to the client 
     var err = new ErrorsModel() 
      { 
       ErrorMessage = message, 
       StatusCode = statusCode 
      }; 
     return this.Jsonp(err, false); 
    } 
} 

我们一点点的鲁棒性添加到我的应用程序中,我创建的自定义Exceptions对应于HTTP StatusCodes。现在

public sealed class UnauthorizedException : HttpException 
{ 
    /// <summary> 
    /// Similar to 403 Forbidden, but specifically for use when authentication is possible but has failed or not yet been provided 
    /// </summary> 
    public UnauthorizedException(string message) : base((int)StatusCode.Unauthorized, message) { } 
} 

我可以在我的应用程序抛出异常(如适用),他们都将得到回升,并发送到客户端以在容易控制的方式。

下面是抛出其中一个错误的示例。

if (!User.Identity.IsAuthenticated) 
    throw new UnauthorizedException("You are not authorized"); 
+1

这是我遇到过的MVC中的错误处理的第一个例子,我可以复制+粘贴并实际工作。荣誉给你。 – Graham 2012-10-03 15:08:36

相关问题