我正在开发一个ASP.NET MVC 5应用程序。我一直在阅读一些问题here,这些问题建议不要使用我想要的行为类型。
我想达到的高水平 -
MVC Controller - 在服务层调用方法,然后继续执行控制器中的下一行代码,因为不需要返回任何内容。
服务层中的方法 - 我想调用一些具有Async方法的外部Web服务,所以我希望这些方法能够运行,然后在返回时将数据写入数据库。
这样的事情是否可以实现或不是最佳方法?
将此虚拟出来并测试我在控制器上有以下原理:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult TestAsync()
{
_myService.TestAsync();
return RedirectToAction("Summary");
}
在_myService,该方法如下所示:
public async Task TestAsync()
{
await Task.Delay(10000);
var test = "Testing";
_testRepository.Add(test);
}
我希望这个TestAsync方法等待10秒然后我可以检查数据库,并且会添加测试值。但是这不起作用 - 在按下按钮后,在UI上,页面转到摘要视图,并且命中了等待Task.Delay断点,但下一行永远不会执行。这种方法有什么不对吗? TestAsync方法应该类似于:
public void TestAsync()
{
//Call another private async method here in the class that does the task delay
//which would be similar to calling the actual Async External Web Service methods
var test = "Testing";
_testRepository.Add(test);
}
答案 0 :(得分:3)
我一直在阅读一些问题,建议不要使用我想要的行为类型。
那是因为它很危险。 ASP.NET确定在没有活动请求时卸载AppDomain是安全的,因此如果您在仍有工作要做的时候从控制器操作返回,ASP.NET将不会意识到这项工作。
最佳解决方案是使用单独的后端(例如Azure WebJob)设置可靠的队列(例如Azure队列),以便以可靠的方式处理该队列。这是正确的解决方案,但很多人只是因为它很复杂而不会这样做。
如果解决方案中有SQL Server或Redis数据库,请考虑Hangfire。 Hangfire将数据库用作可靠队列,并在ASP.NET应用程序旁边执行其后端。
如果您想要危险地生活,至少应该使用HostingEnvironment.QueueBackgroundWorkItem
,这将告知ASP.NET您的应用程序在请求之外所做的工作。
这种方法有什么不对吗?
是; _myService.TestAsync
正在尝试在请求上下文中恢复已完成的请求。