Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get an IObservable back from Web API

I have a simple Web API which returns an Iobservable. I am using HttpClient to get the Observable so that I can subscribe to it. My problem is the returned Iobservable on subscription sends out an 'empty' result.

SERVER

public IObservable<DataItem> GetDataItems()
{
    return Observable.Generate(0, i => i < 10, i => i + 1, 
        i => new DataItem 
        {
            Id = i, 
            Name = String.Format("Storage{0}",i)
        });
}

CLIENT

public IObservable<DataItem> GetDataItems()
{
    using (HttpClient apiClient = new HttpClient())
    {
        apiClient.BaseAddress = new Uri("http://localhost:9001");
        apiClient.DefaultRequestHeaders.Add("x-user-authentication", "xxxxxx");
        return apiClient
            .GetAsync("api/xxxx/yyyy").Result.Content
            .ReadAsAsync<DataItem>().ToObservable();
    }
}

var source = GetDataItems();

List<DataItem> items = new List<DataItem>();

IDisposable consoleSubscription = source.Subscribe(
            x => Console.WriteLine("{0}:{1}", x.Id, x.Name),
            ex => Console.WriteLine("OnError : {0} ", ex.Message),
            () =>  Console.WriteLine("Encountered End of Stream")
            );
        consoleSubscription.Dispose();

My issue is I am not getting any data back from the server. I get an 'Empty' observable. I wrote a unit test against my controller and it does give back the dataitems.

Any suggestions please help. Unable to understand where I am going wrong. There are no errors on server or client.

like image 573
saipanyam Avatar asked Nov 27 '13 00:11

saipanyam


People also ask

How do I get responses from Web API?

Depending on which of these is returned, Web API uses a different mechanism to create the HTTP response. Convert directly to an HTTP response message. Call ExecuteAsync to create an HttpResponseMessage, then convert to an HTTP response message. Write the serialized return value into the response body; return 200 (OK).


1 Answers

You're being a little ambitious expecting an IObservable<T> to be streamed over the wire automatically. I'm afraid WebAPI won't do that for you.

What you are seeing is the consequence of the default json serializer outputting the properties of IObservable<T> - and there are none so you get empty braces.

Your unit test works because it's all in-memory - no serialization/deserialization is happening.

There are ways of using HttpResponseMessage's StreamContent property to stream results out which you could bridge to/from IObservable<T> - but it's not really idiomatic WebApi. WebApi's async support is really aimed at asynchronous processing of requests with single-item responses on the server, not at returning continuously streaming events.

Bottom line is that I think WebApi (at least at the time of writing) is the wrong technology choice here. You are far better off looking at SignalR which is purpose built for this sort of scenario, and is included in the current release of ASP.NET. It has both javascript and .NET client support, and you can bridge to IObservable<T> fairly easily. Some people have already looked at this, such as in this post sporting example code.

Some messaging middleware like my-Channels Nirvana (Edit: since bought out by Terracotta and wrapped into Universal Messaging Some example code is available in their documentation.), and CEP solutions like SQL Server StreamInsight have out of box IObservable support too.

like image 73
James World Avatar answered Nov 21 '22 04:11

James World