0

Can a System.Web.Http endpoint be an IObservable? Can it be done while still using Attributes such as Route and AcceptVerbs?

Basically, I want to make the following code example into an IObservable stream so I'm subscribing and handling it via reactive extensions:

    [Route("{id}")]
    [AcceptVerbs("GET")]
    public async Task<IHttpActionResult> example(int id)
    {
        return Ok(await Service.GetExampleAsync(id));
    }

Edit: I'm looking for a more elegant solution like https://blogs.msdn.microsoft.com/jeffva/2010/09/15/rx-on-the-server-part-5-of-n-observable-asp-net (Observable from IHttpHandler) but hopefully more mature after seven years?

Chip
  • 1,439
  • 3
  • 15
  • 29
  • I am not sure I get it. You want to handle all requests using an observable? How do you know where to return the response to? – Peter Bons Nov 06 '17 at 09:39
  • Yeah trying to see how "everything is a stream" can be done for this case where you're essentially just getting multiple events from requests and producing multiple events as responses. The response side could just subscribe to the resulting observable stream. – Chip Nov 06 '17 at 17:04

1 Answers1

2

There is no direct way. But you could publish your own Observable. The main problem is, you need to return a value in the example function.

One solution could be to create an Observable in which you pass a TaskCompletionSource. This would allow you to set the result from the Event handler.

public class Request
{
    public int Parameter { get; }

    public Request(int parameter)
    {
         Parameter = parameter;
    }

    public TaskCompletionSource<IHttpActionResult> Result { get; } = new TaskCompletionSource<IHttpActionResult>();
}

public class Handler
{
    public Subject<Request> ExampleObservable { get; } = new Subject<Request>();

    [Route("{id}")]
    [AcceptVerbs("GET")]
    public async Task<IHttpActionResult> example(int id)
    {
        var req = new Request(id);
        ExampleObservable.OnNext(req);
        return await req.Result.Task;
    }
}

In the example above, we push a Request in the ExampleObservable. You can subscribe to this and use Request.Result.SetResult(...) to return the request.

ExampleObservable.Subscribe(req => req.Result.SetResult(Ok(Service.GetExample(id)));
Iqon
  • 1,920
  • 12
  • 20
  • Thanks for your solution! I did stumble upon this solution: https://blogs.msdn.microsoft.com/jeffva/2010/09/15/rx-on-the-server-part-5-of-n-observable-asp-net to create an observable implementation of the async http handler. I feel like this should be part of the .net framework libraries though and not have to implement our own every time. It's been over seven years since that writeup so I'm now trying to see what's the latest way that's hopefully more elegant and concise. – Chip Nov 08 '17 at 17:34