我的猜测是我正在处理 IIS 路由问题。
我有一个正在 Visual Studio 中开发的 React/dotnet 核心 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 末尾的参数