【问题标题】:Await a request to the controller from another controller - ASP .NET Core等待另一个控制器对控制器的请求 - ASP .NET Core
【发布时间】:2020-06-19 00:17:55
【问题描述】:

我有一个应用程序 LocalApp 和一个 API 控制器 MyController_A

当有人向MyController_A 发送请求时,控制器会将请求重定向到另一个应用程序RemoteApp 并暂停。

RemoteApp 完成计算后,它会向LocalApp 发送一个发布请求到另一个控制器MyController_B

任务是在发送响应之前等待来自MyController_BMyController_A 内的发布请求。

下面的例子可以帮助澄清问题:

public class MyController_A : ControllerBase
{
    public object Post([FromBody] MyModel message)
    {
        SendDataToAnotherApp(message);

        object result = new Task<object>(() => 
        {
            // Listening requests to MyController_B

            return request;

        }).Result;

        return result;
    }
}

【问题讨论】:

  • @mortb,感谢您的推荐。一旦我找到一种方法使它与远程应用程序一起工作,我将立即进行重构:)
  • 您的远程应用程序所做的请求与对您的应用程序的原始请求无关。因此,您只需要确保远程应用程序仅在对 B 的请求也完成后才响应。
  • 啊,现在我明白了,远程应用程序调用了 Controller_B
  • @mortb,没错。所以我找到了一种方法,正如我在下面发布的那样。也许不是最好的,但它确实有效。
  • 回调是否包含一些id?否则多个同时回调可能会触发错误的响应

标签: c# asp.net-core


【解决方案1】:

也许你应该重新设计你的架构,而不是让你的控制器保持活动状态等待另一个调用返回。

请记住,HTTP 请求的时间有限,一旦它们关闭,里面的线程就会死掉。

我不知道它是否适合您的场合,但我建议在第二个控制器完成工作时使用信号器通过 Web 套接字将数据发送到您的客户端。

aspnet/signalr

【讨论】:

  • 感谢您的回答。问题只是 RemoteApp。它的架构极大地限制了我的可能性:)
  • 但我会尝试用 SignalR 重新设计它!
  • :) 我相信你会很满意 :D
【解决方案2】:

您可以为控制器 A 使用 async/await

public class MyController_A : ControllerBase
{
    public async Task<object> Post([FromBody] MyModel message)
    {
        return await SendDataToAnotherApp(message);
    }
}

【讨论】:

  • 不,它没有回答我的问题。
  • OP 询问如果响应来自不同的控制器操作 (B/Index),他如何在 (A/Index) 处等待。
  • 如果你从 ControllerA.Index() 说,你调用 ControllerB.Index()。那是错误的,不要那样做。相反,创建一个服务 (CommonService.cs) 并将其注入到两个控制器中。
  • @Alex-TinLe,感谢您的回答。我稍后会做,一旦我发现如何捕获另一个请求
【解决方案3】:

所以,也许不是最好的解决方案,但它确实有效。

我将请求保存到 HttpContext.Session 中的 MyController_B,并从 MyController_A 获取其值。

public class MyController_B : ControllerBase {
    public void Post([FromBody] string message)
    {
        HttpContext.Session.SetString("MyController_B_request", message);
    }
}

public class MyController_A : ControllerBase
{
    public object Post([FromBody] MyModel message)
    {
        SendDataToAnotherApp(message);

        object result = new Task<object>(() => 
        {
            string request;
            while (true)
            {
                request = HttpContext.Session.GetString("MyController_B_request");
                if (!string.IsNullOrEmpty(request))
                    break;

                Task.Delay(1000).Wait();
            }

            return request;

        }).Result;

        return result;
    }
}

【讨论】:

  • 新建一个任务并以阻塞的方式等待它有什么意义?这也是一种非常……糟糕的做事方式。如果用户运行了两个请求,你不知道哪个会在会话中
  • 或者如果它是一个 Web 应用程序(即使它不是但在您的控制下,您可以在应用程序上使用 singalR C# 客户端进行第一次调用),在调用外部后结束第一个请求并使用 SignalR 通知操作已完成的浏览器,以便您的 Web 应用程序可以发起第二个请求以获取结果,而不是一直阻塞连接
  • @Tseng,感谢您的评论!阻塞任务不是真正使用的。它实际上是一个单独的方法,但是为了使帖子更紧凑,我将它打包成一个任务。
  • 我以前没用过 SignalR,但听起来是对的。我试试看!
  • 启动一个任务并等待它(以阻塞的方式)仍然没有意义。你期待它做什么?如果您只在操作方法中使用 while 循环(根本没有任务或线程),那么您实际上是在阻塞 两个线程,而不是一个。就像我说的那样,并发(同一用户的多个请求)它是不安全的
猜你喜欢
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 1970-01-01
  • 2022-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多