2013-08-13 19 views
23

We współczesnych projektach internetowych korzystających z interfejsów API RESTful często widzimy wywołania AJAX, takie jak te znajdujące się pod naszymi plikami JavaScript.Generowanie klienta JS w oparciu o kontroler ASP ASP.NET WebAPI

$.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 
}); 

Uwielbiam WebAPI, uwielbiam Knockout i uwielbiam wiązać te dwa elementy razem. Jednak te AJAX rozmowy są dość rozwlekły i zawiera wszystkie rodzaje informacji, że nie jestem naprawdę zainteresowany Zamiast więc tworzę owijkę wokół tych metod.

myapp.api.saveNote(note) 

Jednak to nadal wymaga ode mnie faktycznie napisać otoki zawierające wywołanie AJAX. Zastanawiam się, czy faktycznie można wygenerować te opakowania. W istocie generowałbym klienta opartego na JS dla mojego interfejsu WebAPI, podobnie jak Java i .NET mogą generować klientów na podstawie WSDL.

  1. Czy zrobiono to wcześniej?
  2. Czy istnieją inne sposoby powiązania interfejsu ASP.NET WebAPI i JavaScript bez pisania zestawu kodu standardowego AJAX?
  3. Innymi słowy, czy istnieją ramy do tworzenia interfejsów JS w oparciu o interfejsy po stronie serwera, takie jak ASP.NET WebAPI?

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

Odpowiedz

30

Wystarczy znaleźć projekt o nazwie: ProxyApi

ProxyApi to biblioteka, która automatycznie tworzy proxy obsługa JavaScript obiektów dla ASP.NET MVC i kontrolerów WebAPI.

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

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

ProxyApi generowane nieprawidłowy JavaScript na moim roztwór, który zawierał ponad sto odrębnych działań WebAPI. Jest tak prawdopodobnie dlatego, że ProxyApi nie obejmuje wszystkich funkcji WebApi, takich jak niestandardowe atrybuty ActionName. Co więcej, biblioteka ProxyApi znajduje się nieco na mojej wielkiej stronie. Musi być na to skuteczniejszy sposób ...

Postanowiłem więc rzucić okiem na kod źródłowy ASP.NET WebAPI i okazało się, że WebAPI ma wbudowaną samoopisującą się funkcjonalność. Możesz użyć następującego kodu z dowolnego miejsca w ASP.Rozwiązanie NET dostęp do metadanych WebAPI:

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

oparciu o wyjściu z apiExplorer.ApiDescriptions, przewróciłam własnego dostawcę Metadane:

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żywaj tego kontrolera w połączeniu z następującym zdaniem:

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

Sterownik użyje ApiExplorer do generowania metadanych o wszystkich dostępnych operacjach WebAPI. Widok wyrenderuje te dane jako JSON, a następnie uruchomi JavaScript, aby przekształcić te dane w rzeczywiste wykonywalne funkcje JavaScript.

Aby użyć tej odrobiny magii, wstaw następującą linię w nagłówku strony Układ, aby uzyskać odniesienie do jQuery.

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

Od tej chwili można dokonać połączenia WebAPI wyglądać następująco:

// 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 proxy automatycznie odróżnić parametry ciągu kwerendy z parametrami prośba ciała. Brakujące parametry lub wiele parametrów ciała wygeneruje błąd, aby zapobiec literom lub innym typowym błędom programowania WebAPI.

+1

Jak odzyskać Lista stosując metodę dostać? Wygląda na to, że zawsze oczekuje parametru ID –

+1

Awsome przy okazji! –

+1

Zorientowałem się, właśnie dodałem 'if (parametry typeof! = 'Undefined' && parametry!= null) {' instrukcja dotycząca bloku sprawdzania parametrów i dodana ' url = url.replace ("" {"" + parameter.Name + ""} "", "');' w innej części –

-1

pracuję na toolchain Swagger open source NSwag NET: Za pomocą tego narzędzia można wygenerować klienta maszynopis dla pojedynczego lub wielu kontrolerów Web API.

W interfejsie tylko

  1. Wybierz DLL Web API
  2. Wybierz klasy kontroler
  3. Generowanie kodu klienta maszynopisu (w przypadku wyboru szablonu JQueryCallbacks lub JQueryPromises)

Spójrz na http://nswag.org

FYI: TypeScript jest językiem, który zostaje przeniesiony do JavaScript

0

Ten znakomity inny projekt pozwala ci zrobić to, o co prosiłeś. Pojekt ten automatycznie generuje proxy JavaScript dla kontrolerów MVC i WebApi. Ten projekt obejmuje także funkcje WebApi, takie jak niestandardowe atrybuty ActionName. Za pomocą tego projektu otrzymasz także IntelliSense.
http://jsnet.codeplex.com/

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

}); 
}