I created an Asp Net Razor project in visual studio 2019.
I'm learning the technology with some exercises. Specifically, I would like to display on a page a chart whose data i would like to retrieve via an ApiController.
[Route("api/[controller]")]
[ApiController]
public class AjaxAPIController : ControllerBase
{
public ChartData chartData = new ChartData();
[HttpGet]
[Route("ChartDataJson")]
public IActionResult ChartDataJson()
{
// First example
var x = new List<double> { 1.0,};
var y = new List<double> { 10.0,};
var chartData = new { x, y };
return Ok(chartData);
}
[HttpGet]
[Route("ChartDataJson2")]
public IActionResult ChartDataJson2()
{
// Second Example
var x = new List<double> {1.0, 20.0, 30.0 };
var y = new List<double> {2.0, 30.0, 45.0};
var chartData = new { x, y };
return Ok(chartData);
}
[HttpPost]
[Route("UpdateChartData")]
public IActionResult UpdateChartData([FromBody] ChartData data)
{
// Read received data
var newDataX = data.X;
var newDataY = data.Y;
var chartData = new { x = new List<double>[] { newDataX }, y = new List<double>[] { newDataY } };
return Ok(chartData);
}
}
The values of the chart, can be updated in 3 different ways:
// When the button 1 is clicked, get data from the controller and update the chart
$("#btnGet").click(function () {
console.log("button 1 click is executed.");
$.get("/api/AjaxAPI/ChartDataJson", function (data) {
updateScatterChart(data);
});
});
// When the button 2 is clicked, get data from the controller and update the chart
$("#btnGet2").click(function () {
console.log("button 2 click is executed.");
$.get("/api/AjaxAPI/ChartDataJson2", function (data) {
updateScatterChart(data);
});
});
// Update the data chart when a post request is received
$.post("/api/AjaxAPI/UpdateChartData", function (data) {
console.log("X values:", data.x);
console.log("Y values:", data.y);
updateScatterChart(data);
});
The result is something like:
Steps 1 and 2 work correctly but step 3 doesn't work...
The first problem occurs when the page is loaded:
jquery.min.js:2 POST https ://localhost:44354/api/AjaxAPI/UpdateChartData 400 (Bad Request)
In addition, if I try to launch in the browser console the script:
fetch("https://localhost:44354/api/AjaxAPI/UpdateChartData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ X: [400.0], Y: [600.0] }),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error: " + error));
to simulate the post request, I can in debug read the values in the ApiController class but I can't correctly update the values of the chart.
My full code is available here: https://github.com/DanielScerpa/RazorPageChart/tree/dev_chart
Summarizing:
I would like to understand how I can correctly update my chart values when I receive a post request and I would like to understand the startup problem 400 (Bad Request)
!!!...EDIT...!!!
Summarazing:
Example, someone calls:
<https://localhost:44354/api/AjaxAPI/UpdateChartData>
I intercept the post call via the code:
[HttpPost]
[Route("UpdateChartData")]
public IActionResult UpdateChartData([FromBody] ChartData data)
{
// Read received data
var newDataX = data.X;
var newDataY = data.Y;
var chartData = new { x = new List<double>[] { newDataX }, y = new List<double>[] { newDataY } };
return Ok(chartData);
}
}
at this point how can I update the chart with the newly retrieved values (data.x and data.y)?
From your requirement, you are expecting the web application to be updated for the chart when any user posts the request to the "UpdateChartData" API.
This requires the SignalR for the real-time communication. The full demo for the installation and tutorial you may refer to the link provided.
As you are using the .NET Core 2.2 for the project and this version is deprecated, the only supported version for Microsoft.AspNetCore.SignalR.Common is with version 1.1.0. The provided steps below are for setting up the SignalR in your application specified for .NET Core 2.2.
Via NuGet, install Microsoft.AspNetCore.SignalR.Common 1.1.0
Right-click the project > Manage Client-side Libraries, it will generate a libman.json file. In the file, you install the @microsoft/signalr library as below:
{
"version": "1.0",
"defaultProvider": "unpkg",
"libraries": [
{
"library": "@microsoft/signalr@latest",
"destination": "wwwroot/js/signalr",
"files": [
"dist/browser/signalr.js",
"dist/browser/signalr.min.js"
]
}
]
}
namespace Razor_WebAPI_Application.Hubs
{
public class ChartHub : Hub
{
public async Task UpdateChart(ChartData chartData)
{
await Clients.All.SendAsync("UpdateChart", chartData);
}
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseSignalR(routes =>
{
routes.MapHub<ChartHub>("/chartHub");
});
}
}
ChartHub
from the DI. And emit the data to all clients.using Microsoft.AspNetCore.SignalR;
using Razor_WebAPI_Application.Hubs;
[Route("api/[controller]")]
[ApiController]
public class AjaxAPIController : ControllerBase
{
private readonly IHubContext<ChartHub> _hubContext;
public AjaxAPIController(IHubContext<ChartHub> hubContext)
{
_hubContext = hubContext;
}
}
[HttpPost]
[Route("UpdateChartData")]
public IActionResult UpdateChartData([FromBody] ChartData data)
{
// Read received data
var newDataX = data.X;
var newDataY = data.Y;
var chartData = new { x = new List<double>[] { newDataX }, y = new List<double>[] { newDataY } };
_hubContext.Clients.All.SendAsync("UpdateChart", chartData);
return Ok(chartData);
}
<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script type="text/javascript">
...
var connection = new signalR.HubConnectionBuilder().withUrl("/chartHub").build();
connection.on("UpdateChart", function (data) {
updateScatterChart(data);
});
connection.start().then(function () {
}).catch(function (err) {
return console.error(err.toString());
});
</script>