正如标题所示,我使用 CORS 在 .NET 8 中设置了一个最小的 WEB API,并且路由似乎在后端运行良好,甚至使用 VSCode 中的 REST 客户端扩展测试了 CRUD 操作。
当我尝试从其中一条路线获取数据并将数据记录在控制台上时,我收到此错误:
从源“http://localhost:3000”获取“http://localhost:5050/words”的访问已被 CORS 策略阻止:请求中不存在“Access-Control-Allow-Origin”标头资源。
下面是从路由获取的 React 组件的代码:
import { useEffect } from "react"
const NewWord = () => {
const submitHandler = async() => {
try {
const response = await fetch("http://localhost:5050/words")
const data = await response.json()
console.log(data)
} catch (error) {
console.error(error)
}
}
return (
<>
<h1 className="text-center text-bold text-white">New Word</h1>
{/* Major container */}
<div className="">
{/* Container */}
<div className="border border-solid p-4 my-4 rounded-xl bg-green-300">
{/* Word */}
<div className=" p-2">
<input type="text" name="" id=""
placeholder="Word"
className="w-full"/>
</div>
{/* Definition */}
<div className="p-2">
<input type="text"
name="" id=""
placeholder="Type your definition here..."
className="w-full" />
</div>
{/* Example */}
<div className="p-2">
<input type="text"
name="" id=""
placeholder="Example sentence..."
className="w-full"/>
</div>
{/* Tags */}
<div className="p-2">
<input type="text"
placeholder="Type a list of comma-separated tags..."
className="w-full" />
</div>
{/* Language */}
<div className="p-2">
<select name="" id="">
<option value="english">English</option>
<option value="hausa">Hausa</option>
<option value="french">French</option>
<option value="arabic">Arabic</option>
<option value="wolof">Wolof</option>
<option value="zulu">Zulu</option>
<option value="swahili">Swahili</option>
<option value="igbo">Igbo</option>
<option value="xhosa">Xhosa</option>
</select>
</div>
<div className="mt-2 flex justify-center">
<button
className="border-4 rounded-xl p-2 w-full font-bold"
onClick={submitHandler}>
Submit
</button>
</div>
</div>
</div>
</>
)
}
export default NewWord
和最小的 API:
using AUB_backend;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// DbContext configuration
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
// CORS configuration
builder.Services.AddCors(options => {
options.AddPolicy("AllowSpecificOrigin", builder =>
{
builder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
// enable CORS
app.UseCors("AllowSpecificOrigin");
app.UseRouting();
// default page
app.MapGet("/", () => "API Default Page");
// CRUD actions
// CREATE a new word
app.MapPost("/words", async(AppDbContext DbContext, Word newWord) => {
DbContext.Words.Add(newWord); // add new word to db
await DbContext.SaveChangesAsync(); // save changes to db asynchronously
return Results.Created($"/words/{newWord.Id}", newWord);
});
// READ all words
app.MapGet("/words", async(AppDbContext DbContext) => {
var words = await DbContext.Words.ToListAsync(); // fetch words from db
return Results.Ok(words);
});
// READ an existing word by Id
app.MapGet("/words/{id}", async(AppDbContext DbContext, int id) => {
var word = await DbContext.Words.FindAsync(id); // fetch word from db using Id
if (word is not null)
{
return Results.Ok(word);
}
else
{
return Results.NotFound();
}
});
// UPDATE a word
app.MapPut("/words/{id}", async(AppDbContext DbContext, int id, Word updatedWord) =>
{
var word = await DbContext.Words.FindAsync(id);
if (word is null)
{
return Results.NotFound();
}
// update word properties
word.Term = updatedWord.Term;
word.Definition = updatedWord.Definition;
word.Example = updatedWord.Example;
word.Tags = updatedWord.Tags;
word.Language = updatedWord.Language;
await DbContext.SaveChangesAsync(); // save changes to db
return Results.Ok(word);
});
// DELETE an existing word
app.MapDelete("words/{id}", async(AppDbContext DbContext, int id) => {
var word = await DbContext.Words.FindAsync(id); // find word by Id
if (word is null)
{
return Results.Ok(word);
}
DbContext.Words.Remove(word); // remove word from db
await DbContext.SaveChangesAsync(); // save changed
return Results.NoContent(); // return a 204 response (No Content)
});
app.Run();
来自 CORS 以及命名策略和中间件,
对
的呼叫必须在UseCors
之后进行。UseRouting
您的中间件管道(结构)应如下所示:
var app = builder.Build();
app.UseRouting();
// enable CORS
app.UseCors("AllowSpecificOrigin");
...
此外,我建议将“http://localhost:3000”放入 appsettings.{Environment}.json 中,并从应用程序设置 (
builder.Configuration
) 中获取值,而不是在代码中进行硬编码(如果您是)计划在不同的环境中托管您的应用程序:暂存和生产。因此,允许的来源(值)是根据其托管环境分配的。参考:访问Program.cs中的配置