东莞市连易网络科技有限公司
东莞市连易网络科技有限公司
  • 网站
  • 用户
  • 购物车
  • 购物车
  • 搜索
  • 网站
  • 用户
帮助
帮助
开发文档 公开数据给外部源
  • 用户文档
  • 开发文档
  • API文档
  • 提及
  • 标签
  • 更多
  • 取消
  • 新建
  • +开始
  • +UI 自定义
  • +外部集成
  • -插件/框架扩展
    • -插件
      • 异常和日志记录
      • 插件生命周期
      • -插件示例
        • 使用小组件从插件渲染内容
        • 公开数据给外部源
        • 公开配置选项
        • 创建动态
        • +创建自定义应用程序和内容
        • 基于模板的电子邮件
        • 处理事件
        • 处理内容中的嵌入文件
        • 定义权限
        • 扩展规则支持
        • 文件交互
        • 文件查看器
        • 注册模板令牌
        • 管理依赖关系
        • 管理物理文件存储
        • 翻译插件文本
        • 通知
    • +设置开发环境
    • +进程 API

公开数据给外部源

在 Limyee 电商平台中创建新内容、应用程序/或其他自定义数据和服务时,您可以通过 REST 公开这些服务来进行外部集成。这提供了极大的灵活性,允许外部集成访问您的定制数据。

何时应使用 REST 端点?

每当您希望使 Limyee 电商平台外部的应用程序能够与您的自定义数据进行交互时,都应通过 REST 公开数据。这也可以在 Limyee 电商平台界面中使用,用于小组件的 AJAX 操作。此外,如果要提供更广泛的响应,或将响应限制为特定字段,则可以将一个或多个进程 API 包装到新的 REST 端点中。

我们的示例为实体提供推荐的标准 REST 端点集:创建、更新、删除、获取和列表。如果你的方案不需要它们,则不需要全部使用它们。

必需引用的 DLL:

  • Limyee.Components.dll
  • Limyee.Rest.dll

示例内容

该过程的第一步是编写自定义数据或服务以创建 REST 端点。虽然本文重点介绍自定义数据,但您也可以创建一个自定义对象来存储从一个或多个进程 API 检索的平台数据并返回这些数据。在此示例中,我们将重点介绍一个名为“Dog”的自定义类。

using System;

namespace Samples
{
    public class Dog
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Breed { get; set; }
    }
}

在本演示中,我们假设存在一个支持服务来对此对象执行 CRUD 操作。我们将其称为 DogService,并假定其方法单独采用所有必需参数,并将所有可选参数分组到 Dog<MethodName>Options 类中。这与进程 API 的模式相同。

注册 REST 路由

实现 IRestEndpoints 需要一个 Register 方法,该方法为您提供了一个用于注册 REST 路由的控制器。路由将始终以标准的 Limyee 电商平台 REST URL(<siteurl> + “/api/{version}”)开头,我们将定义 URL 的其余部分,包括每个所需方法的版本。IRestEndpoints 也是从 IPlugin 派生出来的,所以你还需要实现基本的 IPlugin 接口。

端点的声明实际上相当简单。参数为:

  • int version:这允许您在同一 URL 上拥有多个版本的端点。这允许您更改API,但如果您愿意,可以保持一些向后兼容性。此值也用于 api 之后的 url 的根目录中。例如,如果将此值设置为 1,则端点的基本 url 为 http://<siteurl>/api/v1,如果设置为 2,则为 /api/v2,依此类推。
  • string relativeUrl:这是对基本 REST URL(<siteurl> + “/api/{version}”) 的添加,用于向处理程序标识此方法。与 HTTP 方法和任何参数约束一起,这使得 url 是唯一的。
  • object parameterDefaults:指定有关路由的默认设置,例如:REST 资源名称是什么以及正在执行的 REST 操作。它还可用于为任何可选参数设置默认值。
  • object parameterConstraints:约束将用于指定路由 URL 中参数的所需格式等内容。
  • HttpMethod method:对应于标准的 HTTP 方法(GET、POST、PUT、DELETE)。在这里,我们使用 HttpMethod 枚举。
  • Func<IRestRequest,IRestResponse> handler:这是将用于处理请求和发出响应的委托。它可以是已定义的方法,也可以是内联 Func<> 声明。

