Using Google.Apis.Auth results in a unique exception in .Net project - c#

Good day!
I am trying to add Google Authentication to Firestore project.
Used various bundles VS2017, VS2019, .net Core 2.2, 3.1, .net 5.0.
The whole project works fine until any mention of Google.Apis.Auth.OAuth2.Mvc.Controllers (or AspNetCore3) is added.
Once a simple mention is added in the Startup.cs
app.UseEndpoints (...);
an exception is thrown
System.TypeLoadException: "Could not load type 'System.Web.HttpContextBase' from assembly 'System.Web, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a'."
Dependencies used:
<PackageReference Include="Firebase.Auth" Version="1.0.0" />
<PackageReference Include="FirebaseDatabase.net" Version="4.0.6" />
<PackageReference Include="Google.Apis.Auth.AspNetCore3" Version="1.55.0" />
<PackageReference Include="Google.Cloud.Firestore" Version="2.4.0" />
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.7" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Session" Version="2.2.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
I tried adding Google.Apis, Google.Apis.Auth, Google.Apis.Auth.Mvc, Google.Apis.Core, result was the same.
Small code with this exception:
AuthCallbackController.cs
using System.Web.Mvc;
namespace Google.Apis.Auth.OAuth2.Mvc.Controllers
{
public class AuthCallbackController : Controller
{
public ActionResult Index()
{
return Redirect("/");
}
}
}
Program.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace ToDo2019Help
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ToDo2019Help
{
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();
}
// 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("/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.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
}
There is more code in the final project, but the same exception is still thrown on app.UseEndpoints. i'm sorry for bad english. Thank you for any help!
EDIT
If replaced in AuthCallbackController.cs
using System.Web.Mvc;
with line
using Microsoft.AspNetCore.Mvc;
this exception is no longer thrown,
but GetUserId require System.Web.Mvc.Controller and controller.Session is
error "CS7069. Reference The reference to the type "HttpSessionStateBase" requires its definition in "System.Web", but it could not be found"
AppFlowMetadata.cs
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
public class AppFlowMetadata : Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
{
private static readonly IAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "PPPPPPPP",
ClientSecret = "PPPPPPPPP"
},
Scopes = new[] { "email", "profile" },
});
public override string GetUserId(System.Web.Mvc.Controller controller)
{
var user = controller.Session["user"];
if (user == null)
{
user = System.Guid.NewGuid();
controller.Session["user"] = user;
}
return user.ToString();
throw new System.NotImplementedException();
}
public override string AuthCallback
{
get
{
return #"/AuthCallback/IndexAsync";
}
}
public override IAuthorizationCodeFlow Flow
{
get { return flow; }
}
}

My mistake was using Google.Apis.Auth.OAuth2.Flows in a .Net Core project. You need to use the Google.Apis.Auth.AspNetCore3 library. An example of how to use it

Related

ASP.NET Core 6 MVC: Not supported Http Methods

