asp.net mvc3 利用ajax实现局部刷新,Asp.net MVC3扩展之Ajax异常处理特性

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

#region AjaxExceptionAttribute

/// ///Ajax Exception Handle Attribute/// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]

public class AjaxExceptionAttribute : ActionFilterAttribute, IExceptionFilter

{

/// ///Called when an exception occurs./// /// The filter context. public void OnException(ExceptionContext filterContext)

{

if (!filterContext.HttpContext.Request.IsAjaxRequest())

return;

filterContext.Result = AjaxError(filterContext.Exception.Message, filterContext);

//Let the system know that the exception has been handled filterContext.ExceptionHandled = true;

}

/// ///Ajaxes the error./// /// The message./// The filter context./// JsonResult protected JsonResult AjaxError(string message, ExceptionContext filterContext)

{

//If message is null or empty, then fill with generic message if (String.IsNullOrEmpty(message))

message = "Something went wrong while processing your request. Please refresh the page and try again.";

//Set the response status code to 500 filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

//Needed for IIS7.0 filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;

return new JsonResult

{

//can extend more properties Data = new AjaxExceptionModel () { ErrorMessage = message },

ContentEncoding = System.Text.Encoding.UTF8,

JsonRequestBehavior = JsonRequestBehavior.DenyGet

};

}

}

#endregion

/// ///AjaxExceptionModel/// public class AjaxExceptionModel

{

/// ///Gets or sets the error message./// /// ///The error message./// public string ErrorMessage { get; set; }

}

代码已有相关注释。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的单元测试,这里使用Moq类库:

[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开发有帮助。

你可能感兴趣的:(asp.net,mvc3,利用ajax实现局部刷新)