Reputation: 295
I am trying to push my data from web API to client, so I use PushStreamContent in Web API. My data are all student exist in database.
public HttpResponseMessage GetAll()
{
HttpResponseMessage response = new HttpResponseMessage();
var students = _symboleService.GetAll();
response.Content = new PushStreamContent((students, httpContent, context) =>
{
OnStreamAvailable(students, httpContent, context);
}, "text/plain");
return response;
}
private void OnStreamAvailable(Stream stream, HttpContent content,TransportContext context)
{
StreamWriter responseStreamWriter = new StreamWriter(stream);
clients.Add(responseStreamWriter);
}
But an error shows on "students" on this line:
response.Content = new PushStreamContent((students, httpContent, context) =>
A local or parameter named 'students' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
Update My point here is to push the data to the client side, After some modification, this my code but it shows an error on line,
var students = _symboleService.GetAll();
An object reference is required for the non-static field, method, or property 'SymbolesController._symboleService'
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>();
public HttpResponseMessage GetAll()
{
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new PushStreamContent((responseStream, httpContent, context) =>
{
StreamWriter responseStreamWriter = new StreamWriter(responseStream);
_outputs.TryAdd(responseStreamWriter, responseStreamWriter);
}, "text/plain");
Timer t = _timer.Value;
return response;
}
// Runs every second after the first request to this controller and
// writes to the response streams of all currently active requests
private static void TimerCallback(object state)
{
foreach (var kvp in _outputs.ToArray())
{
StreamWriter responseStreamWriter = kvp.Value;
try
{
var students = _symboleService.GetAll();
responseStreamWriter.Write(students);
responseStreamWriter.Flush();
}
catch { }
}
}
By the way, if I change studentsby DateTime.Now here, it works:
responseStreamWriter.Write(students); to
responseStreamWriter.Write(DateTime.Now);
Upvotes: 0
Views: 6741
Reputation: 454
There are a couple of issues here that are going to impede your progress.
To start with, the Action in your PushStreamContent constructor cannot reuse the variable name "students". It appears that you think you're passing the reference to the Action, but that's not how this works.
You could try this:
response.Content = new PushStreamContent(OnStreamAvailable, "text/plain");
But there remains another problem. The stream in the PushStreamContent constructor's action is an output stream.
public PushStreamContent(Action<Stream, HttpContent, TransportContext> onStreamAvailable);
You'll want to write to that stream from within your OnStreamAvailable handler.
Since it's not clear what the _symbolService.GetAll() method, I can only speculate that a Byte[] generated from the method should be written to your output stream within your action itself.
Assuming that your student data is not really a stream or inherently streamable, this may be a misuse of the PushStreamContent class.
Upvotes: 2
Reputation: 4873
You need to rename the students
parameter used in PushStreamContent
constructor.
For example, from:
response.Content = new PushStreamContent((students, httpContent, context) =>
{
OnStreamAvailable(students, httpContent, context);
}, "text/plain");
to:
response.Content = new PushStreamContent((stream, httpContent, context) =>
{
OnStreamAvailable(stream, httpContent, context);
}, "text/plain");
The reason why you cannot use students
is because it's already declared as a variable in the previous line:
var students = _symboleService.GetAll();
Upvotes: 4