最近在熟悉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. 利用JavaScript来实现省份—市县的二级联动

    所谓省-市二级联动是指当选择省份下拉选择框时,市县的下拉框会根据选择的省市而有相应的市县加载出来,如下图所示选择"上海市",城市的下拉选择框只会出现上海的市县: 这种二级联动非常常 ...

  2. Bootstrap相关总结

    1.工具提示 Tooltips js调用显示 $('#example').tooltip( { title:'这个是一个提示', }); $('#example').tooltip('show');

  3. 完整安装cocoaPods

    cocoaPods是一款xcode项目管理第三方库的工具 *ruby源码镜像下载:https://ruby.taobao.org/mirrors/ruby/*升级gem的版本: $sudo gem u ...

  4. js中文乱码怎么解决【转】

    ①.js 文件中文显示乱码Javascript文件XX.js编辑保存时有一种编码方案(如GBK),当打开文件的时候所用的编码(如UTF-8)和保存时的编码方案不一致时,则会出现中文显示乱码.解决方案: ...

  5. Selenium的PO模式(Page Object Model)|(Selenium Webdriver For Python)

            研究Selenium + python 自动化测试有近两个月了,不能说非常熟练,起码对selenium自动化的执行有了深入的认识. 从最初无结构的代码,到类的使用,方法封装,从原始函数 ...

  6. Mapreduce体系架构

    Mapreduce也采用master和slave的架构设计.Jobtracker负责作业的初始化和分配 与任务节点进行通信,协调整个作业的执行. 一个job分为两种task(map/reduce),包 ...

  7. 自己常用JS和JQ 函数

    //验证码函数 <button id="send">点击发送验证码</button> <script src="jquery.min.js& ...

  8. asp.net天网代码

    自己整理的asp.net中国天气网的城市代码 完整下载 case "北京": Code = "101010100"; break; case "海淀& ...

  9. solr 3.5.0 与 tomcat 7.0.5 整合配置

    1.将D:\software\lucene-3.6.0\apache-solr-3.5.0\example\solr下的文件拷贝到要作为服务器的位置(如:D:\lucene\solr\home),可以 ...

  10. lucene 索引 demo

    核心util /** * Alipay.com Inc. * Copyright (c) 2004-2015 All Rights Reserved/ */ package com.lucene.de ...