Unexpected "Cache entry must specify a value for Size when SizeLimit is set" message in AspNetCore 3 - asp.net-core

So this all worked fine before updating to AspNetCore 3 today.
I am using a memory cache with dependency injection (IMemoryCache cache).
I add it to my middleware with services.AddMemoryCache();
and do NOT set a size, but I still end up with the error message:
Cache entry must specify a value for Size when SizeLimit is set.
When I inspect the instance of MemoryCache and it does indeed have a size of 10240 set (see image).
The problem is I've been looking for a hour and I have no clue where this was set. Nowhere in my code do I have SizeLimit or 10240 anywhere - including config files.
It seems to have started when I switched to using app.UseEndpoints instead of app.UseMvc() - but I've made so many changes I'm not sure.
Where could this possibly be set that is elluding me.?

I managed to stop this exception from being thrown by removing the call to AddEntityFrameworkSqlServer() from my ConfigureServices() method in Startup.cs:
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
...
services
.AddEntityFrameworkSqlServer() // <-- Removed this
.AddDbContext<MyContext>(options =>
options.UseSqlServer(...)
)
...
}
...
}
Apparently calling AddEntityFrameworkSqlServer() is no longer needed in EF Core 3:
Calling this method is no longer necessary when building most applications, including those that use dependency injection in ASP.NET or elsewhere.
Thanks to #Simon_Weaver for his clue about EF Core!

Related

Is there an option in Serilog to change log file parameters in runtime, the same way LogLevel can be changed?

With Serilog in asp.net core you can change the log level in runtine by using
MinimumLevel.ControlledBy(SeriLogLevelSwitch).
Is there a similar way to do this with LoggerConfiguration().WriteTo.File(...)
For instance i need to change the configuration for log fileSizeLimitBytes, or rollingInterval withour restaring the service. Can this be achieved with Serilog?
By pulling in the latest Serilog.AspNetCore you'll find a class called ReloadableLogger, constructed through the CreateBootstrapLogger() extension method:
// using Serilog;
var logger = new LoggerConfiguration()
.WriteTo.File(...)
.CreateBootstrapLogger();
// Optional but suggested:
Log.Logger = logger;
// Use the logger...
// Change parameters later on:
logger.Reload(lc => lc
.WriteTo.File(...));
You might find that some interactions between CreateBootstrapLogger() and UseSerilog(callback) in ASP.NET Core trip things up a bit; if you use this technique, try the parameterless version of UseSerilog().
ReloadableLogger has only just appeared and is focusing on a slightly different scenario, so you may still need to work through some awkwardness setting this up - YMMV.

Can I determine `IsDevelopment` from `IWebJobsBuilder`

Very much an XY problem, but I'm interested in the underlying answer too.
See bottom for XY context.
I'm in a .NET Core 3 AzureFunctions (v3) App project.
This code makes my question fairly clear, I think:
namespace MyProj.Functions
{
internal class CustomStartup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
var isDevelopment = true; //Can I correctly populate this, such that it's true only for local Dev?
if(isDevelopment)
{
// Do stuff I wouldn't want to do in Prod, or on CI...
}
}
}
}
XY Context:
I have set up Swagger/Swashbuckle for my Function, and ideally I want it to auto-open the swagger page when I start the Function, locally.
On an API project this is trivial to do in Project Properties, but a Functions csproj doesn't have the option to start a web page "onDebug"; that whole page of project Properties is greyed out.
The above is the context in which I'm calling builder.AddSwashBuckle(Assembly.GetExecutingAssembly()); and I've added a call to Diagnostics.Process to start a webpage during Startup. This works just fine for me.
I've currently got that behind a [Conditional("DEBUG")] flag, but I'd like it to be more constrained if possible. Definitely open to other solutions, but I haven't been able to find any so ...
While I am not completely sure that it is possible in azure functions I think that setting the ASPNETCORE_ENVIRONMENT application setting as described in https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings should allow you to get whether the environment is set as production or development by injecting a IHostEnvironment dependency and checking
.IsDevelopment()
on the injected dependency.

Rebus.Defer missing header on Timeout

I am using Rebus 0.84 and I'm attempting to use the Defer method with a custom header like this.
_theBus.AttachHeader(message, "tenant_id", tenantId);
_theBus.Defer(delay, message);
But the header does not exist when the 'timeout' happens. This is my bus configuration.
Configure.With(new WindsorContainerAdapter(container))
.Logging(l => l.Serilog())
.Transport(t => t.UseMsmqAndGetInputQueueNameFromAppConfig())
.MessageOwnership(d => d.FromRebusConfigurationSection())
.Timeouts(t => t.Use(new RavenDbTimeoutStorage(container.Resolve<IDocumentStore>())))
.Sagas(x => x.Use(new RavenDbSagaPersister(container.Resolve<IDocumentSession>, session => { })))
.Events(x => x.AddUnitOfWorkManager(new Config.WindsorUnitOfWorkManager(container)))
.CreateBus()
.Start()
Is that expected behavior? This is a windows service so am I setting this up properly to be a singleton?
Edit - I know have a better idea what's happening and I hope that it will lead to a better understanding of Rebus.
The problem is with this line
.Sagas(x => x.Use(new RavenDbSagaPersister(container.Resolve<IDocumentSession>, session => { })))
In our application we use the tenant_id header to help us connect to the correct database for that message. If I change the line to use the IDocumentStore that is configured to point to a specific database everything works. It means my sagas and timeouts are stored in a database that is separate from the actual tenant database. I can live this this but I'd like to understand why the header does not exist when I use a session retrieved from the container. I suspect this is due to the timing of the creation of the session for the RavenDbSagaPersister. Is that correct?
EDIT 2 - Well that was mistaken. That change still does not work. Using very similar sampel code but with the default adapter, the timeout headers work great. I'm going to attempt to isolate the cause by adding the windsor container adapter. I'll post a link to the code when I can replicate the issue.
That sounds weird - the headers should be included when the deferred message gets delivered, and in fact I've just verified that it works with Rebus 0.84.0.
I do remember though that an earlier version of Rebus had a bug that would not include the headers, but according to Rebus' changelog that error was removed in version 0.58.0.
So, to answer your questions:
Message headers should definitely be preserved, also when deferring messages.
And yes: The IBus instance passed to you from the configuration API should be kept as a singleton instance for the duration of the application lifetime. With Castle Windsor, the container will ensure that it is a singleton, and will also ensure that it is properly disposed when you dispose the container.

