您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 1浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

开发可扩展的Web API

寒冰屋 发布时间:2019-07-06 23:06:55 ,浏览量:1

目录

介绍

架构

代码

用Postman测试

下一步

  • 下载文章的源代码(GitHub存储库)
介绍

我最近需要准备一个Web API,它有几个小操作,并且会不断添加新的操作。我决定使用可扩展的架构,而不是添加许多带有少量操作的控制器。因此,只能通过添加新的操作类型来添加新操作。

架构

架构和项目非常简单。该项目是使用Visual Studio 2017的Web API 2项目模板创建的。只有一个名为OperationsController的API控制器,其具有一个名为Process的单个操作。操作必须实现一个简单的IOperation接口,并为样板代码命名一个基类OperationBase。

Autofac和Autofac WebAPI2集成包用于自动发现操作类型并将其注入控制器。

代码

IOperation 接口如下:

public interface IOperation
{
    string Name { get; }
    string Description { get; }
    Type ParameterClassType { get; }
    object Execute(object prm);
}

ParameterClassType是Execute方法所需的参数对象的类型。解析request体内的JSON数据时使用它。如果Execute方法返回非null值,则将其作为结果返回给调用者,否则只返回Ok响应。

OperationController及其Process操作如下:

public class OperationsController : ApiController
{

   //Implemented operations are injected in the constructor
   public OperationsController(IEnumerable supportedOperations)
   {
      _supportedOperations = new List(supportedOperations);
   }

   //Single action that gets the operation name and 
   //reads the operation parameters as JSON from request body

   [HttpPost]
   public async Task Process(string operationName)
   {
      //Find the operation
      IOperation operation = _supportedOperations.FirstOrDefault(x => x.Name == operationName);
      if (operation == null)
           return BadRequest($"'{operationName}' is not supported.");

      //Get the request body as string
      string jsonBody = await Request.Content.ReadAsStringAsync();
      object operationParams = null;  

      try
      {
          //Parse the JSON data in the request body t construct operation's parameter object
          if (operation.ParameterClassType != null)
                operationParams = Newtonsoft.Json.JsonConvert.DeserializeObject
                                  (jsonBody, operation.ParameterClassType);

          object result = operation.Execute(operationParams);

          //Return the result value as JSON to the caller
          if (result != null)
              return Json(result);
      }
      catch(Exception ex)
      {
           return InternalServerError(ex);
      }

      //Return Ok if the operation has no return value
      return Ok();          
   }    
}

仅需要operationName值的路由配置如下:

config.Routes.MapHttpRoute(
      name: "DefaultApi",
      routeTemplate: "api/{operationName}",
      defaults: new { controller = "operations", action = "process", operationName = "help" }
);

该路由配置将所有请求路由到OperationsControlller的Process操作。如果没有提供操作名称,则执行帮助。

配置Autofac依赖注入并将其设置为Web API管道的依赖项解析器:

ContainerBuilder builder = new ContainerBuilder();

//Register controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

//Register all operations
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
           .Where(t=> t.IsAssignableTo())
           .As();

var container = builder.Build();

//Set Autofac container as the dependency resolver
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
用Postman测试

测试无参数操作“help”。

响应从“help”操作返回。

测试期望具有属性“Number1”和“Number2”的对象的“sum”操作。

响应从“sum”操作返回。

下一步

为了只展示这个想法,剩下的代码非常简单。将命令处理操作与控制器类分开是很好的。

“帮助”命令仅显示操作的名称和描述,但最好提供特定操作是否需要参数及其名称类型。由于操作不是控制器操作,因此Swagger对参数信息没有帮助。

也没有自动验证。验证可以在操作Execute方法之前完成,或者每个操作可以执行其自己的验证逻辑。

还应添加身份验证和授权操作以保护Web API。

 

原文地址:https://www.codeproject.com/Articles/5161177/Developing-an-Extensible-Web-API

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.0459s