ASP .NET Core Publish Errors AddDbContext - asp.net

i actually dont know deploy IIS for LAN server. We are working on this project together with my friend. We share same Wifi. So we want shared api project. Because i working on backend (API-DAL-BLL) layers, my friends working on FrontEnd. But i cant deploy very well.
First my publish cant see my DBContext.So i added Startup addDbContext.
My Startup.cs like this
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GastroDB>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IMainCategoryService, MainCategoryService>();
}
My Program.cs like this
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel().UseContentRoot(Directory.GetCurrentDirectory()).UseUrls("myIpAdress:80").UseIISIntegration().UseStartup<Startup>();
});
}
But iis can not get start. This is my errors ;
.Net Runtime:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ArgumentException: 'AddDbContext' was called with configuration, but the context type 'GastroDB' only declares a parameterless constructor. This means that the configuration passed to 'AddDbContext' will never be used. If configuration is passed to 'AddDbContext', then 'GastroDB' should declare a constructor that accepts a DbContextOptions<GastroDB> and must pass it to the base constructor for DbContext.
2)IIS AspNetCore Module V2
Application '/LM/W3SVC/1/ROOT' with physical root 'C:\Users\Tuğçe\Desktop\almanya projesi BE\EcommerceGastro.API\bin\Release\net5.0\publish\' hit unexpected managed exception, exception code = '0xe0434352'. First 30KB characters of captured stdout and stderr logs:
Unhandled exception. System.ArgumentException: 'AddDbContext' was called with configuration, but the context type 'GastroDB' only declares a parameterless constructor. This means that the configuration passed to 'AddDbContext' will never be used. If configuration is passed to 'AddDbContext', then 'GastroDB' should declare a constructor that accepts a DbContextOptions<GastroDB> and must pass it to the base constructor for DbContext.
I understand i will shoul add my context constructor like this
public GastroDB(DbContextOptions<GastroDB> options):base(options){}
But i cant add because first start like that on DBContext:
public class GastroDB : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.; database=GastroDB; user id=sa; password=123;");
}
private static GastroDB _dbInstance;
public static GastroDB DBInstance
{
get
{
if (_dbInstance == null)
{
_dbInstance = new GastroDB();
}
return _dbInstance;
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new MyMap());
...
}
public DbSet<MyClass> MyClass{ get; set; }
....
}
}
If i add ctor on this code, my some services throw exeption because i use like this
using (var transaction = new GastroDB())
{
var productList = transaction.Set<DBProduct>().Include(x => x.ProductImage).ToList();
return this.mapper.Map<List<Product>>(productList);
}
How can i fix this problems i dont know how. Please help me

You Should create a constructor that accept
DbContextOptions<GastroDB>.
You don't need to use public static GastroDB DBInstance because
DbContext are registerd as Scoped life time.
public class GastroDB : DbContext
{
public GastroDB(DbContextOptions<GastroDB> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.; database=GastroDB; user id=sa; password=123;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new MyMap());
...
}
public DbSet<MyClass> MyClass{ get; set; }
....
}
}
3 . If you want your DbContext register as singleton lifetime you can use below code instead of create a static property in DbContext
services.AddDbContext<GastroDB>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
}, ServiceLifetime.Singleton);

Related

'AddDbContext' was called with configuration, but the context type only declares a parameterless constructor

I got an error while developing the project.
My codes are below..
Error Message :
System.ArgumentException: ''AddDbContext' was called with
configuration, but the context type 'NoteDbContext' only declares a
parameterless constructor. This means that the configuration passed to
'AddDbContext' will never be used. If configuration is passed to
'AddDbContext', then 'NoteDbContext' should declare a constructor that
accepts a DbContextOptions and must pass it to the base
constructor for DbContext.'
DbContext
public class NoteDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer(
"Server=DESKTOP-BELVBNK\\SQLEXPRESS;" +
"DataBase=NoteAppDB;Trusted_Connection=True;");
}
public DbSet<Entities.Note> Notes { get; set; }
}
ASP.Net Project - Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<NoteDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("NoteAppDB")));
}
I searched for the solution of these errors, but could not find it.
When you register a DbContext with AddDbContext you need to have a special constructor, like:
public NoteDbContext(DbContextOptions options) : base(options) {}
This is required. See https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/.

Eager loading doesn't work with BackgroundService

I'm trying to load related entities in a console application that runs a BackgroundService,
but it doesn't load related entities, I have had this problem for hours now and I just noticed it happens only in the BackgroundService, tried the same DbContext in a web application by injecting the DbContext class in the Index page model, without a problem.
Here's the code from the console application:
the Background Service:
public class MyService : BackgroundService
{
private readonly MyDbContext _context;
public MyService(MyDbContext context)
{
_context = context;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
//Jobs always empty!
var theBatch = _context.Batches.Include(x => x.Jobs).FirstOrDefault();
}
}
the program file:
class Program
{
static async Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddLogging()
.AddDbContext<MyDbContext>(options => options
.UseSqlServer(context.Configuration.GetConnectionString("MyConnection")))
.AddHostedService<MyService>()
.BuildServiceProvider();
});
}
I'm using .NET 5 and EF Core 5.0.12
What you have should work as written. So double-check your configuration. As #Nkosi points out you should use shorter scopes, but putting one scope in your ExecuteAsync isn't enough, as the Task it returns has the same lifetime as the BackgroundService instance.
Anyway here's a complete repro that works fine in .NET 6.
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
class Program
{
static async Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddLogging()
.AddDbContext<MyDbContext>(options => options
.UseSqlServer(context.Configuration.GetConnectionString("MyConnection")))
.AddHostedService<MyService>()
.BuildServiceProvider();
});
}
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{ }
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public DbSet<Batch> Batches { get; set; }
public DbSet<Job> Jobs{ get; set; }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
}
public class Job
{
public int Id { get; set; }
}
public class Batch
{
public int Id { get; set; }
public virtual ICollection<Job> Jobs { get; set; } = new HashSet<Job>();
}
public class MyService : BackgroundService
{
private readonly MyDbContext _context;
public MyService(MyDbContext context)
{
_context = context;
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var batch = new Batch();
batch.Jobs.Add(new Job() );
context.Batches.Add(batch);
context.SaveChanges();
context.ChangeTracker.Clear();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var theBatch = await _context.Batches.Include(x => x.Jobs).FirstOrDefaultAsync();
Console.WriteLine(theBatch.Jobs.Count);
}
}
OK, I'm writing this while I'm really angry for the hours and the effort spent on this problem, I don't know who to blame, Microsoft or the person who installed EF 6 in .NET core project. Microsoft made it difficult to find out the source of the problem.
I was using Include from System.Data.Entity namespace not Microsoft.EntityFrameworkCore
I figured it out by a mere coincidence, I used FirstOrDefaultAsync without a specific reason, and got this weird exception:
'The provider for the source IQueryable doesn't implement
IDbAsyncQueryProvider. Only providers that implement
IDbAsyncQueryProvider can be used for Entity Framework asynchronous
operations.
When I looked at it, I found that I was using the wrong namespace for FirstOrDefaultAsync (System.Data.Entity instead of Microsoft.EntityFrameworkCore)
when I changed the namespace, everything worked!

EF Core DbContext sql connection string error (Tried Following info in MS Docs)

