.NET Core API 端点仅在部署版本中提供 404
.NET Core API Endpoint gives 404 only in deployed version
我正在构建一个托管在 IIS 中的 .NET Core (3.1) Web API。
我有 2 个端点:
/api/status
/api/widget/config/{id}
当 运行 在本地时,两个端点都能正常工作。 /api/status 端点也适用于我的部署版本。但是另一个端点在部署版本中给出了 404 错误。由于它在本地工作,我认为这是它的部署方式的问题。你能帮我理解这个问题吗?
这是我的 2 个控制器代码:
[Route("api/[controller]")]
[ApiController]
public class StatusController : ControllerBase
{
[HttpGet]
public ActionResult Get()
{
return Ok("API is available");
}
}
和
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
private readonly IWidgetService service;
public WidgetController(IWidgetService _service)
{
service = _service;
}
[HttpGet]
[Route("~/api/[controller]/[action]/{id}")]
public ActionResult Config(Guid id)
{
return Ok(service.GetWidgetConfig(id));
}
}
下面是我的 Program.cs 和 Startup.cs:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
SeedDatabase.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occured seeding the DB");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel();
webBuilder.UseContentRoot(Directory.GetCurrentDirectory());
webBuilder.UseIIS();
webBuilder.UseStartup<Startup>();
});
和
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(opts => opts.UseSqlServer(Configuration.GetConnectionString("sqlConnection"),
options => options.MigrationsAssembly("MyProject")));
services.AddIdentity<ApplicationUser, IdentityRole>(opt =>
{
opt.Password.RequiredLength = 8;
opt.Password.RequireDigit = true;
opt.Password.RequireUppercase = true;
opt.Password.RequireNonAlphanumeric = true;
opt.SignIn.RequireConfirmedAccount = false;
opt.SignIn.RequireConfirmedAccount = false;
opt.SignIn.RequireConfirmedPhoneNumber = false;
}).AddEntityFrameworkStores<ApplicationDbContext>();
services.AddScoped<IWidgetService, WidgetService>();
services.AddCors(o => o.AddPolicy("CorsPolicy", builder => {
builder
.WithMethods("GET", "POST")
.AllowAnyHeader()
.AllowAnyOrigin();
}));
services.AddMvc()
.AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
将您的控制器代码更改为:
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
private readonly IWidgetService service;
public WidgetController(IWidgetService _service)
{
service = _service;
}
[HttpGet("Config/{id}")]
public ActionResult Config(Guid id)
{
return Ok(service.GetWidgetConfig(id));
}
}
像下面这样更改您的代码:-
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
控制器:-
[ApiController]
[Route("api/[controller]")]
public class WidgetController : ControllerBase
{
private readonly IWidgetService service;
public WidgetController(IWidgetService _service)
{
service = _service;
}
[HttpGet("Config/{id}")]
public ActionResult Config(Guid id)
{
return Ok(service.GetWidgetConfig(id));
}
}
也尝试在 appsettings.Development.json
文件中写入连接字符串。
它将解决您的问题。
我正在构建一个托管在 IIS 中的 .NET Core (3.1) Web API。
我有 2 个端点:
/api/status
/api/widget/config/{id}
当 运行 在本地时,两个端点都能正常工作。 /api/status 端点也适用于我的部署版本。但是另一个端点在部署版本中给出了 404 错误。由于它在本地工作,我认为这是它的部署方式的问题。你能帮我理解这个问题吗?
这是我的 2 个控制器代码:
[Route("api/[controller]")]
[ApiController]
public class StatusController : ControllerBase
{
[HttpGet]
public ActionResult Get()
{
return Ok("API is available");
}
}
和
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
private readonly IWidgetService service;
public WidgetController(IWidgetService _service)
{
service = _service;
}
[HttpGet]
[Route("~/api/[controller]/[action]/{id}")]
public ActionResult Config(Guid id)
{
return Ok(service.GetWidgetConfig(id));
}
}
下面是我的 Program.cs 和 Startup.cs:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
SeedDatabase.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occured seeding the DB");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel();
webBuilder.UseContentRoot(Directory.GetCurrentDirectory());
webBuilder.UseIIS();
webBuilder.UseStartup<Startup>();
});
和
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(opts => opts.UseSqlServer(Configuration.GetConnectionString("sqlConnection"),
options => options.MigrationsAssembly("MyProject")));
services.AddIdentity<ApplicationUser, IdentityRole>(opt =>
{
opt.Password.RequiredLength = 8;
opt.Password.RequireDigit = true;
opt.Password.RequireUppercase = true;
opt.Password.RequireNonAlphanumeric = true;
opt.SignIn.RequireConfirmedAccount = false;
opt.SignIn.RequireConfirmedAccount = false;
opt.SignIn.RequireConfirmedPhoneNumber = false;
}).AddEntityFrameworkStores<ApplicationDbContext>();
services.AddScoped<IWidgetService, WidgetService>();
services.AddCors(o => o.AddPolicy("CorsPolicy", builder => {
builder
.WithMethods("GET", "POST")
.AllowAnyHeader()
.AllowAnyOrigin();
}));
services.AddMvc()
.AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
将您的控制器代码更改为:
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
private readonly IWidgetService service;
public WidgetController(IWidgetService _service)
{
service = _service;
}
[HttpGet("Config/{id}")]
public ActionResult Config(Guid id)
{
return Ok(service.GetWidgetConfig(id));
}
}
像下面这样更改您的代码:-
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
控制器:-
[ApiController]
[Route("api/[controller]")]
public class WidgetController : ControllerBase
{
private readonly IWidgetService service;
public WidgetController(IWidgetService _service)
{
service = _service;
}
[HttpGet("Config/{id}")]
public ActionResult Config(Guid id)
{
return Ok(service.GetWidgetConfig(id));
}
}
也尝试在 appsettings.Development.json
文件中写入连接字符串。
它将解决您的问题。