2016-08-08 41 views
6

Mam potrzebę utworzenia usługi sieciowej REST. W tym celu postępowałem zgodnie z tym samouczkiem: http://www.odata.org/blog/how-to-use-web-api-odata-to-build-an-odata-v4-service-without-entity-framework/REST webservice WebAPI - utwórz punkt końcowy na podstawie wielu obiektów

Wszystko działało dobrze, dodałem do tego BasicAuth, działa jak rękawiczka.

Teraz moje pytanie ... Ta usługa będzie działała z możliwymi wersjami, więc zdecydowaliśmy się na wdrożenie systemów wersji. Chcemy również, aby aplikacje klienckie wybierały bazę danych, którą chcą wykonywać swoje działania. Do tego, myśleliśmy, że byłoby miło mieć URI z tego stylu:

http://localhost/Connection/northwind/API/1/DataRow

Jest to kod, który mam. Kiedyś miałem zdefiniowany tylko podmiot DataRow. Teraz zdefiniowałem również encję API i połączenie.

Jak zaimplementować URI/punkt końcowy tak, jak chcę? To jest kod, który mam do tej pory.

pliku: WebApiConfig.cs

using Integration.Models; 
using Microsoft.OData.Edm; 
using System.Web.Http; 
using System.Web.OData.Batch; 
using System.Web.OData.Builder; 
using System.Web.OData.Extensions; 
using Integration.Controllers; 
namespace Integration 
{ 
    public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      config.MapODataServiceRoute("odata", null, GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer)); 
      config.EnsureInitialized(); 
     } 
     private static IEdmModel GetEdmModel() 
     { 
      //GlobalConfiguration.Configuration.Filters.Add(new BasicAuthenticationFilter()); // basicAutenthentication 
      ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); 
      builder.Namespace = "Integration"; 
      builder.ContainerName = "DefaultContainer"; 
      builder.EntitySet<DataRow>("DataRow"); 
      builder.EntitySet<Connection>("Connection"); 
      builder.EntitySet<API>("API"); 
      var edmModel = builder.GetEdmModel(); 
      return edmModel; 
     } 
    } 
} 

Sterowniki \ DataRows.cs

using Integration.DataSource; 
using System.Linq; 
using System.Web.Http; 
using System.Web.OData; 
using System.Net; 

namespace Integration.Controllers 
{ 
    [EnableQuery] 
    public class DataRowController : ODataController 
    { 
     [BasicAuthenticationFilter] 
     public IHttpActionResult Get() 
     { 
      return Content(HttpStatusCode.NoContent,"NoContent"); 
     } 
     [BasicAuthenticationFilter] 
     public IHttpActionResult Post(Models.DataRow row) 
     { 
      if (!ModelState.IsValid) 
      { 
       return BadRequest(ModelState); 
      } 

      //do stuff to save data 
      // .. 
      return Content(HttpStatusCode.Created, "OK"); 
     } 
    } 
} 

Kontrolery \ Connections.cs

using Integration.DataSource; 
using System.Linq; 
using System.Web.Http; 
using System.Web.OData; 
using System.Net; 

namespace Integration.Controllers 
{ 
    [EnableQuery] 
    public class ConnectionController : ODataController 
    { 
     [BasicAuthenticationFilter] 
     public IHttpActionResult Get() 
     { 
      return Ok(IntegrationDataSources.Instance.Connection.AsQueryable()); 
     } 

     [BasicAuthenticationFilter] 
     public IHttpActionResult Post(Models.Connection connection) 
     { 
      return Content(HttpStatusCode.NotImplemented, "NotImplemented"); 
     } 
    } 
} 

modele \ DataRow.cs

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.Linq; 
using System.Web; 

namespace Integration.Models 
{ 
    public class DataRow 
    { 
     [Key] 
     public int ID { get; set; } 
     [Required] 
     public int Type { get; set; } 
     [Required] 
     public string DataType { get; set; } 
     [Required] 
     public string Data { get; set; } 
     [Required] 
     public int APIVersion { get; set; } 
     [Required] 
     public string IntegrationProvider { get; set; } 
    } 
    public class Connection 
    { 
     [Key] 
     public string ConnectionName { get; set; } 
     public API Api { get; set; } 
    } 
    public class API 
    { 
     [Key] 
     public int Version { get; set; } 
     public DataRow row { get; set; } 
    } 
} 

Odpowiedz

3

Możesz config API wersjonowanie z Global Route prefiksów Atrybut Routing ... Można utworzyć klasę, która dziedziczy DefaultDirectRouteProvider jak jeden z poniżej

public class CentralizedPrefixProvider : DefaultDirectRouteProvider 
{ 
    private readonly string _centralizedPrefix; 

    public CentralizedPrefixProvider(string centralizedPrefix) 
    { 
     _centralizedPrefix = centralizedPrefix; 
    } 

    protected override string GetRoutePrefix(HttpControllerDescriptor controllerDescriptor) 
    { 
     var existingPrefix = base.GetRoutePrefix(controllerDescriptor); 
     if (existingPrefix == null) return _centralizedPrefix; 

     return string.Format("{0}/{1}", _centralizedPrefix, existingPrefix); 
    } 
} 

i dodać go w WebApiConfig.cs jak ten

config.MapHttpAttributeRoutes(new CentralizedPrefixProvider("api/v{version:int}"));

Aby uzyskać więcej informacji na ten temat można uzyskać pomoc z tym linkiem ... http://www.strathweb.com/2015/10/global-route-prefixes-with-attribute-routing-in-asp-net-web-api/

2

Istnieje wiele sposobów radzenia sobie z wersjami z Web-API: przez URI, poprzez ciąg zapytania lub przez nagłówek żądania.

Ostatecznie, niezależnie od tego, jakie podejście podejmiesz, musisz dokonać jakiejś abstrakcji "Selektor kontrolera" za pomocą logiki, aby zinterpretować numer wersji i wybrać odpowiedni kontroler.

wykonuje dobrą pracę wyjaśniając podstawy.

1

Wystarczy rzucić okiem na pomysł: co z użyciem wtyczki zależności, aby mieć kontener DI lub interfejs fabryczny zdefiniowany przez kontener, aby utworzyć instancję z wersjonowanego interfejsu API, która będzie używana przez kontroler?

public interface IApiVersion { 
    //the public method signatures 
} 

public interface IApiVersionFactory { 
    IApiVersion Create(int version); 
} 

wstrzyknąć fabryki do sterownika i wywoływać metody prawidłowo wersjonowanym API i chcesz być dobry, aby przejść.