У меня есть приложение MVC 2, и я хочу, чтобы все запросы возвращали json. Я переопределил HandleErrorAttribute
и AuthorizeAttribute
. Моя цель состоит в том, чтобы все ошибки (даже 403 и 404) возвращались в виде json.
Вот мой обработчик ошибок. ExceptionModel
— это простой класс, определяющий любую ошибку, возвращаемую моим приложением. Обработчик исключений — это класс, который переводит сведения об ошибке в форматированное сообщение электронной почты и отправляет его мне.
public class HandleErrorJsonAttribute : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
context.ExceptionHandled = true;
RaiseErrorSignal(context.Exception);
context.RequestContext.HttpContext.Response.ContentType = "application/json";
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(context.HttpContext.Response.Output, new ExceptionModel(context.Exception));
}
private static void RaiseErrorSignal(Exception ex)
{
IExceptionHandler handler = Resolve();
handler.HandleError(ex.GetBaseException());
}
private static IExceptionHandler Resolve()
{
return ServiceLocator.Locate<IExceptionHandler>();
}
}
Вот модель исключения для пояснения
public class ExceptionModel
{
public int ErrorCode { get; set; }
public string Message { get; set; }
public ExceptionModel() : this(null)
{
}
public ExceptionModel(Exception exception)
{
ErrorCode = 500;
Message = "An unknown error ocurred";
if (exception != null)
{
if (exception is HttpException)
ErrorCode = ((HttpException)exception).GetHttpCode();
Message = exception.Message;
}
}
public ExceptionModel(int errorCode, string message)
{
ErrorCode = errorCode;
Message = message;
}
}
и, наконец, мой настраиваемый атрибут авторизации. Я использую формы для аутентификации, но мне не нужно автоматическое перенаправление. Я просто хочу, чтобы ошибка отображалась на экране и прекращала дальнейшую обработку.
public class AuthorizeTokenAttribute : System.Web.Mvc.AuthorizeAttribute
{
public bool SuperAdminOnly { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool authorized = base.AuthorizeCore(httpContext);
if(!SuperAdminOnly)
return authorized;
if(!authorized)
return authorized;
return SessionHelper.UserIsSuperAdmin(httpContext.User.Identity.Name);
}
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
throw new HttpException(403, "Access Denied");
}
}
Все это отлично работает для большинства ошибок, но не хватает одной вещи. У меня есть такое действие контроллера.
[AuthorizeToken]
[HttpPost]
public JsonResult MyAction()
{
return new JsonResult();
}
Он отлично работает, когда вы отправляете по почте, но при получении я получаю необработанную ошибку 404.
Ошибка сервера в приложении '/'
Ресурс не может быть найден.
Описание: HTTP 404. Ресурс, который вы ищете (или одна из его зависимостей), мог быть удален, его имя было изменено или он временно недоступен. Просмотрите следующий URL-адрес и убедитесь, что он написан правильно.
Запрошенный URL-адрес: /MyController/MyAction
Информация о версии: Версия Microsoft .NET Framework: 4.0.30319; Версия ASP.NET: 4.0.30319.1
Это происходит при GET, что следует ожидать как поведение по умолчанию. Однако, как я могу справиться с этим условием, чтобы вместо этого я мог вернуть json, подобный этому
{"ErrorCode":404,"Message":"Page Not Found"}