EF Core 适用于剃刀页面,但不适用于 MVC

时间:2021-01-14 00:54:13

标签: c# entity-framework asp.net-core asp.net-core-5.0

所以我正在处理我的应用程序,出于某种原因,与 UserManager、RoleManager 和 SigninManager 相关的任何事情都无法在视图和控制器中工作。它告诉我它无法访问数据库。我猜这是一个上下文问题。迁移工作正常,我可以在身份系统之外的数据库中创建对象。如果我使用脚手架使用剃刀页面覆盖 auth/identity 中的页面,则一切正常(注册、登录等)。当我尝试在我对控制器的视图操作之一中检查角色作为测试它时,它给了我以下错误:

Microsoft.EntityFrameworkCore.Database.Connection: Error: An error occurred using the connection to database 'DDDTemplate' on server '.'.

这是一个本地数据库设置,在 SQL 服务器上具有受信任的连接。

Startup.cs

public class Startup
{
    private readonly IWebHostEnvironment _env;
    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
        Configuration = configuration;
        _env = env;
    }

    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.AddApplication();
        services.AddInfrastructure(Configuration);
        services.AddDatabaseDeveloperPageExceptionFilter();

        services.AddSingleton<ICurrentUserService, CurrentUserService>();

        services.AddHttpContextAccessor();

        services.AddControllersWithViews()
                .AddFluentValidation();

        //services.AddRazorPages();

        if (_env.IsDevelopment())
        {
            services.AddSingleton<IConsoleLogger, ConsoleLogger>();
            
        }
        else
        {
            services.AddSingleton<IConsoleLogger, NullConsoleLogger>();
        }
        
    }

    // 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();
            app.UseMigrationsEndPoint();
        }
        else
        {
            app.UseExceptionHandler("/Home/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.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            Routes.Addroutes(endpoints);
        });
    }
}

Routes.cs

public static class Routes
{

    public static void Addroutes(IEndpointRouteBuilder endpoints)
    {
        endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        //endpoints.MapRazorPages();
    }
}

appsettings.json

{
  "UseInMemoryDatabase": false,
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=.;Initial Catalog=DDDTemplate;Integrated Security=True;MultipleActiveResultSets=true;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

AccountController.cs

public class AccountController : Controller
{
    private readonly RoleManager<ApplicationRole> _roleManager;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IIdentityService _identityService;

    public AccountController(RoleManager<ApplicationRole> RoleManager, UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IIdentityService identityService)
    {
        _roleManager = RoleManager;
        _userManager = userManager;
        _signInManager = signInManager;
        _identityService = identityService;
    }

    public IActionResult Index()
    {
        return View();
    }

    public IActionResult Register()
    {
        return View();
    }

    public IActionResult Login(string t)
    {
        return View();
    }

    [HttpPost]
    public void Register(RegisterViewModel userInfo)
    {

    }

    [HttpPost]
    public async void Login(LoginViewModel loginInfo)
    {
        try
        {

            bool x = await _roleManager.RoleExistsAsync("Admin");
            Console.WriteLine("test");

        }
        catch (Exception exception)
        {
           
        }
        
    }
}

Login.cshtml 来自视图/帐户文件夹

@model DDDTemplate.App.LoginViewModel
@using Microsoft.AspNetCore.Identity
@using DDDTemplate.Data.Identity
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@inject RoleManager<ApplicationRole> RoleManager
@{
    ViewData["Title"] = "Login";
}
<div class="text-center">
    <h1 class="display-4">Register Account</h1>
    <form asp-controller="Account" asp-action="Login" method="post">
        <div asp-validation-summary="ModelOnly"></div>
        <div>
            <label asp-for="Username"></label>
            <input asp-for="Username" />
            <span asp-validation-for="Username"></span>
        </div>
        <div>
            <label asp-for="Password"></label>
            <input asp-for="Password" />
            <span asp-validation-for="Password"></span>
        </div>

        <div>
            <input type="submit" value="Login" />
        </div>
    </form>
</div>

在服务配置期间调用的引用项目的依赖注入文件中

public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            configuration.GetConnectionString("DefaultConnection"),
            b =>
                b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)
        )
    );

    services
        .AddIdentity<ApplicationUser,ApplicationRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultUI()
        .AddDefaultTokenProviders(); ;

    services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

    services.AddScoped<IDomainEventService, DomainEventService>();

    services.AddTransient<IDateTime, DateTimeService>();
    services.AddTransient<IIdentityService, IdentityService>();
    services.AddTransient<ICsvFileBuilder, CsvFileBuilder>();

    services.AddAuthorization();

    return services;
}

ApplicationDBContext.cs

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IApplicationDbContext
{

    private IDomainEventService _domainEventService {get;}
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IDomainEventService domainEventService) : base(options)
    {
        _domainEventService = domainEventService;
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.ApplyConfigurationsFromAssembly(Assembly.GetAssembly(typeof(ApplicationDbContext)));
        
    }

    public DbSet<TodoItem> TodoItems { get; set; }

    public DbSet<TodoList> TodoLists { get; set; }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
    {
        foreach (Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<AuditableEntity> entry in ChangeTracker.Entries<AuditableEntity>())
        {
            switch (entry.State)
            {
                case EntityState.Added:
                    entry.Entity.CreatedBy = _currentUserService.;
                    entry.Entity.Created = _dateTime.Now;
                    break;

                case EntityState.Modified:
                    entry.Entity.LastModifiedBy = _currentUserService.UserId;
                    entry.Entity.LastModified = _dateTime.Now;
                    break;
            }
        }

        var result = await base.SaveChangesAsync(cancellationToken);

        await DispatchEvents();

        return result;
    }

    private async Task DispatchEvents()
    {
        while (true)
        {
            var domainEventEntity = ChangeTracker.Entries<IHasDomainEvent>()
                .Select(x => x.Entity.DomainEvents)
                .SelectMany(x => x)
                .Where(domainEvent => !domainEvent.IsPublished)
                .FirstOrDefault();
            if (domainEventEntity == null) break;

            domainEventEntity.IsPublished = true;
            await _domainEventService.Publish(domainEventEntity);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我发现问题是我从一个有任务的异步函数返回 void。只有某些情况是可以接受的,这不是其中之一。因此,在 AccountController.cs 上,我更改了以下内容以返回 Task 而不是 void,并且一切正常:

    [HttpPost]
    public async Task Login(LoginViewModel loginInfo)
    {
        try
        {

            bool x = await _roleManager.RoleExistsAsync("Admin");
            Console.WriteLine("test");

        }
        catch (Exception exception)
        {
           
        }
        
    }
相关问题