public void Register(IRestEndpointController restRoutes)
{
    restRoutes.Add(1, "dogs", new { resource = "dog", action = "create" }, null, HttpMethod.Post, CreateDog);
    restRoutes.Add(1, "dog/{id}", new { resource = "dog", action = "update" }, null, HttpMethod.Put, UpdateDog);
    restRoutes.Add(1, "dog/{id}", new { resource = "dog", action = "delete" }, null, HttpMethod.Delete, DeleteDog);
    restRoutes.Add(1, "dog/{id}", new { resource = "dog", action = "show" }, null, HttpMethod.Get, GetDog);
    restRoutes.Add(1, "dogs", new { resource = "dog", action = "list" }, null, HttpMethod.Get, ListDogs);
}

声明路由 URL 类似于 MVC 路由,因为路由可能会意外重叠,从而完全隐藏某些路由。您需要确保不会发生这种情况,以便所有方法都可用,并且对这些方法的调用不会路由到错误的内部方法。您可以通过 HTTP 方法、参数约束和路由本身的组合来区分路由。关于重叠路由,需要注意和避免的几种情况:

  • 匹配路由:只要 HTTP 方法不同,这是安全的。例如,“更新”、“删除”和“获取”都使用相同的路由(“dog/{id}”),但使用 HTTP 方法(分别为 PUT、DELETE 和 GET)进行区分。
  • 匹配 Http 方法:只要路由是唯一的,这是安全的。Get 和 List 具有相同的 HTTP 方法 (GET),因此它们需要不同的路由 URL 来区分它们(“dog/{id}”和“dogs”)。
  • 匹配路由参数令牌:当路由与包含参数标记的路由相似时,需要小心。例如,如果在路由“dog/create”(映射到 Create 方法)之前声明了路由“dog/{id}”(映射到 Get 方法),如果在 {id} 上没有参数约束指定它必须是字符串以外的内容时,则“create”可以被解释为与 {id} 令牌匹配,从而导致“dog/create”触发 Id 无效的 Get 方法。

每个 REST 方法都接受一个 IRestRequest 对象,并返回一个实现 IRestResponse 的对象。请求存储数据有两个主要组件:PathParameters 和 Form。PathParameters 的内容是从 url 路径解析的内容,包括查询字符串,Form 的内容是从请求正文中解析的。您还可以选择直接从 IRestRequest.Request.QueryString 访问查询字符串。

IRestResponse 接口相当通用,提供位置允许您放置数据对象,以便可以将其序列化到 HTTP 响应中。它还需要数据对象的名称(对于最外层的序列化实体),并提供列表访问响应中的错误字符串。

用于执行每个操作的函数是单独声明的。首先,我们必须创建一个实现 IRestResponse 的 响应对象,以便我们可以以已知格式发送数据。

[XmlRoot(ElementName = "Response")]
[RestAction(RestAction.Show, "achievement")]
public class DogResponse : IRestResponse
{
    private Dog _dog;
    public Dog Dog
    {
        get { return _dog; }
        set
        {
            _dog = value;
        }
    }

    public string Name { get { return "Dog"; } }
    public object Data { get { return _dog; } }
    public string[] Errors { get; set; }
}

当我们要添加对象的实例时,将使用 Create。在此示例中,添加狗只需要名称,因此我们检查该名称,如果缺少,则提前返回错误。可以在此处进行其他检查,例如,必需的参数需要是整数。检查可选参数更容易,我们只需要将其分配给选项对象(如果它确实存在)。收集到所需的全部信息后,您可以调用内部服务,执行必要的操作,并在 REST 响应中返回相关信息。重要的是要将内部调用包装在 try...catch  代码块中,因此您可以确保返回的请求是 REST 响应,而不是 ASP.net 错误页。如果缺少必需的参数或未满足要求,或者内部出现其他问题,则可能会返回错误响应(建议为此使用 IUserRenderableException)。如果包含全部必需的参数,则可以分析每个参数,然后将其与基础内部服务一起使用以执行请求的操作。

