I have a .NET Core 2.0 application that injects configuration sections using IOptions<> into my various services. Works fine if I run the app in visual studio and in most environments (stage/production etc). For some reason, running the built application locally on my machine causes an error in which it appears as though the injected config classes have NULL values.
Code:
Startup.cs (uses structuremap to inject other services)
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 IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSingleton(Configuration);
services.AddOptions();
services.Configure<RedisCacheConfiguration>(c => Configuration.GetSection("RedisCacheConfiguration").Bind(c));
return ConfigureIoC(services);
}
private IServiceProvider ConfigureIoC(IServiceCollection services)
{
var container = new Container();
container.Configure(config =>
{
config.Scan(_ =>
{
_.AssemblyContainingType(typeof(Startup));
_.WithDefaultConventions();
});
});
container.Populate(services);
return container.GetInstance<IServiceProvider>();
}
// 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();
}
app.UseMvc();
}
}
appsettings.json
{
"RedisCacheConfiguration": {
"RedisAddress": "redis.server:6379"
}
}
RedisCacheConnectionFactory.cs
public class RedisCacheConnectionFactory
{
private readonly ConnectionMultiplexer _connection;
public RedisCacheConnectionFactory(IOptions<RedisCacheConfiguration> configAssessor)
{
var configuration = configAssessor.Value;
var redisAddress = configuration.RedisAddress;
if (_connection == null || !_connection.IsConnected || !_connection.GetDatabase().IsConnected(default(RedisKey)))
{
var addressChunks = redisAddress.Split(':');
var address = addressChunks[0];
var port = int.Parse(addressChunks[1]);
var configurationOptions = new ConfigurationOptions
{
AbortOnConnectFail = false,
ConnectTimeout = 600,
};
configurationOptions.EndPoints.Add(new DnsEndPoint(address, port));
_connection = ConnectionMultiplexer.Connect(configurationOptions);
}
}
public ConnectionMultiplexer Connection => _connection;
}
The Error
Hosting environment: Development
Content root path: C:\Work\MyApi\MyApi
Now listening on: http://localhost:57070
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 POST http://localhost:57070/outboundpayload application/json 1141
info: MyApi.Authentication.MyApiAuthHandler[8]
AuthenticationScheme: MyApi was successfully authenticated.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
Authorization was successful for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action MyApi.Controllers.OutboundPayloadController.Post (MyApi) in 170.5965ms
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[0]
An unhandled exception has occurred while executing the request
StructureMap.Building.StructureMapBuildException: Error while building type MyApi.Infrastructure.Factories.RedisCacheConnectionFactory. See the inner exception for details
1.) new RedisCacheConnectionFactory(*Default of IOptions<RedisCacheConfiguration>*)
2.) MyApi.Infrastructure.Factories.RedisCacheConnectionFactory
3.) Instance of MyApi.Infrastructure.Factories.RedisCacheConnectionFactory
4.) new RedisCacheProvider(*Default of RedisCacheConnectionFactory*, *Default of IOptions<RedisCacheConfiguration>*)
5.) MyApi.Infrastructure.Providers.RedisCacheProvider
6.) Instance of MyApi.Domain.Contracts.Providers.ICacheProvider (MyApi.Infrastructure.Providers.RedisCacheProvider)
7.) new EncryptedLeadCacheManager(*Default of ICacheProvider*, *Default of IEnvironmentWrapper*, *Default of IAesCryptographyService*)
8.) MyApi.Domain.Managers.EncryptedLeadCacheManager
9.) Instance of MyApi.Domain.Contracts.Managers.ICacheManager (MyApi.Domain.Managers.EncryptedLeadCacheManager)
10.) new OutboundLeadService(*Default of IUidService*, *Default of ICacheManager*)
11.) MyApi.Domain.Services.OutboundLeadService ('MyApi.Domain.Services.OutboundLeadService, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
12.) Instance of MyApi.Domain.Contracts.Services.IOutboundLeadService ('MyApi.Domain.Services.OutboundLeadService, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
13.) new OutboundPayloadFactory(*Default of ICertificateRepository*, *Default of IAes128Encryptor*, *Default of IQueryStringHelper*, *Default of IOutboundLeadService*, *Default of ILogger*, *Default of IMapProcessedLeadToIssuerLeadDto*)
14.) MyApi.Domain.Factories.OutboundPayloadFactory ('MyApi.Domain.Factories.OutboundPayloadFactory, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
15.) Instance of MyApi.Domain.Contracts.Factories.IOutboundPayloadFactory ('MyApi.Domain.Factories.OutboundPayloadFactory, MyApi.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')
16.) Container.GetInstance(MyApi.Domain.Contracts.Factories.IOutboundPayloadFactory)
17.) Container.TryGetInstance(MyApi.Domain.Contracts.Factories.IOutboundPayloadFactory)
---> System.NullReferenceException: Object reference not set to an instance of an object.
at MyApi.Infrastructure.Factories.RedisCacheConnectionFactory..ctor(IOptions`1 configAssessor) in C:\Work\MyApi\MyApi\MyApi.Infrastructure\Factories\RedisCacheConnectionFactory.cs:line 19
at lambda_method(Closure , IBuildSession , IContext )
--- End of inner exception stack trace ---
at lambda_method(Closure , IBuildSession , IContext )
at StructureMap.Building.BuildPlan.Build(IBuildSession session, IContext context)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at StructureMap.SessionCache.GetObject(Type pluginType, Instance instance, ILifecycle lifecycle)
at StructureMap.SessionCache.GetDefault(Type pluginType, IPipelineGraph pipelineGraph)
at StructureMap.Container.GetInstance(Type pluginType)
at StructureMap.Container.TryGetInstance(Type pluginType)
at Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method(Closure , IServiceProvider , Object[] )
at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextResourceFilter>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 474.7396ms 500 text/html; charset=utf-8
The IOptions seems to be injected but has null values, see the Inner Exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at MyApi.Infrastructure.Factories.RedisCacheConnectionFactory..ctor(IOptions`1 configAssessor) in C:\Work\MyApi\MyApi\MyApi.Infrastructure\Factories\RedisCacheConnectionFactory.cs:line 19
Once I put in null handling in this class the error changes to the next instance of using the IOptions<> injected configuration.
Anyone know why I'm getting this behavior?
Related
Currently on a project to create a check-in system and I'm creating this in ASP.NET MVC. I'm at the stage where I'm in my ImportController and using the Nuget package CsvHelper.
I'm getting errors including 'No overload for method 'Add' takes 3 arguments. Is anyone able to help? I've included a snip of my code below.
Any help would be much appreciated :)
[Route("import")]
public class ImportController : Controller
{
private readonly AppDbContext _appDbContext;
public ImportController(AppDbContext appDbContext)
{
_appDbContext = appDbContext;
}
[HttpGet("")]
public IActionResult Index()
{
return View();
}
public IActionResult Index(ImportIndexViewModel vm)
{
if (ModelState.IsValid)
{
using (var csvStream = new StreamReader(vm.File.OpenReadStream()))
using (var csv = new CsvReader(csvStream))
{
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
try
{
// Application reference
var AdmissionNumber = csv["Admission Number"];
var Firstname = csv["Students Firstname"];
var Surname = csv["Students Surname"];
if (string.IsNullOrWhiteSpace(AdmissionNumber))
throw new NullReferenceException("admissionNumber");
if (string.IsNullOrWhiteSpace(Firstname))
throw new NullReferenceException("Forename");
if (string.IsNullOrWhiteSpace(Surname))
throw new NullReferenceException("Surname");
// Add student to system
_appDbContext.Students.Add(AdmissionNumber.Trim(), Firstname.Trim(), Surname.Trim());
}
catch (NullReferenceException ex)
{
throw;
Console.WriteLine($"'{ex.Message}' is missing from row {csv.Context.Row}");
}
}
}
}
return View(vm);
}
}
}
Here is the exception stack it's providing me when I click upload. I think this again is due to this line here: _appDbContext.Students.Add(AdmissionNumber.Trim(), Firstname.Trim(), Surname.Trim());
System.InvalidOperationException: Could not create an instance of type 'System.Func`1[[SelfRegister.WebApp.Models.StudentsIndexViewModel+StudentViewModel, SelfRegister.WebApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the '_appDbContext' parameter a non-null default value.
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext, Int32 propertyData)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
I have asp.net core 2.1.6 application
It is running fine on Windows with IIS
public static IWebHostBuilder BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args)
.UseStartup<StartupShutdownHandler>()
.UseLibuv(o => o.ThreadCount = 1000) //todo to explore concurrent connection option
;
when I tried to run same application on ubuntu i am not able to start and getting some exception. When I comment out UseLibuv(o => o.ThreadCount = 1000) line then it runs.
Exception i am getting is
Info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using '/home/devops/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58]
Creating key {0184c7ca-fe6a-40dc-979f-152a89b50560} with creation date 2019-10-08 14:36:01Z, activation date 2019-10-08 14:36:01Z, and expiration date 2020-01-06 14:36:01Z.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {0184c7ca-fe6a-40dc-979f-152a89b50560} may be persisted to storage in unencrypted form.
info: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[39]
Writing data to file '/home/devops/.aspnet/DataProtection-Keys/key-0184c7ca-fe6a-40dc-979f-152a89b50560.xml'.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:5000 on the IPv4 loopback interface: 'Exception of type 'System.OutOfMemoryException' was thrown.'.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Exception of type 'System.OutOfMemoryException' was thrown.'.
crit: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to start Kestrel.
System.IO.IOException: Failed to bind to address http://localhost:5000. ---> System.AggregateException: One or more errors occurred. (Exception of type 'System.OutOfMemoryException' was thrown.) (Exception of type 'System.OutOfMemoryException' was thrown.) ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Threading.Thread.StartInternal()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.LibuvThread.StartAsync()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.LibuvTransport.BindAsync()
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<>c__DisplayClass22_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.BindAsync(AddressBindContext context)
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.BindAsync(AddressBindContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.DefaultAddressStrategy.BindAsync(AddressBindContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IServerAddressesFeature addresses, KestrelServerOptions serverOptions, ILogger logger, Func`2 createBinding)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
Unhandled Exception: System.IO.IOException: Failed to bind to address http://localhost:5000. ---> System.AggregateException: One or more errors occurred. (Exception of type 'System.OutOfMemoryException' was thrown.) (Exception of type 'System.OutOfMemoryException' was thrown.) ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Threading.Thread.StartInternal()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.LibuvThread.StartAsync()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.LibuvTransport.BindAsync()
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<>c__DisplayClass22_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.BindAsync(AddressBindContext context)
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions.BindAsync(AddressBindContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.DefaultAddressStrategy.BindAsync(AddressBindContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IServerAddressesFeature addresses, KestrelServerOptions serverOptions, ILogger logger, Func`2 createBinding)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.StartAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
at Auth.Interfaces.Program.Main(String[] args)
Aborted (core dumped)
As per suggestion on github i have removed UseLibuv option
I have set up my own context using (as I believe is correct):
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<JobTrackingContext>(options => options.UseNpgsql(connection));
services.AddScoped<IJobRepository, JobRepository>();
}
Then I define my JobTrackingContext as follows:
public JobTrackingContext(DbContextOptions<JobTrackingContext> options)
: base(options)
{
public DbSet<Job> Jobs { get; set; }
}
Now I can define a repository to actually create/edit/delete Jobs:
public class JobRepository : GenericRepository<Job, long>, IJobRepository
{
private Job currentJob;
public JobRepository(JobTrackingContext jobTrackingContext, JobTrackingSettings settings)
: base(jobTrackingContext)
{
_settings = settings;
}
public async Task StartSync(JobType jobType, JobTriggerType jobTriggerType)
{
var tempJob = new Job(jobType, jobTriggerType);
await _dbContext.Jobs.AddAsync(tempJob);
await _dbContext.SaveChangesAsync();
}
}
And all this code gets instantiated by a Post-request to this API:
public async void Post()
{
_logger.LogDebug("Going to start account sync");
await _jobRepository.StartSync(JobType.ZRequestSync, JobTriggerType.Scheduled);
try
{
await _sync.StartAsync();
await _jobRepository.ChangeSyncStatus(JobStatusType.Finished);
}
catch (Exception e)
{
_logger.LogError(e, "Error occured during sync :(");
await _jobRepository.ChangeSyncStatus(JobStatusType.Failed);
}
}
Yet when I do this, I get an Exception with the message Reset() called on connector with state Connecting. I do not understand where this comes from.
When I do not use the injected version, but instead do this:
using (var c = new JobTrackingContext())
{
var job = new Job(jobType, jobTriggerType)
await c.Jobs.AddAsync(job);
await c.SaveChangesAsync();
}
All seems to be working fine. It seems that the context gets disposed too early. But how can I prevent this and/or what am I missing?
The Full Stacktrace:
System.ObjectDisposedException
HResult=0x80131622
Message=Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__52.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at ZShared.JobRepository.<StartSync>d__4.MoveNext() in C:\Users\richa\Documents\Codes\Company\Product\Shared\Folder\JobRepository.cs:line 38
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ZAccountSyncService.AccountSyncController.<Post>d__4.MoveNext() in C:\Users\richa\Documents\Code\Company\Product\SubProduct\AccountSyncController.cs:line 32
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
The gist of the problem is the declaration of your AccountSyncController.Post method. You have async void Post() instead of async Task Post().
When there is no task, a request has nothing to await and ends before the call of method _sync.StartAsync() is completed. With an end of a request comes also the end of a lifetime scope. On lifetime scoped end, all instances with scoped lifetime get disposed. Thus, your context is disposed before you get to the call of SaveChanges method. And this is the cause of your exception.
I have .NET Core 1.1.1 web project that I can't run properly. I'm compiling against .NET 452 or/and .NET 462, this project has several regular .NET libraries references. The exception that I'm getting is:
System.AggregateException was unhandled
HResult=-2146233088
Message=An error occurred while writing to logger(s).
Source=Microsoft.Extensions.Logging
StackTrace:
at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
at Microsoft.Extensions.Logging.LoggerExtensions.LogCritical(ILogger logger, EventId eventId, Exception exception, String message, Object[] args)
at Microsoft.AspNetCore.Server.Kestrel.KestrelServer.Start[TContext](IHttpApplication`1 application)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.Start()
at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host, CancellationToken token, String shutdownMessage)
at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
at ClientFacingWeb.Program.Main(String[] args) in E:\..\ClientFacingWeb\Program.cs:line 18
InnerException:
HResult=-2147467262
Message=Unable to cast object of type 'System.Configuration.Internal.ConfigurationManagerInternal' to type 'System.Configuration.TimeSpanValidator'.
Source=System
StackTrace:
at System.Configuration.ConfigurationManagerInternalFactory.get_Instance()
at System.Diagnostics.DiagnosticsConfiguration.Initialize()
at System.Diagnostics.DiagnosticsConfiguration.get_IndentSize()
at System.Diagnostics.TraceInternal.InitializeSettings()
at System.Diagnostics.TraceInternal.WriteLine(String message, String category)
at Microsoft.Extensions.Logging.Debug.DebugLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
InnerException:
The message being printed in the console is:
Compilation=DEBUG
Environment=Development
crit: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to start Kestrel.
System.AggregateException: One or more errors occurred. ---> System.Configuration.ConfigurationErrorsException: The configuration is read only.
at System.Configuration.ConfigurationElementCollection.BaseRemoveAt(Int32 index)
at System.Configuration.PrivilegedConfigurationManager.GetSection(String sectionName)
at System.Net.Configuration.SettingsSectionInternal.get_Section()
at System.Net.Sockets.Socket.InitializeSockets()
at System.Net.IPAddress.InternalParse(String ipString, Boolean tryParse)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvTcpHandle.CreateIPEndpoint(ServerAddress address)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvTcpHandle.Bind(ServerAddress address)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.TcpListenerPrimary.CreateListenSocket()
at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Listener.<StartAsync>b__8_0(Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.ListenerPrimary.<StartAsync>d__12.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Internal.KestrelEngine.CreateServer(ServerAddress address)
at Microsoft.AspNetCore.Server.Kestrel.KestrelServer.Start[TContext](IHttpApplication`1 application)
---> (Inner Exception #0) System.Configuration.ConfigurationErrorsException: The configuration is read only.
at System.Configuration.ConfigurationElementCollection.BaseRemoveAt(Int32 index)
at System.Configuration.PrivilegedConfigurationManager.GetSection(String sectionName)
at System.Net.Configuration.SettingsSectionInternal.get_Section()
at System.Net.Sockets.Socket.InitializeSockets()
at System.Net.IPAddress.InternalParse(String ipString, Boolean tryParse)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvTcpHandle.CreateIPEndpoint(ServerAddress address)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvTcpHandle.Bind(ServerAddress address)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.TcpListenerPrimary.CreateListenSocket()
at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Listener.<StartAsync>b__8_0(Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.ListenerPrimary.<StartAsync>d__12.MoveNext()<---
If I remove those regular .NET references the project executes successfully.
I'm not able to identify which one of the references is causing the error.
I have look into the output window too see the loaded modules, and none of the loaded modules are different if I use, have or not my regular .NET project/library references.
I am using a Ninject DI in my web application with a bunch of technoligies from Asp.Net stack (MVC, Web Api 2, SignalR).
I have managed to make DI work for all technologies in use with the following approach:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
internal static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
// Binding services here
}
}
So far so good.
All this was working with Web Api being initialized in Global.asax.
Now I'm switching to OWIN pipeline. So I removed GlobalConfiguration.Configure(WebApiConfig.Register); from Global.asax and added
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
to my OwinStartup class. DI for Web Api stoped working.
I started searching for appropriate solution and found Ninject.Web.WebApi.OwinHost package. So in order to have a single Kernel resolving dependencies for all technologies, I've made the following changes:
in OwinStartup:
app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
app.UseNinjectWebApi(config);
in NinjectWebCommon:
//[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(App.TradingServer.ConfiguratorApp.App_Start.NinjectWebCommon), "Start")]
//[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(App.TradingServer.ConfiguratorApp.App_Start.NinjectWebCommon), "Stop")]
These lines were disabled to avoid initializing kernel twice.
This fixed DI for Web Api but not for SignalR. When client tries to connect to hub I get the following exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessNegotiationRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(IDictionary`2 environment)
at Microsoft.AspNet.SignalR.Owin.Middleware.HubDispatcherMiddleware.Invoke(IOwinContext context)
at Microsoft.Owin.Infrastructure.OwinMiddlewareTransition.Invoke(IDictionary`2 environment)
at Microsoft.Owin.Mapping.MapMiddleware.<Invoke>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.Owin.HttpMessageHandlerAdapter.<InvokeCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Ninject.Web.Common.OwinHost.OwinBootstrapper.<Execute>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.<RunApp>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.<DoFinalWork>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow()
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar)
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar)
at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) | RuntimeMethodInfo.UnsafeInvokeInternal => RuntimeMethodHandle.InvokeMethod => Application.Application_Error
I am kind of lost. I'we read around two dozens of articles but none of them gave me the solution. Would appreciate any help.
My final aim is to have a single kernel that serves Web Api, MVC and SignalR and supports OWIN pipeline.
Edit: Since I've got a comment that my case might be a duplicate of another question I believe I need to give some explanations.
I have three scenarios.
WebApi initialization in Global.asax with GlobalConfiguration.Configure(WebApiConfig.Register), Ninject initialization with NinjectWebCommon and Bootstrapper.
This gives me both injection in WebApi and SignalR. But since I would like to move WebApi initialization to OWIN startup this approach is obsolete.
WebApi initialization with OWIN Startup, Ninject initialization with NinjectWebCommon and Bootstrapper.
SignalR injection works, WebApi injection does not work.
WebApi initialization with OWIN Startup, Ninject initialization with UseNinjectMiddleware, UseNinjectWebApi.
WebApi injection works, SignalR injection does not work.
So basically I need to figure out how to put this together so that both WebApi and SignalR injection work when I initialize WebApi on OWIN pipeline.
The code for NinjectWebCommon is in original question below. It contains code for creating SignalR resolver but it does not help in scenario 3.
Edit 2: After a couple of hours of trial and error method I came to a conclusion that calling
app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
app.UseNinjectWebApi(config);
conflicts with this call:
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
So problem description narrows to this. When I use the following pattern SignalR stops working:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseNinjectMiddleware(CreateKernel);
app.UseNinjectWebApi(config);
GlobalHost.HubPipeline.AddModule(new GlobalSignalRExceptionHandler());
app.MapSignalR();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(new Ninject.Web.Mvc.NinjectDependencyResolver(kernel));
return kernel;
}
But if I comment the line
//GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
SignalR starts working again. But no injection inside hubs of course.
Finally I managed to get the working Ninject configuration that supports OWIN pipe, WebApi, MVC and SignalR.
By the time when I posted the question I had a work-around (which was disabling DI in SignalR hubs) so I decided to waste no more time on this and moved on.
But when I tried running OWIN in-memory Test Server with my Startup class it occurred that DI was not working. CreateKernel method was called too late which resulted in creating several instances of an object that was used in sengleton scope.
After playing with different variations of initialization I've made DI work for OWIN Test Server and it also fixed the SignalR DependencyResolver.
The Solution:
I stopped using packages Ninject.Web.Common.OwinHost and Ninject.Web.WebApi.OwinHost so these calls were removed from my Configuration method:
//app.UseNinjectMiddleware(NinjectWebCommon.CreateKernel);
//app.UseNinjectWebApi(config);
Instead I do the following:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
NinjectWebCommon.Start();
config.DependencyResolver = new NinjectDependencyResolver(NinjectWebCommon.bootstrapper.Kernel);
app.UseWebApi(config);
app.MapSignalR();
}
public static class NinjectWebCommon
{
private static bool _isStarted;
internal static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
// When creating OWIN TestService instances during unit tests
// Start() method might be called several times
// This check ensures that Ninject kernel is initialized only once per process
if (_isStarted)
return;
_isStarted = true;
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
internal static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
// DI for SignalR
GlobalHost.DependencyResolver = new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(kernel);
// DI for MVC
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
// Binding code here
kernel.Bind<Something>().ToSelf().InSingletonScope();
}
}
in order to use a dependency resolver for both WebApi and SignalR you need to implement a class that looks like this:
public class NinjectDependencyResolver : Microsoft.AspNet.SignalR.DefaultDependencyResolver,
System.Web.Http.Dependencies.IDependencyResolver
{
public readonly IKernel Kernel;
public NinjectDependencyResolver(string moduleFilePattern)
: base()
{
Kernel = new StandardKernel();
Kernel.Load(moduleFilePattern);
}
public override object GetService(Type serviceType)
{
var service = Kernel.TryGet(serviceType) ?? base.GetService(serviceType);
return service;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
IEnumerable<object> services = Kernel.GetAll(serviceType).ToList();
if (services.IsEmpty())
{
services = base.GetServices(serviceType) ?? services;
}
return services;
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{ }
}
then in your startup class you should register NinjectDependencyResolver for both WebApi and SignalR, like this:
public void Configuration(IAppBuilder app)
{
var dependencyResolver = new NinjectDependencyResolver("*.dll");
var httpConfiguration = new HttpConfiguration();
httpConfiguration.DependencyResolver = dependencyResolver;
app.UseWebApi(httpConfiguration);
var hubConfig = new HubConfiguration { Resolver = dependencyResolver };
app.MapSignalR(hubConfig);
}
SignalR must be configured after your dependency injection configuration. So, in your OWIN Startup class, make sure that app.MapSignalR() is called after setting the MVC dependency resolver (System.Web.MVC.DependencyResolver), the WebApi dependency resolver (System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver) and the SignalR dependency resolver (Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver).