基础上产生一个ASP.NET的WebAPI控制器一个JS-客户 [英] Generating a JS-client based on a ASP.NET WebAPI Controller

查看:170
本文介绍了基础上产生一个ASP.NET的WebAPI控制器一个JS-客户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用REST风格的API,我们经常看到的AJAX调用象那个下面我们围绕JavaScript的文件散落现代Web项目。

In modern web-projects that use RESTful API's we often see AJAX-calls like the one below littered around our JavaScript-files.

$.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,我爱淘汰赛,我喜欢绑两者结合起来。然而,这些AJAX的调用是相当冗长,并包含各种我不是真正感兴趣的细节,以便相反,我创建一个围绕这些方法的包装:

I love WebAPI, I love Knockout and I love tying the two together. However these AJAX-calls are quite verbose and contain all kinds of details that I am not really interested in. So instead, I create a wrapper around these methods:

myapp.api.saveNote(note)

然而,这仍然需要我实际编写包含AJAX调用的包装。我想知道,如果你能真正的生成这些包装。从本质上讲,我会生成一个基于JS的客户端我的WebAPI,类似于Java和.NET如何基于WSDL的生成客户端。

However this still requires me to actually write a wrapper containing the AJAX-call. I was wondering if you could actually generate these wrappers. In essence, I would be generating a JS-based client for my WebAPI, similar to how Java and .NET can generate clients based on WSDL's.


  1. 的这个人做过?

  2. 是否有其他方法,以配合ASP.NET的WebAPI和JavaScript在一起,而无需编写一堆AJAX样板code的?

  3. 换句话说,对于根据像ASP.NET的WebAPI?
  4. 服务器侧接口创建的JS-接口有框架
  1. Has this been done before?
  2. Are there other ways to tie ASP.NET WebAPI and JavaScript together without writing a bunch of AJAX boilerplate code?
  3. In other words, are there frameworks for creating JS-interfaces based on server-side interfaces like ASP.NET WebAPI?

我已经看了amplifyJS但这只是部分地解决了这个问题。我要寻找的实际创建基于在我的解决方案中的WebAPI控制器的接口解决方案。如果不存在,我将开始摆弄自己。我已经得到了一个想法 WebAPIClientGenerator 使用反射来遍历所有 ApiController

I've already looked at amplifyJS but this only partially solves the problem. I am looking for a solution that actually creates an interface based on the WebAPI-controllers in my solution. If this does not exist, I will start tinkering myself. I've already got an idea for a WebAPIClientGenerator that uses reflection to iterate over all ApiController's.

推荐答案

刚刚发现了一个名为: ProxyApi

ProxyApi是自动创建JavaScript代理库
  对象为你的ASP.NET MVC和的WebAPI控制器。

ProxyApi is a library that automatically creates JavaScript proxy objects for your ASP.NET MVC and WebApi Controllers.

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

博客:<一href=\"http://blog.greatrexpectations.com/2012/11/06/proxyapi-automatic-javascript-proxies-for-webapi-and-mvc/\">http://blog.greatrexpectations.com/2012/11/06/proxyapi-automatic-javascript-proxies-for-webapi-and-mvc/

ProxyApi产生无效的JavaScript我的解决方案,其中载百余单独的WebAPI的行动。这可能是因为ProxyApi并不包括所有的WebAPI的功能,如自定义的ActionName属性。此外,该ProxyApi库是在笨重的侧合我的口味了一下。必须有这样做更有效的方式...

ProxyApi generated invalid JavaScript for my solution which contained over a hundred separate WebAPI actions. This is probably because ProxyApi does not cover all WebApi features such as custom ActionName attributes. Moreover the ProxyApi library is a bit on the bulky side to my taste. There has to be a more efficient way to do this...

所以我决定去看看在ASP.NET的WebAPI源$ C ​​$ c和原来的WebAPI已自描述的功能内置到它。您可以使用下面的code从任何地方在你的ASP.NET解决方案来访问的WebAPI的元数据:

So I decided to take a look at the ASP.NET WebAPI source code and it turns out WebAPI has self-describing functionality built into it. You can use the following code from anywhere in your ASP.NET solution to access WebAPI metadata:

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

根据从 apiExplorer.ApiDescriptions 输出

,我滚我自己的元数据提供商:

Based on the output from apiExplorer.ApiDescriptions, I rolled my own metadata provider:

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;
        }
    }
}

一起使用此控制器以下几种观点:

Use this controller in conjunction with the following view:

@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>

控制器将使用所有可用的WebAPI行动 ApiExplorer 生成的元数据。该视图将呈现此数据为JSON,然后执行一些JavaScript将这些数据转换为实际的可执行的JavaScript函数。

The controller will use the ApiExplorer to generate metadata about all available WebAPI actions. The view will render this data as JSON and then execute some JavaScript to transform this data to actual executable JavaScript functions.

要使用魔法这一点,请将下面一行在布局网页的头部您的jQuery的参考。

To use this little bit of magic, insert the following line in the head of your Layout page after your jQuery reference.

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

从现在起,你可以让你的WebAPI调用看起来是这样的:

From now on, you can make your WebAPI calls look like this:

// 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       
});

这个简单的代理会自动区分请求体参数查询字符串参数。缺少参数或多个身体参数将产生错误prevent错字的或其他常见的WebAPI开发错误。

This simple proxy will automatically distinguish query string parameters from request body parameters. Missing parameters or multiple body-parameters will generate an error to prevent typo's or other common WebAPI development errors.

这篇关于基础上产生一个ASP.NET的WebAPI控制器一个JS-客户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