【问题标题】:Reporting errors from Ajax invoked PartialView methods in MVC从 Ajax 报告错误在 MVC 中调用 PartialView 方法
【发布时间】:2012-01-04 02:15:49
【问题描述】:

如果正常页面加载错误,我可以通过Error 视图和HandleErrorInfo 模型向用户报告异常详细信息。

如果 ajax 调用期待 Json 结果错误,我可以显式处理错误并将详细信息传递给客户端:

public JsonResult Whatever()
{
    try
    {
        DoSomething();
        return Json(new { status = "OK" });
    }
    catch (Exception e)
    {
        return Json(new { status = "Error", message = e.Message });
    }
}

所以,我的问题是,我看不到任何方法来报告从 Ajax 调用到返回局部视图的操作的错误详细信息。

$.ajax({
    url: 'whatever/trevor',
    error: function (jqXHR, status, error) {
        alert('An error occured: ' + error);
    },
    success: function (html) {
        $container.html(html);
    }
});

这只会报告对客户端没有帮助的 Http 错误代码(例如 Internal Server Error)。是否有一些巧妙的技巧可以传递成功的 PartialView (html) 结果错误消息?

显式评估来自ViewResult 的html 并将其作为Json 对象的一部分连同状态一起返回似乎太臭了。是否有处理这种情况的既定模式?

【问题讨论】:

    标签: ajax asp.net-mvc-3 error-handling asp.net-mvc-partialview


    【解决方案1】:

    创建一个覆盖版本的 HandleErrorAttribute (JsonHandleErrorAttribute ?) 并在您的 json 操作中添加 [JsonHandleError]。

    看看asp.net mvc [handleerror] [authorize] with JsonResult?中的AjaxAuthorizeAttribute

    【讨论】:

      【解决方案2】:

      控制器动作:

      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 错误订阅 global error handler,这样我们就不必为所有 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);
          }
      });
      

      【讨论】:

      • 你对 MVC 的了解让我再次震惊。我没有完全理解这里的几点,但我发现我可以通过在全局过滤器中注册的 ajax 过滤器更简单地实现类似的东西。它似乎工作正常。谢谢。
      • 请注意,如果您使用上面的代码来捕获 404 并显示自定义页面,您可能需要添加 Response.TrySkipIisCustomErrors = true(我相信只有 .net 3.5 及更高版本)跨度>
      • 像魅力一样工作,太棒了
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      相关资源
      最近更新 更多