最近在熟悉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. 移动APP项目优化

    团队计划:设计一款给用户提供就医帮助的安卓APP. 项目计划:两个月内团队成员共同开发完成此款APP,此款APP提供预约挂号,名医名院咨询,就医导航等功能. 角色职责:负责交互设计.UI界面设计.1. ...

  2. cocos2dx && Lua 环境配置

    需要的材料: 1.vs2013 2.python-2.7.3(2.7.x高于2.7的版本可能会出现错误) 3.Sublime Text 2(破解的) 4.cocos2dx-3.2 步骤: 1.安装vs ...

  3. tinkphp验证码的使用

    页面显示验证码: <div class="input-group has-feedback "> <input id="yzm" type=& ...

  4. spring mybatis 事务配置及使用

    转自:http://kinglixing.blog.51cto.com/3421535/723870

  5. Mybatis配置文件

    XML 映射配置文件 MyBatis 的配置文件包含了设置(settings)和属性(properties)信息. properties 这些属性都是可外部配置且可动态替换的,既可以在典型的 Java ...

  6. USB OTG插入检测识别

    转载请标注原文地址:http://blog.csdn.net/uranus_wm/article/details/9838847 一 USB引脚一般四根线,定义如下: 为支持OTG功能,mini/mi ...

  7. acvity和fragment通过广播联系

    今天我遇到一个问题,就是在activity中需要动态改变fragment中的控件,以前看到过可以在activity中得到fragment实例,然后修改控件: 今天实验了一个新的办法,通过新的办法,就是 ...

  8. 在windows上搭建react-native的android环境

    参考文档: http://facebook.github.io/react-native/docs/getting-started.html http://reactnative.cn/docs/0. ...

  9. fonts.googleapis.com 加载慢的解决方法

    把:fonts.googleapis.com 替换成 fonts.useso.com

  10. ~/.config/user-dirs.dirs【桌面设置】

    # This file is written by xdg-user-dirs-update # If you want to change or add directories, just edit ...