首页 > 解决方案 > 在 Core 3.1 MVC 上重构启动

问题描述

我正在尝试在核心迁移到 3.1 后重构 MVC;我像这样转换了启动(LightInject):

public Startup(IWebHostEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
           

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddCookie(options =>
        {
            options.LoginPath = "/signin";
            options.LogoutPath = "/signin";
            options.AccessDeniedPath = "/access-denied";
           // AutomaticAuthenticate = true,
            // AutomaticChallenge = true
        });

        services
            .AddControllersWithViews()
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
            .AddFluentValidation(configuration =>
            {
                configuration.RegisterValidatorsFromAssemblyContaining<Startup>();
                configuration.RegisterValidatorsFromAssemblyContaining<AgentModel>();
            })
            .AddMappers(configuration =>
            {
                configuration.RegisterMappersFromAssemblyContaining<Startup>();
            });


        services.AddSingleton<IConfigurationRoot>(Configuration);

        services.AddAuthorization(options => { options.AddPolicy("Enabled", policy => policy.Requirements.Add(new UserEnableRequirement())); });

        services.AddSingleton<IAuthorizationHandler, UserEnableHandler>();

        // Register the IConfiguration instance which MyOptions binds against.
        services.Configure<SettingsModel>(Configuration);

        var container = new ServiceContainer();
        container.RegisterModule<DependencyInjectionModule>();

        return container.CreateServiceProvider(services);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        using (var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder.AddConsole();
            builder.AddDebug();
        }
        ))
        { }
        // Configuration.GetSection("Logging")
        if (env.IsDevelopment() || env.IsEnvironment("Local"))
        {
            app.UseDeveloperExceptionPage();
            //app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        

        var supportedCultures = new[]
        {
            new CultureInfo("en-US"),
        };

        app.UseRequestLocalization(new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture("en-US"),
            // Formatting numbers, dates, etc.
            SupportedCultures = supportedCultures,
            // UI strings that we have localized.
            SupportedUICultures = supportedCultures
        });

        // app.UseHttpsRedirection(); doesn't work 
        app.UseStaticFiles();
        app.UseRouting();
        app.UseFileServer();

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

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
        });

    }

这是我的程序

public static void Main(string[] args)
    {
        Host.CreateDefaultBuilder()
       .ConfigureWebHostDefaults(webBuilder => webBuilder
       .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseUrls("http://0.0.0.0:81")
            .UseIISIntegration()
            .UseStartup<Startup>()).Build().Run();
    }

它返回此错误:System.NotSupportedException:'不支持返回 System.IServiceProvider 的配置服务。'

据此我必须使用 Autofac 而不是 IServiceProvider,但我不知道如何组织容器,等等。我试了两次,但错误是一样的。那么,我应该如何重构启动文件呢?另外,有没有办法在不使用 Autofac 的情况下解决这个问题?

标签: c#asp.net-core-3.1

解决方案


我在 .NET CORE MVC 3.1 上运行 LightInject 时遇到了同样的问题。

我设法获得了代码的工作版本。

需要添加ConfigureContainer() *

public void ConfigureContainer(IServiceContainer container)
{
    container.RegisterFrom<CompositionRoot>();
}

我安装的软件包。也许并非所有这些都是必需的。

LightInject
LightInject.Microsoft.DependencyInjection
LightInject.Microsoft.Hosting

启动.cs

using Project.Web.DI;
using LightInject;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Project.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureContainer(IServiceContainer container)
        {
            container.RegisterFrom<CompositionRoot>();
        }

        //This method gets called by the runtime.Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            this.AddConnectionDb(services);

            services.AddMvc(option =>
                {
                    option.EnableEndpointRouting = false;
                })
                .AddControllersAsServices()
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); ;

        }

        public void AddConnectionDb(IServiceCollection services)
        {
            services.AddDbContext<CacheContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("ProjectConnection")));
        }

        // 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("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();

            app.UseAuthorization();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "Default",
                    template: "{controller=Home}/{action=Index}/{id?}",
                    defaults: ""
                );
            });
        }
    }
}

程序.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace Project.Web
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseLightInject()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

组合根.cs

using LightInject;

namespace Project.Web.DI
{
    public class CompositionRoot : ICompositionRoot
    {
        public void Compose(IServiceRegistry serviceRegistry)
        {
            serviceRegistry.Register<IUserRepository, UserRepository>();
            serviceRegistry.Register<IActRepository, ActRepository>();
        }
    }
}

推荐阅读