当 jquery.unobtrusive-ajax.js 遇上Web API
最近在熟悉Abp框架,其基于DDD领域驱动设计。。。前段可以绕过mvc直接调用根据app层动态生成的webapi,有点神奇~,Web API之前有简单接触过,WCF的轻量级版,一般用于做一写开发性的服务接口,形式上类似与MVC,只是不渲染视图(其他基于restful设计什么的我不想去扯)。
因此我的想法是页面用mvc view带model验证,提交操作使用jquery.unobtrusive-ajax.js自动收集form表单内容直接调webapi;因为人少做的东西不大,view model就是dto,这样配合jquery.validate.unobtrusive.js基本可以不用写前端js验证,部分代码如下:
@model ArticleEdit
@section styles{
<link href="~/Content/bootstrap-tagsinput.css" rel="stylesheet" />
}
<form class="form-horizontal" action="/api/services/app/article/CreateAndGetIdAsync" method="post" novalidate="novalidate" data-ajax="true" data-ajax-success="AjaxCallback" data-ajax-method="Post" role="form">
<div class="form-group">
@Html.LabelFor(o => o.Title, new { @class = "col-sm-2 control-label" })
<div class="col-sm-10">
@Html.TextBoxFor(o => o.Title, new { @class = "form-control" })
@Html.ValidationMessageFor(o => o.Title)
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
@Html.LabelFor(o => o.Keywords, new { @class = "col-sm-2 control-label" })
<div class="col-sm-10">
@Html.TextBoxFor(o => o.Keywords, new { @class = "form-control", data_role = "tagsinput", placeholder = "Tab键或英文','分割" })
@Html.ValidationMessageFor(o => o.Keywords)
</div>
</div>
<div class="form-group">
@Html.LabelFor(o => o.Description, new { @class = "col-sm-2 control-label" })
<div class="col-sm-10">
@Html.TextBoxFor(o => o.Description, new { @class = "form-control" })
@Html.ValidationMessageFor(o => o.Description)
</div>
</div>
<div class="form-group">
@Html.LabelFor(o => o.Content, new { @class = "col-sm-2 control-label" })
<div class="col-sm-10">
@Html.TextAreaFor(o => o.Content, new { style = "height:300px;" })
@Html.ValidationMessageFor(o => o.Content)
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-primary" type="submit">保存内容</button>
<button class="btn btn-white" type="reset">重置</button>
</div>
</div>
</form>
@section scripts{
//jquery.js & bootstrap.js here
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Scripts/bootstrap-tagsinput.js"></script>
<script type="text/javascript">
function AjaxCallback(data) {
console.log("新增数据id:"+data.result);
}
</script>
}
ArticleEdit:
[AutoMap(typeof(Article))]
public class ArticleEdit
{
[Display(Name = "文章标题")]
[Required(ErrorMessage = "{0} 不能为空")]
[MaxLength(Article.MaxTitleLength, ErrorMessage = "{0} 不能超过{1}个字符")]
public string Title { get; set; } /// <summary>
/// 关键词
/// </summary>
[Display(Name = "关键词")]
[StringLength(Article.MaxKeywordsLength, ErrorMessage = "{0} 不能超过{1}个字符")]
public string Keywords { get; set; } /// <summary>
/// 简介描述
/// </summary>
[Display(Name = "简介描述")]
[StringLength(Article.MaxDescriptionLength, ErrorMessage = "{0} 不能超过{1}个字符")]
public string Description { get; set; } /// <summary>
/// 正文内容
/// </summary>
[Display(Name = "正文内容")]
[DataType(DataType.MultilineText)]
[AllowHtml]
public string Content { get; set; }
}
Abp应用层对应接口:
Task<int> CreateAndGetIdAsync(ArticleEdit input); //这里会生成一个post api
这样一切都大功告成了……
////////////////////////////////////////////////////////////////////////////////////////////////////////我是华丽的分割线//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
才怪呢 。
解决思路:
应用层接收不到数据。经过反复测试:改为调用mvc post action正常,说明view内容没写错,将ArticleEdit替换成string等简单类型正常,根据abp官网的有关dynamic api说明 安装了WebApi测试工具 Swagger用它来调用该api发现也正常;这让我更疑惑了,难道是ajax提交的datatype不对,再尝试直接用 jquery ajax 测试: $.post("http://****/CreateAndGetIdAsync",{Title:"",Keywords:"",Discription:"",Content:""},function(){console.log("新增数据id:"+data.result);}); 失败,***************最后发现正确的传参格式如下:
$.ajax({
type: "method",
url: "http://****/CreateAndGetIdAsync",
data: '{Title:"",Keywords:"",Discription:"",Content:""}',//注意这里是字符串
dataType: "json",
contentType: "application/json",//$.post()没法用就是因为没法设置这个属性
success: function (response) {
console.log("新增数据id:"+data.result);
}
});
问题找到了,再次被webapi坑了一把,它的ModelBinder没有MVC的强大(详细https://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api),mvc的ModelBinder可以同时从同时从url及post body查找数据绑定复杂数据类型的model,至于微软没什么不把这两个弄成一样还是因为webapi是基于restful设计¥@…&。
解决办法:一种是替换掉webapi默认的ModelBinder,相信直接拿mvc的ModelBinder照抄过来注册给它就能搞定,暂时不想用这种破坏其风格的方式,我软这样设计肯定有他的道理;我用的另外一种是去改jquery.unobtrusive-ajax.js的源代码判断webapi请求,幸好该文件代码很少(这也不算是一种优雅的方式),改动如下:
1.在jquery.unobtrusive-ajax.js之前引入jquery.serialize-object.js (一个自动序列化表单的插件,也可以参照 这里 自己写,jquery的 serializeArray() 的格式不对;后面发现这个插件也不是很符合asp.net mvc model在数组生成input name命名方式)。
2.找到jquery.unobtrusive-ajax.js发出ajax请求的地方 $.ajax(options); 改为:
if (method == "POST" && element.getAttribute("data-ajax-webapi")) { options.contentType = "application/json;charset=utf-8"; options.data = $(element).serializeJSON(); }//这句是添加的
$.ajax(options);
3.最后使用的时候给第一段代码中的form加上 data-ajax-webapi="true" 。
总结:
1。webapi的设计跟mvc还是很大区别,包括其他很多地方,自己还需要多多熟悉
2。webapi理应该支持$.post()的json参数传递啊~~~~
3。有时间还是学学angularjs吧。
4。生命不息折腾不止
当 jquery.unobtrusive-ajax.js 遇上Web API的更多相关文章
- ASP.NET Core中的jQuery Unobtrusive Ajax帮助器
最近在ASP.NET Core下写文章管理系统时,准备在分页显示文章内容时,使用Ajax.网上找了篇帖文,简单翻一下,仅供自己查阅. 原链接:https://dotnetthoughts.net/jq ...
- AjaxHelper创建的ajax无效,JQuery直接方法post有效,原来是Microsoft.jQuery.Unobtrusive.Ajax错误,NuGet解决
Get-Package -ListAvailable -Filter Microsoft.JQuery Microsoft.jQuery.Unobtrusive.Ajax –Version 3.2.0
- 使用jquery的ajax提交文件上传
以前的项目大多的使用jquery的插件来进行文件上传,对于就只引用jquery而不使用插件来上传文件之前未有写过,最近项目里有写到和用到,就记录一下,以后方便查找. 提示:存在浏览器皆容问题,谨慎使用 ...
- jQuery的ajax实现文件上传大小限制
用jquery的ajax实现简单的文件上传功能,并且限制文件大小,先上代码. <!DOCTYPE html> <html> <head> <meta char ...
- 通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用
REFERENCE FROM : http://www.cnblogs.com/artech/archive/2012/07/04/Knockout-web-api.html 较之面向最终消费者的网站 ...
- $.ajax 跨域请求 Web Api
WepApi确实方便好用,没有配置文件,一个apicontroller直接可以干活了.但今天用$.ajax跨域请求的时候总是获取不到数据,用fiddler一看确实抓到了数据,但回到$.ajax函数中, ...
- jQuery+php+ajax+PHPExcel实现上传excel文件导入数据库
项目中需要批量导入数据,感觉这个需求以后也会经常用,必须总结分享下: 引入jquery的第三方表单插件: <scripttype="text/javascript&qu ...
- jquery 的ajax无刷新上传文件之后,页面还是会莫名的刷新-----解决办法
文件上传用到全局数组: $_FILES 只需要把下面的 <button onclick="post()">提交</button> 改为 <input ...
- jquery 通过ajax FormData 对象上传附件
之前上传附件都是用插件,或者用form表单体检(这个是很久以前的方式了),今天突发奇想,自己来实现附件上传,具体实现如下 html: <div> 流程图: <input id=& ...
随机推荐
- 在Excel中制作雷达图
雷达图的作用 雷达图是专门用来进行多指标体系比较分析的专业图表.从雷达图中可以看出指标的实际值与参照值的偏离程度,从而为分析者提供有益的信息.雷达图一般用于成绩展示.效果对比量化.多维数据对比等等,只 ...
- 查找二维数组list[][]中的最大的子数组的和
之前做过最大一维数组子数组的和的题目,现在将数组扩展成二维: 代码如下: #include<iostream> #define null -858993460 using namespac ...
- mysql查询一个小知识点,查询结果是空与查询出错是不一样的
$conn = new mysqli(....); $sql = ""; $query = $conn->query($sql); 这里,如果查询正常,有数据返回,那么$qu ...
- Python if 和 for 的多种写法
a, b, c = 1, 2, 3 [对比Cpp里:c = a >b? a:b]这个写法,Python只能常规的空行,缩进吗? 人生苦短,我用python,下面介绍几种if的方便的方法. 1.常 ...
- linux服务器下安装nodejs
http://www.cnblogs.com/kevinchou/p/5405540.html
- 远程调试 ASP.NET MVC 项目
Visual Studio 支持从一台计算机到另一台设备的远程调试.进行远程调试时,主机可以是任何支持 Visual Studio 的平台.远程设备可以是 x86.x64 或 ARM 平台. 本文将指 ...
- 在SQL SERVER中获取表中的第二条数据
在SQL SERVER中获取表中的第二条数据, 思路:先根据时间逆排序取出前2条数据作为一个临时表,再按顺时排序在临时表中取出第一条数据 sql语句如下: select top 1 * from(se ...
- img和css背景的选择
在什么情况下更适合使用HTML IMG标签来显示一个图像,而不是一个CSS有背景图像,反之亦然? 如下场景使用img标签比较合适: 1.如果图像是等内容的一部分或图表或人(真正的人,而不是股票图人), ...
- 转 unity 优化
最近研究U3D开发,个人认为,精通一种新的技术,最快最好的方法就是看它的document,而且个人习惯不喜欢看中文的资料,原汁原味的东西是最正确的,一翻译过来很多东西就都不那么准确了.于是通读了uni ...
- Struts2 简介
回顾Struts2的使用过程,网上搜的教程多多少少都会有点问题,重新记录下创建过程,方便查阅. 1.下载Struts2的jar包 下载地址:http://archive.apache.org/dist ...