无法使用 wwwroot 作为 Angular 项目文件的路径在 Kestrel 服务器上使用 ASP.Net API 项目 运行 获取 Angular

Can't get Angular with ASP.Net API project running on Kestrel server using wwwroot as path to Angular project files

INFO - 我正在 运行ning 并在 VS Code 连接中成功调试我的 (Angular 10 / ASP.Net 5) 站点localhost:4200 使用 >ng serve 和 >dotnet 运行,我现在想将它发布到 Azure,但首先我只想在 Kestrel 上本地测试它,方法是构建 Angular 项目.Net API 项目中的 wwwroot 文件夹和 运行 来自 localhost:5001 的站点。我在我的 API 项目文件夹中构建 (>ng build) 到 wwwroot,我看到所有 Angular 文件都在 wwwroot 文件夹中创建,然后我执行 >dotnet 运行.

明白了

Now listening on: https://localhost:5001

然后我打开浏览器点击 url,我在终端中看到这些错误

info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 GET https://localhost:5001/ - - info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user. info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12] AuthenticationScheme: Bearer was challenged. info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user. info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12] AuthenticationScheme: Bearer was challenged. info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished HTTP/1.1 GET https://localhost:5001/ - - - 401 0 - 70.3847ms

问题 - 这是配置问题吗? CORS/permission 问题?身份验证问题? folder/path 个问题?

这是额外的代码,可以帮助任何可能帮助我理解正在发生的事情的人

Startup.cs

配置服务()

public void ConfigureServices(IServiceCollection services)
    {
        services.AddAutoMapper(typeof(MappingEvents));
        services.AddAutoMapper(typeof(MappingMembers));
        services.AddAutoMapper(typeof(MappingUsers));
        services.AddAutoMapper(typeof(MappingYogabands));
        services.AddAutoMapper(typeof(MappingReviews));
        // services.AddControllers();
        services.AddControllers()
            .AddNewtonsoftJson(opt => 
            {
                opt.SerializerSettings.ReferenceLoopHandling =
                     Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            });


        services.AddDbContext<DataContext>(x =>
            x.UseSqlServer(_config.GetConnectionString("SqlServerConnection"), y => y.UseNetTopologySuite()));

        services.AddTransient<IEmailSender, EmailSender>();
        services.Configure<AuthMessageSenderOptions>(_config.GetSection("SendGrid"));
        services.Configure<ConfirmationOptions>(_config.GetSection("Confirmation"));

        services.Configure<CloudinarySettings>(_config.GetSection("CloudinarySettings"));
        
        services.AddApplicationServices();
        services.AddIdentityServices(_config);
        services.AddSwaggerDocumentation();


        // telling out client app, that if it's running on an unsecure port, we won't return a header, 
        // that will allow our browser to display that information
        // * only allowed to access info from localhost:4200, all others will be denied?
        services.AddCors(opt => 
        {
            opt.AddPolicy("CorsPolicy", policy => 
            {
                policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("https://localhost:4200");
            });
        });
    }

配置()

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware<ExceptionMiddleware>();

        // when coming into the server and we don't have an endpoint that matches the request, then we hit this below
        // it will then re direct to our error controller, pass in the status code and return an object result
        app.UseStatusCodePagesWithReExecute("/errors/{0}"); // after creating ErrorController

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseCors("CorsPolicy");

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseSwaggerDocumention();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers().RequireAuthorization();
            // endpoints.MapControllers();
            endpoints.MapFallbackToController("Index", "Fallback");
        });
    }

AddIdentityService()(在 ConfigureServices() 中调用)

public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration config)
    {
        services.Configure<IdentityOptions>(options =>
        {
            options.User.RequireUniqueEmail = true;
            options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@";
        });

        var builder = services.AddIdentityCore<User>(opt =>
        {
            opt.Password.RequireDigit = false;
            opt.Password.RequiredLength = 2;
            opt.Password.RequireNonAlphanumeric = false;
            opt.Password.RequireUppercase = false;
            // *******************************************************
            // for email confirmation
            opt.SignIn.RequireConfirmedEmail = true;
            // *******************************************************
        });

        builder = new IdentityBuilder(builder.UserType, typeof(Role), builder.Services);
        // AddDefaultTokenProviders() allows the ability to create a token to send to user when they forgot password
        builder.AddEntityFrameworkStores<DataContext>().AddDefaultTokenProviders();
        
        // for roles
        builder.AddRoleValidator<RoleValidator<Role>>();
        builder.AddRoleManager<RoleManager<Role>>();

        builder.AddSignInManager<SignInManager<User>>();

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options => 
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Token:Key"])),
                    ValidIssuer = config["Token:Issuer"],
                    ValidateIssuer = true,
                    ValidateAudience = false
                };
            });

        services.AddAuthorization(options =>
        {
            options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
            options.AddPolicy("ModeratePhotoRole", policy => policy.RequireRole("Admin", "Moderator"));
            options.AddPolicy("VipOnly", policy => policy.RequireRole("VIP"));
        });

        return services;
    }

Angular.json 文件的构建部分

"build": {
      "builder": "@angular-devkit/build-angular:browser",
      "options": {
        "allowedCommonJsDependencies": ["angular2-wizard", "hammerjs"],
        "outputPath": "../API/wwwroot",
        "index": "src/index.html",
        "main": "src/main.ts",
        "polyfills": "src/polyfills.ts",
        "tsConfig": "tsconfig.app.json",
        "aot": true,
        "assets": [
          "src/favicon.ico",
          "src/assets"
        ],
        "styles": [
          "src/styles.scss"
        ],
        "scripts": []
      },
      "configurations": {
        "production": {
          "fileReplacements": [
            {
              "replace": "src/environments/environment.ts",
              "with": "src/environments/environment.prod.ts"
            }
          ],
          "optimization": true,
          "outputHashing": "all",
          "sourceMap": false,
          "extractCss": true,
          "namedChunks": false,
          "extractLicenses": true,
          "vendorChunk": false,
          "buildOptimizer": true,
          "budgets": [
            {
              "type": "initial",
              "maximumWarning": "2mb",
              "maximumError": "5mb"
            },
            {
              "type": "anyComponentStyle",
              "maximumWarning": "6kb",
              "maximumError": "10kb"
            }
          ]
        }
      }
    }

Environment.ts 在我的 Angular 项目中

export const environment = {
  production: false,
  apiUrl: 'https://localhost:5001/api/'
};

我解决了我的问题。 这是我所做的。

  1. 将此行添加到 Startup.cs

    中的 Configure()

    app.UseStaticFiles();

  2. 已删除

    .RequireAuthorization() 来自

    endpoints.MapControllers().RequireAuthorization();

现在工作正常,运行 我的 API 项目中来自 wwwroot 的 Ng 应用程序