繁体   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