簡體   English   中英

基於ASP.NET WebAPI控件生成JS客戶端

[英]Generating a JS-client based on a ASP.NET WebAPI Controller

在使用RESTful API的現代Web項目中,我們經常會看到AJAX調用,就像下面的JavaScript文件一樣。

$.ajax({
    type: "POST",
    url: myapp.baseUrl + 'Api/Note',
    data: ko.mapping.toJSON(note),
    contentType: 'application/json',
}).done(function (response) {
    // do something
}).fail(function (jqxhr) {
    // do something else
});

我喜歡WebAPI,我喜歡Knockout,我喜歡將兩者結合在一起。 然而,這些AJAX調用非常冗長,包含了我並不感興趣的各種細節。相反,我創建了一個圍繞這些方法的包裝器:

myapp.api.saveNote(note)

但是,這仍然需要我實際編寫一個包含AJAX調用的包裝器。 我想知道你是否真的可以生成這些包裝器 本質上,我將為我的WebAPI生成一個基於JS的客戶端,類似於Java和.NET如何基於WSDL生成客戶端。

  1. 以前做過嗎?
  2. 有沒有其他方法可以將ASP.NET WebAPI和JavaScript結合在一起,而無需編寫大量的AJAX樣板代碼?
  3. 換句話說,是否存在基於ASP.NET WebAPI等服務器端接口創建JS接口的框架?

我已經看過amplifyJS,但這只能部分地解決問題。 我正在尋找一種解決方案,它實際上在我的解決方案中基於WebAPI控制器創建了一個接口。 如果這不存在,我會開始修補自己。 我已經有了一個WebAPIClientGenerator的想法,它使用反射迭代所有的ApiController

剛剛找到一個叫做ProxyApi的項目

ProxyApi是一個自動為ASP.NET MVC和WebApi控制器創建JavaScript代理對象的庫。

GitHub: https//github.com/stevegreatrex/ProxyApi

博客: http//blog.greatrexpectations.com/2012/11/06/proxyapi-automatic-javascript-proxies-for-webapi-and-mvc/

ProxyApi為我的解決方案生成了無效的JavaScript,其中包含一百多個單獨的WebAPI操作。 這可能是因為ProxyApi未涵蓋所有WebApi功能,例如自定義ActionName屬性。 此外,ProxyApi庫對我來說有點笨重。 必須有一種更有效的方法來做到這一點......

所以我決定看一下ASP.NET WebAPI源代碼,結果發現WebAPI內置了自我描述功能。 您可以從ASP.NET解決方案的任何位置使用以下代碼來訪問WebAPI元數據:

 var apiExplorer = GlobalConfiguration.Configuration.Services.GetApiExplorer(); 

根據apiExplorer.ApiDescriptions的輸出,我推出了自己的元數據提供程序:

 public class MetadataController : Controller { public virtual PartialViewResult WebApiDescription() { var apiExplorer = GlobalConfiguration.Configuration.Services.GetApiExplorer(); var apiMethods = apiExplorer.ApiDescriptions.Select(ad => new ApiMethodModel(ad)).ToList(); return PartialView(apiMethods); } public class ApiMethodModel { public string Method { get; set; } public string Url { get; set; } public string ControllerName { get; set; } public string ActionName { get; set; } public IEnumerable<ApiParameterModel> Parameters { get; set; } public ApiMethodModel(ApiDescription apiDescription) { Method = apiDescription.HttpMethod.Method; Url = apiDescription.RelativePath; ControllerName = apiDescription.ActionDescriptor.ControllerDescriptor.ControllerName; ActionName = apiDescription.ActionDescriptor.ActionName; Parameters = apiDescription.ParameterDescriptions.Select(pd => new ApiParameterModel(pd)); } } public class ApiParameterModel { public string Name { get; set; } public bool IsUriParameter { get; set; } public ApiParameterModel(ApiParameterDescription apiParameterDescription) { Name = apiParameterDescription.Name; IsUriParameter = apiParameterDescription.Source == ApiParameterSource.FromUri; } } } 

