当ASP.NET MVC邂逅jQuery.Ajax提交数组的示例分析
本篇文章给大家分享的是有关当ASP.NET MVC邂逅jQuery.Ajax提交数组的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
当ASP.NET MVC 通过JQuery的Ajax 提交数组时,MVC的model binder机制就失效了。我们不得不在Controller里面编写自定义代码,将Request提交的数据转换成需要的数据类型。这个过程往往枯燥乏味。下面以某项目的实际例子来演示如何解决这个问题,提供一个通用的解决方案。
需求描述
当用户更改了配置,需要Ajax提交到服务器。
前端代码:
var items = []; $("input:checked").each(function () { items.push($(this).val()); }); $.ajax({ type: 'post', url: 'Configure/Status', data: { answers: items } });
后端代码:
public enum AnswerStatus { Correct = 1, Incorrect = 2, Unanswered = 3 } [HttpPost] public ActionResult Status(IList<AnswerStatus> answers) { …. }
这里的answers始终为null. 神器fiddler出场,发现用JQuery.Ajax 提交Array的数据,提交的时候始终会在名称后面加上”[]”, 问题就出在这里。
根据发现的结果修改代码:
[HttpPost] public ActionResult Status(IList<AnswerStatus> answers) { answers = Request.Form.GetValues(“answers[]”).Select(d => d.ToEnum<AnswerStatus>(AnswerStatus.Unanswered).ToList(); }
虽然这样能够通过解决我的问题,但每次提交Array都要这样手工解析request,视乎一夜回到石器时代了。其实我们马上会想到MVC 的Mode Binder。
尝试进行***次重构:
public class AnswerModelBinder : IModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { return controllerContext.RequestContext.HttpContext.Request.Form.GetValues(“answers[]”).Select(d => d.ToEnum<AnswerStatus>(AnswerStatus.Unanswered).ToList(); } }
硬编码味道太重,换个类型又得重写,工作量跟之前比还视乎增加了,只是Controller变得优雅了。这种浪费青春又耗电的做法还是不符合要求。
进行第二次重构 : DefaultModelBinder 出场
***的DefaultModelBinder,能够绑定任何类型,可惜就是client传过来的name后面多加了”[]”,导致DefaultModelBinder无法准确解析。那我们能不能欺骗DefaultModelBInder呢?
查看ModelBindingContext发现有一个ModelName属性,感觉有点像要绑定的参数的名称,调试跟踪发现ModelName确实就是参数的名称,那我们修改ModelName让他跟client传过来的name保持一致是否就能够充分发挥DefaultModelBinder。于是动手创建一个JQAjaxModelBinder
并继承自DefaultModelBinder:
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if(bindingContext.ModelType.IsEnumerable()) { var key = bindingContext.ModelName + "[]"; var valueResult = bindingContext.ValueProvider.GetValue(key); if(valueResult != null && !string.IsNullOrEmpty(valueResult.AttemptedValue)) { bindingContext.ModelName = key; } } return base.BindModel(controllerContext, bindingContext); }//如何使用自定义ModelBinder。该方法是Controller里面的Action public ActionResult Status([ModelBinder(typeof(ModelBinder.JQAjaxModelBinder))] IList<AnswerStatus> answers) { … }
这时,Controller里面的Status (Action)方法已经能够正确得到前端传来的数据。并且还是强类型的。当然很多程序员都是懒惰的,笔者也是这其中一份子。笔者连Parameter前面的参数([ModelBinder(typeof(ModelBinder.JQAjaxModelBinder))])都不想写,那我们直接在ModelBinders里面注册吧。其实注册的时候也有点麻烦,必须设定Type,我那能提前知道有那些类型啊。干脆将JQAjaxModelBinder设置成默认的ModerBinder,一劳永逸,再也没有烦心事情了。
ModelBinder不同注册方法
通过在Action方法的参数前面添加ModelBinder标签,上文则是采用的这种方法。
数据类型上面添加ModelBinder标签
[ModelBinder(typeof(ModelBinder.JQAjaxModelBinder))] Public class User { }
通过ModelBinders注册
ModelBinders.Binders.Add(typeof(User), new ModelBinder.JQAjaxModelBinder());
设置默认的ModerBinder
ModelBinders.Binders.DefaultBinder = new ModelBinder.JQAjaxModelBinder();
后记: 当我们在开发的时候,经常做重复的事情,当一件事情重复多次后,我们就需要停下来认真思考,能不能将这些事情抽象出来,做一个通用的解决方案呢?一劳永逸的解决这些问题。
以上就是当ASP.NET MVC邂逅jQuery.Ajax提交数组的示例分析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341