首页 > 解决方案 > 图片的内容类型无效(.net core sdk 2.1)

问题描述

我们正在将我们的项目从 .net core sdk 1.0 迁移到 2.1。到目前为止一切顺利,我已经能够将项目部署到暂存环境,但丢失的图像让我很困惑。所有图像都存在于服务器上,并且使用 .net core sdk 1.0 渲染得很好,但是当迁移到 2.1 时,图像的 mime 类型似乎错误地从服务器作为 text/html 发送,我猜这可能是原因我不断收到 500 错误。这是我的项目文件的外观:

.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
  <TargetFramework>net472</TargetFramework>
  <PreserveCompilationContext>true</PreserveCompilationContext>
  <AssemblyName>GoalEnvision.Public</AssemblyName>
  <OutputType>Exe</OutputType>
  <PackageId>GoalEnvision.Public</PackageId>
</PropertyGroup>
<ItemGroup>
  <None Update="wwwroot\**\*;Views\**\*;Areas\**\Views\**\*.cshtml;Resources\**\*">
    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
  </None>
</ItemGroup>
<ItemGroup>
  <Content Update="migrationsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>
<ItemGroup>
  <PackageReference Include="AbTestMaster" Version="1.2.1" />
  <PackageReference Include="AutoMapper" Version="7.0.1" />
  <PackageReference Include="BundlerMinifier.Core" Version="2.8.391" />
  <PackageReference Include="CommonMark.NET" Version="0.15.1" />
  <PackageReference Include="EPPlus" Version="4.5.2.1" />
  <PackageReference Include="MaxMind.GeoIP2" Version="2.10.0" />
  <PackageReference Include="Microsoft.AspNetCore" Version="2.1.4" />
  <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.1.2" />
  <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.1.1" />
  <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.3" />
  <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.3" />
  <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.1.2" />
  <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.1.3" />
  <PackageReference Include="Microsoft.AspNetCore.Session" Version="2.1.1" />
  <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.4" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.4">
    <PrivateAssets>All</PrivateAssets>
  </PackageReference>
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.4">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
  </PackageReference>
  <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.1" />
  <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
  <PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
  <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
  <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.1" />
  <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.1" />
  <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.1.1" />
  <PackageReference Include="murmurhash-signed" Version="1.0.2" />
  <PackageReference Include="Optimizely.SDK" Version="1.3.1" />
  <PackageReference Include="WindowsAzure.Storage" Version="9.3.2" />
  <PackageReference Include="Microsoft.AspNet.WebPages" Version="3.2.6" />
  <PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.6" />
  <PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.2" />
  <PackageReference Include="System.Collections" Version="4.3.0" />
  <PackageReference Include="Microsoft.AspNet.WebApi.WebHost" Version="5.2.6" />
  <PackageReference Include="Sendgrid" Version="9.10.0" />
  <PackageReference Include="iTextSharp" Version="5.5.13" />
  <PackageReference Include="itextsharp.xmlworker" Version="5.5.11" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
  <Reference Include="System.Drawing" />
  <Reference Include="System.Web" />
  <Reference Include="System" />
  <Reference Include="Microsoft.CSharp" />
</ItemGroup>

启动.cs

using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using GoalEnvision.Public.DAL;
using Microsoft.EntityFrameworkCore;
using GoalEnvision.Public.Areas.Admin.Models;
using GoalEnvision.Public.DAL.Initializer;
using GoalEnvision.Public.DAL.Repositories;
using Microsoft.AspNetCore.Identity;
using GoalEnvision.Public.Helpers;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.StaticFiles;