I have been working for a few days on a little C# micro service project.
About the project:
Project uses a SwaggerAPI
Project uses Entity Framework
Project version: .NET 6.0
Project uses MVC architecture
My csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<Description>IO.Swagger</Description>
<Copyright>IO.Swagger</Copyright>
<TargetFramework>net6.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PreserveCompilationContext>true</PreserveCompilationContext>
<AssemblyName>IO.Swagger</AssemblyName>
<PackageId>IO.Swagger</PackageId>
<IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.2.3" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.2.3" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.2.3" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.2.3" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
</ItemGroup>
</Project>
My StartUp.cs:
using System;
using System.IO;
using System.Web.Mvc;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using IO.Swagger.Filters;
using IO.Swagger.Models;
using IO.Swagger.Controllers;
using Microsoft.AspNetCore.Mvc.Formatters;
using IO.Swagger.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Cors.Infrastructure;
namespace IO.Swagger
{
public class Startup
{
private readonly IWebHostEnvironment _hostingEnv;
private IConfiguration Configuration { get; }
public Startup(IWebHostEnvironment env, IConfiguration configuration)
{
_hostingEnv = env;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
// Add MVC API Endpoints
services.AddControllers().AddNewtonsoftJson();
services.AddControllers();
services.AddHttpClient();
services.AddMvcCore(options =>
{
options.RequireHttpsPermanent = true;
options.RespectBrowserAcceptHeader = true;
});
services.AddSwaggerGen();
services.AddCors();
services.AddDbContext<TaskContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
});
services.AddControllersWithViews().AddNewtonsoftJson();
// services.AddRazorPages();
services.AddMvc(options =>
options.EnableEndpointRouting = false
);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(ep =>
{
ep.MapControllerRoute(
name: "DefaultApi",
pattern: "{controller}/{action}/{id?}",
defaults: new {controller = "DefaultApi", action = "Index"}
);
ep.MapControllers();
});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("openapi.yaml", "My first API");
});
app.UseMvc();
}
}
}
My Controller Class:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections;
using System.ComponentModel.DataAnnotations;
using Swashbuckle.AspNetCore.Annotations;
using Swashbuckle.AspNetCore.SwaggerGen;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using IO.Swagger.Attributes;
using IO.Swagger.Data;
using IO.Swagger.Models;
namespace IO.Swagger.Controllers
{
[Route("{controller}/{action}/{id}")]
[ApiController]
public class DefaultApiController : ControllerBase
{
private readonly TaskContext _context;
public DefaultApiController(TaskContext taskContext)
{
this._context = taskContext;
}
/*
public ActionResult Index(string id)
{
return View();
}
*/
[HttpGet]
[Route("/v1/tasks")]
[ValidateModelState]
[SwaggerOperation("TasksGet")]
[SwaggerResponse(statusCode: 200, type: typeof(List<GetTask>), description: "A JSON array of tasks")]
public async Task<IActionResult> TasksGet()
{
var tasks = await _context.Tasks.ToListAsync();
return Ok(tasks);
}
[HttpPost("post")]
[Route("/v1/tasks")]
[ValidateModelState]
[SwaggerOperation("TasksPost")]
[SwaggerResponse(statusCode: 201, type: typeof(GetTask), description: "Successfully created", contentTypes: "application/json")]
public async Task<IActionResult> TasksPost([FromBody]PostTask body)
{
IO.Swagger.Models.Task task = createTask(body);
_context.Add(task);
await _context.SaveChangesAsync();
return Ok(task);
}
[HttpDelete]
[Route("/v1/tasks/{uuid}")]
[ActionName("TasksUuidDelete")]
[ValidateModelState]
[SwaggerOperation("TasksUuidDelete")]
[SwaggerResponse(statusCode: 200, type: typeof(GetTask), description: "Delete Task")]
public virtual async Task<IActionResult> TasksUuidDelete([FromRoute][Required]string uuid)
{
uuid = "{" + uuid + "}";
var taskToDelete = new IO.Swagger.Models.Task();
var allTasks = await _context.Tasks.ToArrayAsync();
foreach (var task in allTasks)
{
if(task.Uuid.Equals(uuid))
{
taskToDelete = task;
}
}
if(taskToDelete != null)
{
_context.Remove(taskToDelete);
await _context.SaveChangesAsync();
return Ok(taskToDelete);
} else
{
return NotFound();
}
}
}
[HttpGet]
[Route("/v1/tasks/{uuid}")]
[ActionName("TasksUuidGet")]
[ValidateModelState]
[SwaggerOperation("TasksUuidGet")]
[SwaggerResponse(statusCode: 200, type: typeof(GetTask), description: "Get Task")]
public async Task<IActionResult> TasksUuidGet([FromRoute][Required]string uuid)
{
uuid = "{" + uuid + "}";
var taskToFind = new IO.Swagger.Models.Task();
var allTasks = await _context.Tasks.ToArrayAsync();
foreach (var task in allTasks)
{
if(task.Uuid.Equals(uuid))
{
taskToFind = task;
}
}
if (taskToFind == null)
{
return NotFound();
}
await _context.SaveChangesAsync();
return Ok(taskToFind);
}
[HttpPut]
[Route("/v1/tasks/{uuid}")]
[ActionName("TasksUuidPut")]
[ValidateModelState]
[SwaggerOperation("TasksUuidPut")]
[SwaggerResponse(statusCode: 200, type: typeof(PostTask), description: "Replace Task")]
public async Task<IActionResult> TasksUuidPut([FromBody]PostTask body, [FromRoute][Required]string uuid)
{
uuid = "{" + uuid + "}";
var taskToUpdate = new IO.Swagger.Models.Task();
var allTasks = await _context.Tasks.ToArrayAsync();
foreach (var task in allTasks)
{
if(task.Uuid.Equals(uuid))
{
taskToUpdate = task;
taskToUpdate.Title = body.Title;
taskToUpdate.Description = body.Description;
}
}
await _context.SaveChangesAsync();
if (taskToUpdate != null)
{
return Ok(taskToUpdate);
} else
{
return NotFound();
}
}
private IO.Swagger.Models.Task createTask(PostTask body)
{
IO.Swagger.Models.Task taskForList = new IO.Swagger.Models.Task();
taskForList.Title = body.Title;
taskForList.Description = body.Description;
taskForList.Uuid = System.Guid.NewGuid().ToString("B");
return taskForList;
}
}
}
My problem is when I try to execute the HttpPut, HttpDelete methods with the cURL command, I get the following error:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 'PUT' https://localhost:5001/v1/tasks/c18556a8-635f-4fd7-8aea-13ff7a9c42d1 application/json 74
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '405 HTTP Method Not Supported'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '405 HTTP Method Not Supported'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 'PUT' https://localhost:5001/v1/tasks/c18556a8-635f-4fd7-8aea-13ff7a9c42d1 application/json 74 - 405 0 - 8.4272ms
But when I add to the HttpAttributes an ID like in HttpPost it works fine, but I can't put an ID to two or more HttpAttributes with the same URL because then I get an multiple methods error. I guess the problem is that HttpPut, HttpGet and HttpDelete have the same routing URL.
I read a lot about the routing but can't fix the problem.
What I have tried:
Use one method for HttpGet, HttpPut and HttpDelete and use a switch-case for the different implementations
Use an ID for all HttpAttributes
Different configurations with app.UseEndpoints
Tried to use different controller classes for the HttpActions
Nothing really helps.
My question is: how can I map different HttpActions with the same route URL?
I'm not sure if this is the solution to your issue but .NET 6.0+ does not automatically generate the startup.cs file anymore.

