allyouneedisdave
allyouneedisdave

Reputation: 39

ASP.NET Core MVC Identity features not working when published to server

I have an ASP.NET Core MVC web app that uses Entity Framework and Microsoft Identity for user accounts. I am able to run the application in debug and create an account/login etc, however, when published to iis, I receive the following error:

Error Message

The offending bit of code is in _Layout.cshtml below, which, as far as I can tell, is not implementing user identity like it does in debug.

_Layout.cshtml

@using Microsoft.AspNetCore.Identity
@using MyApp.Areas.Identity.Data
@inject UserManager<MyAppUser> userManger
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - MyApp</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <div style="height:30px; margin-top:0px;">
                    <img class="navbar-brand" style="height:auto; width:auto; max-height:100%; max-width:100%;" src="~/images/AASLogoDarkMinimal.png" />
                </div>
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">My App</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial.cshtml" />






                    <ul class="navbar-nav flex-grow-1">

                          @{if (User.Identity.IsAuthenticated)
                            {
                                var user = await userManger.GetUserAsync(User);

                                var rolesArray = userManger.GetRolesAsync(user).Result;

                                if (rolesArray.Contains("Administrator") || rolesArray.Contains("Sales Administrator"))
                                {
                                <li class="nav-item dropdown">

                                    <a class="nav-link dropdown-toggle text-info" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                        Admin Tools
                                    </a>
                                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                                        @if (rolesArray.Contains("Administrator"))
                                            {
                                        <a type="button" class="dropdown-item btn btn-info btn-sm" asp-controller="User" asp-action="Index">User Management</a>
                                            }
                                        @if (rolesArray.Contains("Sales Administrator"))
                                            {
                                        <a type="button" class="dropdown-item btn btn-info btn-sm" asp-controller="User" asp-action="Index">Price Management</a>
                                            }

                                    </div>

                                </li>

                                }

                            }
                            }

                    </ul>


                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; @DateTime.Now.Year - My Application
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>

Could it be something to do with IdentityHostingStartup.cs?

IdentityHostingStartup.cs

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MyApp.Areas.Identity.Data;
using MyApp.Data;

[assembly: HostingStartup(typeof(MyApp.Areas.Identity.IdentityHostingStartup))]
namespace MyApp.Areas.Identity
{
    public class IdentityHostingStartup : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureServices((context, services) => {
                services.AddDbContext<MyAppAuthDbContext>(options =>
                    options.UseSqlServer(
                        context.Configuration.GetConnectionString("MyAppAuthDbContextConnection")));

                services.AddDefaultIdentity<MyAppUser>(options => options.SignIn.RequireConfirmedAccount = true)
                    .AddRoles<IdentityRole>()
                    .AddEntityFrameworkStores<MyAppAuthDbContext>();
            });
        }
    }
}

Startup.cs

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }


        public void ConfigureServices(IServiceCollection services)
        {


           
           
            services.AddDbContext<DbContextSQLIdentity>(options => options.UseSqlServer(Configuration.GetConnectionString("SQLIdentDB")));


           

            services.AddTransient<IEmailSender, EmailSender>();
            services.Configure<AuthMessageSenderOptions>(Configuration);


            services.AddControllersWithViews().AddRazorRuntimeCompilation();
            
            services.AddRazorPages();

        
        }

       
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
              
                app.UseHsts();
            }
         
            app.UseStaticFiles();

            app.UseRouting();

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

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

Upvotes: 0

Views: 854

Answers (2)

allyouneedisdave
allyouneedisdave

Reputation: 39

I found the issue! I needed to disable Windows Authentication and enable anonymous authentication in IIS on the server.

Upvotes: 1

Neil
Neil

Reputation: 11889

I'm guessing that this line:

var rolesArray = userManger.GetRolesAsync(user).Result;

is returning null, and therefore the next lines that use .Contains will fail with NRE.

That would suggest to me that your logged in user has no roles.

BTW Calling .Result on a Task is not good practice and will sometimes result in a locked task.

Upvotes: 1

Related Questions