博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Asp.net MVC3扩展之Ajax异常处理特性
阅读量:7079 次
发布时间:2019-06-28

本文共 6041 字,大约阅读时间需要 20 分钟。

      在Asp.net MVC 3 Web开发中,我们会大量使用各种ajax请求,针对ajax请求如何结何server端如何做异常处理呢?我们可以扩展ActionFilterAttribute,实现一个Ajax异常处理特性。假设您是使用JQuery脚本开发来实现Ajax,看代码:

1: #region AjaxExceptionAttribute
2: /// 
3: /// Ajax Exception Handle Attribute
4: /// 
5: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
6: public class AjaxExceptionAttribute : ActionFilterAttribute, IExceptionFilter
7: {
8:     /// 
9:     /// Called when an exception occurs.
10:     /// 
11:     /// The filter context.
12:     public void OnException(ExceptionContext filterContext)
13:     {
14:         if (!filterContext.HttpContext.Request.IsAjaxRequest())
15:             return;
16: 
17:         filterContext.Result = AjaxError(filterContext.Exception.Message, filterContext);
18: 
19:         //Let the system know that the exception has been handled
20:         filterContext.ExceptionHandled = true;
21:     }
22: 
23:     /// 
24:     /// Ajaxes the error.
25:     /// 
26:     /// The message.
27:     /// The filter context.
28:     /// 
JsonResult
29:     protected JsonResult AjaxError(string message, ExceptionContext filterContext)
30:     {
31:         //If message is null or empty, then fill with generic message
32:         if (String.IsNullOrEmpty(message))
33:             message = "Something went wrong while processing your request. Please refresh the page and try again.";
34: 
35:         //Set the response status code to 500
36:         filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
37: 
38:         //Needed for IIS7.0
39:         filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
40: 
41:         return new JsonResult
42:         {
43:             //can extend more properties
44:             Data = new AjaxExceptionModel () { ErrorMessage = message },
45:             ContentEncoding = System.Text.Encoding.UTF8,
46:             JsonRequestBehavior = JsonRequestBehavior.DenyGet
47:         };
48:     }
49: }
50: #endregion
51: 
52: /// 
53: /// AjaxExceptionModel
54: /// 
55: public class AjaxExceptionModel
56: {
57:     /// 
58:     /// Gets or sets the error message.
59:     /// 
60:     /// 
61:     /// The error message.
62:     /// 
63:     public string ErrorMessage { get; set; }
64: }

代码已有相关注释。AjaxExceptionModel您完全可以自定义更多的属性,然后在Controller或Action上增加这个特性。 像下面这个HomeController有一个YouKnow的Action,这里为演示我们故意throw一个Exception:

[AjaxException]
public class HomeController : BaseController
{
[HttpPost]
public ActionResult YouKnow(FormCollection fc)
{
throw new ArgumentNullException("YouKnow method: fc should not be null");
}
}

接下来看HTML与JQuery:

 

 

