【问题标题】:REST webservice WebAPI - create endpoint based on multiple entitiesREST Web 服务 Web API - 基于多个实体创建端点
【发布时间】:2016-12-14 04:50:28
【问题描述】:

我需要创建一个 REST 网络服务。 为此,我遵循了本教程:http://www.odata.org/blog/how-to-use-web-api-odata-to-build-an-odata-v4-service-without-entity-framework/

一切正常,我还添加了 BasicAuth,它就像手套一样工作。

现在,我的问题... 这个 web 服务将与它的可能版本一起工作,所以我们决定实现一种版本系统。此外,我们希望客户端应用程序选择他们想要执行其操作的数据库。 为此,我们认为拥有这种风格的 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");
        }
    }
}

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

【问题讨论】:

    标签: c# web-services rest asp.net-web-api odata


    【解决方案1】:

    您可以使用带有属性路由的全局路由前缀配置 API 版本控制...您可以创建一个继承自 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 很好地解释了基础知识。

      【讨论】:

        【解决方案3】:

        只是向您抛出一个现成的想法:使用依赖注入来拥有 DI 容器或容器定义的工厂接口来创建控制器使用的版本化 API 实例怎么样?

        public interface IApiVersion {
            //the public method signatures
        }
        
        public interface IApiVersionFactory {
            IApiVersion Create(int version);
        }
        

        将工厂注入控制器并调用正确版本化 API 的方法,然后一切顺利。

        【讨论】:

          猜你喜欢
          • 2018-07-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-20
          • 1970-01-01
          • 2014-01-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多