I am building an ASP.NET web API application, and I'm stuck in a problem... :/
I have appsettings.json to configure mysql connection:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"CoinConnection": "server=127.0.0.1;user id=root;password=root;port=3306;database=coin_db;Allow User Variables=True;",
"UserConnection": "server=127.0.0.1;user id=root;password=root;port=3306;database=user_db;Allow User Variables=True;"
}
}
I have Startup.cs to execute the service to connect mysql:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace WebApplication2
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<AppDb>(_ => new AppDb(Configuration["ConnectionStrings:CoinConnection"]));
services.AddControllers();
}
// 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.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
I have AppDb.cs to receive a string and connect in database coin_db in mysql:
using System;
using MySqlConnector;
namespace WebApplication2
{
public class AppDb : IDisposable
{
public MySqlConnection Connection { get; }
public AppDb(string connectionString)
{
Connection = new MySqlConnection(connectionString);
}
public void Dispose() => Connection.Dispose();
}
}
I don't know how I can do to connect the second database (user_db)... I've tried everything and I don't know how to do it.
You don't need a second connection, if it is the same server.
Simply add the database name before the table name
SELECT a.*,b.* FROM coin_db.table1 a INNER JOIN user_db.tabl2 b ON a.id P= b.id
Mysql can identify so, whichtable you mean.
two connection is possible see here Choose one of many Internet connections for an application
Have you tried using a different AppDb implementation for each db?
Then you can access them via dependency injection in your routes.
public class UserDb : AppDb
{
public UserDb(string connectionString)
: base(connectionString)
{}
// ...
}
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<AppDb>(_ => new AppDb(Configuration["ConnectionStrings:CoinConnection"])); // TODO: use CoinDb class and make AppDb class abstract
services.AddTransient<UserDb>(_ => new UserDb(Configuration["ConnectionStrings:UserConnection"]));
services.AddControllers();
}
Related
I am a beginner in ASP.NET Core. I am creating a Web API service. While I am fetching the data from the database, I had a problem. What is the error I got? I have successfully done the database migration part and created the database successfully.
System.InvalidOperationException: Unable to resolve service for type 'webb.StudentDbContext' while attempting to activate 'webb.Controllers.StudentController'.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method3(Closure , IServiceProvider , Object[] )
StudentController:
[Route("api/[controller]")]
[ApiController]
public class StudentController : ControllerBase
{
private StudentDbContext studentDbContext;
public StudentController(StudentDbContext studentDbContext)
{
studentDbContext = studentDbContext;
}
// GET: api/<EmployeeController>
[HttpGet]
public IEnumerable<Student> Get()
{
return studentDbContext.Student;
}
}
Model class:
namespace webb.Model
{
public class Student
{
public int id { get; set; }
public int stname { get; set; }
public int course { get; set; }
}
}
StudentDbContext:
public class StudentDbContext : DbContext
{
public DbSet<Student> Student { get; set; }
public StudentDbContext()
{
}
public StudentDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().HasKey(e => e.id);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=sms;Integrated Security=True; TrustServerCertificate = True");
}
}
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"StudentConnStr": "Data Source=.;Initial Catalog=sms;Integrated Security=True;"
}
}
Where I am going to set the key.
Program.cs:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using webb;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
builder.Services.AddDbContext<StudentDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("StudentDbContext")));
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Look like you are missing out inject StudentDbContext which is the DbContext to DI container.
Add below to your Program.cs:
builder.Services.AddDbContext<StudentDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("StudentConnStr")));
refer to this and Part 5, work with a database in an ASP.NET Core MVC app
Update
builder.Services.AddDbContext<StudentDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("StudentConnStr")));
var app = builder.Build();
builder.Build() should be after all AddXXX functions. In other words, you need to swap it with AddDbContext()
builder.Services.AddDbContext<StudentDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("StudentDbContext")));
var app = builder.Build();
This line is causing an error in my project:
options.UseSqlServer(Configuration.GetConnectionString("SchoolContext")));
Error:
System.ArgumentNullException: 'Value cannot be null. (Parameter 'connectionString')'
I have read through a bunch of similar problems online and I cannot find a change that works. It seems that the parameter inside UseSqlServer() is returning null. This leads me to believe that I have a configuration mistake.
Here is my code for my Startup and json files:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Data;
namespace ContosoUniversity
{
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.AddRazorPages();
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SchoolContext")));
services.AddDatabaseDeveloperPageExceptionFilter();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
}
{
"ConnectionStrings": {
"DefaultConnection": "Server=(***;Database=***;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore.Database.Command": "Information"
}
},
"AllowedHosts": "*"
}
Any assistance is appreciated. Thanks.
You are trying to get a connection string called SchoolContext but you only have one in the config called DefaultConnection. So either fix your code:
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
Or fix your config:
{
"ConnectionStrings": {
"SchoolContext": "Server=....."
},
// etc...
I cant create a migration in asp.net core because i keep getting cant construct db context and im using 2 contexts. Ive tried everything to try and fix this but I still cant create migrations because it says it has an error constructing db context and all my code is fine and I cant find out why this wont work. Can someone please help, Thanks.
ApplicationDbContext
using GraphQlApiFullStack.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace GraphQlApiFullStack.Data
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
}
}
IdentityAppDbContext.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GraphQlApiFullStack.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace GraphQlApiFullStack.Data
{
public class IdentityAppDbContext : IdentityDbContext<AppUser>
{
public IdentityAppDbContext(DbContextOptions<IdentityDbContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
}
}
}
identityServicesExtension.cs
using System.Text;
using GraphQlApiFullStack.Data;
using GraphQlApiFullStack.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
namespace GraphQlApiFullStack.Extensions
{
public static class IdentityServiceExtensions
{
public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration config)
{
var builder = services.AddIdentityCore<AppUser>();
builder = new IdentityBuilder(builder.UserType, builder.Services);
builder.AddEntityFrameworkStores<IdentityAppDbContext>();
builder.AddSignInManager<SignInManager<AppUser>>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Token:Key"])),
ValidIssuer = config["Token:Issuer"],
ValidateIssuer = true,
ValidateAudience = false
};
});
return services;
}
}
}
startup.cs
using GraphQL.Server.Ui.Voyager;
using GraphQlApiFullStack.Data;
using GraphQlApiFullStack.Extensions;
using GraphQlApiFullStack.GraphQL;
using GraphQlApiFullStack.Services;
using GraphQlApiFullStack.Services.Interfaces;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
namespace GraphQlApiFullStack
{
public class Startup
{
private readonly IConfiguration _configuration;
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.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo {Title = "GraphQlApiFullStack", Version = "v1"});
});
// We use a pooled Db Context Factory here to avoid issues with graphql concurrency
services.AddPooledDbContextFactory<ApplicationDbContext>(builder =>
{
builder.UseSqlServer(_configuration.GetConnectionString("defaultConnection"));
});
// Identity will use just a normal db context since we wont be making multiple concurrent queries to it.
services.AddDbContext<IdentityAppDbContext>(options =>
{
options.UseSqlServer(_configuration.GetConnectionString("identityConnection"));
});
services.AddHttpContextAccessor();
services.AddGraphQLServer()
.AddQueryType<Query>()
.AddMutationType<Mutation>()
.AddFiltering()
.AddSorting()
.AddProjections();
services.AddScoped<ITokenService, TokenService>();
//services.AddIdentityServices(_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();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "GraphQlApiFullStack v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapGraphQL();
});
app.UseGraphQLVoyager(new VoyagerOptions()
{
GraphQLEndPoint = "/graphql"
});
}
}
}
I get an error of "Ambiguity between 'Startup.Configuration' and 'Startup.Configuration'" on my startup class. I don't know what I have done to cause this issue. All I did was create a DBContext class and this error occured. Please see my code below:
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using System;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using IssueTracker.Data;
namespace IssueTracker
{
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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
// Enabling CORS
services.AddCors(options =>
{
options.AddPolicy("EnableCORS", builder =>
{
builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials().Build();
});
});
// Connect to the Database
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.getConnectionString("DefaultConnection")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/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.UseCors("EnableCORS");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
}
ApplicationDbContext
using IssueTracker.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace IssueTracker.Data
{
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) {}
// Creating the roles
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<IdentityRole>().HasData(
new { Id = "1", name="Admin", NoralizeName = "ADMIN" },
new { Id = "1", name="Customer", NoralizeName = "CUSTOMER" },
new { Id = "1", name="Moderator", NoralizeName = "MODERATOR" }
);
}
public DbSet<ProductModel> Products { get; set; }
}
}
Could you please tell me what is wrong here? Thank you.
I had the same error and simply closing and reopening my IDE (Visual Studio Code) solved it. I hope it helps
One reason for this error might be that you have accidently made a copy of Startup.cs file.
I coppied solution file for backup purposes then I got that error. When I delete the backup file problem solved.
First of all, I'm trying to seed my database with sample data. I have read that this is the way to do it (in Startup.Configure) (please, see ASP.NET Core RC2 Seed Database)
I'm using ASP.NET Core 2.0 with the default options.
As usual, I register my DbContext in ConfigureServices.
But after that, in the Startup.Configure method, when I try to resolve it using GetRequiredService, it throws with this message:
System.InvalidOperationException: 'Cannot resolve scoped service
'SGDTP.Infrastructure.Context.SGDTPContext' from root
provider.'
My Startup class like this:
public abstract class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SGDTPContext>(options => options.UseInMemoryDatabase("MyDatabase"))
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
SeedDatabase(app);
}
private static void SeedDatabase(IApplicationBuilder app)
{
using (var context = app.ApplicationServices.GetRequiredService<SGDTPContext>())
{
// Seed the Database
//...
}
}
}
What am I doing wrong?
Also, is this the best place to create seed data?
You're registering SGDTPContext as a scoped service and then attempting to access it outside of a scope. To create a scope inside your SeedDatabase method, use the following:
using (var serviceScope = app.ApplicationServices.CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<SGDTPContext>();
// Seed the database.
}
Credit to #khellang for pointing out the CreateScope extension method in the comments and to #Tseng's comment and answer re how to implement seeding in EF Core 2.
Was getting this error while following the official ASP.Net MVC Core tutorial, in the section where you are supposed to add seeded data to your application. Long story short, adding these two lines
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
to the SeedData class solved it for me:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
namespace MvcMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new MvcMovieContext(
serviceProvider.GetRequiredService<DbContextOptions<MvcMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}
...
Can't tell you the WHY, but these were two of the options I got from following the Alt + Enter quick fix option.
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)
{
var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
services.AddDbContext<DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")).EnableSensitiveDataLogging());
services.AddMvc();
services.AddTransient<Seed>();
services.AddCors();
services.AddScoped<IAuthRepository, AuthRepository>();
services.AddScoped<IUserRepository, UserRepository>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(Options =>
{
Options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
}
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env ,Seed seeder)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(builder =>
{
builder.Run(async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
}
});
});
}
seeder.SeedUser();
app.UseCors(x=>x.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
app.UseMvc();
}
}
}