在ASP.NET Core中的响应之后做一些工作

时间:2017-01-16 00:16:28

标签: entity-framework asp.net-core asp.net-core-mvc

我有一个使用EFCore的ASP.NET Core网站。 我想做一些像登录到数据库的工作,但是在将响应发送给用户以便更快地回答之后。

我可以在不同的线程中执行此操作,但由于DbContext的异步访问,我不确定它是否安全。有没有推荐的方法呢?

public async Task<IActionResult> Request([FromForm]RequestViewModel model, string returnUrl = null)
{
    try 
    {
      var newModel = new ResponseViewModel(model);
      // Some work 
      return View("RequestView",newModel)
    }
    finally
    {
        // Some analysis on the request
        // I would like to defer this part
        await Log(model);
    }
}

其中一个原因是我想调用一个不需要回答的网络服务(地理编码),但是很好地处理日志(我需要坐标的城市/国家)。

5 个答案:

答案 0 :(得分:2)

没有开箱即用的方法来做你想做的事。

但是,这是一种可能的方法:

  1. 拥有队列和工作人员(线程或进程)
  2. 在将请求发送回客户端之前,在该队列中添加一条消息
  3. 工作人员将在未来的某个时间点接收该消息并进行处理。
  4. 由于工作运行在其他地方,而不是在请求线程上,服务器可以完成请求线程,工作人员可以执行剩下的工作。

答案 1 :(得分:0)

我看到这从未得到解答,但实际上有解决方案。 简单的解决方案:

public async Task<IActionResult> Request([FromForm]RequestViewModel model, string returnUrl = null)
{
    try 
    {
      var newModel = new ResponseViewModel(model);
      // Some work 
      return View("RequestView",newModel)
    }
    finally
    {
        Response.OnCompleted(async () =>
        {
            // Do some work here
            await Log(model);
        });
    }
}

安全解决方案(如OnCompleted曾经在发送响应之前被调用,因此延迟了响应:

public static void OnCompleted2(this HttpResponse resp, Func<Task> callback)
{
    resp.OnCompleted(() =>
    {
        Task.Run(() => { try { callback.Invoke(); } catch {} });
        return Task.CompletedTask;
    });
}

并致电Response.OnCompleted2(async () => { /* some async work */ })

答案 2 :(得分:0)

Jeans answerEcto.Changeset.cast_assoc( setting, :data, with: &SettingData.changeset/2 ) 模式上的question and answer为基础,可以删除try - return - finallytry块(如果您确实不想要捕获异常)。

这导致以下代码:

finally

答案 3 :(得分:-1)

创建一个继承自ActionFilterAttribute的新类,覆盖OnResultExecuted方法以执行日志记录,然后将属性类应用于要进行日志记录的控制器操作。

答案 4 :(得分:-1)

尝试使用Hangfire。 Hangfire是在.NET和.NET Core应用程序中执行后台处理的简便方法。无需Windows服务或单独的过程。 以持久存储为后盾。开放和免费用于商业用途。

您可以执行类似

的操作
var jobId = BackgroundJob.Enqueue(() => Log(model));

这是我在ASP.NET Core中使用HangFire的blog post