zoukankan      html  css  js  c++  java
  • 当 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; }
        }
    View Code

    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。生命不息折腾不止

  • 相关阅读:
    2019高考数学理科Ⅱ卷解析版[解答题]
    对风说爱你
    佛教人生-伴侣
    【Echarts每天一例】-1
    算法中涉及的专业英语
    python--随机函数(random,uniform,randint,randrange,shuffle,sample)
    【linux shell系列--1】crontab命令
    【Python爬虫实战--3】html写正则表达式
    mysql启动参数 skip-grant-tables
    php通过反射执行某方法
  • 原文地址:https://www.cnblogs.com/CameronWu/p/6091512.html
Copyright © 2011-2022 走看看