The code below it is supposed to write into the console the value of the current datetime every one second. It doesn't. But if the controller is hosted under IIS (instead of under SHS), it works fine.
Test code (console app):
```
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Client {
using System.Web.Http;
using System.Web.Http.SelfHost;
class Program {
static readonly Uri _address = new Uri("http://localhost/ddsrpc/PushContent");
static void RunClient() {
HttpSelfHostServer httpServer = new HttpSelfHostServer(new HttpSelfHostConfiguration("http://localhost"));
httpServer.Configuration.Routes.MapHttpRoute("SseTransport", "ddsrpc/{controller}");
httpServer.OpenAsync().Wait();
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage {
Method = HttpMethod.Get,
RequestUri = _address,
};
client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ContinueWith(
getTask => {
if (getTask.IsCanceled) {
return;
}
if (getTask.IsFaulted) {
throw getTask.Exception;
}
HttpResponseMessage response = getTask.Result;
response.Content.ReadAsStreamAsync().ContinueWith(
(streamTask) => {
if (streamTask.IsCanceled) {
return;
}
if (streamTask.IsFaulted) {
throw streamTask.Exception;
}
byte[] readBuffer = new byte[512];
ReadResponseStream(streamTask.Result, readBuffer);
});
});
}
private static void ReadResponseStream(Stream rspStream, byte[] readBuffer) {
Task.Factory.FromAsync<byte[], int, int, int>(rspStream.BeginRead, rspStream.EndRead, readBuffer, 0, readBuffer.Length, state: null).ContinueWith(
(readTask) => {
if (readTask.IsCanceled) {
return;
}
if (readTask.IsFaulted) {
throw readTask.Exception;
}
int bytesRead = readTask.Result;
string content = Encoding.UTF8.GetString(readBuffer, 0, bytesRead);
Console.WriteLine("Received: {0}", content);
if (bytesRead != 0) {
ReadResponseStream(rspStream, readBuffer);
}
});
}
static void Main(string[] args) {
RunClient();
Console.WriteLine("Hit ENTER to exit...");
Console.ReadLine();
}
}
public class PushContentController : ApiController {
private static readonly Lazy<Timer> _timer = new Lazy<Timer>(() => new Timer(TimerCallback, null, 0, 1000));
private static readonly ConcurrentDictionary<StreamWriter, StreamWriter> _outputs = new ConcurrentDictionary<StreamWriter, StreamWriter>();
[HttpGet]
public HttpResponseMessage GetUpdates(HttpRequestMessage request) {
Timer t = _timer.Value;
request.Headers.AcceptEncoding.Clear();
HttpResponseMessage response = request.CreateResponse();
response.Content = new PushStreamContent(OnStreamAvailable, "text/plain");
return response;
}
private static void OnStreamAvailable(Stream stream, HttpContent headers, TransportContext context) {
StreamWriter sWriter = new StreamWriter(stream);
_outputs.TryAdd(sWriter, sWriter);
}
private static void TimerCallback(object state) {
foreach (var kvp in _outputs.ToArray()) {
try {
kvp.Value.Write(DateTime.Now);
kvp.Value.Flush();
} catch {
StreamWriter sWriter;
_outputs.TryRemove(kvp.Value, out sWriter);
}
}
}
}
}
```
Test code (console app):
```
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Client {
using System.Web.Http;
using System.Web.Http.SelfHost;
class Program {
static readonly Uri _address = new Uri("http://localhost/ddsrpc/PushContent");
static void RunClient() {
HttpSelfHostServer httpServer = new HttpSelfHostServer(new HttpSelfHostConfiguration("http://localhost"));
httpServer.Configuration.Routes.MapHttpRoute("SseTransport", "ddsrpc/{controller}");
httpServer.OpenAsync().Wait();
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage {
Method = HttpMethod.Get,
RequestUri = _address,
};
client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ContinueWith(
getTask => {
if (getTask.IsCanceled) {
return;
}
if (getTask.IsFaulted) {
throw getTask.Exception;
}
HttpResponseMessage response = getTask.Result;
response.Content.ReadAsStreamAsync().ContinueWith(
(streamTask) => {
if (streamTask.IsCanceled) {
return;
}
if (streamTask.IsFaulted) {
throw streamTask.Exception;
}
byte[] readBuffer = new byte[512];
ReadResponseStream(streamTask.Result, readBuffer);
});
});
}
private static void ReadResponseStream(Stream rspStream, byte[] readBuffer) {
Task.Factory.FromAsync<byte[], int, int, int>(rspStream.BeginRead, rspStream.EndRead, readBuffer, 0, readBuffer.Length, state: null).ContinueWith(
(readTask) => {
if (readTask.IsCanceled) {
return;
}
if (readTask.IsFaulted) {
throw readTask.Exception;
}
int bytesRead = readTask.Result;
string content = Encoding.UTF8.GetString(readBuffer, 0, bytesRead);
Console.WriteLine("Received: {0}", content);
if (bytesRead != 0) {
ReadResponseStream(rspStream, readBuffer);
}
});
}
static void Main(string[] args) {
RunClient();
Console.WriteLine("Hit ENTER to exit...");
Console.ReadLine();
}
}
public class PushContentController : ApiController {
private static readonly Lazy<Timer> _timer = new Lazy<Timer>(() => new Timer(TimerCallback, null, 0, 1000));
private static readonly ConcurrentDictionary<StreamWriter, StreamWriter> _outputs = new ConcurrentDictionary<StreamWriter, StreamWriter>();
[HttpGet]
public HttpResponseMessage GetUpdates(HttpRequestMessage request) {
Timer t = _timer.Value;
request.Headers.AcceptEncoding.Clear();
HttpResponseMessage response = request.CreateResponse();
response.Content = new PushStreamContent(OnStreamAvailable, "text/plain");
return response;
}
private static void OnStreamAvailable(Stream stream, HttpContent headers, TransportContext context) {
StreamWriter sWriter = new StreamWriter(stream);
_outputs.TryAdd(sWriter, sWriter);
}
private static void TimerCallback(object state) {
foreach (var kvp in _outputs.ToArray()) {
try {
kvp.Value.Write(DateTime.Now);
kvp.Value.Flush();
} catch {
StreamWriter sWriter;
_outputs.TryRemove(kvp.Value, out sWriter);
}
}
}
}
}
```