最近在熟悉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的更多相关文章

  1. ASP.NET Core中的jQuery Unobtrusive Ajax帮助器

    最近在ASP.NET Core下写文章管理系统时,准备在分页显示文章内容时,使用Ajax.网上找了篇帖文,简单翻一下,仅供自己查阅. 原链接:https://dotnetthoughts.net/jq ...

  2. AjaxHelper创建的ajax无效,JQuery直接方法post有效,原来是Microsoft.jQuery.Unobtrusive.Ajax错误,NuGet解决

    Get-Package -ListAvailable -Filter Microsoft.JQuery Microsoft.jQuery.Unobtrusive.Ajax –Version 3.2.0

  3. 使用jquery的ajax提交文件上传

    以前的项目大多的使用jquery的插件来进行文件上传,对于就只引用jquery而不使用插件来上传文件之前未有写过,最近项目里有写到和用到,就记录一下,以后方便查找. 提示:存在浏览器皆容问题,谨慎使用 ...

  4. jQuery的ajax实现文件上传大小限制

    用jquery的ajax实现简单的文件上传功能,并且限制文件大小,先上代码. <!DOCTYPE html> <html> <head> <meta char ...

  5. 通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用

    REFERENCE FROM : http://www.cnblogs.com/artech/archive/2012/07/04/Knockout-web-api.html 较之面向最终消费者的网站 ...

  6. $.ajax 跨域请求 Web Api

    WepApi确实方便好用,没有配置文件,一个apicontroller直接可以干活了.但今天用$.ajax跨域请求的时候总是获取不到数据,用fiddler一看确实抓到了数据,但回到$.ajax函数中, ...

  7. jQuery+php+ajax+PHPExcel实现上传excel文件导入数据库

            项目中需要批量导入数据,感觉这个需求以后也会经常用,必须总结分享下: 引入jquery的第三方表单插件: <scripttype="text/javascript&qu ...

  8. jquery 的ajax无刷新上传文件之后,页面还是会莫名的刷新-----解决办法

    文件上传用到全局数组: $_FILES 只需要把下面的 <button onclick="post()">提交</button> 改为 <input ...

  9. jquery 通过ajax FormData 对象上传附件

    之前上传附件都是用插件,或者用form表单体检(这个是很久以前的方式了),今天突发奇想,自己来实现附件上传,具体实现如下 html: <div>   流程图: <input id=& ...

随机推荐

  1. 【状压DP】bzoj1087 互不侵犯king

    一.题目 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上.下.左.右,以及左上.左下.右上.右下八个方向上附近的各一个格子,共8个格子. I ...

  2. 获得本机IP,并且将ip放在CIpAdress里

    char szHostName[MAX_PATH + 1]; gethostname(szHostName, MAX_PATH); //得到计算机名 hostent *p = gethostbynam ...

  3. 公钥私钥和RSA算法

    1, RSA算法原理(一) http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 2, RSA算法原理(二) http: ...

  4. psr的规范

    基本代码规范 本篇规范制定了代码基本元素的相关标准, 以确保共享的PHP代码间具有较高程度的技术互通性. 关键词 "必须"("MUST")."一定不可 ...

  5. GZDBHelperDemo 一

    1.新建Window窗体项目GZDBHelperDemo 2.从Nuget添加GZDBHelper引用 添加完成后会出现GZDBHelper的引用 3.添加数据库链接管理类 添加类库文件:Databa ...

  6. Linux截屏工具scrot用法详细介绍

    Scrot是Linux命令行中使用的截图工具,能够进行全屏.选取等操作,下面小编将针对Scrot截图工具的用法给大家做个详细介绍,通过操作实例来学习Scrot的使用.   在Linux中安装Scrot ...

  7. sprint2的总结及团队贡献分

    本次sprint做了订餐方法,用户可以通过搜索餐桌号进行点餐,查看已点的东西,也可以删除自己不想要的,当订单进入厨房时,厨房根据订单的顺序先后排列做餐,用户也可以通过扫描餐桌的二维码进行点餐. 148 ...

  8. .proto 文件转js 文件方法【nodejs】

    npm install protobufjs -g pbjs proto\IM.Other.proto -t js>proto\IM.Other.js

  9. 一篇讲Java指令重排和内存可见性的好文

    在这里: http://tech.meituan.com/java-memory-reordering.html 指令重排和内存可见性(缓存不一致)是两个不同的问题. volatile关键字太强,即阻 ...

  10. sublime-text3 3059基本配置

    1.下载安装官方版注册机语言包 参考安装: http://www.xiumu.org/note/sublime-text-3.shtml 2.插件 Package ControlConvertToUT ...