Previously I was working with react projects on .NET 3.1, and I just tried to create a fresh project on .NET 8.0 and encountered a lot of troubles and misunderstandings. I created a new controller and now trying to access it method, but I get the error 404 Not Found. I found out that frontend is trying to send requests to its own port instead of backend port. When I press "Run", my project starts in two windows: one is google chrome that represents backend, I guess, and one in edge where frontend is. So, in the google chrome window the link is http://localhost:5239/
and in edge the link is https://localhost:5173/
which is also uncommon to me.
This is my controller:
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
private readonly UserRepository _repo;
public UsersController(UserRepository repo)
{
_repo = repo;
}
[HttpPost("[action]")]
public async Task<IActionResult> RegisterUser(User user)
{
try
{
var existingUser = await _repo.GetUserByUsernameAsync(user.Login);
if (existingUser != null)
{
return Conflict("This login already exists.");
}
// Hash the password using BCrypt
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(user.Password);
// Replace the plaintext password with the hashed password
user.Password = hashedPassword;
var result = await _repo.CreateUserAsync(user, user.Password);
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost("[action]")]
public async Task<IActionResult> GetUserByUserName(string username)
{
try
{
return Ok(await _repo.GetUserByUsernameAsync(username));
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
This are my Program.cs
file contents:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseRouting();
app.MapControllers();
app.MapFallbackToFile("/index.html");
app.Run();
This is my react component:
import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import './register.scss';
const Register: React.FC = () => {
const [username, setUsername] = useState('');
const [fio, setFio] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const handleRegister = async () => {
try {
const response = await fetch('api/users/RegisterUser', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ login: username, name: fio, password: password }),
});
if (response.ok) {
console.log('User registered successfully');
} else {
console.error('Registering user failed');
}
} catch (error) {
console.error('Error on registering user:', error);
}
};
return (
<div className="register-container">
<h2>Регистрация</h2>
<div className='register-content'>
<div>
<label htmlFor="username">Login:</label>
<input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
</div>
<div>
<label htmlFor="fio">Name:</label>
<input
type="text"
id="fio"
value={fio}
onChange={(e) => setFio(e.target.value)}
required
/>
</div>
<div>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<button onClick={handleRegister}>Register</button>
</div>
<p>
Already have an account? <Link to="/login">Log in</Link>
</p>
</div>
);
};
export default Register;
These are my response headers:
HTTP/1.1 404 Not Found
Access-Control-Allow-Origin: *
Date: Wed, 15 May 2024 08:34:36 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 0
These are my request headers:
POST /api/users/RegisterUser HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: ru,en;q=0.9,en-GB;q=0.8,en-US;q=0.7
Connection: keep-alive
Content-Length: 45
Content-Type: application/json
Host: localhost:5173
Origin: https://localhost:5173
Referer: https://localhost:5173/register
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0
sec-ch-ua: "Microsoft Edge";v="123", "Not:A-Brand";v="8", "Chromium";v="123"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Please, tell me, what am I doing wrong or how to properly configure my app, I feel completely lost and destroyed by the modern .NET. Also please ask if you need any additional info/code.
In your react code in the function handleRegister you have
const response = await fetch('api/users/RegisterUser', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
The fetch without a base url will be called on the current url of the page, so in this case it's just appending 'api/users/RegisterUser' to your frontend url. You must set the backend url in the fetch target:
fetch('http://localhost:5239/api/users/RegisterUser'...
I suggest to have it stored somehow as env or global variable and set in every backend endpoint call. (but that's not my field i cannot say what's the best practice).
Also just for you to know this is not a minimal api aproach (as stated in the title), but it's a classic controller.