skip to Main Content

I have just started building a website using React with a .NET Core backend. The default framework gives me the WeatherForecast controller. When making calls to this, there are no issues: fetch('weatherforecast') returns the data.

Next I tried adding a second endpoint, Sitemap, which is designed to return a JSON string (or array) to the client. Every time it is returning the base HTML page being displayed. In the setupProxy.js file I have added /sitemap to the createProxyMiddleware context and I have used the "add Controller" option in VS2022.

I would blame this on my code but for one thing: when I replace the code in the WeatherForecast controller with my own to return the sitemap, it works perfectly and returns the data I want.

Since this site will eventually have multiple API endpoints I need to know what I was doing wrong to get this functioning.

Below are the 3 files involved:

//setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');

const context = [
    "/weatherforecast",
    "/sitemap"
];

module.exports = function (app) {
    const appProxy = createProxyMiddleware(context, {
        target: 'https://localhost:7245/',
        secure: false
    });

    app.use(appProxy);
};
//app.js
import React, { Component } from 'react';

export default class App extends Component {
    static displayName = App.name;

    constructor(props) {
        super(props);
        this.state = { forecasts: [], loading: true, sitemap:[] };
    }

    componentDidMount() {
        this.populateWeatherData();
        this.populateSitemapData();
    }

    static renderForecastsTable(forecasts) {
        return (
            <div>
            <table className='table table-striped' aria-labelledby="tabelLabel">
                <thead>
                    <tr>
                        <th>Date</th>
                        <th>Temp. (C)</th>
                        <th>Temp. (F)</th>
                        <th>Summary</th>
                    </tr>
                </thead>
                <tbody>
                    {forecasts.map(forecast =>
                        <tr key={forecast.date}>
                            <td>{forecast.date}</td>
                            <td>{forecast.temperatureC}</td>
                            <td>{forecast.temperatureF}</td>
                            <td>{forecast.summary}</td>
                        </tr>
                    )}
                </tbody>
                </table>
                {/*{JSON.stringify(this.state.sitemap)}*/}
            </div>
        );
    }

    render() {
        let contents = this.state.loading
            ? <p><em>Loading... Please refresh once the ASP.NET backend has started. See <a href="https://aka.ms/jspsintegrationreact">https://aka.ms/jspsintegrationreact</a> for more details.</em></p>
            : App.renderForecastsTable(this.state.forecasts);

        return (
            <div>
                <h1 id="tabelLabel" >Weather forecast</h1>
                <p>This component demonstrates fetching data from the server.</p>
                {contents}
            </div>
        );
    }

    async populateWeatherData() {
        const response = await fetch('weatherforecast');
        const data = await response.json();
        this.setState({ sitemap: data, loading: false });
        //this.setState({ forecasts: data, loading: false });
    }
    async populateSitemapData() {
        const response = await fetch('sitemap');
        const data = await response.json();
        const temp = data;
        console.log(data);
        this.setState({ sitemap: temp, loading: false });
    }
}
//WeatherForecastController.cs (with my code working)
using Microsoft.AspNetCore.Mvc;

namespace webapi.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<Intranet2.MCA.SitemapEntry> Get()
    //public IEnumerable<WeatherForecast> Get()
    {
        //return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        //{
        //    Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
        //    TemperatureC = Random.Shared.Next(-20, 55),
        //    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        //})
        //.ToArray();
        return Intranet2.MCA.Data.Sitemap().ToArray<Intranet2.MCA.SitemapEntry>();
    }
}
//SitemapController.cs
using Intranet2.MCA;
using Microsoft.AspNetCore.Mvc;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace webapi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class SitemapController : ControllerBase
    {
        // GET: api/<SitemapController>
        [HttpGet]
        //public string Get() //IEnumerable<Intranet2.MCA.SitemapEntry>
        //{
        //    Console.WriteLine("Sitemap Test");
        //    var siteMap = Data.Sitemap();
        //    return siteMap;
        //}
    }
}
//Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

I am sure that there is some overkill in the code displayed here but as I don’t know where the problem lies (obviously API call, but where?) I included everything which may play a part.

Any advice on where to find the solution to this would be appreciated. Having read multiple tutorials and pages on this, and even resorting to ChatGPT has availed nothing. Thank you.

*** EDIT ***
When I make a direct call to https://localhost:7245/sitemap from the address bar it returns the correct data, so the problem appears to be in the proxy code.

2

Answers


  1. Chosen as BEST ANSWER

    So in playing around this morning and trying different things I found that I could call the sitemap controller directly from the URL of the browser. After doing that I found that it was working correctly. I modified populateWeatherData() to call both API's

    async populateWeatherData() {
            const response = await fetch('weatherforecast');
            const weather = await response.json();
    
            const resp = await fetch('sitemap');
            const sitemap = await resp.json();
            const temp = sitemap;
            console.log(sitemap);
            this.setState({forecasts: weather, sitemap: sitemap, loading: false });
        }
    

    and I am now seeing the results I needed on the page. Not sure why it's working now when it wasn't yesterday but I am content.


  2. I think your code about endpoint is correct. and your issue may come from here.

    enter image description here

    I created a new react asp.net core project, and I added an endpoint in Weather controller which url should be /weatherforecast/getstring

    [HttpGet("GetString")]
    public string GetString()
    {
        return "hello world";
    }
    

    Then in the react page. I added new property cont in this.state, and define a function to call the endpoint.

    async populateWeatherData2() {
            const response = await fetch('weatherforecast/getstring');
            const data = await response.text();
            this.setState({ cont: data, loading: false });
        }
    

    Then change FetchData.renderForecastsTable(this.state.forecasts); to FetchData.renderForecastsTable(this.state.forecasts, this.state.cont); , and change static renderForecastsTable(forecasts) { to static renderForecastsTable(forecasts,cont) {, then code worked. So I’m afraid this is the issue.

    enter image description here
    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search