Slowly migrating system up from .net core 2.1 to 3.1.
While updating IdentityServer4 to 3.1 version.
I've stucked into problem method AddIdentityServer where options are specified..
var builder = services.AddIdentityServer(options =>
{
(!string.IsNullOrWhiteSpace(identityServerSettingsConfig.PublicOrigin))
{
options.PublicOrigin = identityServerSettingsConfig.PublicOrigin;
}
})
Error: 'IdentityServerOptions' does not contain a definition for 'PublicOrigin' and no accessible extension method 'PublicOrigin' accepting a first argument of type 'IdentityServerOptions' could be found
Installed packages:
<PackageReference Include="IdentityServer4" Version="4.1.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.5.3" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
The IdentityServerOptions.PublicOrigin property was removed in IdentityServer4 1.0 back in 2016.
This GitHub issue is asking the same question as yourself: https://github.com/IdentityServer/IdentityServer4/issues/4535
One of IdentityServer's authors said it was removed and explained why - and how you can work-around it (assuming you actually need it, I mention this because you probably don't need to restore this functionality):
leastprivilege commented on 19 Jun 2020:
It's gone. It was a hack - please use the forwarded headers approach in ASP.NET Core from now on.
The workaround is to add a middleware step that calls HttpContextExtensions.SetIdentityServerOrigin at the beginning of your pipeline, so it should look something like this:
In the code-block below, add the code between the //------- comments.
I included other Configure pipeline/appBuilder methods from one of my own IS4 projects so you can see a complete example.
using IdentityServer4.Extensions; // For IS4's `HttpContextExtensions`
public class Startup
{
// ...
public void Configure( IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLifetime )
{
_ = app
//-------------------------------- Add the code below this line
.Use( async (ctx, next) =>
{
ctx.SetIdentityServerOrigin( "https://example.com" );
await next();
})
//-------------------------------- Add the code above this line
.UseCors()
.UseAuthentication()
.UseOpenApi()
.UseSwaggerUi3()
.UseIdentityServer()
.UseRouting()
.UseAuthorization()
.UseEndpoints( routeBuilder =>
{
_ = routeBuilder.MapControllers();
} )
.UseStaticFiles();
}
}
Related
I've got a problem when trying to deploy my App Service to Azure from VS 2022. Each time I'm getting this error:
I'm using .NET 6 as my target framework and I've got the Swashbuckle.AspNetCore package updated to the newest version. The app service is published with success, but the error pops up when trying to update the API.
In my version of the project there is no Startup.cs but Program.cs, and the way I'm implementing the Swagger generation is:
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
I've browsed through similar posts and based on them I can add that I am not fetching any environment variables too.
I've also tried using UseSwaggerUI() like this but I get the same error anyway:
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
options.RoutePrefix = string.Empty;
});
Weird thing is that the deployment works for my colleague and it worked for me until last week when it stopped when nothing in the Program.cs was changed on the way.
My Program.cs:
var builder = WebApplication.CreateBuilder(args);
var azureKeyVaultUrl = builder.Configuration[AppConfigurationConst.AzureKeyVaultUrl];
var logAnalyticsWorkspaceId = AzureKeyVaultHelper.GetAzureKeyVault(azureKeyVaultUrl, AppConfigurationConst.LogAnalyticsWorkspaceId);
var logAnaliticsAuthenticationId = AzureKeyVaultHelper.GetAzureKeyVault(azureKeyVaultUrl, AppConfigurationConst.LogAnaliticsAuthenticationId);
var CrmConnectionString = AzureKeyVaultHelper.GetAzureKeyVault(azureKeyVaultUrl, AppConfigurationConst.OneCrmConnectionString);
var logger = new LoggerConfiguration()
.WriteTo.AzureAnalytics(logAnalyticsWorkspaceId, logAnaliticsAuthenticationId)
.Enrich.FromLogContext()
.CreateLogger();
var serviceClient = new ServiceClient(CrmConnectionString);
builder.Logging.AddSerilog(logger);
logger.Information("Start ALGOI App Service");
builder.Services.AddControllers().AddNewtonsoftJson();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<IAuthenticationService, AuthenticationService>();
builder.Services.AddSingleton<IWebClientService, WebClientService>();
builder.Services.AddScoped<ICreateSessionService, CreateSessionService>();
builder.Services.AddScoped<ICreateFolderService, CreateFolderService>();
builder.Services.AddScoped<IDeleteFolderService, DeleteFolderService>();
builder.Services.AddScoped<IVerifyFolderService, VerifyFolderService>();
builder.Services.AddScoped<IUndoFolderService, UndoFolderService>();
builder.Services.AddSingleton(serviceClient);
builder.Services.AddApplicationInsightsTelemetry(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]);
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
And my .csproj:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>{usersecretsid}</UserSecretsId>
<GenerateRuntimeConfigurationFiles>True</GenerateRuntimeConfigurationFiles>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Connected Services\**" />
<Content Remove="Connected Services\**" />
<EmbeddedResource Remove="Connected Services\**" />
<None Remove="Connected Services\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.7.0" />
<PackageReference Include="JsonSubTypes" Version="1.9.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.15.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Graph" Version="4.34.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.48.1" />
<PackageReference Include="Microsoft.Identity.Web" Version="1.16.0" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="1.16.0" />
<PackageReference Include="Microsoft.PowerPlatform.Dataverse.Client" Version="1.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="RestSharp" Version="106.13.0" />
<PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.AzureAnalytics" Version="4.8.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="TypeSafe.Http.Net.HttpClient" Version="2.2.16" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="someprojectpath" />
<ProjectReference Include="someprojectpath" />
<ProjectReference Include="someprojectpath" />
</ItemGroup>
<ItemGroup>
<Content Update="local.settings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "domain",
"TenantId": "tenantid",
"ClientId": "clientid",
"Scopes": "access_as_user",
"CallbackPath": "/signin-oidc",
"ClientSecret": "Client secret from app-registration. Check user secrets/azure portal.",
"ClientCertificates": []
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AzureKeyVaultUrl": "keyvaulturl",
"AllowedHosts": "*",
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read"
},
"ApplicationInsights": {
"ConnectionString": "appinsightsconnectionstring"
}
}
EDIT:
I've found out that the cause of the error are those lines:
var azureKeyVaultUrl = builder.Configuration[AppConfigurationConst.AzureKeyVaultUrl];
var logAnalyticsWorkspaceId = AzureKeyVaultHelper.GetAzureKeyVault(azureKeyVaultUrl, AppConfigurationConst.LogAnalyticsWorkspaceId);
var logAnaliticsAuthenticationId = AzureKeyVaultHelper.GetAzureKeyVault(azureKeyVaultUrl, AppConfigurationConst.LogAnaliticsAuthenticationId);
var CrmConnectionString = AzureKeyVaultHelper.GetAzureKeyVault(azureKeyVaultUrl, AppConfigurationConst.OneCrmConnectionString);
I've since changed them to get values directly from configuration instead of keyvault:
var azureKeyVaultUrl = builder.Configuration.GetValue<string>(AppConfigurationConst.AzureKeyVaultUrl);
var logAnalyticsWorkspaceId = builder.Configuration.GetValue<string>(AppConfigurationConst.LogAnalyticsWorkspaceId);
var logAnaliticsAuthenticationId = builder.Configuration.GetValue<string>(AppConfigurationConst.LogAnaliticsAuthenticationId);
var CrmConnectionString = builder.Configuration.GetValue<string>(AppConfigurationConst.OneCrmConnectionString);
When running locally, it takes the values correctly and assignes them to the variables. But it seems that when deploying it encounters a problem with that. In line var serviceClient = new ServiceClient(CrmConnectionString); when I change the variable to static string it works correctly, but when using the variable the startup.cs error pops up (only when deploying). Same thing with initializing logger which uses the log analitycs values. Again, locally runs with no problems, only the deployment crashes.
I have created a sample ASP.NET Core 6.0 Web API and able to deploy the Application to Azure App Service without any errors.
Generally, this type of error occurs when there is any error in the code or Configuration issues.
In my version of the project there is no Startup.cs but Program.cs
.Net6 Core Folder Structure:
Yes, we need to Configure the code related to Swagger in Program.cs itself.
Check the below steps and make sure you are following the same to deploy without any issues.
Select the ASP.NET Core Web API template.
Select Enable openAPI support.
My .csproj file :
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
</Project>
My Program.cs file :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
else
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
options.RoutePrefix = string.Empty;
});
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Output of Deployed Azure App Service:
My csproject file is indicating: <TargetFramework>netcoreapp3.0</TargetFramework>
In my startup im using the followinhg:
services.AddMvc(x => x.Filters.AddService<TransactionFilter>())
.AddJsonOptions(options => options.JsonSerializerOptions... )
But, ReferenceLoopHandling is not available inside options.JsonSerializerOptions.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentNHibernate" Version="2.1.2" />
<PackageReference Include="FullContact.Contacts.API" Version="1.0.3" />
<PackageReference Include="Google.Cloud.Storage.V1" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="5.5.0" />
<PackageReference Include="MySql.Data" Version="8.0.17" />
<PackageReference Include="piplclient" Version="5.0.9" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.5.0" />
</ItemGroup>
</Project>
As part of the work to improve the ASP.NET Core shared framework, Json.NET has been removed from the ASP.NET Core shared framework. Your app may require this reference if it uses Newtonsoft.Json-specific feature such as JsonPatch or converters or if it formats Newtonsoft.Json-specific types.
To use Json.NET in an ASP.NET Core 3.0 project:
Add a package reference to Microsoft.AspNetCore.Mvc.NewtonsoftJson.
Update Startup.ConfigureServices to call AddNewtonsoftJson.
services.AddMvc()
.AddNewtonsoftJson();
This sets up MVC and configures it to use Json.NET instead of that new API. And that AddNewtonsoftJson method has an overload that allows you to configure the Json.NET options like you were used to with AddJsonOptions in ASP.NET Core 2.x.
services.AddMvc()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings = new JsonSerializerSettings() { … };
});
Reference:
https://learn.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-2.2&tabs=visual-studio#jsonnet-support
https://stackoverflow.com/a/55666898/10201850
As of March 2020, the default JSON serializer does not support reference loop handling.
In order to handle that issue, you'll have to first install the older JSON serializer (used in older versions of .NET Core), Microsoft.AspNetCore.Mvc.NewtonsoftJson in the Nuget package manager.
The usage is pretty simple:
services.AddMvc().AddNewtonsoftJson(o =>
{
o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
Or like this if you are using a simple web API:
services.AddControllers().AddNewtonsoftJson(o =>
{
o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
As mentioned above you need to install Microsoft.AspNetCore.Mvc.NewtonsoftJson, Microsoft.AspNetCore.SignalR.Protocols.Newtonsoft packages and configure with AddNewtonsoftJsonProtocol in order to still use Newtonsoft instead of System.Text.Json (ReferenceLoopHandling not available yet)
For SignalR it would be
services.AddSignalR().AddNewtonsoftJsonProtocol(p =>
{
p.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
Add a package Microsoft.AspNetCore.Mvc.NewtonsoftJson
version - 3.1.3
services.AddMvc().AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
MvcNewtonsoftJsonOptions
services.PostConfigure<MvcNewtonsoftJsonOptions>(o =>
{
o.SerializerSettings.ContractResolver = new MyCustomContractResolver()
{
NamingStrategy = new CamelCaseNamingStrategy()
};
o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
I have a solution name BugDemo consisting of 2 projects. Here is the github repo.
a class library named Data.
an Asp.Net Core Minimal Api named Api referencing Data project. I set Api project as the startup project.
I use User Secret to share secret.json between these 2 projects.
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=BugDemoDb;Integrated Security=true;TrustServerCertificate=true"
}
}
I successfully generated the database with the following (executed from solution directory):
dotnet ef migrations add Initialization --startup-project Data --project Data
dotnet ef database update --startup-project Data
I attempted to invoke scaffolding with the following:
$env:codegen_trace=1
dotnet-aspnet-codegenerator minimalapi --project api
And I got the following errors:
Line: minimalapi --project api Trace: Executing external command:
dotnet msbuild C:\Projects\BugDemo\api\Api.csproj
/t:EvaluateProjectInfoForCodeGeneration
/p:OutputFile=C:\Users\amd\AppData\Local\Temp\wybiwf1d.d4d;CodeGenerationTargetLocation=C:\Users\amd.dotnet\tools.store\dotnet-aspnet-codegenerator\7.0.0-rc.1.22452.2\dotnet-aspnet-codegenerator\7.0.0-rc.1.22452.2\tools\net7.0\any;Configuration=Debug -restore
Building project ... Trace: Executing external command: dotnet build
C:\Projects\BugDemo\api\Api.csproj --configuration Debug --framework
net7.0
Trace: Executing external command: dotnet exec --runtimeconfig
C:\Projects\BugDemo\api\bin\Debug\net7.0\Api.runtimeconfig.json
--depsfile C:\Projects\BugDemo\api\bin\Debug\net7.0\Api.deps.json C:\Users\amd.nuget\packages\microsoft.visualstudio.web.codegeneration.design\7.0.0-rc.1.22452.2\lib\net7.0\dotnet-aspnet-codegenerator-design.dll
--no-dispatch --port-number 62322 minimalapi --project api --dispatcher-version 7.0.0-rc.1.22452.2
Trace: Command Line: --no-dispatch --port-number 62322 minimalapi
--project api --dispatcher-version 7.0.0-rc.1.22452.2 Scaffolding failed. Could not load information for project ..\Data\Data.csproj
Trace: at
Microsoft.VisualStudio.Web.CodeGeneration.Utils.RoslynWorkspaceHelper.GetProjectReferenceInformation(IEnumerable1 projectReferenceStrings) at Microsoft.VisualStudio.Web.CodeGeneration.Utils.RoslynWorkspace..ctor(IProjectContext projectInformation, String configuration) at Microsoft.VisualStudio.Web.CodeGeneration.Design.CodeGenCommandExecutor.AddFrameworkServices(ServiceProvider serviceProvider, IProjectContext projectInformation) at Microsoft.VisualStudio.Web.CodeGeneration.Design.CodeGenCommandExecutor.Execute(Action1
simModeAction) at
Microsoft.VisualStudio.Web.CodeGeneration.Design.Program.<>c__DisplayClass4_0.<b__0>d.MoveNext()
RunTime 00:00:12.60
Project Api
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>b3fdc987-781a-4fd4-853d-e279524cb5c6</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0-rc.1.22427.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-rc.1.22426.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0-rc.1.22426.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.0-rc.1.22452.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Data\Data.csproj" />
</ItemGroup>
</Project>
using Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<AppDbContext>(opts =>
{
opts.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/", async (AppDbContext ctx) =>
{
return await ctx.Students.ToListAsync();
});
app.Run();
Project Data
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>b3fdc987-781a-4fd4-853d-e279524cb5c6</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0-rc.1.22426.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-rc.1.22426.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0-rc.1.22426.10" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.0-rc.1.22452.2" />
</ItemGroup>
</Project>
namespace Data;
public class Student
{
public int Id { get; set; }
public string Name { get; set; } = default!;
}
using Microsoft.EntityFrameworkCore;
namespace Data;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> opts) : base(opts) { }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder mb)
{
base.OnModelCreating(mb);
mb.Entity<Student>().HasData(new Student[]
{
new Student{ Id=1,Name="Albert Einstein"},
new Student{ Id=2,Name="Isaac Newton"},
new Student{ Id=3,Name="Blaise Pascal"},
new Student{ Id=4,Name="Nicola Tesla"}
});
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
namespace Data;
public class AppDesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
IConfiguration config = new ConfigurationBuilder()
.AddUserSecrets<Data.AppDesignTimeDbContextFactory>()
.Build();
var opts = new DbContextOptionsBuilder<AppDbContext>();
opts.UseSqlServer(config.GetConnectionString("DefaultConnection"));
return new AppDbContext(opts.Options);
}
}
Question
How to fix this issue?
The issue is fixed in Visual Studio version - 17.3.4 and above. Currenly the latest one is 17.3.4
The problem was that during scaffolding the CodeGeneration library was downgraded from 6.0.10 to 6.0.9.
With the fix it is not downgrading anymore and it works properly.
https://github.com/dotnet/Scaffolding/issues/2034
I've raised that to the project community. There is an issue with downgrading the version of the Microsoft.VisualStudio.Web.CodeGeneration.Design library during scaffolding. As I understand how the discussion ended - they assigned the issue to a developer and in future will be fixed(as I can see in next major version).
You can follow the it in github.
The scaffolding project during the process of scaffolding updates the libraries of the projects and do a build behind the scene. And wrongly downgrading their own project version.
My workaround is to create a clean new project with pre-configured Identity, scaffolding what I need and copy the results to my project.
Works perfect.
I have .Net Core web API works fine. When I try to add Entity Framework Core, firstly, compile-error. It said, I must add Microsoft.Bcl.AsyncInterfaces even though I used .Net Core 3.1. When I added this, compiled well but when api run, it gives this exception. I cannot find any solution of this exception on internet:
When run .net core web api (debugging):
namespace CoreWebApi{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<PKDbContext>(options =>
options.UseMySql(Configuration.GetConnectionString("LocalConnection")));
services.AddScoped(typeof(IBankProduct), typeof(BankProductRepo));
services.AddScoped(typeof(IProductType), typeof(ProductTypeRepo));
services.AddScoped(typeof(IProductRequest), typeof(ProductRequestRepo));
services.AddScoped(typeof(IProfile), typeof(ProfileRepo));
services.AddScoped(typeof(INotification), typeof(NotificationRepo));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Startup codes works fine. When my dbContext class (PKDbContext) runs, it gives exception on this part: (: base(options))
public class PKDbContext : DbContext{
public PKDbContext() { }
public PKDbContext(DbContextOptions<PKDbContext> options) : base(options)
{
// some codes
}
}
Exception thrown: 'System.InvalidOperationException' in Microsoft.EntityFrameworkCore.dll
An exception of type 'System.InvalidOperationException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code
The database provider attempted to register an implementation of the 'IRelationalTypeMappingSource' service. This is not a service defined by EF and as such must be registered as a provider-specific service using the 'TryAddProviderSpecificServices' method.
*Edit: I am using Pomelo.EntityFrameworkCore.MySql
**Edit: I added csproj file code:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<StartupObject>CoreWebApi.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.7.20365.15" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.7.20365.15" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.2" />
</ItemGroup>
</Project>
Had the same issue, turns out the current version of Pomelo.EntityFrameworkCore.MySql requires a version of Microsoft.EntityFrameworkCore between 3.1.8 and before 5.0.0
Downgrading Microsoft.EntityFrameworkCore to the version before 5.0.0 (3.1.11) solved the problem for me
I decided to change db to Sql Server. I've removed Pomelo.EntityFrameworkCore.MySql and added Microsoft.EntityFrameworkCore.SqlServer and problem's solved.
if you want EF Core 5 to work with MySQL you need to install Pomelo.EntityFrameworkCore.MySql 5.0.0-alpha.2
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.3" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0-alpha.2" />
or you can downgrade Pomelo.EntityFrameworkCore.MySql to a more stable version which is 3.2.4 along with EF Core 3.1.12
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.12" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.2.4" />
PS: for more information visit Pomelo.EntityFrameworkCore.MySql compatibility section
I have a function that I'm porting from Azure Functions v1 to v2, and as part of that I've run into an issue updating my unit tests which create a stubbed HttpRequestMessage. Here's the code that works on Functions v1, targeting .NET Framework 4.7
public class FunctionExample
{
[FunctionName(nameof(SomeFunction))]
public static async Task<HttpResponseMessage> SomeFunction
(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "SomeFunction")]
HttpRequestMessage request
)
{
var body = await request.Content.ReadAsStringAsync();
if (string.IsNullOrEmpty(body))
{
return request.CreateResponse(HttpStatusCode.BadRequest, "Bad job");
}
else
{
return request.CreateResponse(HttpStatusCode.OK, "Good job");
}
}
}
And my test code
public class FunctionExampleTests
{
[Test]
public async Task TestSomeFunction()
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost/"),
Content = new StringContent("", Encoding.UTF8, "application/json")
};
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey,
new HttpConfiguration());
var response = await FunctionExample.SomeFunction(request);
var content = await response.Content.ReadAsStringAsync();
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
Assert.That(content, Is.EqualTo("\"Bad job\""));
}
}
After porting to v2, my function project csproj file looks like this. The only differences are that I'm no longer targeting full framework, and the addition of the AzureFunctionsVersion node.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.24" />
</ItemGroup>
</Project>
And this is the csproj for my test project after retargeting to .NET Core 2.0
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.11.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunctionExample\FunctionExample.csproj" />
</ItemGroup>
</Project>
Previously, I was using the answers to this question to properly stub out HttpRequestMessage but that no longer appears to work.
When I try to compile this, I get the following compilation errors
Error CS0246 The type or namespace name 'HttpConfiguration' could not be found (are you missing a using directive or an assembly reference?)
Error CS0103 The name 'HttpPropertyKeys' does not exist in the current context
So if I just remove the line, hoping that the fix is no longer needed
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
Instead I get this error message
System.InvalidOperationException : The HttpRequestMessage instance is not properly initialized. Use HttpRequestMessageHttpContextExtensions.GetHttpRequestMessage to create an HttpRequestMessage for the current request.
Trying to follow the error message's directions didn't prove fruitful to me, I tried to set the HttpContext like was done in this question
request.Properties.Add(nameof(HttpContext), new DefaultHttpContext());
But that gave me a different error (same as in the question)
System.ArgumentNullException : Value cannot be null.
Parameter name: provider
Azure Functions is somewhat based on ASP.NET MVC WebApi, which has had some changes for .NET Core. HttpConfiguration for example doesn't appear to be available in any packages that target .NET Core/Standard. In order to fix this, I had to install a couple of packages in my test project, namely Microsoft.AspNetCore.Mvc for AddMvc() and Microsoft.AspNetCore.Mvc.WebApiCompatShim for .AddWebApiConventions(), which:
Provides compatibility in ASP.NET Core MVC with ASP.NET Web API 2 to simplify migration of existing Web API implementations
So I added these to my test project
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
and now my test project looks like this
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.11.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunctionExampleFunction\FunctionExampleFunction.csproj" />
</ItemGroup>
</Project>
To mock the services that the ArgumentNullException was implying were missing (which in this case I think are MediaTypeFormatters), I had to essentially bootstrap MVC to get the HttpContext initialized properly.
[Test]
public async Task TestSomeFunction()
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost/"),
Content = new StringContent("", Encoding.UTF8, "application/json")
};
var services = new ServiceCollection()
.AddMvc()
.AddWebApiConventions()
.Services
.BuildServiceProvider();
request.Properties.Add(nameof(HttpContext), new DefaultHttpContext
{
RequestServices = services
});
var response = await FunctionExample.SomeFunction(request);
var content = await response.Content.ReadAsStringAsync();
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
Assert.That(content, Is.EqualTo("\"Bad job\""));
}
And that makes the test compile, run, and pass.