上一篇使用ModelBinder解决了asp.net Mvc下接收使用jQuery异步提交复杂对象参数的问题;
在asp.net Mvc框架下,解决问题的方法并不是唯一的,只要在Action方法真正本调用之前,对Context.ActionParameters对象中的参数进行处理,就能解决此问题。
下面的代码是使用ActionFilter处理参数。
首先,把要提交的对象参数序列化成字符串,再异步提交:
/*按钮点击事件*/
$("#btn_post_test").click(function() {
var data = {
UserId: "11",
UserName: { FirstName: "323", LastName: "2323" },
Keys: ["xiaoming", "xiaohong"]
};
$.post("Home/TestFilter", { user: String.toSerialize(data) }, function(text) {
alert(String.toSerialize(text));
}, "json");
});
$("#btn_post_test").click(function() {
var data = {
UserId: "11",
UserName: { FirstName: "323", LastName: "2323" },
Keys: ["xiaoming", "xiaohong"]
};
$.post("Home/TestFilter", { user: String.toSerialize(data) }, function(text) {
alert(String.toSerialize(text));
}, "json");
});
在Action添加属性,对参数进行预处理:
/// <summary>
/// Filter处理参数测试方法
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
[JsonFilter(typeof(User), "user")]
public ActionResult TestFilter(User user)
{
//输入接收到的参数的json字符串
return Json(user, JsonRequestBehavior.AllowGet);
}
/// Filter处理参数测试方法
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
[JsonFilter(typeof(User), "user")]
public ActionResult TestFilter(User user)
{
//输入接收到的参数的json字符串
return Json(user, JsonRequestBehavior.AllowGet);
}
Filter代码,对参数反序列化,转换成对象:
/// <summary>
/// json参数处理类
/// </summary>
public class JsonFilterAttribute : ActionFilterAttribute
{
/// <summary>
/// 构造方法
/// </summary>
/// <param name="type">参数类型,如果是数组请输入数组元素类型</param>
/// <param name="modelName">参数名称</param>
public JsonFilterAttribute(Type type, string modelName)
{
DataType = type;
ModelName = modelName;
}
protected Type DataType { get; set; }
protected string ModelName { get; set; }
/// <summary>
/// 参数转换处理
/// </summary>
/// <param name="filterContext"></param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//获取客户端提交的字符串
string json = filterContext.HttpContext.Request.Form[ModelName];
//判断提交对象是object对象还是Array对象
if (json.StartsWith("{") && json.EndsWith("}"))
{
//object对象反序列化
JObject jsonBody = JObject.Parse(json);
JsonSerializer js = new JsonSerializer();
object obj = js.Deserialize(jsonBody.CreateReader(), DataType);
filterContext.ActionParameters[ModelName] = obj;
}
if (json.StartsWith("[") && json.EndsWith("]"))
{
//Array对象反序列化
ArrayList list = new ArrayList();
JArray jsonRsp = JArray.Parse(json);
if (jsonRsp != null)
{
for (int i = 0; i < jsonRsp.Count; i++)
{
JsonSerializer js = new JsonSerializer();
object obj = js.Deserialize(jsonRsp[i].CreateReader(), DataType);
list.Add(obj);
}
}
filterContext.ActionParameters[ModelName] = list.ToArray(DataType);
}
}
}
/// json参数处理类
/// </summary>
public class JsonFilterAttribute : ActionFilterAttribute
{
/// <summary>
/// 构造方法
/// </summary>
/// <param name="type">参数类型,如果是数组请输入数组元素类型</param>
/// <param name="modelName">参数名称</param>
public JsonFilterAttribute(Type type, string modelName)
{
DataType = type;
ModelName = modelName;
}
protected Type DataType { get; set; }
protected string ModelName { get; set; }
/// <summary>
/// 参数转换处理
/// </summary>
/// <param name="filterContext"></param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//获取客户端提交的字符串
string json = filterContext.HttpContext.Request.Form[ModelName];
//判断提交对象是object对象还是Array对象
if (json.StartsWith("{") && json.EndsWith("}"))
{
//object对象反序列化
JObject jsonBody = JObject.Parse(json);
JsonSerializer js = new JsonSerializer();
object obj = js.Deserialize(jsonBody.CreateReader(), DataType);
filterContext.ActionParameters[ModelName] = obj;
}
if (json.StartsWith("[") && json.EndsWith("]"))
{
//Array对象反序列化
ArrayList list = new ArrayList();
JArray jsonRsp = JArray.Parse(json);
if (jsonRsp != null)
{
for (int i = 0; i < jsonRsp.Count; i++)
{
JsonSerializer js = new JsonSerializer();
object obj = js.Deserialize(jsonRsp[i].CreateReader(), DataType);
list.Add(obj);
}
}
filterContext.ActionParameters[ModelName] = list.ToArray(DataType);
}
}
}
使用Filter处理参数与ModelBinder的方式有一个不一致的地方,由于Filter不能使用泛型,接收数组参数是,不能转换成泛型数组对象IList<T>,只能使用普通数组方式。
或许有更好的方式可以解决,但是我没发现。