The sample solution has for FetchData.Razor forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast"); The quoted part Seems to indicate the name of the controller. Is that correct ?
I want to extend the example to understand how to use it. To do this I would enable the user to choose a refresh rate and automatically refresh the data - but first step is to record the 2 values with a new class LastUpdateInfo in .shared weatherForcast.cs
public class LastUpDateInfo
{
public int updateRateSecs { get; set; }
public DateTime RefreshDateTime { get; set; }
}
While the solution does compile, I get an unhandled exception -response status code does not indicate success. (500)
I added this to controller
public LastUpDateInfo GetUpdateInfo()
{
var thisUpDateInfo = new LastUpDateInfo();
thisUpDateInfo.RefreshDateTime = DateTime.Now;
thisUpDateInfo.updateRateSecs = 3; // needs to be fed from UX
return thisUpDateInfo;
}
and called from FetchData.razor
protected override async Task OnInitializedAsync()
{
currInfo = await Http.GetFromJsonAsync<LastUpDateInfo>("WeatherForecast");
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast"); // URI ? is the quoted the controllerName ?
// why is there a literal here called "WeatherForecast" ??
}
The blazor assembly feels quite different than previous Rest API with razor pages (cshtml) and Im struggling to get a grasp of the mechanics.
Thanks !
I added a second class, updated the controller and called from FetchData.razor However the call throws an error ( 500 ) but dont understand how it should work
In Client/Program.cs
you can find a line like this:
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
This registers an HttpClient
as a scoped service. The BaseAddress
of the HttpClient
is configured to be the address of the "host environment". The host is basically the Server application where the api also exists. Let's say your server is listening on https://localhost:3377
so this is the BaseAddress
of the HttpClient
.
When you call:
await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
the string parameter is the relative uri that should be appended to the base address, in this case "WeatherForecast". The final uri will be base address uri + relative uri so it will send a GET request to https://localhost:3377/WeatherForecast
.
This is the route for the Get
endpoint in the WeatherForecastController
. This happens because the controller has the [Route("[controller]")]
attribute. This means all the endpoints inside this controller will start with /WeatherForecast
in the route. The Get
method does not have its own Route
attribute so the final route to access it is https://localhost:3377/WeatherForecast
.
On your GetUpdateInfo
method you also did not specify a route so both endpoints have the same route and the app can't differentiate between the two so it throws exception. Instead in your GetUpdateInfo
endpoint you can add a [Route("UpdateInfo")]
attribute.
[HttpGet]
[Route("UpdateInfo")]
public LastUpDateInfo GetUpdateInfo()
{
var thisUpDateInfo = new LastUpDateInfo();
thisUpDateInfo.RefreshDateTime = DateTime.Now;
thisUpDateInfo.updateRateSecs = 3; // needs to be fed from UX
return thisUpDateInfo;
}
Then the absolute route to that endpoint will be https://localhost:3377/WeatherForecast/UpdateInfo
and in your Client you can do:
await Http.GetFromJsonAsync<LastUpDateInfo>("WeatherForecast/UpdateInfo");
You can check Attribute routing for REST APIs to better understand how routing in ASP.NET Core controllers works.