ajax post

 
JQuery的全局AjaxError配置,可参考
$("#errorh3info").ajaxError(function (event, request, settings) {
$(this).append("
  • settings.url:" + settings.url + "
  • ");
    $(this).append("
  • request.status:" + request.status + "
  • ");
    $(this).append("
  • request.statusText:" + request.statusText + "
  • ");
     
    //request.responseText
    if (request.responseText != "") {
    var jsonValue = jQuery.parseJSON(request.responseText);
    $(this).append("
  • ErrorMessage:" + jsonValue.ErrorMessage + "
  • ");
    }
    });

    给button增加一个Post请求:

    $('#inputajax1').click(function () {
    $.post('/Home/YouKnow/'
    , { id: 1 }
    , function (data) {
    $('div#right-box.data').html(data);
    });
    });

    这时View上将显示, 我们将看到ErrorMessage是JSON对象的属性:

    settings.url:/Home/YouKnow/ request.status:500 request.statusText:error ErrorMessage:Value cannot be null. Parameter name: YouKnow method: fc should not be null

    当然也可以这样:

    //ajax post when throw an exception at server side
    $('#inputajax2').click(function () {
    $.ajax({
    type: "POST",
    url: "/Home/YouKnow2",
    data: "fail=1",
    dataType: "json",
    error: function (xhr, status, error) {
    // Show the error
    $('#lblMethodError').append(xhr.responseText);
    $('#lblMethodError').show();
    },
    success: function (data, textSuccess) {
    // show the success message
    $('#lblMethodSuccess').show();
    }
    });
    });

    这时View上,比上面那个请求多显示一条信息, 这是因为我们这里定义了自己error处理callback.

    {"ErrorMessage":"Value cannot be null.\r\nParameter name: YouKnow method: fc should not be null"}

    当我们请求一个不存在Action时呢:

    //request undefined url
    $('#inputajax3').click(function () {
    $.post('/Home/YouKnow2233/'
    , { id: 1 }
    , function (data) {
    $('div#right-box.data').html(data);
    });
    });

    页面上将显示:

    settings.url:/Home/YouKnow2233/ request.status:0 request.statusText:error

    最后我们来看这个ActionFilter的单元测试,这里使用类库:

    [TestMethod]
    public void Test_Native_AjaxExceptionAttribute()
    {
    //arrange
    var header = new System.Collections.Specialized.NameValueCollection();
    header.Add("X-Requested-With", "XMLHttpRequest");
     
    var mockRequest = new Mock
    ();
    mockRequest.SetupGet(http => http.Headers).Returns(header);
     
    var mockResponse = new Mock
    ();
     
    var mockHttpContext = new Mock
    ();
    mockHttpContext.SetupGet(c => c.Request).Returns(mockRequest.Object);
    mockHttpContext.SetupGet(c => c.Response).Returns(mockResponse.Object);
     
    var context = mockHttpContext.Object;
    var exceptonContextMock = new Mock
    ();
    exceptonContextMock.SetupGet(ac => ac.HttpContext).Returns(context);
    string errorStr="error";
    exceptonContextMock.SetupGet(ec => ec.Exception).Returns(new AggregateException(errorStr));
     
    //act
    var ajaxAttribute = new AjaxExceptionAttribute();
    var exceptionContext = exceptonContextMock.Object;
    ajaxAttribute.OnException(exceptionContext);
     
    //verify
    mockRequest.VerifyAll();
    mockResponse.VerifyAll();
    mockHttpContext.VerifyAll();
    exceptonContextMock.VerifyAll();
     
    //assert
    var jsonResult = exceptionContext.Result as JsonResult;
    Assert.IsNotNull(jsonResult.Data);
    Assert.IsTrue(exceptionContext.HttpContext.Request.IsAjaxRequest());
    Assert.AreEqual((jsonResult.Data as AjaxExceptionModel).ErrorMessage, errorStr);
    Assert.AreEqual(JsonRequestBehavior.DenyGet, jsonResult.JsonRequestBehavior);
    Assert.AreEqual(typeof(AggregateException), exceptionContext.Exception.GetType());
     
    }

    上面的UnitTest我们Mock HttpContext,HttpRequest,HttpResponse来实现对ActionFilter的测试。
    希望您Web开发有帮助。

    作者:
    出处:
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    该文章也同时发布在我的独立博客中-。

    你可能感兴趣的文章
    排错之网络映射缓存凭证记录导致备份计划任务失败
    查看>>
    vSphere Data Protection 6.1.2部署与配置
    查看>>
    PfSense基于BSD的软件防火墙的安装、配置与应用
    查看>>
    使用shell和expect一键批量分发SSH密钥脚本
    查看>>
    ESXI上的vm虚拟机文件被锁定无法POWER ON的问题处理
    查看>>
    《统一沟通-微软-培训》-2-部署-反向代理-2-配置初始的部署设置
    查看>>
    Exchange Server 2013部署系列之五:在Windows8上部署管理工具
    查看>>
    “3.15”曝二维码安全漏洞 瑞星呼吁重视WiFi安全
    查看>>
    关于团队建设的访谈
    查看>>
    Openstack:一根中国稻草-【中国IC微专栏】2016.4.28
    查看>>
    Lync 小技巧-51-Lync 2013-不加域-客户端-1-下载-证书-信任链
    查看>>
    安装Exchange Server 2013
    查看>>
    Win7部署基础知识(1):部署的基本概念与方法论
    查看>>
    州小吃”小程序正式发布,酷客多全程技术支持
    查看>>
    理解思科IPS系统的virtual sensor
    查看>>
    MySQL5.6创建用户密码不再明文显示在binlog二进制日志文件里
    查看>>
    Lync 小技巧-28-同一环境同一客户端不同的结果
    查看>>
    正在变味的网络红包
    查看>>
    共享汽车不是一盘好生意,入坑需谨慎!
    查看>>
    ***组网不用愁之2-总部路由器配置
    查看>>