Juste3alfaz
Juste3alfaz

Reputation: 295

PushStreamContent Web API

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

Answers (2)

S. Brentson
S. Brentson

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

IronGeek
IronGeek

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

Related Questions