2016-08-08 1 views
6

Мне нужно создать веб-сервис REST. Для этого я следовал этому руководству: http://www.odata.org/blog/how-to-use-web-api-odata-to-build-an-odata-v4-service-without-entity-framework/REST webservice WebAPI - создание конечной точки на основе нескольких объектов

Все работало нормально, я также добавил к нему BasicAuth, он работает как перчатка.

Теперь мой вопрос ... Этот веб-сервис будет работать с возможными версиями, поэтому мы решили внедрить системы версий. Кроме того, мы хотим, чтобы клиентские приложения выбирали базу данных, в которой они хотят выполнять свои действия. Для этого, мы думали, что было бы неплохо иметь идентификаторы URI с этим стилем:

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

Это код, который у меня есть. Раньше я определял только объект DataRow. Теперь я также определил API-интерфейс и соединение.

Как реализовать URI/конечную точку, как то, что я хочу? Это код, который у меня есть, до сих пор.

Файл: 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; 
     } 
    } 
} 

Контроллеры \ 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"); 
     } 
    } 
} 

Контроллеры \ 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"); 
     } 
    } 
} 

Модели \ 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; } 
    } 
} 

ответ

3

Вы можете сконфигурировать API управления версиями с Global Route префиксов с Attribute маршрутизации ... Вы можете создать класс, который наследует от DefaultDirectRouteProvider как один из ниже

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

и добавить его в WebApiConfig.cs как этот

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

Для получения дополнительной информации, вы можете получить помощь по этой ссылке ... http://www.strathweb.com/2015/10/global-route-prefixes-with-attribute-routing-in-asp-net-web-api/

2

Существует множество способов обработки версий с помощью Web-API: через URI, через строку запроса или через заголовок запроса.

В любом случае, независимо от того, какой подход вы предпримете, вам потребуется сделать абстракцию «Контроллер-селектор» с логикой для интерпретации номера версии и выбора соответствующего контроллера.

This article делает хорошую работу, объясняя основы.

1

Просто для того, чтобы бросить вам идею о том, как использовать инъекцию зависимостей, чтобы иметь либо контейнер DI, либо контейнерный интерфейс фабрики, чтобы создать экземпляр вашего версированного API, который будет использоваться контроллером?

public interface IApiVersion { 
    //the public method signatures 
} 

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

Инжектируйте завод в контроллер и вызывать методы для правильной версированной API и вы хорошо идти.