ASP.NET Core Testing - No method 'public static IHostBuilder CreateHostBuilder(string[] args)

I'm trying to setup my application in tests and use in Startup's Configure method context.Database.EnsureCreated() and expecting Sqlite file appear in Test's bin folder
Here's my code:
using Microsoft.AspNetCore.Mvc.Testing;
using System.Threading.Tasks;
using Xunit;
namespace MyApp.Tests
{
public class UnitTest1 : IClassFixture<CustomWebApplicationFactory<FakeStartup>>
{
private readonly CustomWebApplicationFactory<FakeStartup> _factory;
public UnitTest1(CustomWebApplicationFactory<FakeStartup> factory)
{
_factory = factory;
}
[Fact]
public async Task Test1()
{
// Arrange
var client = _factory.CreateClient();
// Act
var response = await client.GetAsync("https://localhost:5001/");
// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString());
}
}
}
Which is using WebAppFactory:
using MyApp.Tests;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseStartup<FakeStartup>();
}
}
Where FakeStartup is:
using MyApp.Database;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace MyApp.Tests
{
public class FakeStartup
{
public FakeStartup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<Context>(x => x.UseSqlite($"filename={Guid.NewGuid():N}.db"));
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
});
}
}
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, Context context)
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API v1");
c.RoutePrefix = string.Empty;
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseAuthentication();
app.UseCors(x =>
{
x.AllowAnyOrigin();
x.AllowAnyMethod();
x.AllowAnyHeader();
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Here's problem
Message:
System.InvalidOperationException : No method 'public static IHostBuilder CreateHostBuilder(string[] args)' or 'public static IWebHostBuilder CreateWebHostBuilder(string[] args)' found on 'AutoGeneratedProgram'. Alternatively, WebApplicationFactory`1 can be extended and 'CreateHostBuilder' or 'CreateWebHostBuilder' can be overridden to provide your own instance.
Stack Trace:
WebApplicationFactory`1.CreateWebHostBuilder()
WebApplicationFactory`1.EnsureServer()
WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers)
WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
WebApplicationFactory`1.CreateClient()
UnitTest1.Test1() line 20
--- End of stack trace from previous location where exception was thrown
What may be causing this? thanks in advance
Updated with comment from CoreyP:
If you are getting this error and you're on .NET 6.0, you might need to update the Microsoft.AspNetCore.Mvc.Testing package, see this question: Integration test for ASP.NET Core 6 web API throws System.InvalidOperationException
Solution:
Create CustomWebApplicationFactory this way
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
protected override IHostBuilder CreateHostBuilder()
{
var builder = Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(x =>
{
x.UseStartup<FakeStartup>().UseTestServer();
});
return builder;
}
}
Found here:
https://thecodebuzz.com/no-method-public-static-ihostbuilder-createhostbuilder/
I was getting this error because I had not followed the MS prerequisites closely enough. In my case I had not updated the Project SDK in the test csproj file. It needs to be <Project Sdk="Microsoft.NET.Sdk.Web"> (note the '.Web' on the end).

Cosmos provider for Entity Framework Core creating container with DbContext class name

I'm using Azure Cosmos DB in asp net core 3.1 app with Microsoft.EntityFrameworkCore.Cosmos package. In my AppContext class on OnModelCreating method i've give every dbset ToContainer() method to define the name of container otherwise it'll give AppContext name to container. Everything is working fine but it still create one container AppContext in CosmosDb, how can i fix this? Please help. Below is my code.
AppContext Class
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace CosmosApp.Context
{
public class AppContext : IdentityDbContext<AppUser>
{
public DbSet<Teacher> Teachers { get; set; }
public DbSet<Student> Students { get; set; }
public AppContext(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>().ToContainer("Users");
modelBuilder.Entity<AppUser>().ToContainer("Users");
modelBuilder.Entity<IdentityUserRole<string>>().ToContainer("UserRoles");
modelBuilder.Entity<IdentityUserLogin<string>>().ToContainer("UserLogins");
modelBuilder.Entity<IdentityUserClaim<string>>().ToContainer("UserClaims");
modelBuilder.Entity<IdentityRole>().ToContainer("Roles");
modelBuilder.Entity<IdentityUserToken<string>>().ToContainer("UserTokens");
modelBuilder.Entity<Teacher>().ToContainer("Teachers");
modelBuilder.Entity<Student>().ToContainer("Students");
modelBuilder.Entity<Teacher>().HasNoDiscriminator();
modelBuilder.Entity<Student>().HasNoDiscriminator();
}
}
}
AppUser Class
using Microsoft.AspNetCore.Identity;
namespace CosmosApp.Entities
{
public class AppUser : IdentityUser
{
public string DisplayName { get; set; }
}
}
Startup Class
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppContext>(options =>
{
options.UseCosmos(
"https://localhost:8081/",
"C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
"TestDb");
});
services.AddControllers();
services.AddIdentity<AppUser, IdentityRole>(options => { })
.AddEntityFrameworkStores<AppContext>()
.AddDefaultTokenProviders();
services.AddAuthentication();
}
Program Class
using System;
using CosmosApp.Context;
using CosmosApp.Entities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using AppContext = CosmosApp.Context.AppContext;
namespace CosmosApp
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<AppContext>();
var userManager = services.GetRequiredService<UserManager<AppUser>>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
context.Database.EnsureCreated();
Seed.SeedData(context, userManager, roleManager).Wait();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occured during migration");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Packages Info
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Cosmos" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Now you can see it was creating unknown conatiner AppContext
Use HasDefaultContainer for the first Entity and ToContainer on subsuquent Entities.
protected override void OnModelCreating( ModelBuilder builder ) {
builder.HasDefaultContainer("Users");
builder.Entity<User>().ToContainer("Users");
builder.Entity<Teacher>().ToContainer("Teachers");
builder.Entity<Student>().ToContainer("Students");
}

