cofoundry-cms / cofoundry

Cofoundry is an extensible and flexible .NET Core CMS & application framework focusing on code first development
https://www.cofoundry.org
MIT License
835 stars 146 forks source link

Null exception when calling app.UseCofoundry(); #539

Closed kenan-kajkus closed 7 months ago

kenan-kajkus commented 1 year ago

I am trying to update to cofoundry 0.11 but when I call app.UseCofoundry() in my Startup procedure i get this Exception:

System.ArgumentNullException: Value cannot be null. (Parameter 'source')
   at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
   at System.Linq.Enumerable.OfType[TResult](IEnumerable source)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionDescriptorProvider..ctor(IEnumerable`1 pageRouteModelProviders, IOptions`1 mvcOptionsAccessor, IOptions`1 pagesOptionsAccessor)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitNoCache(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.GetOrCreateDataSource(IEndpointRouteBuilder endpoints)
   at Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapControllerRoute(IEndpointRouteBuilder endpoints, String name, String pattern, Object defaults, Object constraints, Object dataTokens)
   at Cofoundry.Web.Admin.AdminApiRouteBuilderContext`1.AddVerbRoute(String verbActionName, String path, String actionName)
   at Cofoundry.Web.Admin.AdminApiRouteBuilderContext`1.AddGetRoute(String path, String actionName)
   at Cofoundry.Web.Admin.AdminApiRouteBuilderContext`1.MapGet()
   at Cofoundry.Web.Admin.AdminApiRouteRegistration.MapAccountApiRoutes(IEndpointRouteBuilder routeBuilder)
   at Cofoundry.Web.Admin.AdminApiRouteRegistration.RegisterRoutes(IEndpointRouteBuilder routeBuilder)
   at Cofoundry.Web.RouteInitializer.Initialize(IEndpointRouteBuilder routeBuilder)
   at Cofoundry.Web.AddEndpointRoutesStartupConfigurationTask.RegisterInjectedRoutes(IEndpointRouteBuilder routes)
   at Cofoundry.Web.AddEndpointRoutesStartupConfigurationTask.GetRoutes(IEndpointRouteBuilder routes)
   at Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseEndpoints(IApplicationBuilder builder, Action`1 configure)
   at Cofoundry.Web.AddEndpointRoutesStartupConfigurationTask.Configure(IApplicationBuilder app)
   at Cofoundry.Web.UseCofoundryStartupExtension.UseCofoundry(IApplicationBuilder application, Action`1 configBuilder)
   at MartinaKajkus.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in C:\Users\Kenan\RiderProjects\MartinaKajkus\src\MartinaKajkus\Startup.cs:line 41
   at MartinaKajkus.Program.Main(String[] args) in C:\Users\Kenan\RiderProjects\MartinaKajkus\src\MartinaKajkus\Program.cs:line 18

My Main:

 public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            var startup = new Startup(builder.Configuration);
            startup.ConfigureServices(builder.Services);

            var app = builder.Build();

            startup.Configure(app, app.Environment);

            using (var scope = app.Services.CreateScope())
            {
                var db = scope.ServiceProvider.GetRequiredService<SiteDbContext>();
                db.Database.Migrate();
            }

            app.Run();
        }

My Startup:

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)
        {
            services.AddDbContext<SiteDbContext>();
            services
                .AddControllersWithViews()
                .AddCofoundry(Configuration);
        }

        // 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");
                // 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.UseMiddleware<VisitorCounterMiddleware>();
            app.UseCofoundry();
        }
    }
HeyJoel commented 1 year ago

Hi there, some things to look at first:

  1. What version are you upgrading from?
  2. What .NET version are you targeting? 0.11.x targets .NET 6
  3. The error is triggered when Cofoundry tries to register a controller route using the .NET MVC method MapControllerRoute, the stack bounces through various DI methods and ends up in PageActionDescriptorProvider, so it could also be an unrelated DI issue. Perhaps you could check you have any non-cofoundry bits registered with the DI container.
  4. You could also try using the minimal hosting mode program.cs shown in the v0.11 release post, and checking the linked Microsoft .NET 6 upgrade notes.
HeyJoel commented 1 year ago

Also, if you're using Razor pages in your app you'll need to use .AddMvc() instead of .AddControllersWithViews(). Perhaps you could try that anyway as the stack trace looks like it's trying to use the RazorPages PageActionDescriptorProvider.

kenan-kajkus commented 1 year ago

Hey @HeyJoel, thank you very much. Actually it was the .AddMvc(). But how does it come that with older versions of cofoundry this was not an issue?

HeyJoel commented 1 year ago

I'm not certain, but thinking back to the .NET 6 migration I think the ASP.NET team made some changes around what was/was not registered when using AddControllersWithViews(). So it depends what else you're using in your app. Cofoundry itself does work with just AddControllersWithViews(), as shown in the sample app, but maybe it's just safer to use AddMvc() in our samples.

HeyJoel commented 7 months ago

Documentation and samples have been updated to use AddMvc(), these changes will be published alongside the v0.12 release.