javascript - 部署到 IIS 7.5 服务器的 React/dotnetcore 3.1 mvc 应用程序正确加载,但对 API 的 javascript 调用每个返回 index.html
问题描述
我的猜测是我正在处理 IIS 路由问题。
我有一个在 Visual Studio 中开发的 React/dotnet core 3.1 应用程序。加载后,React 应用程序会尝试调用应用程序中的 REST 服务来为选择组件提取数据(选择组件是公司的下拉列表)。
一切都在开发环境中运行良好。当我部署到登台服务器时,所有 API 调用都被重定向到 index.html 并且我从未得到我期望的数据。
我最好的猜测是我的 IIS 7.5 服务器中的路由配置错误,它不知道如何处理对“/api/”的调用
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
DATA REMOVED HERE
}
}
程序.cs:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args)
.Build()
.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
启动.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
// DI
services.AddSingleton<IConfiguration>(this.Configuration);
/*services.Configure<IISServerOptions>(options =>
{
options.AutomaticAuthentication = false;
});*/
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/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.UseSpaStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
}
- 主应用程序的 URL 是:
http://vmsaudit.esdev2.elwood.local
- 服务器的 API 调用 URL 为:
http://vmsaudit.esdev2.elwood.local/api/Company/er
这是我的公司控制器的代码:
[ApiController]
[Route("api/[controller]")]
public class CompanyController
{
VMSImportEngineContext db;
ErecruitContext erdb;
IConfiguration config;
public CompanyController (VMSImportEngineContext db, ErecruitContext erdb, IConfiguration config)
{
this.db = db;
this.erdb = erdb;
this.config = config;
}
[HttpGet("{datastore}")]
public List<Company> Get(string datastore)
{
List<Company> ret = new List<Company>();
if ("ss".Equals(datastore))
{
List<int?> vmsClients = db.VmsClient
.Where(c => c.legacyID != null && c.audit == true)
.Select(c => c.legacyID)
.ToList();
ret = this.GetSSCompanies(vmsClients);
}
else // Has to be ERecruit client
{
List<int> vmsClients = db.VmsClient
.Where(c => c.audit == true)
.Select(c => c.clientid)
.ToList();
ret = this.erdb
.Company
.Where(c => vmsClients.Contains(c.company_id))
.ToList();
}
return ret;
}
private List<Company> GetSSCompanies(List<int?> vmsClients)
{
List<Company> ret = new List<Company>();
// Generate a linked query
string connectionString = this.config.GetConnectionString("vmsimportengine");
SqlConnection connection = new SqlConnection(connectionString);
if (connection.State != System.Data.ConnectionState.Open)
{
connection.Open();
}
DbCommand command = connection.CreateCommand();
command.CommandText = GenSSCompanyQuery(vmsClients);
DbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Company company = GetCompanyFromDataRow(reader);
ret.Add(company);
}
return ret;
}
private Company GetCompanyFromDataRow(DbDataReader reader)
{
Company c = new Company();
if (!reader.IsDBNull(reader.GetOrdinal("name")))
{
c.name = reader.GetString(reader.GetOrdinal("name"));
}
if (!reader.IsDBNull(reader.GetOrdinal("company_component_id")))
{
int cid = (int)reader.GetDouble(reader.GetOrdinal("company_component_id"));
// now get the real ID from the current system...
List<int> potential = this.db.VmsClient
.Where(c => c.legacyID == cid)
.Select(c => c.clientid)
.ToList();
if (potential.Count > 0)
{
c.company_id = potential[0];
}
}
return c;
}
private string GenSSCompanyQuery(List<int?> vmsClients)
{
// Code Suppressed
}
}
更新
我决定向我的控制器添加一个新方法,该方法似乎正在返回数据......我的问题显然是在 API URL 调用结束时传递一个参数???这是我刚刚添加到控制器中的方法,它成功返回“pong”
[HttpGet]
public string ping()
{
return "pong";
}
总之:
- 此 API URL 有效 - http://vmsaudit.esdev2.elwood.local/api/Company
- 此 API URL 不 - http://vmsaudit.esdev2.elwood.local/api/Company/ss
唯一的区别是 URL 末尾的参数
解决方案
问题是数据库连接。我使用的应用程序池的身份验证凭据不正确。结果是所有使用连接的 REST 服务调用都返回了 index.html 页面。我认为这是因为实体框架代码在启动时引发了异常并且从未到达路由代码?
推荐阅读
- javascript - StripeInvalidRequestError:创建“account_onboarding”类型的帐户链接时,您必须提供具有功能的帐户
- linux - 我可以在同一行的 file.txt 上写吗
- ruby-on-rails - Rails 6、Webpack、Bootstrap 5 - Bootstrap 无法在生产环境中编译
- python - 如何在使用带有请求库的 POST 方法时修复 406 状态代码
- python - python返回xmlblock并删除编码标签
- java - 检查字符串是否存在于 HashSet Java 中的时间复杂度
- r - 创建每个采样站点的唯一访问列
- android - 使用 Gradle 7.1.0-alpha03 和 Composer 的新 Android 项目无法构建
- excel - Excel - 格式化一个单元格,使其显示另一个单元格的算术表达式
- python - 在 Windows Python 中处理权限被拒绝错误