How to fix "Method 'ApplyServices' does not have an implementation" at Program with efCore 3 and .net core 3

I'm developing a new Web API on EfCore 3 and .net core 3 and not able to start this because of an error "Method 'ApplyServices' in type 'Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal.SqlServerOptionsExtension' from assembly 'Microsoft.EntityFrameworkCore.SqlServer, Version=3.0.0.0' does not have an implementation.
I should note that ApplicationContext that I inject to my project is located in another project (.net core 3 too).
Debugging showed that application is crashed in this part of code -->
services
.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(connectionString));
Here you can see All StartUp Class
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
private readonly IConfiguration _configuration;
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
var connectionString = _configuration.GetConnectionString("DefaultConnection");
services
.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(connectionString));
services.AddControllers()
.SetCompatibilityVersion(CompatibilityVersion.Latest)
.AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
services.AddHostedService<MigratorHostedService>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors("AllowAll");
app.UseStaticFiles();
app.UseRouting();
}
Here is MigratorHostedService
private readonly IServiceProvider _serviceProvider;
public MigratorHostedService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
using (var scope = _serviceProvider.CreateScope())
{
var myDbContext = scope.ServiceProvider.GetRequiredService<ApplicationContext>();
await myDbContext.Database.MigrateAsync();
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
Here is Program
private const int Port = ...;
public static async Task Main()
{
var cts = new CancellationTokenSource();
var host = Host.CreateDefaultBuilder();
host.ConfigureWebHostDefaults(ConfigureWebHost);
await host.Build()
.RunAsync(cts.Token)
.ConfigureAwait(false);
}
private static void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseUrls($"http://*:{Port}");
builder.UseStartup<Startup>();
builder.UseDefaultServiceProvider((context, options) =>
{
options.ValidateOnBuild = true;
});
}
As .net core 3 is new, I haven't found solution of this problem
Also my project packages:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<NoWarn>$(NoWarn);NU1605</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0-preview-18579-0056" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0-preview.19080.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview.19080.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview.19080.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.DotNetAppHost" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Utils" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
</Project>
ApplicationContext
public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)
{
}
Interfaces define the signature of a Functions - name, arguments, return value. But they can not define any code for them. They expect the class that implements them, to give them code. You have to give an implementation.
Now this is a absolutely valid implementation for every imaginable Interface functions:
{
throw new NotImplementedException();
}
So is this:
{
throw new NotSupportedException();
}
It even fullfills the "must return a value" rule.
It is also the default implementation. And in some cases it might be the only implementation. Not every function of every Interface might have a sensible implementation for every class that implements it. In some cases, the function being not implemented is even expected.
If you control that class, you have to provide an actuall implementation for that function.
If you do not control that class, then you are largely out of luck.
I can not see any call to ApplyServices. So that means you hand the instante to to some code that expects the function to exist (and have sensible behavior). Wich is not the case.
Whatever you tried to do that expects a class with code for ApplyServices, it can not be applied to this class. There should be a way to hand some code to the function. Like there is a override for Array.Sort() that accepts a custom Comparer, rather then using a default Comparer. But if not, it is simply a no-go.
after all tryings the right implementation of startup was there
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly("CRM.API")));
services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
//.AllowCredentials();
});
});
services.AddControllers().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors("AllowAll");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Departments}/{action=GetDepartments}/{id?}");
});
}
And right Program class implementation was there
public static async Task Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<ApplicationContext>();
await context.Database.MigrateAsync();
await DbInitializer.InitializeAsync(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
Sure, this answer will help you

Ambiguity between 'Startup.Configuration' and 'Startup.Configuration'

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.

Categories