namespace GoalEnvision.Public
{
    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)
        {
            // Add framework services.
            services.AddDbContext<GoalEnvisionDbContext>(options => options.UseSqlServer(this.Configuration.GetSection("connectionString").Value));
                services.AddIdentity<ApplicationUser, ApplicationRole>(config => {
                    // Config here
                    config.User.RequireUniqueEmail = true;
                    config.Password = new PasswordOptions
                    {
                        RequireDigit = true,
                        RequireNonAlphanumeric = false,
                        RequireUppercase = false,
                        RequireLowercase = true,
                        RequiredLength = 8,
                    };
                })
                    .AddEntityFrameworkStores<GoalEnvisionDbContext>()
                    .AddDefaultTokenProviders();

            services.ConfigureApplicationCookie(options =>
            {
                // Cookie settings
                options.Cookie.HttpOnly = true;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
                // If the LoginPath isn't set, ASP.NET Core defaults 
                // the path to /Account/Login.
                options.LoginPath = new PathString("/admin/users/login");
                // If the AccessDeniedPath isn't set, ASP.NET Core defaults 
                // the path to /Account/AccessDenied.
                options.AccessDeniedPath = new PathString("/admin/users/login");
                options.SlidingExpiration = true;
            });

            services.AddDirectoryBrowser();
            services.AddMvc();

            // Adds a default in-memory implementation of IDistributedCache.
            services.AddDistributedMemoryCache();

            services.AddSession(options =>
            {
                // One day for Optimizely User ID cookie
                options.IdleTimeout = TimeSpan.FromSeconds(86400);
                options.Cookie.HttpOnly = true;
            });

            services.AddRouting(options => {
                options.LowercaseUrls = true;
                options.AppendTrailingSlash = true;
            });

            services.AddTransient<IUserRepository, UserRepository>();
            services.AddTransient<INewsRepository, NewsRepository>();
            services.AddTransient<IImageRepository, ImageRepository>();
            services.AddTransient<IVideoRepository, VideoRepository>();
            services.AddTransient<IRegistrationRepository, RegistrationRepository>();
            services.AddTransient<IBlobStorageUtility, BlobStorageUtility>();

            services.AddScoped<IEmailUtility, EmailUtility>(provider => new EmailUtility(this.Configuration.GetSection("sendGridApiKey").Value, this.Configuration.GetSection("GoalEnvisionSettings:SiteBaseUrl").Value));

            services.Configure<GoalEnvisionSettings>(options => this.Configuration.GetSection("GoalEnvisionSettings").Bind(options));
            services.Configure<BlobStorageSettings>(options => this.Configuration.GetSection("blobStorage").Bind(options));
            Translations.Translations.Initialize();
            AutoMapperSetup.Initialize();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            //404 error
            app.Use(async (context, next) =>
            {
                await next();
                if (context.Response.StatusCode == 404)
                {
                    context.Request.Path = "/not-found";
                    await next();
                }
            });

            if (env.IsDevelopment())
            {
                app.UseForwardedHeaders(new ForwardedHeadersOptions
                {
                    ForwardedHeaders = ForwardedHeaders.XForwardedFor,

                    // IIS is also tagging a X-Forwarded-For header on, so we need to increase this limit, 
                    // otherwise the X-Forwarded-For we are passing along from the browser will be ignored
                    ForwardLimit = 2
                });
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //for generic errors
                app.UseExceptionHandler("/error");
            }

            // Set up custom content types - associating file extension to MIME type
            var provider = new FileExtensionContentTypeProvider();
            // Add new mappings
            provider.Mappings[".myapp"] = "application/x-msdownload";
            provider.Mappings[".htm3"] = "text/html";
            provider.Mappings[".image"] = "image/png";

            app.UseStaticFiles(new StaticFileOptions()
            {
                ContentTypeProvider = provider,
                OnPrepareResponse = ctx =>
                {
                    ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=1209600");    //14 days=1209600
                }
            });

            using (var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
            {
                using (var context = scope.ServiceProvider.GetService<GoalEnvisionDbContext>())
                {
                    context.Database.Migrate();
                    context.EnsureSeedData(app.ApplicationServices).Wait();
                }
            }
            app.UseAuthentication();
            app.UseSession();
            app.UseMvc(routes =>
            {
                routes.MapRoute(name: "areaRoute", 
                    template: "{area:exists}/{controller=News}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "WithoutHomeInUrl",
                    template: "{action}",
                    defaults: new { controller = "Home", action = "Index" }
                );

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

程序.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace GoalEnvision.Public
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

项目结构快照 在此处输入图像描述

有趣的是,css、font 和 js 文件看起来都很好。这是我的项目 url ( https://goalenvisionpublic-test.azurewebsites.net/sv/ ) 和缺少的示例图像 ( https://goalenvisionpublic-test.azurewebsites.net/images/home/cover_test_now_sv.png )

任何指针将不胜感激。

标签: c#azureasp.net-core.net-coreasp.net-core-2.1

解决方案


对于任何面临类似问题的人,问题的原因是重复的 staticContent 标签。显然 .net core 2.1 转换了 web.config 并添加了自己的标签来管理缓存时间。所以附加标签导致配置文件无效。我所要做的就是删除我自己的标签:

<location path="images">
  <system.webServer>
    <staticContent>
      <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
    </staticContent>
  </system.webServer>
</location>
<location path="fonts">
<system.webServer>
  <staticContent>
    <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
  </staticContent>
</system.webServer>


推荐阅读