當 jquery.unobtrusive-ajax.js 遇上Web API

来源:http://www.cnblogs.com/CameronWu/archive/2016/12/10/6091512.html
-Advertisement-
Play Games

最近在熟悉Abp框架,其基於DDD領域驅動設計。。。前段可以繞過mvc直接調用根據app層動態生成的webapi,有點神奇~,Web API之前有簡單接觸過,WCF的輕量級版,一般用於做一寫開發性的服務介面,形式上類似與MVC,只是不渲染視圖(其他基於restful設計什麼的我不想去扯)。 因此我的 ...


最近在熟悉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。生命不息折騰不止


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [joy@localhost ~]$ java -version openjdk version "1.8.0_91" OpenJDK Runtime Environment (build 1.8.0_91-b14)OpenJDK 64-Bit Server VM (build 25.91-b14, ...
  • Linux通過系統硬體定時器以規律的間隔(由HZ度量)產生定時器中斷,每次中斷使得一個內核計數器的值jiffies累加,因此這個jiffies就記錄了系統啟動開始的時間流逝,然後內核據此實現軟體定時器和延時。 ...
  • 參考:https://wiki.archlinux.org/index.php/Installation_guide_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) 安裝準備 連接到網際網路 守護進程 dhcpcd 已被預設啟用來探測有線設備, 並會嘗試連接。如需驗證網路... ...
  • 中斷(interrupt)是指CPU在執行程式的過程中,出現了某些突發事件急待處理,CPU必須暫停執行當前的程式,轉去處理突發事件,處理完畢後CPU又返回原程式被中斷的位置並繼續執行。中斷服務程式的執行並不存在於進程上下文,因此,要求中斷服務程式的時間儘可能地短。因此,Linux在中斷處理中引入了頂... ...
  • 樹莓派是當前最火的嵌入計算平臺沒有之一,樹莓派可以給我們無數的想象,樹莓派的高性能、低功耗、低成本、可擴展性(最新的樹莓派原生支持WIFI和藍牙,這功能太贊了)深受大家的喜愛。雖然樹莓派到目前為止已經很好安裝系統了。但是要想方便的使用和部署開發的軟體還是比較麻煩的。 安裝環境的話,你的有樹莓派硬體( ...
  • 從此刻開始,我已封閉!概不接客! 像風一樣的男人,像風一樣的性格,無拘無束,不拘一格。那麼問題來了,當風遇到沙,不一定你是風兒,我是沙兒的纏纏綿綿,。也許是漫天黃沙,飛粒走石。如果我們期望擒住這漫天的塵埃,必須有強有力的手臂!那麼曬網、撒網、收網!讓他老實的封閉起來吧,永遠相依偎,阿拉! 讀在最前面 ...
  • Vs支持多種語言,但有可能創建項目時,預設的開發語言不是你需要的,比如:預設是Visual C++ 你可以通過"工具"----選項----導入和導出設置來修改。 引用: https://weblogs.asp.net/sreejukg/change-default-language-settings... ...
  • string 與 String,大 S 與小 S 之間有關字元串的秘密 字元串是 String 類型的對象,它的值是文本。 在內部,文本被存儲為 Char 對象的順序只讀集合。 C# 字元串末尾沒有以 null 結尾的字元;因此 C# 字元串可以包含任意數目的嵌入式 null 字元(“\0”)。 字 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...