当 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=& ...
随机推荐
- Css样式基础
1.Css的语法 CSS的语法主要由两个部分组成,一个是选择器,一个是属性. 选择器又分为以下几种: 1.元素选择器:即Html标签去掉括号的就是元素 2.类选择器:所谓的类就是说class=“名称” ...
- zigbee学习之路(十二):zigbee协议原理介绍
一.前言 从今天开始,我们要正式开始进行zigbee相关的通信实验了,我所使用的协议栈是ZStack 是TI ZStack-CC2530-2.3.0-1.4.0版本,大家也可以从TI的官网上直接下载T ...
- libevent源码分析:eventop
eventop:定义了event_base使用的后端IO复用的一个统一接口 /** Structure to define the backend of a given event_base. */ ...
- 用CSS制作伪标签云
performance testing stress testing conformance testing acceptane testing smoke testing regression te ...
- 常用的logging配置
centos 6.5,python 2.6 习惯封装一个log.py #!/usr/bin/python # -*- coding: UTF-8 -*- import logging from log ...
- nginx :413 Request Entity Too Large
nginx出现这个问题的原因是请求实体太长了.一般出现种情况是Post请求时Body内容Post的数据太大了, 如上传大文件过大.POST数据比较多. 处理方法 在nginx.conf增加 clien ...
- 复旦大学2015--2016学年第二学期(15级)高等代数II期末考试第六大题解答
六.(本题10分) 设 $n$ 阶复方阵 $A$ 的特征多项式为 $f(\lambda)$, 复系数多项式 $g(\lambda)$ 满足 $(f(g(\lambda)),g'(\lambda))= ...
- apache域名本地映射
A: 第一步(搜索allow) 第二步(搜索vhost) 第三步(搜索rewrite) B: C:
- HDFS shell
bin/hdfs -help bin/hdfs dfs -mkdir -p /yfq/test/ bin/hdfs dfs -put /etc/profile /yfq/test/profile 上传 ...
- RabbitMQ 开启WEB管理
rabbitmq-plugins 插件管理器 1.开启rabbitmq management - WEB管理插件 # rabbitmq-plugins enable rabbitmq_manage ...