Действие контроллера:
public ActionResult Foo()
{
// Obviously DoSomething could throw but if we start
// trying and catching on every single thing that could throw
// our controller actions will resemble some horrible plumbing code more
// than what they normally should resemble: a.k.a being slim and focus on
// what really matters which is fetch a model and pass to the view
// Here you could return any type of view you like: JSON, HTML, XML, CSV, PDF, ...
var model = DoSomething();
return PartialView(model);
}
Затем мы определяем глобальный обработчик ошибок для нашего приложения:
protected void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
var httpException = exception as HttpException;
Response.Clear();
Server.ClearError();
if (new HttpRequestWrapper(Request).IsAjaxRequest())
{
// Some error occurred during the execution of the request and
// the client made an AJAX request so let's return the error
// message as a JSON object but we could really return any JSON structure
// we would like here
Response.StatusCode = 500;
Response.ContentType = "application/json";
Response.Write(new JavaScriptSerializer().Serialize(new
{
errorMessage = exception.Message
}));
return;
}
// Here we do standard error handling as shown in this answer:
// http://stackoverflow.com/q/5229581/29407
var routeData = new RouteData();
routeData.Values["controller"] = "Errors";
routeData.Values["action"] = "General";
routeData.Values["exception"] = exception;
Response.StatusCode = 500;
if (httpException != null)
{
Response.StatusCode = httpException.GetHttpCode();
switch (Response.StatusCode)
{
case 404:
routeData.Values["action"] = "Http404";
break;
case 500:
routeData.Values["action"] = "Http500";
break;
}
}
IController errorsController = new ErrorsController();
var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
errorsController.Execute(rc);
}
Вот как может выглядеть ErrorsController, используемый в глобальном обработчике ошибок. Возможно, мы могли бы определить некоторые пользовательские представления для действий 404 и 500:
public class ErrorsController : Controller
{
public ActionResult Http404()
{
return Content("Oops 404");
}
public ActionResult Http500()
{
return Content("500, something very bad happened");
}
}
Тогда мы могли бы подписаться на глобальный обработчик ошибок для всех ошибок AJAX, чтобы нам не приходилось повторять этот код обработки ошибок для всех запросов AJAX, но при желании мы могли бы повторить его:
$('body').ajaxError(function (evt, jqXHR) {
var error = $.parseJSON(jqXHR.responseText);
alert('An error occured: ' + error.errorMessage);
});
И, наконец, мы запускаем AJAX-запрос к действию контроллера, который, как мы надеемся, вернет частичное HTML в этом случае:
$.ajax({
url: 'whatever/trevor',
success: function (html) {
$container.html(html);
}
});