public IRestResponse CreateDog(IRestRequest request)
{
    var response = new DogResponse();

    if (request.Form["Name"] == null)
    {
        response.Errors = new[] { "Name is required" };
        return response;
    }
    var name = request.PathParameters["Name"].ToString();

    var options = new DogCreateOptions();

    if (request.Form["Breed"] != null)
        options.Breed = request.Form["Breed"];

    try
    {
        var createdDog = DogService.Create(name, options);

        response.Dog = createdDog;
    }
    catch (Exception ex)
    {
        response.Errors = new[] { "Error: '{0}'", ex.ToString() };
    }

    return response;
}

Update 使用最初从 Create 返回的 Id 来查找对象,这允许所有其他参数都是可选的,并且仅在指定时更改。

public IRestResponse UpdateDog(IRestRequest request)
{
    var response = new DogResponse();

    if (!request.PathParameters.ContainsKey("Id"))
    {
        response.Errors = new[] { "Id is required" };
        return response;
    }
    var id = Guid.Parse(request.PathParameters["Id"].ToString());

    var options = new DogUpdateOptions();

    if (request.Form["Name"] != null)
        options.Name = request.PathParameters["Name"].ToString();
    if (request.Form["Breed"] != null)
        options.Breed = request.PathParameters["Breed"].ToString();

    try
    {
        var createdDog = DogService.Update(id, options);

        response.Dog = createdDog;
    }
    catch (Exception ex)
    {
        response.Errors = new[] { "Error: '{0}'", ex.ToString() };
    }

    return response;
}

Delete 只需要对象的 ID 即可将其从数据库中删除。

public IRestResponse DeleteDog(IRestRequest request)
{
    var response = new DefaultRestResponse();

    if (!request.PathParameters.ContainsKey("Id"))
    {
        response.Errors = new[] { "Id is required" };
        return response;
    }
    var id = Guid.Parse(request.PathParameters["Id"].ToString());

    try
    {
        DogService.Delete(id);
    }
    catch (Exception ex)
    {
        response.Errors = new[] { "Error: '{0}'", ex.ToString() };
    }

    return response;
}

Get 也只需要 Id 即可返回完整对象。

public IRestResponse GetDog(IRestRequest request)
{
    var response = new DogResponse();

    var options = new DogGetOptions();

    if (!request.PathParameters.ContainsKey("Id"))
    {
        response.Errors = new[] { "Id is required" };
        return response;
    }
    options.Id = Guid.Parse(request.PathParameters["Id"].ToString());

    try
    {
        var dog = DogService.Get(options);
        response.Dog = dog;
    }
    catch (Exception ex)
    {
        response.Errors = new[] { "Error: '{0}'", ex.ToString() };
    }

    return response;
}

List 在从中返回的内容而言,是最灵活的方法,因为不包含必需的参数,可使用其他可选参数用于返回自定义列表。

public IRestResponse ListDogs(IRestRequest request)
{
    var response = new DefaultRestResponse();
    var options = new DogListOptions();

    if (request.PathParameters.ContainsKey("Name"))
        options.Name = request.PathParameters["Name"].ToString();
    if (request.PathParameters.ContainsKey("Breed"))
        options.Breed = request.PathParameters["Breed"].ToString();

    if (request.PathParameters.ContainsKey("SortBy"))
        options.SortBy = request.PathParameters["SortBy"].ToString();
    if (request.PathParameters.ContainsKey("SortOrder"))
        options.SortOrder = request.PathParameters["SortOrder"].ToString();

    if (request.PathParameters.ContainsKey("PageSize"))
        options.PageSize = Int32.Parse(request.PathParameters["PageSize"].ToString());
    if (request.PathParameters.ContainsKey("PageIndex"))
        options.PageIndex = Int32.Parse(request.PathParameters["PageIndex"].ToString());

    try
    {
        var dogs = DogService.List(options);

        response.Name = "Dogs";
        response.Data = dogs;
    }
    catch (Exception ex)
    {
        response.Errors = new[] { "Error: '{0}'", ex.ToString() };
    }

    return response;
}

使用已注册的路由

有关调用 REST 端点的信息,请参阅 REST API:发起请求。

  • 分享
  • 历史
  • 更多
  • 取消
相关
推荐
Copyright © 2021 东莞市连易网络科技有限公司. All rights reserved.
Powered by Limyee Commerce System(3.0.0). © 2014 - 2025 Limyee Inc.