Подтвердить что ты не робот

Создание JS-клиента на основе контроллера ASP.NET WebAPI

В современных веб-проектах, использующих API RESTful, мы часто видим, что 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, я люблю Нокаут, и мне нравится связывать их вместе. Однако эти AJAX-вызовы довольно подробные и содержат всевозможные детали, которые мне не очень интересны. Поэтому вместо этого я создаю оболочку вокруг этих методов:

myapp.api.saveNote(note)

Однако это по-прежнему требует, чтобы я действительно написал оболочку, содержащую вызов AJAX. Мне было интересно, можете ли вы на самом деле создать эти обертки. По сути, я бы создал клиент JS для моего WebAPI, похожий на то, как Java и .NET могут генерировать клиентов на основе WSDL.

  • Это было сделано раньше?
  • Существуют ли другие способы связать ASP.NET WebAPI и JavaScript вместе без написания набора шаблонов AJAX?
  • Другими словами, существуют ли рамки для создания JS-интерфейсов на основе интерфейсов на стороне сервера, таких как ASP.NET WebAPI?

Я уже посмотрел на amplifyJS, но это лишь частично решает проблему. Я ищу решение, которое фактически создает интерфейс на основе WebAPI-контроллеров в моем решении. Если этого не будет, я начну заниматься себя. У меня уже есть идея для WebAPIClientGenerator, которая использует отражение для итерации по всем ApiController.

4b9b3361

Ответ 1

Просто нашел проект с именем: ProxyApi

ProxyApi - это библиотека, которая автоматически создает прокси-сервер JavaScript объекты для ваших ASP.NET MVC и контроллеров WebApi.

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.

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

Ответ 2

Этот отличный другой проект позволяет вам делать то, что вы просили. Этот poject автоматически генерирует прокси-серверы JavaScript для контроллеров MVC и WebApi. И этот проект охватывает функции WebApi, такие как пользовательские атрибуты ActionName. С этим проектом у вас будет также Intellisense.
http://jsnet.codeplex.com/

Пример Intellisense

window.test = function test() {
/// <summary>
///This example works.
///You have the Intellisense. It 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);

});
}

Ответ 3

Я работаю над инструментальной цепочкой Swagger с открытым исходным кодом NSwag для .NET. С помощью этого инструмента вы можете генерировать клиента TypeScript для одного или нескольких контроллеров Web API.

В пользовательском интерфейсе просто

  • Выберите DLL веб-API
  • Выберите классы контроллера
  • Создайте код клиента TypeScript (в вашем случае выберите шаблон JQueryCallbacks или JQueryPromises)

Посмотрите http://nswag.org

FYI: TypeScript - это язык, который переводится в JavaScript