ASP.NET Core - Criando uma Streaming API \| TreinaWeb               Promoção no ar   Matricule-se agora e garanta **54% de desconto**  

  Termina em   Tempo restante da oferta: 03 Horas 

 05 Min 

 23 Seg 

   Tempo restante da oferta: 03 05 23 

  [Assinar →](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26) 

   [                ](https://www.treinaweb.com.br)  Explorar  

 [ Quanto custa? ](#assinatura) [ FAQ ](https://www.treinaweb.com.br#faq) [Matricule-se](#assinatura) [ Entrar ](https://www.treinaweb.com.br/login) 

     [ Início ](https://www.treinaweb.com.br) [ Artigos ](https://www.treinaweb.com.br/blog) ASP.NET Core - Criando uma Streaming API  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) [ ASP .NET ](https://www.treinaweb.com.br/blog/categoria/asp-net) [ .NET Core ](https://www.treinaweb.com.br/blog/categoria/net-core) 

# ASP.NET Core - Criando uma Streaming API

 Streaming não se resume apenas a conteúdo de media. Aprenda neste artigo como criar uma streaming API de dados no ASP.NET Core.

 [ Wladimilson M. Nascimento ](https://www.treinaweb.com.br/blog/autor/wladimilson-m-nascimento) 7 anos atrás

  ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/01/06113752/streaming-api.png)  

Quando falamos de streaming de dados, a primeira coisa que vem a cabeça são streaming mídia: áudio e mídia. Mas em algumas situações, pode ser necessário a implementação de streaming de dados textuais.

Utilizado para a entrega de dados em tempo real, o streaming de dados em uma API é uma técnica utilizada principalmente por redes sociais, como Twitter e Facebook.

No .NET Core este tipo de recurso pode ser implementado via [SignalR](https://dotnet.microsoft.com/apps/aspnet/signalr), mas neste artigo exemplificaremos isso utilizando a estrutura tradicional do ASP.NET Core. Futuramente abordarei o uso do **SignalR**.

[  ![C# (C Sharp) - APIs REST com ASP.NET Web API](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/csharp.svg)   Curso C# (C Sharp) - APIs REST com ASP.NET Web API Conhecer o curso ](https://www.treinaweb.com.br/curso/c-sharp-apis-rest-com-asp-net-web-api)

## Criando uma Web API Simples

Para exemplificar a API Streaming, inicialmente iremos criar uma API simples:

```dos
dotnet new web -n ApiSimples

```

Que conterá apenas um model:

```csharp
namespace ApiSimples.Models
{
    public class Item
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }

        public override string ToString() => $"{Id} - {Name} - {IsComplete}";
    }
}

```

E um controller:

```csharp
namespace ApiSimples.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TodoController : ControllerBase
    {
        private static List _itens = new List();

        [HttpGet]
        public ActionResult Get() => _itens;

        [HttpPost]
        public async Task Post([FromBody] Item value)
        {
            if(value == null)
                return BadRequest();

            if(value.Id == 0)
            {
                var max = _itens.Max(i => i.Id);
                value.Id = max+1;
            }

            _itens.Add(value);
            return value;
        }

        [HttpPut("{id}")]
        public async Task Put(long id, [FromBody] Item value)
        {
            var item = _itens.SingleOrDefault(i => i.Id == id);
            if(item != null)
            {
                _itens.Remove(item);
                value.Id = id;
                _itens.Add(value);
                return item;
            }

            return BadRequest();
        }

        [HttpDelete("{id}")]
        public async Task Delete(long id)
        {
            var item = _itens.SingleOrDefault(i => i.Id == id);
            if(item != null)
            {
                _itens.Remove(item);
                return Ok(new { Description = "Item removed" });
            }

            return BadRequest();
        }
    }
}

```

À frente este controller será modificado com adição do streaming.

Não se esqueça de adicionar o suporte para o controller em `Startup`:

```csharp
public class Startup
{
    public void ConfigureServices(IServiceCollection services) => services.AddControllers();

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

```

## Adicionando o streaming de dados

No ASP.NET Core, ao acessar uma rota, a solicitação é processada e o seu resultado retornado para o usuário. Ao definir um streaming de dados, a solicitação se manterá em um processamento contínuo, retornando dados de um evento, enquanto a conexão se mantiver ativa.

Por não seguir o comportamento padrão, o streaming não pode retornar um objeto `ActionResult`, que é o tipo de retorno mais comum. Assim, a primeira coisa a ser feita é definir um `ActionResult` customizado:

```csharp
public class StreamResult : IActionResult
{
    private readonly CancellationToken _requestAborted;
    private readonly Action _onStreaming;

    public StreamResult(Action onStreaming, CancellationToken requestAborted)
    {
        _requestAborted = requestAborted;
        _onStreaming = onStreaming;
    } 

    public Task ExecuteResultAsync(ActionContext context)
    {
        var stream = context.HttpContext.Response.Body;
        context.HttpContext.Response.GetTypedHeaders().ContentType = new MediaTypeHeaderValue("text/event-stream");
        _onStreaming(stream, _requestAborted);
        return Task.CompletedTask;
    }
}

```

Note que esta classe implementa a interface `IActionResult`. Assim, ela poderá ser utilizada no lugar de `ActionResult`.

O ponto mais importante dela é a definição do callback `onStreaming`, que é recebido por parâmetro:

```csharp
public StreamResult(Action onStreaming, CancellationToken requestAborted)
{
  _requestAborted = requestAborted;
  _onStreaming = onStreaming;
} 

```

Este callback será utilizado para salvar os clients que estiverem “ouvindo” o streaming. E o `CancellationToken` será utilizado para finalizar o streaming caso a solicitação seja interrompida/cancelada.

Voltando ao controller, é necessário definir uma coleção para salvar os clients:

```csharp
private static ConcurrentBag _clients = new ConcurrentBag();

```

Esta coleção precisa ser thread-safe, por isso que foi utilizada uma coleção do namespace `System.Collections.Concurrent`.

Agora é possível definir o endpoint do streaming de dados:

```csharp
[HttpGet]
[Route("streaming")]
public IActionResult Streaming()
{
    return new StreamResult(
        (stream, cancelToken) => {
            var wait = cancelToken.WaitHandle;
            var client = new StreamWriter(stream);
            _clients.Add(client);

            wait.WaitOne();

            StreamWriter ignore;
            _clients.TryTake(out ignore);
        }, 
        HttpContext.RequestAborted);
}

```

Note que na função callback da classe `StreamResult` estamos adicionando o client na coleção e aguarda-se que a solicitação seja cancelada. Com isso, ao acessar o endpoint, a solicitação se manterá ativa.

No momento já temos um streaming de dados, mas nada está sendo enviado para os clients. Para isso, definiremos um método que irá percorrê-los e escreverá dados no stream:

```csharp
private async Task WriteOnStream(Item data, string action)
{
    foreach (var client in _clients)
    {
        string jsonData = string.Format("{0}\n", JsonSerializer.Serialize(new { data, action }));
        await client.WriteAsync(jsonData);
        await client.FlushAsync();
    }
}

```

Os dados escritos, serão as ações do nosso controller:

```csharp
public async Task Post([FromBody] Item value)
{
    if(value == null)
        return BadRequest();

    if(value.Id == 0)
    {
        var max = _itens.Max(i => i.Id);
        value.Id = max+1;
    }

    _itens.Add(value);

    await WriteOnStream(value, "Item added");

    return value;
}

[HttpPut("{id}")]
public async Task Put(long id, [FromBody] Item value)
{
    var item = _itens.SingleOrDefault(i => i.Id == id);
    if(item != null)
    {
        _itens.Remove(item);
        value.Id = id;
        _itens.Add(value);

        await WriteOnStream(value, "Item updated");

        return item;
    }

    return BadRequest();
}

[HttpDelete("{id}")]
public async Task Delete(long id)
{
    var item = _itens.SingleOrDefault(i => i.Id == id);
    if(item != null)
    {
        _itens.Remove(item);
        await WriteOnStream(item, "Item removed");
        return Ok(new { Description = "Item removed" });
    }

    return BadRequest();
}

```

Pronto, o nosso streaming de dados já está completo.

[  ![C# (C Sharp) - APIs REST com ASP.NET Web API](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/csharp.svg)   Curso C# (C Sharp) - APIs REST com ASP.NET Web API Conhecer o curso ](https://www.treinaweb.com.br/curso/c-sharp-apis-rest-com-asp-net-web-api)

## 123 Testando…

Para testar a API, inicialmente é necessário acessar o endpoint do streaming de dados:

![](https://dkrn4sk0rn31v.cloudfront.net/2020/01/03162549/streaming_1.png)

Note que o navegador indicará que a página está sendo carregada. Este é o comportamento padrão. Ao enviar uma solicitação para o controller, ela será mostrada nesta página:

![](https://dkrn4sk0rn31v.cloudfront.net/2020/01/03162548/streaming_2.png)

A página sempre mostrará que está sendo carregada, mas todas as ações que forem geradas do nosso controller serão exibidas nela.

Simples, não é? Você pode ver esta aplicação completa no meu [Github](https://github.com/wladimilson/apisimples).

No próximo artigo mostrarei como obter isso utilizando o *SignalR*.

- [ #C# ](https://www.treinaweb.com.br/blog/tag/csharp)
- [ #.NET Core ](https://www.treinaweb.com.br/blog/tag/net-core)
- [ #ASP .NET Core ](https://www.treinaweb.com.br/blog/tag/asp-net-core)
- [ #Streaming API ](https://www.treinaweb.com.br/blog/tag/streaming-api)

Autor

 ![Wladimilson M. Nascimento](//secure.gravatar.com/avatar/f0dd442f156a3eacd2880e9cd0eafbd1?d=mm)

## Wladimilson M. Nascimento

 Instrutor, nerd, cinéfilo e desenvolvedor nas horas vagas. Graduado em Ciências da Computação pela Universidade Metodista de São Paulo. 

 [Todos os artigos](https://www.treinaweb.com.br/blog/autor/wladimilson-m-nascimento)  

## Continue estudando

 Transforme leitura em prática com os cursos e formações da TreinaWeb.

 [Ver cursos](https://www.treinaweb.com.br/cursos)   

  Continue lendo

## Artigos relacionados

- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/01/05103838/SIGNALR-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     7 anos atrás

    ##  [ Criando um Chat com ASP.NET Core SignalR ](https://www.treinaweb.com.br/blog/criando-um-chat-com-asp-net-core-signalr) 

     Continuando o estudo do SignalR, aprenda como criar um chat utilizando esta biblioteca de aplicações em tempo real do ASP.NET Core.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/01/05103838/SIGNALR-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     7 anos atrás

    ##  [ Aplicações em tempo real com ASP.NET Core SignalR ](https://www.treinaweb.com.br/blog/aplicacoes-em-tempo-real-com-asp-net-core-signalr) 

     Aprenda como criar uma streaming api utilizando a biblioteca de aplicações em templo real, SignalR.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/01/16094538/liquid-fluid-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     7 anos atrás

    ##  [ Trabalhando com a template engine Liquid no ASP.NET Core ](https://www.treinaweb.com.br/blog/trabalhando-com-a-template-engine-liquid-no-asp-net-core) 

     Em alguns projetos pode ser necessário substituir o Razor por outra engine template. Neste caso, aprenda como fazer esta substituição pelo Liquid.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2018/01/01132725/PETAPOCO-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     9 anos atrás

    ##  [ Utilizando o Micro ORM PetaPoco em uma aplicação ASP.NET Core ](https://www.treinaweb.com.br/blog/utilizando-o-micro-orm-petapoco-em-uma-aplicacao-asp-net-core) 

     Aprenda a utilizar o Micro ORM PetaPoco em uma aplicação ASP.NET Core.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2017/08/utilizando-o-micro-orm-dapper-em-uma-aplicacao-asp-net-core-400x280.jpg)  [ ASP .NET ](https://www.treinaweb.com.br/blog/categoria/asp-net) 

     9 anos atrás

    ##  [ Utilizando o Micro ORM Dapper em uma aplicação ASP.NET Core ](https://www.treinaweb.com.br/blog/utilizando-o-micro-orm-dapper-em-uma-aplicacao-asp-net-core) 

     Conheça o micro framework ORM Dapper.NET e aprenda a utilizá-lo em uma aplicação ASP.NET Core.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2017/11/06103205/orm-lite-400x280.jpg)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     9 anos atrás

    ##  [ Utilizando o Micro ORM ServiceStack.OrmLite em uma aplicação ASP.NET Core ](https://www.treinaweb.com.br/blog/utilizando-o-micro-orm-servicestack-ormlite-em-uma-aplicacao-asp-net-core) 

     Aprenda na prática como fazer uso do micro framework ORM ServiceStack.OrmLite em uma aplicação ASP.NET Core.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/08/01172547/NET-CORE-3-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     7 anos atrás

    ##  [ .NET Core 3.0 - Criando tarefas de segundo plano com Worker Service ](https://www.treinaweb.com.br/blog/net-core-3-0-criando-tarefas-de-segundo-plano-com-worker-service) 

     Você já quis criar tarefas em segundo plano com o .NET Core? Na versão 3.0 foi introduzido o template Worker Service que facilita a criação deste tipo de aplicação. Caso tenha passado por uma situação assim, neste artigo mostramos como você pode aproveitar este novo recurso do .NET Core 3.0.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/02/18175820/RAZOR-COMPONENTS-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     8 anos atrás

    ##  [ .NET Core 3.0 - Criando componentes no Razor Components ](https://www.treinaweb.com.br/blog/net-core-3-0-criando-componentes-no-razor-components) 

     Veja neste artigo como é a estrutura de um componente do Razor Componente e aprenda a criar um.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2018/05/03175136/NET-CORE-2.1-400x280.png)  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) 

     8 anos atrás

    ##  [ Novos recursos do ASP.NET Core 2.1 ](https://www.treinaweb.com.br/blog/novos-recursos-do-asp-net-core-2-1) 

     Conheça os novos recursos do ASP.NET Core 2.1.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/11/criando-aplicacoes-desktop-multiplataforma-com-asp-net-core-e-electron-net-400x280.png)  [ ASP .NET ](https://www.treinaweb.com.br/blog/categoria/asp-net) 

     6 anos atrás

    ##  [ Criando aplicações desktop multiplataforma com ASP.NET Core e Electron.NET ](https://www.treinaweb.com.br/blog/criando-aplicacoes-desktop-multiplataforma-com-asp-net-core-e-electron-net) 

     Otimize a criação de aplicações desktop reutilizando códigos do ASP.NET Core, com a ajuda do Electron.NET.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2018/09/17132411/middlewares-aspnet-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     8 anos atrás

    ##  [ Criando um middleware customizado para ASP.NET Core ](https://www.treinaweb.com.br/blog/criando-um-middleware-customizado-para-asp-net-core) 

     Aprenda como criar e conheça as opções de configuração de um middleware customizado no ASP.NET Core.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/04/16095041/OCELOT-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     8 anos atrás

    ##  [ Criando um API Gateway com ASP.NET Core e Ocelot ](https://www.treinaweb.com.br/blog/criando-um-api-gateway-com-asp-net-core-e-ocelot) 

     Conheça o conceito de API Gateway e veja como criá-lo em uma aplicação ASP.NET utilizando a biblioteca Ocelot.

     Ler artigo

## Um ano de acesso total para você viver de programação.

 Todos os cursos e formações da TreinaWeb numa única assinatura, com professores que atuam no mercado, suporte direto e certificados. Do primeiro `console.log` ao mercado de trabalho.

- **1 ano** de acesso a **todos os cursos**
- Cursos novos **toda semana**
- Suporte **direto com professores**
- Plano de carreira **personalizado**
- **Certificados digitais** inclusos
- **Aplicativos** para Android e iOS, com **acesso offline**

    **Garantia incondicional de satisfação** 

 Teste por 7 dias e, se não fizer sentido para você, devolvemos seu dinheiro.

### Acesso completo a todos os cursos e dezenas de Formações.

 12 meses 

  Economize R$ 840,00  54% OFF 

 de 12x R$ 129,00 por apenas

 12x  R$ 59,00

 sem juros no cartão de crédito ou R$ 599,00 à vista

  Oferta termina em  **03h 05min 23s**

- Acesso imediato e ilimitado durante 1 ano.
- Plano de carreira personalizado.
- Suporte direto com professores.
- E muito mais!

 [Matricule-se agora](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26)

     [                ](https://www.treinaweb.com.br)

 Escola online de programação, tecnologia e IA.

- [  ](https://www.facebook.com/TreinaWeb/)
- [  ](https://www.instagram.com/treinaweb/)
- [  ](https://www.youtube.com/user/TreinaWeb)
- [  ](https://twitter.com/treinaweb)
- [  ](https://www.linkedin.com/company/treinaweb)
- [  ](https://github.com/treinaweb)

## Inscreva-se em nossa newsletter

Receba lançamentos, promoções e novidades.

   Seu nome     Seu WhatsApp     Seu melhor e-mail   Inscrever-se 

## Cursos

- [ Base para Devs ](https://www.treinaweb.com.br/categoria/base-para-devs)
- [ Front-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-front-end)
- [ Back-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-back-end)
- [ Mobile ](https://www.treinaweb.com.br/categoria/desenvolvimento-mobile)
- [ Bancos de Dados ](https://www.treinaweb.com.br/categoria/bancos-de-dados)
- [ Cloud ](https://www.treinaweb.com.br/categoria/cloud-computing)
- [ IA ](https://www.treinaweb.com.br/categoria/ia)
- [ E mais ](https://www.treinaweb.com.br/categoria/e-mais)
- [ Ver todos os cursos ](https://www.treinaweb.com.br/cursos)

## Conteúdo

- [ Formações ](https://www.treinaweb.com.br/formacoes)
- [ Projetos práticos ](https://www.treinaweb.com.br/projetos-praticos)
- [ Direto ao ponto ](https://www.treinaweb.com.br/direto-ao-ponto)
- [ Planos ](https://www.treinaweb.com.br#assinatura)
- [ Depoimentos ](https://www.treinaweb.com.br#depoimentos)
- [ Comunidade ](https://www.treinaweb.com.br#comunidade)
- [ Corpo docente ](https://www.treinaweb.com.br#docente)

## A empresa

- [ Sobre a TreinaWeb ](https://www.treinaweb.com.br#sobre)
- [ Perguntas frequentes ](https://www.treinaweb.com.br#faq)
- [ Vantagens de estudar na TreinaWeb ](https://www.treinaweb.com.br/vantagens-de-estudar-na-treinaweb)
- [ Cursos para empresas ](https://www.treinaweb.com.br/empresas)
- [ Sugira um novo curso ](https://www.treinaweb.com.br/sugerir-curso)
- [ Trabalhe conosco ](https://www.treinaweb.com.br/trabalhe-conosco)
- [ Artigos ](https://www.treinaweb.com.br/blog)
- [ Desenvolvedores e agentes ](https://www.treinaweb.com.br/developers)
- [ Contato ](https://www.treinaweb.com.br/contato)
- [ Política de privacidade ](https://www.treinaweb.com.br/politica-de-privacidade)
- [ Termos de uso ](https://www.treinaweb.com.br/termos-de-uso)

## Baixe nosso aplicativo

 [   Disponível na **App Store**  ](https://apps.apple.com/us/app/treinaweb/id1322729447) [   Disponível no **Google Play**  ](https://play.google.com/store/apps/details?id=br.com.treinaweb.mobile) 

  Av. Paulista, 1765, Conj 71 e 72 · Bela Vista · São Paulo · SP · 01311-200   © 2004 – 2026 TreinaWeb Tecnologia LTDA · CNPJ 06.156.637/0001-58
