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;
});
Related
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();
}
}
The Azure Function's .csproj definition is per the following snippet:
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>10.0</LangVersion>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.6.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.3.0" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.1.0" />
</ItemGroup>
The Program.cs file's initialization is like the following code snippet:
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureAppConfiguration((context, configure) =>
{
configure
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
})
.ConfigureServices((context, services) =>
{
services.AddMyServices();
})
.Build();
The compiler issues the following error message:
Severity Code Description Project File Line Suppression State
Error MSB4062 The "GenerateFunctionMetadata" task could not be loaded from the assembly C:\Users\myusername.nuget\packages\microsoft.net.sdk.functions\4.0.1\build..\tools\net6.0\Microsoft.NET.Sdk.Functions.MSBuild.dll. Confirm that the declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask. MyApp.Functions C:\Users\myusername.nuget\packages\microsoft.azure.functions.worker.sdk\1.3.0\build\Microsoft.Azure.Functions.Worker.Sdk.targets 60
Would you please give a direction on fixing this problem?
We need to remove Microsoft.NET.Sdk.Functions NuGet package reference to address this compile issue.
I wanted to populate a value for correlationId to my applicationInsights . Right now the value is null. I have installed the serilog.enrichers.correlationId nuget package and have services.AddHTTPContextAccessor in my startup.cs file, but still the value of correlationId is null. Am i Missing something?Any suggestions?
I got the source from :- https://github.com/ekmsystems/serilog-enrichers-correlation-id
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.CreateLogger();
the above is my logger configuration in startup.cs. all the other enrichers that i defined in Enrich tag in appsettings.json are being populated but the correlation id is null.
Here's my test result:
And what I did like below:
In my asp.net core application, install related packages first, then edit the Program.cs -> CreateHostBuilder :
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration).Enrich.WithCorrelationId()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {CorrelationId} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.WriteTo.ApplicationInsights(new TelemetryConfiguration { InstrumentationKey = "your_instrumentation_key" }, TelemetryConverter.Traces)
);
My packages:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.17.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Enrichers.CorrelationId" Version="3.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="3.1.0" />
</ItemGroup>
</Project>
Did you respect this? You need to call services.AddHttpContextAccessor();
https://github.com/ekmsystems/serilog-enrichers-correlation-id#:~:text=You%20need%20to%20register%20the%20IHttpContextAccessor%20singleton%20so%20that%20the%20enricher%20has%20access%20to%20the%20requests%20HttpContext%20so%20that%20it%20can%20attach%20the%20correlation%20ID%20to%20the%20request/response
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.
In .net Core 1 we could do this:
IConfiguration config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.Build();
And that gave use the Configuration object that we could then use in our console app.
All examples for .net core 2.0 seem to be tailored to the new way Asp.Net core config is created.
What is the way to create configurations for console apps?
Update: this question is not related to Asp.net core. Please do not add asp.net core tags when editing.
It seems there is no change, as Jehof says.
ConfigurationBuilder is in its own package, as Jeroen Mostert says.
But make sure you also have the Microsoft.Extensions.Configuration.Json package, where the .AddJsonFile() extension lives.
In summary, you need the following two NuGet packages:
Microsoft.Extensions.Configuration (2.0.0)
Microsoft.Extensions.Configuration.Json (2.0.0)
Store a private static IServiceProvider provider; in your Program.cs. Then Setup the configuration just like you would in aps.net core but of course you would do it in Main(). Then Configure each section inside your IServiceProvider. This way you can use the constructor dependency injection. Also note that I have two configurations in my watered down example. One contains secrets that should be kept out of source control and stored outside of the project structure, and I have AppSettings which contains standard configuration settings that don't need to be kept private.(It is important!)
When you want to use the config then you can take it out of the provider, or pull an object out of the provider that uses your settings classes in their constructors.
private static IServiceProvider provider;
private static EventReceiver receiver;
static void Main(string[] args)
{
IConfigurationRoot config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(path: "/opt/Secrets.json", optional: false, reloadOnChange: true)
.AddJsonFile(path: "AppSettings.json", optional: false, reloadOnChange: true)
.Build();
provider = new ServiceCollection()
.AddSingleton<CancellationTokenSource>()
.Configure<Settings>(config.GetSection("SettingsSection"))
.BuildServiceProvider();
receiver = new EventReceiver<Poco>(ProcessPoco);
provider.GetRequiredService<CancellationTokenSource>().Token.WaitHandle.WaitOne();
}
private static void ProcessPoco(Poco poco)
{
IOptionsSnapshot<Settings> settings = provider.GetRequiredService<IOptionsSnapshot<Settings>>();
Console.WriteLine(settings.ToString());
}
these are the dependencies I recommend starting out with when making a dotnetcore cli app.
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="microsoft.extensions.logging.abstractions" Version="2.0.0" />
Also note that you will need to copy your settings to your publish and build directories. You can do that by adding targets to your csproj file.
<Target Name="CopyToOut" BeforeTargets="BeforeBuild">
<Copy SourceFiles="../ProjPath/AppSettings.json" DestinationFolder="$(TargetDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CopyToOutOnPublish" AfterTargets="Publish">DestinationFolder="$(PublishDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="../ProjPath/AppSettings.json" DestinationFolder="$(PublishDir)" SkipUnchangedFiles="true" />
</Target>