首页 > 解决方案 > 部署到 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");
            }
        });
    }
}

这是我的公司控制器的代码:

[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";
    }

总之:

唯一的区别是 URL 末尾的参数

标签: javascriptc#reactjs.net-core

解决方案


问题是数据库连接。我使用的应用程序池的身份验证凭据不正确。结果是所有使用连接的 REST 服务调用都返回了 index.html 页面。我认为这是因为实体框架代码在启动时引发了异常并且从未到达路由代码?


推荐阅读