Generowanie klienta JS na podstawie ASP.NET Kontroler WebAPI

W nowoczesnych projektach internetowych, które używają RESTful API, często widzimy wywołania AJAX, takie jak te poniżej, zaśmiecone wokół naszych plików 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
});

Kocham WebAPI, kocham nokaut i uwielbiam wiązać je ze sobą. Jednak te połączenia AJAX są dość gadatliwe i zawierają wszelkiego rodzaju szczegóły, które tak naprawdę nie jestem zainteresowany. Zamiast tego tworzę wrapper wokół tych metod:

myapp.api.saveNote(note)

Jednak to nadal wymaga ode mnie napisania wrappera zawierającego wywołanie AJAX. Byłem zastanawiając się, czy mógłbyś rzeczywiście wygenerować te opakowania . Ogólnie rzecz biorąc, generowałbym klienta opartego na JS dla mojego WebAPI, podobnie jak Java i. NET mogą generować klientów opartych na WSDL.

    Czy robiono to już wcześniej?
  1. czy są inne sposoby na Wiązanie ASP.NET WebAPI i JavaScript razem bez pisania kodu AJAX boilerplate?
  2. innymi słowy, czy istnieją frameworki do tworzenia interfejsów JS opartych na interfejsach po stronie serwera jak ASP.NET WebAPI?

Już patrzyłem na amplifyJS, ale to tylko częściowo rozwiązuje problem. Szukam rozwiązania, które faktycznie stworzy interfejs oparty na kontrolerach WebAPI w moim rozwiązaniu. Jeśli to nie istnieje, zacznę sam majstrować. Mam już pomysł na WebAPIClientGenerator, który używa refleksji do iteracji wszystkich ApiController.

Author: Martin Devillers, 2013-08-13

3 answers

właśnie znalazłem projekt o nazwie: ProxyApi

ProxyApi jest biblioteką, która automatycznie tworzy Proxy JavaScript przedmioty dla Twojego ASP.NET Kontrolery MVC i WebApi.

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

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

ProxyApi wygenerował nieprawidłowy JavaScript dla mojego rozwiązania, które zawiera ponad sto oddzielnych akcji WebAPI. Dzieje się tak prawdopodobnie dlatego, że ProxyApi nie obejmuje wszystkich funkcji WebApi, takich jak własne atrybuty ActionName. Ponadto biblioteka ProxyApi jest trochę nieporęczna w moim guście. Musi być na to bardziej efektywny sposób...

Więc postanowiłem rzucić okiem na ASP.NET kod źródłowy WebAPI i okazuje się, że WebAPI ma wbudowaną funkcjonalność samoopisującą. Możesz użyć poniższego kodu z dowolnego miejsca w swoim ASP.NET roztwór do dostęp do Metadanych WebAPI:

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

Na podstawie danych wyjściowych z apiExplorer.ApiDescriptions, zwijałem własnego dostawcę metadanych:

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

Użyj tego kontrolera w połączeniu z następującym widokiem:

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

Kontroler użyje ApiExplorer do wygenerowania metadanych o wszystkich dostępnych akcjach WebAPI. Widok renderuje te dane jako JSON, a następnie wykonuje niektóre JavaScript, aby przekształcić te dane do rzeczywistych funkcji wykonywalnych JavaScript.

Aby użyć tej odrobiny magii, włóż następująca linia w nagłówku strony układu po referencji jQuery.

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

Od teraz możesz sprawić, by Twoje połączenia z WebAPI wyglądały tak:

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

Ten prosty serwer proxy automatycznie odróżni parametry ciągu zapytania od parametrów ciała żądania. Brakujące parametry lub wiele parametrów body-parameters wygeneruje błąd, aby zapobiec typo lub innym częstym błędom programistycznym WebAPI.

 30
Author: Martin Devillers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-22 20:49:28

Ten doskonały kolejny projekt pozwala Ci zrobić to, o co prosiłeś. Ten obiekt automatycznie generuje proxy JavaScript dla kontrolerów MVC i WebApi. Ten projekt obejmuje funkcje WebApi, takie jak niestandardowe atrybuty nazwy akcji. Dzięki temu projektowi będziesz miał również Intellisense.
http://jsnet.codeplex.com /

Przykład Intellisense

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

});
}
 0
Author: Alexandre Tran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-30 10:23:32

Pracuję nad Swagger open-source toolchain NSwagdla.NET: za pomocą tego narzędzia możesz wygenerować klienta TypeScript dla jednego lub wielu kontrolerów Web API.

In the UI just

  1. wybierz bibliotekę DLL Web API
  2. Wybierz klasy kontrolerów
  3. Wygeneruj kod klienta TypeScript (w Twoim przypadku wybierz szablon JQueryCallbacks LUB JQueryPromises)

Spójrz na http://nswag.org

FYI: maszynopis jest językiem, który jest transpilowany do JavaScript

 -1
Author: Rico Suter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-04 18:06:43