將此控制器與以下視圖結合使用:

 @model IEnumerable<Awesome.Controllers.MetadataController.ApiMethodModel> <script type="text/javascript"> var awesome = awesome || {}; awesome.api = { metadata: @Html.Raw(Json.Encode(Model)) }; $.each(awesome.api.metadata, function (i, action) { if (!awesome.api[action.ControllerName]) { awesome.api[action.ControllerName] = {}; } awesome.api[action.ControllerName][action.ActionName] = function (parameters) { var url = '/' + action.Url; var data; $.each(action.Parameters, function (j, parameter) { if (parameters[parameter.Name] === undefined) { console.log('Missing parameter: ' + parameter.Name + ' for API: ' + action.ControllerName + '/' + action.ActionName); } else if (parameter.IsUriParameter) { url = url.replace("{" + parameter.Name + "}", parameters[parameter.Name]); } else if (data === undefined) { data = parameters[parameter.Name]; } else { console.log('Detected multiple body-parameters for API: ' + action.ControllerName + '/' + action.ActionName); } }); return $.ajax({ type: action.Method, url: url, data: data, contentType: 'application/json' }); }; }); </script> 

控制器將使用ApiExplorer生成有關所有可用WebAPI操作的元數據。 該視圖將此數據呈現為JSON,然后執行一些JavaScript以將此數據轉換為實際的可執行JavaScript函數。

要使用這一點魔力,請 jQuery引用之后在Layout頁面的頭部插入以下行。

 @Html.Action(MVC.Metadata.WebApiDescription()) 

從現在開始,您可以使WebAPI調用如下所示:

 // GET: /Api/Notes?id={id} awesome.api.Notes.Get({ id: id }).done(function () { // .. do something cool }); // POST: /Api/Notes awesome.api.Notes.Post({ form: formData }).done(function () { // .. do something cool }); 

這個簡單的代理將自動區分查詢字符串參數和請求主體參數。 缺少參數或多個正文參數將生成錯誤以防止拼寫錯誤或其他常見的WebAPI開發錯誤。

我正在使用Swagger開源工具鏈NSwag for .NET:使用此工具,您可以為單個或多個Web API控制器生成TypeScript客戶端

在UI中

  1. 選擇Web API DLL
  2. 選擇控制器類
  3. 生成TypeScript客戶端代碼(在您的情況下,選擇JQueryCallbacksJQueryPromises模板)

看看http://nswag.org

僅供參考: TypeScript是一種可以轉換為JavaScript的語言

這個優秀的另一個項目可以讓你做你想要的。 此項目自動生成MVC和WebApi控制器的JavaScript代理。 而且,該項目涵蓋了WebApi功能,例如自定義ActionName屬性。 通過這個項目,您還將擁有Intellisense。
http://jsnet.codeplex.com/

智能感知的例子

window.test = function test() {
/// <summary>
///This example works.
///You have the Intellisense. It's great!!!
///No hard coded url.
///</summary>

//-- settings of ajax request.
var a = $dpUrlSet.Customer.Create.$action0.$AjaxSettings();

//-- your parameters of action method
a.data.name = "Scott Gu";
a.data.address = "Somewhere in Redmond";

//-- stringify
a.data = JSON.stringify(a.data);

//-- send ajax request
var xhr = $.ajax(a);

xhr.success(function (id) {
    /// <summary>Response of ajax request</summary>

    //-- settings of ajax request.
    var a = $dpUrlSet.Customer.Update.$action0.$AjaxSettings();

    //-- your parameters of action method
    a.data.id = id;
    a.data.name = "Scott Gu";
    a.data.address = "Somewhere in Seattle";

    //-- stringify
    a.data = JSON.stringify(a.data);

    //-- send ajax request
    var xhr = $.ajax(a);

});
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM