ASP.NET5 500 Error when using the repository pattern - c#

Edit 3: I don't know what I did to fix this, but my problem went away. I think the most important things I found, and to take away if you have this issue is that in ASP.NET 5 MVC 6 we have to add middleware for almost everything, including the developer error pages using app.UseDeveloperExceptionPage();... after that I realized that the stack trace might be referring to other classes referenced from within the controller such as the repository and the context object, in my case. I messed with them a bit but I don't remember changing anything drastic. I think I may have had a typo in the constructor of my repository class.
I'm getting a 500 Internal Server Error with the controller, but it displays the static json data without the constructor just fine. I suspect there is something going wrong with the built-in dependency injection but I can't figure it out as I'm not getting any errors or warnings during build.
Edit: I see absolutely nothing in browser when navigationg to http://localhost:5000/api/blogpost/. Just a blank page. No Error. No nothing. Using Postman to send the HTTP request, I get error code 500. Again, by commenting out the constructor I see {"name":"Cameron"}, and get code 200 OK in both browser and Postman. There are no exceptions within VS, and there are no errors in the Output console either.
Edit 2: I found the middleware app.UseDeveloperExceptionPage(); and it produces MissingMethodException: No parameterless constructor defined for this object. - If I make a parameterless constructor, it produces: InvalidOperationException: Multiple constructors accepting all given argument types have been found in type 'MyApp.Controllers.BlogPostController'. There should only be one applicable constructor. - It seems like something whacky is going on with ASP.NET5's dep injection?
Here's my controller:
using MyApp.Data.Repository;
using MyApp.Models;
using Microsoft.AspNet.Mvc;
using System;
namespace MyApp.Controllers
{
[Route("api/[controller]")]
public class BlogPostController : Controller
{
// If I comment out this var and the constructor this works.
private IBlogPostRepository _repository;
// If I leave them here, I get a 500 Internal Server Error.
// If I set a breakpoint here, it never fires.
// If I create a constructor that takes zero args, it never fires.
// I do not get any errors.
public BlogPostController(IBlogPostRepository repository)
{
_repository = repository;
}
[HttpGet]
public JsonResult Get()
{
return Json(new { name = "Cameron" });
}
}
}
Here is Startup.cs ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
// MVC 6
services.AddMvc();
// EntityFramework 7
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<AppDbContext>(options =>
{
// Will use the last Data:DefaultConnection:ConnectionString
// that was loaded from the config files in the constructor.
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);
});
// Injections
services.AddTransient<AppDbContextSeedData>();
services.AddScoped<IBlogPostRepository, BlogPostRepository>();
}

I had this same problem. My constructor was did not have a scope. The class was public, so I added "public" before the constructor and it worked!
So, NOT WORKING:
public class VisualizationsController : Controller
{
VisualizationsController() {...}
}
And WORKING:
public class VisualizationsController : Controller
{
public VisualizationsController() {...}
}

I came across a situation where I was adding another controller and forgot to update the Startup.cs page.
In Startup.cs, under the ConfigureServices, try adding:
services.AddSingleton<ISomeRepository, SomeRepository>();
services.AddSingleton<ISomeOtherRepository, SomeOtherRepository>();
Assuming you're passing in ISomeOtherRepository in your new controller constructor

Related

ASP.NET Core api controller not being instantiated

I've created an API controller in my .NET Core 3.1 application (with an Angular frontend, C#).
For some strange reason its not being instantiated, if I try to call any methods on the controller from my Typescript service, nothing happens, it just skips past the call, no error message is generated but the method in the controller isn't accessed.
I've traced it to the fact that the controller isn't being instantiated but I can't see why. Has anyone else experienced this issue?
I inject a service into the constructor, but the service is being added to ioc at startup so it cant be that (along with the other services used), can anyone help?
This is part of the controller code, I've added a breakpoint to the constructor, but its not being hit. I had exactly the same issue with a previous controller I had added, I spent ages trying to figure out why it wasn't being instantiated, then suddenly, it was, despite the fact that I had made no code changes, so I'm baffled by this.
public class RepController : BaseApiController
{
private readonly IRepService _repService;
private readonly ILookupService _lookupService;
private readonly IUserContext _userContext;
public RepController(IRepService repService,
ILookupService lookupService,
IUserContext userContext)
{
Assert.NullCheck(repService);
Assert.NullCheck(lookupService);
Assert.NullCheck(userContext);
_repService = repService;
_lookupService = lookupService;
_userContext = userContext;
}
}
I think the problem is inheriting form BaseApiController. You should try setting that to Controller.
You should also make your that you specify routing on your controllers. A link to the docs about endpoint routing.
Maybe your endpoints dont have a correct return type, this should be of Type ActionResult
I found the problem, I had this decorator
[Route("api/[controller]"]
instead of this
[Route("api/[controller]/[action]"]
its working now

no parameterless constructor defined for type dbcontext

I search many posts in stack and another sites about this error but it wasn't my answer
this is my DbCintext
[Table("AspNetUsers")]
public class ApplicationUser : IdentityUser { }
public class EMSContext : IdentityDbContext<ApplicationUser> {
public EMSContext (DbContextOptions<EMSContext> options) : base (options) { }
public DbSet<Ambulance> Ambulances { get; set; }
}
and this is mu StartUp.cs
services.AddControllers();
services.AddDbContext<EMSContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
but when I want to generate api controller I got this error
no parameterless constructor defined for type dbcontext
The error is clear, you don't have a parameterless constructor.
But that said, the tooling shouldn't need it since you are calling AddDbContext and passing in your connection string. The tooling scaffolds controllers/etc. by actually running your program and then requesting the DbContext from the host's service provider. It does this by looking for methods with very specific names.
My guess is that your main Program.cs is not following the prescribed upon pattern and thus cannot construct your Host nor locate its ServiceProvider.
Your options are as follows (my personal choice is #2):
Add a paremeterless constructor like the message says
Make sure your main entry point uses the correct conventions for the host builder methods
Create a Design-Time context factory
Parameterless Constructor
This is the obvious answer, though it's not always possible. Furthermore it should not be necessary since the scaffolding has other means by which to read from your DbContext. Adding a constructor just for this purpose is not something I would do nor recommend.
Correct Naming / Method Signature
The scaffolding looks for a very specific method signature when it attempts to run your program. Basically, it is looking for something like this:
public class Program
{
public static void Main(string[] args)
=> CreateHostBuilder(args).Build().Run();
// EF Core uses this method at design time to access the DbContext
public static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(
webBuilder => webBuilder.UseStartup<Startup>());
}
Now it doesn't need to look exactly like this. The important part is the name and signature of the CreateHostBuilder method.*
If there are any errors raised while attempting to construct the service, for example because there are dependencies that cannot be resolved or configuration is missing then this method will fail. I'm pretty sure you will get either the same error or a DI-related one.**
Design Time Factory
Supposing that still doesn't work or you'd like better control you can create a Design-Time Factory for your context. The tooling will scan your project for types implementing IDesignTimeDbContextFactory<EMSContext> and then use that during scaffolding:
public class EMSContextFactory : IDesignTimeDbContextFactory<EMSContext>
{
public EMSContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<EMSContext>();
optionsBuilder.UseSqlServer("Your Connection String");
return new EMSContext(optionsBuilder.Options);
}
}
See this link for more information.
* Note: You've not specified what version of aspnet core you are running. If you aren't using the generic host (Host.CreateDefaultBuilder) but are instead using WebHost, then the expected method signature will look a bit different. That said it will match that of creating a new project with the same settings.
If you've ever written integration tests for your controllers, the WebApplicationFactory looks for similar methods/signatures. Those same signatures should satisfy the controller scaffolding. I can't seem to find documentation on either other than the link above.
** When the scaffolding runs, it executes as the 'Production' environment. DI errors can occur if service resolution/configuration fails due to being in the "wrong" environment. This is one of the reasons the context factory solution exists.
The error is exactly located in this line:
public EMSContext (DbContextOptions<EMSContext> options) : base (options) { }
No parameterless constructors for DbContext... of course, because your constructor takes one parameter DbContextOptions options,
so you have two options to fix it, fix the call to the constructor or make the constructor take 0 parameters
Here's the error I was getting, sounds very similar to yours.
I had encountered this problem when trying to create a View (the one circled in red). My issue was the Startup.cs file. I had recently done a re-name from LeaveHistory... to LeaveRequest..., and when editing my Startup.cs file I made an incorrect change.
Line 39 should read:
services.AddScoped<ILeaveRequestRepository, LeaveRequestRepository>(); // no "I"
The error I was getting mentioned that the dbContext class didn't have a parameterless constructor - so it was totally deceptive, or at least not that helpful.
So to anyone else looking at this error, don't take it on it's face! I am fairly deep into this project, and none of my other controllers have parameterless constructors, at least not written out.
Think about other clerical changes you've made - class name changes, things like that. Perhaps the error message is not actually what it seems, and you've made a small error somewhere else that is simply generating a confusing error message.

Prism + DryIoc crashes when trying to perform constructor injection?

I'm having trouble using DryIoc for constructor injection into a ViewModel using Prism with Xamarin. I am using the Nuget package Prism.DryIoc.Forms.
In my project I get the following error in AuthenticatePage.xaml.g.cs
Unable to resolve Object {RequiredServiceType=Project.ViewModels.AuthenticatePageViewModel} with 1 arg(s)
in wrapper Func<Xamarin.Forms.Page, Object> {RequiredServiceType=Project.ViewModels.AuthenticatePageViewModel} with 1 arg(s)
from container
with normal and dynamic registrations:
MainPage, {ID=44, ImplType=Project.Views.MainPage}}
NavigationPage, {ID=43, ImplType=Xamarin.Forms.NavigationPage}}
AuthenticatePage, {ID=45, ImplType=Project.Views.AuthenticatePage}}
Specifically, it points to the line
private void InitializeComponent() {
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(AuthenticatePage));
}
Of note is that if I call the following in App.OnInitialized, the object resolves fine:
c.Register<INegotiator, Negotiator>(Reuse.Singleton);
var n = c.Resolve<INegotiator>();
n.ResumeSessionAsync(); // This works fine, no problems.
await NavigationService.NavigateAsync("NavigationPage/AuthenticatePage"); // Error thrown here
If I remove the constructor injection from my ViewModel it works fine (Aside from keeping the default navigationService injection, which works fine). Even trying to inject a basic class like ILogger (no dependencies) fails.
public AuthenticatePageViewModel(INavigationService navigationService, ILogger logger) : base (navigationService)
{
Title = "Authentication Page...";
}
I'm going to keep investigating, but is it obvious to someone here if I'm fundamentally doing something wrong? If I had to guess I would say it's to do with a conflict with Prisms built in Ioc container and DryIoc?
Edit:
I'm using the latest version of Prism.DryIoc.Forms available on NuGet (7.0.0.396) which says it includes DryIoc 2.12.26. I have so far simply followed the template available for Visual Studio which lists setting up navigation as follows:
protected override async void OnInitialized()
{
InitializeComponent();
var c = new Container();
c.Register<ILogger, LoggerConsole>(Reuse.Singleton);
c.RegisterMany(new[] { Assembly.Load("Project.UWP") },
serviceTypeCondition: type => type == typeof (ILocalFileHandler));
c.Register<INegotiator, Negotiator>(Reuse.Singleton);
// var n = c.Resolve<INegotiator>();
// n.ResumeSessionAsync(); // <- This will run fine. Negotiator class has ILogger and ILocalFileHandler injected into it.
await NavigationService.NavigateAsync("NavigationPage/AuthenticatePage");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage>();
containerRegistry.RegisterForNavigation<AuthenticatePage>();
}
I can't find any info online on if/how I should be using Prism.DryIoc.DryIocContainerExtensions to set up navigation? Even modifying the sample app to include basic construction injection results in the error "Value Cannot Be Null" in the same xaml.g.cs file?
Prism 7.0 and below allows the exception to bubble up, in order to diagnose the root cause of your issue you want to better diagnose this issue I suggest you do a little try/catch to see what and where the error really is.
protected override void OnInitialized()
{
try
{
// Check if there is an initialization exception
var page = new AuthenticationPage();
// Validate that the page resolves ok
var page2 = Container.Resolve<object>("AuthenticationPage");
// Validate that your ILogger interface is registered and resolves ok
var logger = Container.Resolve<ILogger>();
// Check for Registration/initialization exceptions
var vm = Container.Resolve<AuthenticationPageViewModel>();
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
System.Diagnostics.Debugger.Break();
}
}
You haven't specified at what point you're getting this error, though typically with XAML Compilation enabled you would see exceptions in the {pageName}.xaml.g.cs during compilation and not runtime. Either way, given that your exception is coming from the generated XAML code behind class, this tells me it is most likely a problem with your XAML. A very simple way to validate this is to remove all of the XAML content in your AuthenticationPage so that you have an empty page.
Given the code you've provided as part of your question, I would say you have no registration for your ILogger interface which would likely throw an exception causing the problem you're seeing. Regardless of what/where the error is, the try/catch shown above would be the easiest way to determine the root cause.
Following #Dan S.'s diagnoses suggestion as well as reading this article (http://brianlagunas.com/whats-new-in-prism-for-xamarin-forms-7-0/) I realized that I should have been using the Prism.Ioc.ContainerRegistry abstraction layer to interface with DryIoc. Prior to this I had been working directly with DryIoc's classes.
Once I modified my registration code to use Prism.Ioc.IContainerRegistry it worked perfectly.
protected override void RegisterTypes(IContainerRegistry cr)
{
cr.Register<ILogger, LoggerConsole>();
cr.GetContainer().RegisterMany(new[] { Assembly.Load("Project.UWP") },
serviceTypeCondition: type => type == typeof(ILocalFileHandler));
cr.Register<INegotiator, Negotiator>();
cr.RegisterForNavigation<NavigationPage>();
cr.RegisterForNavigation<MainPage>();
cr.RegisterForNavigation<AuthenticatePage>();
}

Structuremap mvc 5 injecting applicationdbcontext

Adding Structuremap MVC 5 to an ASP.NET MVC project. I would like to have a singleton of my database connection per request - my controllers would share the same database connection. I am implementing the repository pattern here and need each controller to have a copy of its respective repository. I know this is possible but I think I'm missing or mis-interpretting something wrong.
I have a controller, "Bag," that needs a "IBagRepo"
public class BagController : Controller
{
private readonly IBagRepo repo;
public BagController(IBagRepo repo)
{
this.repo = repo;
}
// actions
}
My first attempt was hooking the singleton database connection in the ControllerConvention, as I assume its called once
public class ControllerConvention : IRegistrationConvention {
public void Process(Type type, Registry registry) {
if (type.CanBeCastTo<Controller>() && !type.IsAbstract) {
// Tried something like
registry.For(type).Singleton().Is(new ApplicationDbContext()); // this
registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
}
}
}
But it came clear that this isn't the right file to make this change. I went into the registry class that was automatically generated upon installing the nuget package and tried fiddling around with this.
public class DefaultRegistry : Registry {
#region Constructors and Destructors
public DefaultRegistry() {
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
// httpContext is null if I use the line below
// For<IBagRepo>().Use<BagRepo>().Ctor<ApplicationDbContext>().Is(new ApplicationDbContext());
}
#endregion
}
I haven't seen a problem like this out here yet. Am I passing in the right types within my DefaultRegistry class?
What you're wanting is effectively the default behavior if you had been using the StructureMap.MVC5 nuget: https://www.nuget.org/packages/StructureMap.MVC5/. As long as your DbContext is registered with the default lifecycle, that package is using a nested container per http request which effectively scopes a DbContext to an HTTP request for unit of work scoping.
Different tooling than MVC & EF, but I described similar mechanics for FubuMVC + RavenDb w/ StructureMap in this blog post: http://jeremydmiller.com/2014/11/03/transaction-scoping-in-fubumvc-with-ravendb-and-structuremap/
I ended overriding the default controller factory and not using structuremap

Ninject Creating an Extra Instance when using NinjectHttpModule

For some reason Ninject is creating an additional instance of my object when I use NinjectHttpModule in my MVC 4 app.
If I use NinjectHttpModule (the Ninject.MVC3 default) but do not actually have any IHttpModule classes that require constructor injection, it works fine. But as soon as I create a class that implements IHttpModule and that requires constructor injection, Ninject for some reason creates two instances of my object.
I added some tracking code to the class that is being duplicated to verify that it was being duplicated. Every time an instance is created, the static count variable is incremented:
namespace Trigger.Events
{
public class TriggerEventRegistry : ITriggerRegistry
{
private static int count;
public TriggerEventRegistry()
{
TriggerEventRegistry.count++;
}
}
}
Here is my IHttpModule:
namespace TriggerDevelopment.ApplicationTriggers
{
public class RegisterTriggerComponentsHttpModule : IHttpModule
{
ITriggerEventRegistry eventRegistry;
public RegisterTriggerComponentsHttpModule(ITriggerEventRegistry eventRegistry)
{
this.eventRegistry = eventRegistry;
}
}
....
}
By the time a TriggerEventRegistry is injected into my controller (on the same request), the TriggerEventRegistry.count equals 2. If I comment out the constructor on RegisterTriggerComponentsHttpModule, then the value of TriggerEventRegistry.count equals 1 (which is should since there should only be one instance/request).
Here is the binding code:
Bind<ITriggerEventRegistry>().To<TriggerEventRegistry>().InRequestScope();
Any help on this would be greatly appreciated!
Note
I even made a request to my app using curl to avoid multiple HTTP requests being made by the browser looking for assets, a favicon or something like that. Still no joy.
Update
Upon further investigation, I'm also seeing that the ctor and the Init method of RegisterTriggerComponentsHttpModule is being called twice.
It's going to call your HttpModule as many times as there are requests. For instance, most web browsers submit at least two requests, the page request and a favicon request. Try adding something like an image to the page, and see if you get three requests...

Categories