Conversion of V2 Ninject Binding to V3

I've been banging my head at this for about 8 hours now, and I just can't seem to find a simple explanation on how to change my custom bootstrapper for ninject (Last worked on the code back in v2.x.x.x) to the new v3.0.0.0 syntax.
I currently have the following:
public class NinjectCustomBootStrapper : NinjectNancyBootstrapper
{
protected override Ninject.IKernel GetApplicationContainer()
{
return Program.MyContainer;
}
}
in a septate class, and :
public static IKernel MyContainer
{
get { return _myContainer ?? (_myContainer = CreateKernel()); }
set { _myContainer = value; }
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<CardMonitorService>().ToSelf().InSingletonScope();
return kernel;
}
in my main program 'Program.c' in a command line app.
Iv'e since updated ninject to V3.0.0.0 only to find that there's been some breaking changes. I'll admit I don't use ninject very often (I usually use structuremap), and the only reason this project does is I didn't write it originally.
Since I've upgraded Ninject, now when the app is started up I get the following exception:
Method not found: 'Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax`1<!0>
Ninject.Syntax.IBindingToSyntax`1.ToConstant(!0)'.
After a ton of searching and researching, the closest I've been able to find is this:
http://sharpfellows.com/post/Ninject-Auto-registration-is-changing-in-version-3.aspx
Which while it points me in the right direction, still isn't quite a solution as I'm not using a custom binding generator.
So my question is this.
How do I rewrite the above so that my project once again works and the WCF service when called gets the correct singleton binding handed to it when a request comes in. Going back to ninject 2 is not an option, as other dependencies in the project that have been added have forced the v3 upgrade and these add new functionality that's been requested hence why I'm working on it.
For reference this is a .NET4 build, running on NancyFX with a self hosting WCF setup as a windows service using Topshelf to provide the SCM interface.
Cheers
Shawty
Addendum to clear things up a little
This is an existing project that was originally written sometime back, I've been asked to add some new features to the project.
As part of adding these new features I have been required to upgrade the version of Ninject being used from an earlier version to V3.0.0.0 as newer dependencies added to the project require the newer version of Ninject.
Under the previous V2 of Ninject the code I have given above worked fine, with no issues, since the project has had Ninject V3 added I now get the exception as described above.
I cannot go back to the earlier version of Ninject as that will mean not being able to add the new functionality that I'm adding.
From the research I've done so far the sharpfellows link above is the closest explanation of my issue that I've managed to find so far on the internet.
I don't use Ninject very often, so I've not got the background to know what's changed between V2 & V3 that (based on my research) is the cause of my issue.
I need to know how to change my code written under V2 (and shown above) so that it works under V3.
MissingMethodException is usually a deployment problem. You compile against a different assembly than you deploy. Check that you deployed the same version and same build.
So after a week or so it turns out that the problem was that the Nancy dev team broke binary comparability with the latest version of ninject (or vice versa) :-)
There is a GitHub pull request to fix this available at :
https://github.com/NancyFx/Nancy.Bootstrappers.Ninject/pull/6
However the next version 'Nancy.Bootstrapper.Ninject' 0.12 will be out on NuGet soon which will have the fix implemented.

Cast causes "Operation could destabilize the runtime" on one ASP.NET 4.0 box and not another

Here's (part of) a simple deserialization method that I've used in .NET 2.0 for years. T is an unconstrained type parameter.
protected virtual T ItemFromString(string s) {
if (typeof(T).IsPrimitive ||
typeof(T) == typeof(string)) {
try {
// needed for string, too: compiler doesn't allow (T)s
return (T)Convert.ChangeType(s, typeof(T));
}
catch (Exception ex) {
// stuff
}
}
}
I changed the application pool to run in 4.0, and everything was fine — until I deployed it to the remote server. There, I get "Operation could destabilize the runtime" on the line
return (T)Convert.ChangeType(s, typeof(T));
(Actually the line reported is the ending brace of the method, but I've narrowed it down to that line.)
The problem goes away if I change the runtime back to 2.0.
The runtime versions are both 4.0.30319. The app is otherwise identical, including web.config. Both apps using shared application pools and running in Full trust. Presumably another setting is affecting it, but I have no idea how to figure out what.
Everything I've found about this involves Reflection.Emit or covariance, which I'm not using.
Any leads?
Thanks.
Now that this question has been viewed 0x80 times, I'll post the solution I recently used when I could no longer put off the move to .NET 4.
You have to target the .NET 4 platform in the build, and set the following assembly property.
using System.Security;
// Needed to enable generic deserialization in partial trust.
[assembly: SecurityRules(SecurityRuleSet.Level1)]
I'd commented that I was in full trust mode, but I must have been wrong about that. This is only an issue in partially-trusted environments.