I am trying to impelement a streamign API in Azure Web App application.
I was able to build a Proof of Concept in a regular application (Blazor Wasm and Azure Function) but not configured as SWA. It worked just fine. When copying the same code to the SWA, it is not working (i.e. streaming is not working, the value comes ones at the completion rather than stream as we go).
Any suggestions whay might be going on?
Here is the code I have for the Azure function
[Function("GetItems")]
public static async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestData req,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger("GetItemsFunction");
logger.LogInformation("C# HTTP trigger function processed a request.");
// Create a response
var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/event-stream");
// Add CORS headers
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
// Start the stream
await using (var writer = new StreamWriter(response.Body))
{
var items = new[] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 3", "Item 4", "Item 3", "Item 4", "Item 3", "Item 4", "Item 3", "Item 4", "Item 3", "Item 4", "Item 3", "Item 4", "Item 3", "Item 4", "Item 3", "Item 2", "Item 1" };
foreach (var item in items)
{
await writer.WriteLineAsync($"data: {item}");
await writer.FlushAsync();
await Task.Delay(1000); // Simulate delay
}
}
return response;
}
And Here is the code in the Blazor wasm Razor page
@page "/items"
@inject StreamingApiService StreamingApiService
<h3>Streaming Data</h3>
@if (streamedData == null)
{
<p><em>Loading...</em></p>
}
else
{
<ul>
@foreach (var item in streamedData)
{
<li>@item</li>
}
</ul>
}
@code {
private List<string> streamedData;
protected override async Task OnInitializedAsync()
{
streamedData = new List<string>();
await foreach (var item in StreamingApiService.GetStreamedData())
{
streamedData.Add(item);
StateHasChanged();
}
}
}
And this is a helper class I am using
using Microsoft.AspNetCore.Components.WebAssembly.Http;
using System.Text.Json;
namespace ClientApp;
public class StreamingApiService
{
private readonly HttpClient _httpClient;
public StreamingApiService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async IAsyncEnumerable<string> GetStreamedData()
{
using var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:7181/api/GetChat");
request.SetBrowserResponseStreamingEnabled(true);
using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
using var stream = await response.Content.ReadAsStreamAsync();
using var reader = new StreamReader(stream);
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
// Deserialize the line into a MyDataItem object
yield return line;
}
}
}
2
Answers
I found the fix to simply use .ConfigureFunctionsWebApplication() in the program.cs of the API project instead of ConfigureFunctionsWorkerDefaults() to make it use ASP.NET Core Integration
Below are the steps to create a Stream API in Azure Static Web Apps using an Azure Function App.
I followed this link to build Blazor and C# APIs in Azure Static Web Apps.
App.js:
Program.cs:
I have registered and configured the
StreamingApiService
class using theAddScoped
method inProgram.cs
local.settings.json
of Function App :Change the Git
yml
according to your folder structure:Refer to this Stack Overflow post for the YAML workflow file of Static Web App.
Deployment Status in git:
Azure Static Output:
Azure Functions app Output in Azure Static: