我试图按照本指南在我的MVC应用中在API部分和MVC部分之间创建逻辑分隔:
这是我正在使用的扩展方法的实现:
public static IApplicationBuilder UseBranchWithServices(this IApplicationBuilder app,
PathString path, Action<IServiceCollection> servicesConfiguration,
Action<IApplicationBuilder> appBuilderConfiguration)
{
var webhost = new WebHostBuilder()
.UseKestrel()
.ConfigureServices(servicesConfiguration)
.UseStartup<StartupHarness>()
.Build()
/* ojO */ .CreateOrMigrateDatabase(); /* Ojo */
var serviceProvider = webhost.Services;
var featureCollection = webhost.ServerFeatures;
var appFactory = serviceProvider.GetRequiredService<IApplicationBuilderFactory>();
var branchBuilder = appFactory.CreateBuilder(featureCollection);
var factory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
branchBuilder.Use(async (context, next) => {
using (var scope = factory.CreateScope()) {
context.RequestServices = scope.ServiceProvider;
await next();
}
});
appBuilderConfiguration(branchBuilder);
var branchDelegate = branchBuilder.Build();
return app.Map(path, builder => { builder.Use(async (context, next) => {
await branchDelegate(context);
});
});
}
当我尝试将其与SignInManager一起使用时,HttpContext始终为空。
这是我的AccountController的一个荒谬的简化版本:
public AccountController(SignInManager<AppUser> mgr) {
_mgr = mgr;
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var result = await _mgr.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
}
}
我是calling app.UseAuthentication()
,在ApplicationBuilder中;为了简洁起见,我将该设置作为扩展方法。这有效:
public void ConfigureServices(IServiceCollection services)
{
services.ConfigureMvcServices(Configuration);
}
public void Configure(IApplicationBuilder builder, IHostingEnvironment env)
{
builder.ConfigureMvcBuilder(env);
}
这不是:
public void Configure(IApplicationBuilder builder, IHostingEnvironment env)
{
builder.UseBranchWithServices(StaticConfiguration.RootPath,
services =>
{
services.ConfigureMvcServices(Configuration);
},
app => { app.ConfigureMvcBuilder(env); }
);
builder
.Run(async c =>
await c.Response.WriteAsync("This should work"));
}
在后一个示例中,services
对象以Count
结尾,包含335个描述符,在前一个(有效)示例中,它具有356个描述符。
我尝试查看this blog以查看是否可以查明发生了什么,但是我看不出方法中的内容与Gordon所描述的内容之间有很强的相关性。所以我完全迷路了。任何帮助,将不胜感激。如果有办法拆分扩展方法并为每个管道传递服务,那对我来说很好。
是的,我知道您在这里只能看到一个管道。关键是要添加更多。
答案 0 :(得分:0)
这就是我最终得到的:
这是解决此问题的错误方法。我需要一个配置正确的管道。我将我的API和Web项目组合到一个项目中(尽管这并不重要,只要所有内容都已注册)。
(出于其他原因,我添加了异步。与此无关。)
Program.cs:
public static async Task Main(string[] args)
{
IWebHost webhost = CreateWebHostBuilder(args).Build();
await webhost.CreateOrMigrateDatabase();
await webhost.RunAsync();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
new WebHostBuilder()
.ConfigureAppConfiguration((host, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
config.AddJsonFile("appsettings.json");
if (host.HostingEnvironment.IsDevelopment())
config.AddUserSecrets<Startup>();
else
config.AddEnvironmentVariables(prefix: "MYAPP_");
})
.UseKestrel()
.ConfigureLogging((app, logging) =>
{
//snip
})
.UseStartup<Startup>()
.UseUrls("http://*:4213");
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
var connString = Configuration.GetConnectionString("default");
services.ConfigureJwt(_signingKey, Configuration);
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization?view=aspnetcore-2.2#configure-localization
services.AddLocalization(options => options.ResourcesPath = StartupConfiguration.ResourcesFolder);
services.AddDbContext<AppDbContext>(builder =>
{
builder.UseLazyLoadingProxies()
.UseSqlServer(connString, with => with.MigrationsAssembly("App.Data"));
});
services.ConfigureAuthentication(Configuration);
var mapperConfig = new MapperConfiguration(maps =>
{
maps.ConfigureMvc();
maps.ConfigureApi();
});
var mapper = mapperConfig.CreateMapper();
services.AddSingleton(mapper);
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization?view=aspnetcore-2.2#configure-localization
services.AddMvc() // (config => { config.Filters.Add(new AuthorizeFilter()); }) // <~ for JWT auth
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSpaStaticFiles(angularApp =>
{
angularApp.RootPath = "dist"; // TODO
});
//snip
}
我拆分了地图(IMapper,不相关;它们只是为两个名称空间配置ViewModel的扩展方法),但我没有拆分管道。一个正确配置的管道,其中静态网站位于{folder} / dist。同时运行API和MVC项目。而且管理起来要少得多。
感兴趣的完整代码是here。