调用两个操作方法并组合它们的响应以生成新的响应在.NET Web API中。

huangapple go评论59阅读模式
英文:

Call two Action Methods and Combine the responses to produce new response in .NET Web API

问题

我有两个版本的API。

API的第二个版本将只有一个操作方法,而不是第一个版本中的两个操作方法。

API的第二个版本的操作方法基本上将合并第一个版本API的两个操作方法的响应,并将合并后的响应返回给客户端。

示例代码如下:

[ApiController]
[Route("[controller]")]
public class NumbersV1Controller : ControllerBase
{
    private readonly ILogger<NumbersV1Controller> _logger;

    public NumbersV1Controller(ILogger<NumbersV1Controller> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public int Get()
    {
        return 1;
    }

    [HttpPost]
    public int Post()
    {
        return 2;
    }
}

[ApiController]
[Route("[controller]")]
public class NumbersV2Controller : ControllerBase
{
    private readonly ILogger<NumbersV2Controller> _logger;

    public NumbersV2Controller(ILogger<NumbersV2Controller> logger)
    {
        _logger = logger;
    }

    [HttpPost]
    public IEnumerable<int> Get()
    {
        // 方法1:进行直接的HTTP请求。
        // int response1 = HTTPClientHelper.GetRequest("Get", "NumbersV1");
        // int response2 = HTTPClientHelper.PostRequest("Post", "NumbersV1");

        // 方法2:使用实例并设置控制器上下文。
        NumbersV1Controller numbersV1Controller = new NumbersV1Controller(null);
        numbersV1Controller.ControllerContext = this.ControllerContext;
        int response1 = numbersV1Controller.Get();
        int response2 = numbersV1Controller.Post();

        // 方法3:使用RedirectToAction方法。
        // RedirectToActionResult response1 = RedirectToAction("Get", "NumbersV1");
        // RedirectToActionResult response2 = RedirectToAction("Post", "NumbersV1");

        return new List<int>() { response1, response2 };
    }
}
  1. 方法1: 进行直接的HTTP请求。

    这个方法可以正常工作,但需要额外的样板代码,并且类似于发起了新的网络调用。

  2. 方法2: 使用实例并设置控制器上下文。

    不确定这是否会像版本1控制器中那样完美工作,也不确定如何初始化具有多个注入对象的版本2控制器。

  3. 方法3: 使用RedirectToAction方法。

    我曾以为RedirectToAction会起作用,但我没有在RedirectToActionResult响应对象中看到操作方法的结果。

在.NET Web API中执行这个操作的最佳选项是什么,或者是否有其他更优雅的方式来实现这个操作?

英文:

I have two versions of an API.

The second version of API will be having only one action method instead of two action methods in first version of API.

Second version of API action method will basically combine responses of first version of API's both action methods and return combined response to client.

Example code as follows:

[ApiController]
[Route(&quot;[controller]&quot;)]
public class NumbersV1Controller : ControllerBase
{
    private readonly ILogger&lt;NumbersV1Controller&gt; _logger;

    public NumbersV1Controller(ILogger&lt;NumbersV1Controller&gt; logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public int Get()
    {
        return 1;
    }

    [HttpPost]
    public int Post()
    {
        return 2;
    }
}

[ApiController]
[Route(&quot;[controller]&quot;)]
public class NumbersV2Controller : ControllerBase
{
    private readonly ILogger&lt;NumbersV2Controller&gt; _logger;

    public NumbersV2Controller(ILogger&lt;NumbersV2Controller&gt; logger)
    {
        _logger = logger;
    }

