我有一个 Web 应用程序,以 React 作为前端,以 .NET core 8 作为后端。 该应用程序有一个带有
Meals
按钮的导航。单击它后,会出现带有两个以上按钮的子导航。其中一个是All meals
,另一个是Add meal
。一切都工作得很好,直到我决定前端应该在获取所有餐点时发送当前日期。然后,当我添加后端控制器 [FromBody] string date
时,它开始抛出两个尚未抛出的错误,并且直到我删除 [FromBody] string date
并重建项目后,它才会得到修复。
错误如下,第一个是后端的,第二个是前端的: 1 - `Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] 执行请求时发生未处理的异常。 Microsoft.AspNetCore.Routing.Matching.AmbigouslyMatchException:请求匹配多个终结点。比赛:
Fitness_Tracker.Controllers.MealController.AllMeals (Fitness-Tracker)
Fitness_Tracker.Controllers.MealController.AllMeals (Fitness-Tracker)
at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ReportAmbiguity(Span1 candidateState)
at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ProcessFinalCandidates(HttpContext httpContext, Span1 candidateState)
at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.Select(HttpContext httpContext, Span1 candidateState)
at Microsoft.AspNetCore.Routing.Matching.DfaMatcher.MatchAsync(HttpContext httpContext)
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)`
2-
Access to fetch at 'https://localhost:7009/api/meal/all' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
import React, { useEffect, useState } from 'react';
import '../../css/AllMealsPage.css';
const AllMealsPage = () => {
const [meals, setMeals] = useState([]);
const [calories, setCalories] = useState(0);
const [errorMessage, setErrorMessage] = useState('');
const [selectedDate, setSelectedDate] = useState(new Date());
useEffect(() => {
const fetchMeals = async () => {
try {
const response = await fetch('https://localhost:7009/api/meal/all', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ date: selectedDate.toISOString() })
});
if (!response.ok) {
throw new Error('Displaying meals failed');
}
const data = await response.json();
setMeals(data);
setErrorMessage('');
} catch (err) {
setErrorMessage(err.message);
}
};
fetchMeals();
}, [selectedDate]);
useEffect(() => {
const fetchCalories = async () => {
try {
const response = await fetch('https://localhost:7009/api/meal/calories', {
method: 'POST',
credentials: 'include'
});
if (!response.ok) {
throw new Error('Displaying calories failed');
}
const data = await response.json();
setCalories(data);
setErrorMessage('');
} catch (err) {
setErrorMessage(err.message);
}
};
fetchCalories();
}, [selectedDate]);
const handlePreviousDay = () => {
setSelectedDate(prevDate => {
const newDate = new Date(prevDate);
newDate.setDate(prevDate.getDate() - 1);
return newDate;
});
};
const handleNextDay = () => {
setSelectedDate(prevDate => {
const newDate = new Date(prevDate);
const today = new Date();
if (newDate.toDateString() !== today.toDateString()) {
newDate.setDate(prevDate.getDate() + 1);
}
return newDate;
});
};
return (
<div className="all-meals-container">
{errorMessage && <p className="error-message">{errorMessage}</p>}
<div className="date-navigation">
<button onClick={handlePreviousDay}>←</button>
<span>{selectedDate.toDateString()}</span>
<button onClick={handleNextDay} disabled={selectedDate.toDateString() === new Date().toDateString()}>→</button>
</div>
<div className="table-wrapper">
<table className="meals-table">
<thead>
<tr>
<th>Meal Name</th>
<th>Meal of the Day</th>
<th>Calories</th>
</tr>
</thead>
<tbody>
{meals.map((meal) => (
<tr key={meal.id}>
<td>{meal.name}</td>
<td>{MealOfTheDayLabel(meal.mealOfTheDay)}</td>
<td>{meal.calories}</td>
</tr>
))}
</tbody>
</table>
</div>
<h1>Total calories: {calories}</h1>
</div>
);
};
const MealOfTheDayLabel = (mealOfTheDay) => {
switch (mealOfTheDay) {
case 0:
return 'Breakfast';
case 1:
return 'Lunch';
case 2:
return 'Dinner';
case 3:
return 'Snack';
default:
return 'Unknown';
}
};
export default AllMealsPage;
这是我的后端控制器(不工作时):
namespace Fitness_Tracker.Controllers
{
using Fitness_Tracker.Data.Models;
using Fitness_Tracker.Models.Meals;
using Fitness_Tracker.Services.Meals;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
public class MealController : BaseApiController
{
private readonly IMealService _mealService;
public MealController(IMealService mealService)
{
this._mealService = mealService;
}
[HttpPost("add")]
public async Task<IActionResult> AddMeal([FromBody] AddMealModel model)
{
if(!ModelState.IsValid)
{
return BadRequest();
}
string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if(userId == null) {
return BadRequest();
}
await _mealService.CreateMealAsync(userId, model);
return Ok();
}
[HttpPost("all")]
public async Task<IActionResult> AllMeals(string date)// Remove [FromBody] string date and it works
{
string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if(userId == null)
{
return BadRequest();
}
List<Meal> result = await _mealService.GetAllUserMealsAsync(userId);
return Ok(result);
}
[HttpPost("calories")]
public async Task<IActionResult> AllMealsCalories()
{
string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (userId == null)
{
return BadRequest();
}
int result = await _mealService.GetTotalUserMealCaloriesAsync(userId);
return Ok(result);
}
}
}
我玩弄了它,基本上无论我添加什么作为参数来捕获,例如
[FromQuery] string date
,简单的string date
等等 - 都会发生错误。
我似乎无法弄清楚问题是什么,因为我收到的错误与实际问题无关,因为否则一切都很好。
我原本希望简单地执行
[FromBody] string date
并捕获从前端发送的日期,但它进入了噩梦模式。
我建议为“所有”操作创建一个模型,如下所示:
[HttpPost("all")]
public async Task<IActionResult> AllMeals(AllMealsRequest allMealsRequest)// Remove [FromBody] string date and it works
{
[...]
}
// With a class similar to this:
public class AllMealsRequest
{
public string Date { get; set; }
}
原因是 json 已成为事实上的标准,并且当您发送有效负载时,api 默认情况下需要 json。创建一个对象只是让它与 api 配合得很好。此外,以后可以更轻松地向请求正文添加属性,而不会破坏将来的 api。