如果请求无效,我有一个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);
}
}
现在因为属性在控制器动作触发之前运行,我永远无法“捕获”控制器中的错误,因此我无法将错误传递给视图。
我怎样才能做到这一点?
答案 0 :(得分:1)
好的,所以简短的回答( tl; dr )就是你需要以干净有序的方式处理所有异常。这并不是每个控制器动作都单独进行的,因为我(作为假人)最初计划。
相反,我已经连接了我的全局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);
}
}
现在为我的应用添加一点健壮性,我创建了与Http StatusCodes对应的自定义Exceptions
。
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");