    [HttpPost]
    public IEnumerable&lt;int&gt; Get()
    {
        // Method 1: Make a direct HTTP request.
        // int response1 = HTTPClientHelper.GetRequest(&quot;Get&quot;, &quot;NumbersV1&quot;);
        // int response2 = HTTPClientHelper.PostRequest(&quot;Post&quot;, &quot;NumbersV1&quot;);

        // Method 2: Use instances and set controller context.
        NumbersV1Controller numbersV1Controller = new NumbersV1Controller(null);
        numbersV1Controller.ControllerContext = this.ControllerContext;
        int response1 = numbersV1Controller.Get();
        int response2 = numbersV1Controller.Post();

        // Method 3: Use RedirectToAction method.
        // RedirectToActionResult response1 = RedirectToAction(&quot;Get&quot;, &quot;NumbersV1&quot;);
        // RedirectToActionResult response2 = RedirectToAction(&quot;Post&quot;, &quot;NumbersV1&quot;);

        return new List&lt;int&gt;() { response1, response2 };
    }
}
  1. Method 1: Make a direct HTTP request.

    It works perfectly but it is having additional boilerplate code and also it like making a new network call.

  2. Method 2: Use instances and set controller context.

    Not sure if this will work perfectly like can I access the Request object in version 1 controller and not sure how to initialize the version 2 controller will multiple injected objects

  3. Method 3: Use RedirectToAction method.

    I was assuming RedirectToAction will work but I don't see the result of the Action method in response object RedirectToActionResult.

What are the best options available for doing this in .NET Web API or is there any other way of doing this elegently?

答案1

得分: 1

避免使用方法2/方法3。为什么?它违反了许多模式,性能将成为一个问题。

如果你真的想这样做,方法1是一种平均方法,但会产生网络调用的成本。

方法4:
您可以直接从您的V2控制器中调用内联业务逻辑代码。如果您已经将业务逻辑代码分离到一个独立的服务中,那么您需要从控制器中调用它。

我引入了一个新的类来执行所有的逻辑操作。您可能有一个类似的类/许多服务类来处理业务需求。

让我给你一个例子:

public class Number1Controller : BaseController {
    // 您可以使用DI容器来解析这个。我只是举个例子。
    private readonly Service _service = new();

    [HttpGet("{id}")]
    public int GetById(int id) => _service.GetById(id);

    [HttpGet("{name}")]
    public string GetByName(string name) => _service.GetByName(name);
}

public class Number2Controller : BaseController {

    // 您可以使用DI容器来解析这个。我只是举个例子。
    private readonly Service _service = new();

    [HttpGet("{id}")]
    public int GetById(int id) => _service.GetById(id);

    [HttpGet("{name}")]
    public string GetByName(string name) => _service.GetByName(name);
}

// 业务逻辑服务
public class Service {
    public int GetById(int id) => 1;
    public string GetByName(string name) => "Stack Overflow";
}

请注意,以上是代码示例,用于演示如何调用业务逻辑服务。

英文:

Avoid using method 2 / method 3. Why? It violates so many patterns and performance will be an issue.

Method 1 is average if you really want to do it that way but will cost a network call though.

Method 4:
You can call directly inline business logic code from your V2 controller. If you already separated your business logic code to an individual service then you need to call it from your controller.

> I have introduced a new class to do all the logical operations. You might have a similar one / many service classes for handling business requirements.

Let me give you an example:

public class Number1Controller : BaseController {
    // You can use DI container to resolve this. I am using this as an example.
    private readonly Service _service = new();

    [HttpGet(&quot;{id}&quot;)]
    public int GetById(int id) =&gt; _service.GetById(id);

    [HttpGet(&quot;{name}&quot;)]
    public string GetByName(string name) =&gt; _service.GetByName(name);
}

public class Number2Controller : BaseController {

    // You can use DI container to resolve this. I am using this as an example.
    private readonly Service _service = new();
    
    [HttpGet(&quot;{id}&quot;)]
    public int GetById(int id) =&gt; _service.GetById(id);

    [HttpGet(&quot;{name}&quot;)]
    public string GetByName(string name) =&gt; _service.GetByName(name);
}

// Business Logic Service
public class Service {
    public int GetById(int id) =&gt; 1;
    public string GetByName(string name) =&gt; &quot;Stack Over Flow&quot;;
}

huangapple
  • 本文由 发表于 2023年1月8日 23:47:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75049153.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定