I have a .net Core application and I've been attempting to read from my local instance of SQL Server (2014) with Windows Authentication and continue to run into a repeat error about my connection string. I've been reviewing the MSDN docs as well as connectionstrings.com and thought I had everything configured correctly.
This is my error:
"System.ArgumentException: 'Format of the initialization string does
not conform to specification starting at index 0.'"
Which I take to mean the very start of my connection string.
I have read the other posts related to this exact issue but haven't been able to use them to find a solution.
Here is what I attempt when the error occurs:
public class HomeController : Controller
{
private ModelContext _context;
public HomeController()
{}
public IActionResult Index()
{
var viewModel = new HomeViewModel();
var optionsBuilder = new DbContextOptionsBuilder<ModelContext>();
optionsBuilder.UseSqlServer("DefaultConnection");
using (_context = new ModelContext(optionsBuilder.Options))
{
>>>>>> viewModel.List = _context.TableName.ToList(); <<<<<<<<
I have the following in my "appsettings.json" file:
"ConnectionStrings": {
"DefaultConnection": "Server=MyComputerName; Database=DBName; IntegratedSecurity=SSPI;"
},
In my "ModelContext.cs" file
public class ModelContext : DbContext
{
public ModelContext(DbContextOptions<ModelContext> options)
:base(options)
{ }
[<Table Properties>]
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("DefaultConnection");
}
And "Startup.cs" file:
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.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDbContext<ModelContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
Thanks for taking a look!
After much contemplation and re-review of the MS Documents site for EF Core DbContext, I found that I was attempting to implement ALL 3 methods of DbContext configuration: Constructor Argument, OnConfiguring, and dependency injection.
Decided to go with OnConfiguring to get the app moving.

Controller not found within a Web forms application

I have a project where there is a controller within a web forms application.
My controller is called Token
public class TokenController : BaseTokenController
{
public override bool IsInherited => true;
}
this controller inherits from BaseTokenController
public abstract class BaseTokenController : ApiController
{
public abstract bool IsInherited { get; }
public virtual bool Post([FromBody]TokenValidateArgs args)
{
if (!IsInherited)
throw new Exception("Attempt to call base token controller not allowed");
return args.Validate();
}
public virtual string Get()
{
if (!IsInherited)
throw new Exception("Attempt to call base token controller not allowed");
return new Token()
}
}
In my global.asax I have a method called Register:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute("API default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
}
and in global.asax Application_Start the first line of code is
protected void Application_Start(object sender, EventArgs e)
{
Register(GlobalConfiguration.Configuration);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I did have this working, however I then merged with the master branch for the project and it stopped working. I can't see anything that has changed.
this is the error:
No HTTP resource was found that matches the request URI 'https://localhost:44398/api/token'.
No type was found that matches the controller named 'token'.
Has anyone else experienced a similar issue and would know how to fix this. I have read other threads and tried to fix this by putting in a RoutePrefix on the controller, moving the order of execution on the global.asax and calling the get() method directly
So for my issue it turns out the project that has the "BaseTokenController" was running version 5.2.3 of WebApi however the web application project was running 5.2.4 which caused a conflict, resulting in a 404 error. To fix this I downgraded the app to 5.2.3

Internal Server Error 500 Asp.net WebApi trying to DI with Entity

I am building an ASP.net WebApi, and trying to use Entity alongside. I am following this guide.
Getting Started with ASP.NET Web API 2 (C#)
I am receiving a 500 internal server error using Fiddler. The JSON Exception message states ExceptionMessage=An error occurred when trying to create a controller of type 'LocationsController'. Make sure that the controller has a parameterless public constructor.
Here is the Controller.cs
[RoutePrefix("api/Locations")]
public class LocationsController : ApiController
{
// GET api/<controller>
private IlocationsRepository LocationsRepo;
public LocationsController(IlocationsRepository _repo)
{
if (_repo == null) { throw new ArgumentNullException("_repo"); }
LocationsRepo = _repo;
}
[HttpGet]
[Route("")]
public IEnumerable<Location> GetAll()
{
return LocationsRepo.GetAll();
}
}
I can't use a parameterless public constructor because I need to use the Database Repository that was created for Locations. I verified the issue was with the IlocationsRepository by doing the following.
When I replace the LocationsController constructor with no parameters , and declare a List<Location> within the controller, and use dummy data. I receive a 200 with all the json data correct.
Here is the start of the Global.asax.cs file
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
protected void Session_Start(object sender, EventArgs e)
{
}
}
It seems as if I need to do the dependency injection in the Global, but none of the guides had any information regarding this part.
For posterity here is the ContextDB cs
public class WebServerContext : DbContext
{
public WebServerContext() : base("WebServerContext") {}
public DbSet<Order> dOrders { get; set; }
public DbSet<Location> dLocations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
For additional posterity, here is the Locations Repository.
public class LocationsRepository : IlocationsRepository
{
private z_Data.WebServerContext db = new z_Data.WebServerContext();
public void Add(Location item)
{
db.dLocations.Add(item);
}
public IEnumerable<Location> GetAll()
{
return db.dLocations;
}
}
As per Dependency Injection for Web Api tutorial on MSDN, you are missing the line to register the dependency resolver (a concrete class that implements System.Web.Http.IDependencyResolver) with Web Api. It acts like a bridge between your DI container and Web Api so it can resolve your constructor dependencies.
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container); // <- You need this
// Other Web API configuration not shown.
}
Of course, that assumes you are using Unity. If not, you should either use the DependencyResolver that came with your DI container or implement your own.
NOTE: With some DI containers, you also need to register all of your controllers explicitly.

Resources