如何从Web API获取IObservable

时间:2013-11-27 00:07:43

标签: asp.net-web-api system.reactive

我有一个简单的Web API,它返回一个Iobservable。我正在使用HttpClient来获取Observable,以便我可以订阅它。我的问题是订阅时返回的Iobservable发出了一个'空'结果。

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)
        });
}

客户端

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();

我的问题是我没有从服务器获取任何数据。我得到一个'空'可观察。我为我的控制器写了一个单元测试,它确实回馈了数据项。

有任何建议请帮忙。无法理解我哪里出错了。服务器或客户端没有错误。

1 个答案:

答案 0 :(得分:19)

你有点野心,希望IObservable<T>能够自动通过网络流式传输。我担心WebAPI不会为你做那件事。

你看到的是默认的json序列化程序输出IObservable<T>属性的结果 - 并且没有,所以你得到空括号。

您的单元测试有效,因为它全部在内存中 - 没有发生序列化/反序列化。

有一些方法可以使用HttpResponseMessage的StreamContent属性来流式传输您可以桥接到IObservable<T>的结果 - 但它并不是真正的惯用WebApi。 WebApi的异步支持实际上是针对服务器上的单项响应异步处理请求,而不是连续返回流事件。

最重要的是,我认为WebApi(至少在撰写本文时)是错误的技术选择。您最好不要查看专为此类场景构建的SignalR,并且包含在当前版本的ASP.NET中。它具有javascript和.NET客户端支持,您可以非常轻松地桥接到IObservable<T>。有些人已经看过这个,例如in this post sporting example code

某些消息传递中间件,例如my-Channel Nirvana编辑:自Terracotta购买并包装到Universal Messaging 一些example code可在其文档中找到。),以及像SQL Server StreamInsight这样的CEP解决方案也有开箱即用的IObservable支持。