5

I totally understand that HTTP world is not the best choice for one-way calls and that WebApi is designed best for HTTP verbose communications. No doubt, WCF is the winner here. But, what if you already have an ApiController with a bunch of verbs exposed and at some point you needed to have a single one-way call too? And you don't want to host/maintain another service (WCF) for that.

Task<HttpResponseMessage> response = client.PostAsJsonAsync<Log>("api/log", log)

If you don't handle the response then you've got something similar to fire-and-forget. Is this the only way in WebApi or there's another solution?

Arman
  • 5,136
  • 3
  • 34
  • 36

2 Answers2

6

Why not just call like this and ignore the returned task?

client.PostAsJsonAsync<Log>("api/log", log);

I do this with all my calls and use a handler in the response pipeline to deal with responses if necessary.

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • This code is potentially dangerous because of unobserved task exceptions. – Aliostad Dec 19 '12 at 09:14
  • In fire-and-forget environment only communication exceptions should be handled on the client. The calling thread will fail with a thrown exception anyway, in case of communication problems. The rest is the headache of the service itself, so unobserved task exceptions should not be dangerous here. – Arman Dec 19 '12 at 16:42
  • @Darrel do you define your WebApi verbs as void or Task for one-way calls? For this particular issue I think void should be preferred since you're not imply any await-ness/await-ability for O/W operations. – Arman Dec 19 '12 at 16:48
5

Your best bet is to start a new Task and send the response immediately rather than returning the task:

public void PostDoFireAndForget() // and NOT public Task PostDoFireAndForget()
    {
        Task.Factory.StartNew
            (() =>
                {
                    // ... start the operation here
                    // make sure you have an exception handler!!
                }

            );

    }
Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • 3
    The only problem I see with this is that if the calling method ends before the actual remote call gets executed the call may never happen since the thread was killed together with the main thread. You should consider that when adopting this solution. – tucaz Dec 18 '12 at 18:35
  • Well that is the inherent problem with fire and forget on a request-response protocol. But chance is really slim – Aliostad Dec 18 '12 at 19:20
  • 1
    @DarrelMiller because returning a Task mean the response will not be returned until task is finished which is not the same as what OP wants. – Aliostad Dec 18 '12 at 19:55
  • @Aliostad Any call to XXXAsync should return very quickly. The OP wants to do FireAndForget which I interpret to mean, he doesn't care about a response. – Darrel Miller Dec 18 '12 at 21:04
  • @DarrelMiller if you are NOT returning a task then it is fine. But your code is dangerous since you are not observing the task exceptions. – Aliostad Dec 18 '12 at 21:19
  • @Aliostad I guess the inherent problem with fire and forget on a request-response protocol you mention has nothing to do with the return type of the WebApi methood, right? And I agree with the void, but without starting a new task. – Arman Dec 19 '12 at 17:00