1

I can't find a solution to the problem despite many similar questions.

There is a Web API. On POST I need

  1. read DB
  2. make a HTTP call to other service to subscribe on notification (let's say it takes 5s)
  3. return the data from the DB

In the step 2, I don't need to wait, I don't need to block the client (for 5sec), so the client should not wait for the response.

However, the server have to wait on result from 2 and log it. So far I've tried

[HttpPost("{callId}")]
public async Task<IActionResult> CreateSubs([FromRoute] string callId)
{
    var data = await ...// read the DB
    _ = SubscribeForUpdates(callId);
    return Ok(data);
}

private async Task SubscribeForUpdates(string callId)
{
    _logger.LogInformation("Subscribe client {ConnectionId} notifications", callId);

    var requestMessage = new HttpRequestMessage
    {
        RequestUri = new Uri(_httpClient.BaseAddress, $"subscribe/{callId}"),
        Method = HttpMethod.Get,
    };

    var result = await SendAsync<SubscriptionResponse>(requestMessage);
    if (result.IsSuccess)
    {
        Console.WriteLine("Success");
    }
    else
    {
        Console.WriteLine("Fail");
    }
}

SendAsync is from some library and so smth like _httpClient.SendAsync

In this case the request will not be blocked, the internal HTTP request is successful but I there is no Success from Console.WriteLine("Success");. Only if I put a breakpoint there it logs.

Could you please help me to understand why this is not log and how to fix that?

I've tried ContinueWith - no result

await SendAsync<ServerSubscriptionResponse>(requestMessage)
.ContinueWith(t =>
{
    if (t.Result.IsSuccess)
    {
        Console.WriteLine("Success");
    }
    else
    {
        Console.WriteLine("Fail");
    }
})

When I use await SubscribeForUpdates(callId) inasted of _ = SubscribeForUpdates(callId) it works and logs but the blocks a client. I need to avoid that

  • 2
    Possibly related: [Web Api - Fire and Forget](https://stackoverflow.com/questions/36335345/web-api-fire-and-forget). – Theodor Zoulias Nov 09 '22 at 22:22
  • @TheodorZoulias unfortunately no, I've tried `Task.Factory.StartNew` - the same result. I don't understand why – Peter Pedigree Nov 09 '22 at 22:24
  • 1
    Have you tried putting the `var result = await SendAsync(requestMessage);` in a try/catch block, and log the possible exception? – Theodor Zoulias Nov 09 '22 at 22:42
  • 1
    @TheodorZoulias oh my God, thanks, it says sometimes "Cannot access a disposed object", when not - log does exists. thanks a lot. Just describe try/catch as an answer< I'll accept it. – Peter Pedigree Nov 09 '22 at 23:23
  • Nah, it won't be a good answer, because there is nothing in the question that suggests that a disposable object is used for the async operation. I would suggest to just close the question for the reason "Not reproducible or was caused by a typo". If you agree, there is a "Close" button under the tags of the question. Alternatively, you could [self-answer](https://stackoverflow.com/help/self-answer) the question. – Theodor Zoulias Nov 09 '22 at 23:50
  • @PeterPedigree Note that if your API "must" log, then your solution is still incorrect. Use [a proper distributed architecture](https://blog.stephencleary.com/2021/01/asynchronous-messaging-1-basic-distributed-architecture.html). – Stephen Cleary Nov 10 '22 at 13:14
  • Hi Stephen, I read your article but unfortunately didn't get what you mean. Could you explain a little bit – Peter Pedigree Nov 23 '22 at 10:13

0 Answers0