2012-03-10 82 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

相關問題