System.Net.Primitives.dll Cannot find the file - asp.net-mvc

In ApsNetCore RC2 web application i'am having a problem injecting IHttpContextAccessor
I have a class HttpContextService which implements IHttpContextAccessor and in stratup.cs I added it like this services.AddTransient<IHttpContextAccessor, HttpContextService>();
And when I run the project it stoppes without showing errors, so I looked into log and found this:
'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\1.0.0-rc2-3002702\System.Net.Primitives.dll'. Cannot find or open the PDB file.
Exception thrown: 'System.IO.FileNotFoundException' in mscorlib.ni.dll
Exception thrown: 'System.IO.FileNotFoundException' in mscorlib.ni.dll
Exception thrown: 'System.InvalidOperationException' in Microsoft.Extensions.DependencyInjection.dll
Does someone has same problem or solution to fix it?
Edit:
I tried to activate the service in two ways:
//this one throws and error Unable to resolve service for type 'Microsoft.AspNetCore.Http.IHttpContextAccessor' while attempting to activate 'EPTV.Services.HttpContextService'.
services.AddTransient<HttpContextService>();
//and with this one the project dont even start like I explained before
services.AddTransient<IHttpContextAccessor, HttpContextService>();
The service looks like this:
public class HttpContextService : IHttpContextAccessor
{
private readonly IHttpContextAccessor _accessor;
public HttpContext HttpContext
{
get { return HttpContext; }
set { HttpContext = value; }
}
public HttpContextService(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
public HttpContext GetHttpContext()
{
return _accessor.HttpContext;
}
public string GetHeader(string value)
{
return _accessor.HttpContext.Request.Headers[value];
}
public string GetUserAgent()
{
return _accessor.HttpContext.Request.Headers["User-Agent"];
}
public string GetHost()
{
return _accessor.HttpContext.Request.Host.Value;
}
}
This is the exception I get:
Exception thrown: 'System.InvalidOperationException' in Microsoft.Extensions.DependencyInjection.dll
Additional information: A circular dependency was detected for the service of type 'Microsoft.AspNetCore.Http.IHttpContextAccessor'.

You need to add "System.Net.Primitives" in dependencies of your project.json.
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-rc2-3002702"
},
"System.Net.Primitives": "4.0.11-rc2-24027"
}

Decorating ASP.NET Core services is not supported, see this Github issue for discussion.
A "hacky" solution to your problem is described here

I finally found a solution.
It seems that in AspNetCore rc2 you have to register IHttpContextAccessor like this in startup.cs services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
And then you will be able to inject IHttpContextAccessor in controllers or other services

Related

Simple Injector throws an error in Caliburn.Micro Bootstrapper.Buildup when calling async method in the viewmodel

I am trying to use Simple Injector as the DI container for Caliburn.Micro. Demo source: https://github.com/nvstrien/WPFDemos
This project has a basic Caliburn.Micro setup with a Simple Injector Container. The ShellView has 1 button and when pressed, an async method is called to get some simulated data.
I am getting this error in Bootstrapper.Buildup.
SimpleInjector.ActivationException: 'No registration for type SequentialResult could be found. Make sure SequentialResult is registered, for instance by calling 'Container.Register<SequentialResult>();' during the registration phase. An implicit registration could not be made because Container.Options.ResolveUnregisteredConcreteTypes is set to 'false', which is now the default setting in v5. This disallows the container to construct this unregistered concrete type. For more information on why resolving unregistered concrete types is now disallowed by default, and what possible fixes you can apply, see https://simpleinjector.org/ructd. '
It has been suggested here that commenting out Bootstrapper.BuildUp should work: Caliburn.Micro Bootstrapper 'BuildUp' method throws exception when Simple Injector is used
However, when doing so, SimpleInjector will still throw an exception.
Any help solving this would be greatly appreciated
My complete Bootstrapper config file looks like this:
public static readonly Container _container = new();
public Bootstrapper()
{
Initialize();
}
protected override void Configure()
{
_container.Register<IWindowManager, WindowManager>();
_container.RegisterSingleton<IEventAggregator, EventAggregator>();
GetType().Assembly.GetTypes()
.Where(type => type.IsClass)
.Where(type => type.Name.EndsWith("ViewModel"))
.ToList()
.ForEach(viewModelType => _container.RegisterSingleton(viewModelType, viewModelType));
_container.Verify();
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
// as discussed here: https://stackoverflow.com/questions/32258863/simple-injector-getallinstances-throwing-exception-with-caliburn-micro
//_container.GetAllInstances(service);
IServiceProvider provider = _container;
Type collectionType = typeof(IEnumerable<>).MakeGenericType(service);
IEnumerable<object> services = (IEnumerable<object>)provider.GetService(collectionType);
return services ?? Enumerable.Empty<object>();
}
protected override object GetInstance(System.Type service, string key)
{
return _container.GetInstance(service);
}
protected override IEnumerable<Assembly> SelectAssemblies()
{
return new[] { Assembly.GetExecutingAssembly() };
}
// see: https://stackoverflow.com/questions/37631468/caliburn-micro-bootstrapper-buildup-method-throws-exception-when-simple-inject
// commenting out BuildUp still throws an exception in SimpleInjector.dll
protected override void BuildUp(object instance)
{
InstanceProducer registration = _container.GetRegistration(instance.GetType(), true);
registration.Registration.InitializeInstance(instance);
}
In the ShellViewModel I have 1 method that runs when pressing a button on the ShellView.
public async Task Button1()
{
Debug.Print("Hello world");
var data = await GetSampleDataAsync();
foreach (var item in data)
{
Debug.Print(item);
}
}
public async Task<IEnumerable<string>> GetSampleDataAsync()
{
// method simulating getting async data
var data = new List<string>() { "hello", "world" };
return await Task.FromResult(data);
}
The error occurs when 'await GetSampleDataAsync()' gets called.
When adding the SequentialResult in Bootstrapper.Configure as follows.
protected override void Configure()
{
_container.Register<IWindowManager, WindowManager>();
_container.RegisterSingleton<IEventAggregator, EventAggregator>();
_container.Register<SequentialResult>();
GetType().Assembly.GetTypes()
.Where(type => type.IsClass)
.Where(type => type.Name.EndsWith("ViewModel"))
.ToList()
.ForEach(viewModelType => _container.RegisterSingleton(viewModelType, viewModelType));
_container.Verify();
}
I get the next error:
System.InvalidOperationException
HResult=0x80131509 Message=The configuration is invalid. Creating
the instance for type SequentialResult failed. The constructor of type
SequentialResult contains the parameter with name 'enumerator' and
type IEnumerator<IResult>, but IEnumerator<IResult> is not registered.
For IEnumerator<IResult> to be resolved, it must be registered in the
container. Source=SimpleInjector StackTrace: at
SimpleInjector.InstanceProducer.VerifyExpressionBuilding() at
SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt(InstanceProducer[]
producersToVerify) at
SimpleInjector.Container.VerifyThatAllExpressionsCanBeBuilt() at
SimpleInjector.Container.VerifyInternal(Boolean
suppressLifestyleMismatchVerification) at
SimpleInjector.Container.Verify(VerificationOption option) at
SimpleInjector.Container.Verify() at
CaliburnMicroWithSimpleInjectorDemo.Bootstrapper.Configure() in
C:\Users\Niels\source\repos\WPFDemos\CaliburnMicroWithSimpleInjectorDemo\Bootstrapper.cs:line
37 at Caliburn.Micro.BootstrapperBase.StartRuntime() at
Caliburn.Micro.BootstrapperBase.Initialize() at
CaliburnMicroWithSimpleInjectorDemo.Bootstrapper..ctor() in
C:\Users\Niels\source\repos\WPFDemos\CaliburnMicroWithSimpleInjectorDemo\Bootstrapper.cs:line
22
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1: ActivationException: The constructor of type
SequentialResult contains the parameter with name 'enumerator' and
type IEnumerator<IResult>, but IEnumerator<IResult> is not registered.
For IEnumerator<IResult> to be resolved, it must be registered in the
container.
When I change the methods in my ShellViewModel to be synchronous like this, I don't get any exceptions:
public void Button1()
{
Debug.Print("Hello world");
var data = GetSampleData();
foreach (var item in data)
{
Debug.Print(item);
}
}
public IEnumerable<string> GetSampleData()
{
var data = new List<string>() { "hello", "world" };
return data;
}
It seems to me that the container doesn't get configured properly to work with some implementation in Caliburn.Micro, but the Bootstrapper configuration follows the recommended path. I am unfortunately not able to follow the explanation here: Caliburn.Micro Bootstrapper 'BuildUp' method throws exception when Simple Injector is used Also, what was marked as solution doesn't seem to work in my code sample.
#Steven: Commenting out BuildUp indeed fixed my problem.
I thought that I had tested commenting out BuildUp in my sample project before coming to SO to ask my question, but trying it again now solved my problem. Thank you for putting me back on the right track!
Solution: comment out / delete BootStrapper.BuildUp as was also suggested here: Caliburn.Micro Bootstrapper 'BuildUp' method throws exception when Simple Injector is used
//protected override void BuildUp(object instance)
//{
// InstanceProducer registration = _container.GetRegistration(instance.GetType(), true);
// registration.Registration.InitializeInstance(instance);
//}

Serilog ForContext not working as expected

I am using serilog & SEQ with Autofac (DI) in my project (MVC/ web api etc). Although it's working fine
but not sure it's the right way.
I have few questions. please help
Q1) How can I make LoggerConfiguration is manage via Web.config (appsetting) such as Verbose/Debug etc.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.WriteTo.Seq(serilogUrl)
.CreateLogger();
Q2) With Everymessage I would like to write userid. I have used push propery with out "using" statement.
see below code
public partial class Repo : BaseRepo<db>
{
public Repo(ILogger logger) : base(logger)
{
var currentuser = GetUserName();
LogContext.PushProperty("User Name", currentuser);
Logger.ForContext<Repo>();
}
public void somefunction()
{
try{}
catch(exception e){
Logger.Error(e, "Message");
}
}
}
Q3) In a constructor I have used Logger.ForContext() assuming this will write class name to each message. but it's not working.
Logger.ForContext<Repo>()
Note: I am not using asp.net core/.Net core
The ForContext returns a new ILogger reference that has the context information being added to the logger, so you have to capture that reference and use that for logging.
e.g.
public class YourClass
{
private readonly ILogger _log;
public YourClass(ILogger log)
{
_log = log
.ForContext<YourClass>()
.ForContext("CurrentUserName", GetUserName());
// ...
}
public void Somefunction()
{
try
{
// ...
}
catch(exception ex)
{
_log.Error(ex, "Message...");
}
}
}
ps: Given that you're using Autofac, you might be interested in using the Autofac-Serilog integration for contextual logger injection, instead of doing it manually.

Exception Handling in Azure Mobile App Service

I have created a Mobile App Service and hosted that on Azure.
Sometime specific line of code throws exception and I'm not handling those. Instead I'm logging those in ExceptionFilterAttribute.
The problem I'm facing is, those exceptions are reported as unhandled by Azure App Service which I think is true. My question is, how can I improve the below line of code such that it will not be considered unhandled exception?
public async Task<SingleResult<DTO.Responses.User>> GetUser(string id, OS os = OS.iOS, string openUrl = null)
{
/* some code written here that sometimes throws exception */
}
if I add try...catch block how will this be handled by Mobile App sync framework?
Below is code for exception filter
public class UnhandledExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
/* Log exception here*/
}
}
Based on my knowledge, we could use global error handing.
We could get the following demo code from this tutorial.
public class TraceSourceExceptionLogger : ExceptionLogger
{
private readonly TraceSource _traceSource;
public TraceSourceExceptionLogger(TraceSource traceSource)
{
_traceSource = traceSource;
}
public override void Log(ExceptionLoggerContext context)
{
_traceSource.TraceEvent(TraceEventType.Error, 1,
"Unhandled exception processing {0} for {1}: {2}",
context.Request.Method,
context.Request.RequestUri,
context.Exception);
}
}
config.Services.Add(typeof(IExceptionLogger),
new TraceSourceExceptionLogger(new
TraceSource("MyTraceSource", SourceLevels.All)));
Then we could config it in the ConfigureMobileApp method
Public static void ConfigureMobileApp(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.Services.Add(typeof(IExceptionLogger),
new TraceSourceExceptionLogger(new
TraceSource("MyTraceSource", SourceLevels.All)));
new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);
...
app.UseWebApi(config);
}

How to add logs in asp.net vNext

I need to set up logs in my asp.net application. It's easy to add output to the console, but I need to configure it in Azure. I don't know how to do it. I need to log all information that occurs with my app into some file and read it.
The ILoggerFactory allows an app to use any implementation of ILogger and ILoggerProvider.
For details on how to implement the interfaces properly, look at the framework's ConsoleLogger and ConsoleLoggerProvider. See also the ASP.NET Core documentation on logging.
Here is a minimal example of a custom ILogger to get started. This is not production code, rather, it demos enough technical depth either to write your own ILogger or to use one from the community.
project.json
"dependencies": {
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging": "1.0.0-rc1-final",
"Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final"
}
MyLoggingProvider.cs
namespace LoggingExample
{
using Microsoft.Extensions.Logging;
public class MyLoggingProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
return new MyLogger();
}
public void Dispose()
{
// TODO Cleanup
}
}
}
MyLogger.cs
In Azure you will want to write to somewhere other than C:/temp/some-guid.txt. This is enough to get you started, though, with writing your own simple logger.
namespace LoggingExample
{
using System;
using Microsoft.Extensions.Logging;
public class MyLogger : ILogger
{
public void Log(LogLevel logLevel, int eventId, object state,
Exception exception, Func<object, Exception, string> formatter)
{
var builder = new StringBuilder();
if (formatter != null) {
builder.AppendLine(formatter(state, exception));
}
var values = state as ILogValues;
if (values != null) {
foreach (var v in values.GetValues()) {
builder.AppendLine(v.Key + ":" + v.Value);
}
}
var logPath = string.Format("C:/temp/{0}.txt", Guid.NewGuid());
File.WriteAllText(logPath, builder.ToString());
}
public bool IsEnabled(LogLevel logLevel) {
return true;
}
public IDisposable BeginScopeImpl(object state) {
return null;
}
}
}
Startup.cs
Now in startup you can use add your logger via loggerFactory.AddProvider(new MyLoggingProvider()). Every call to the ILogger will now log with your provider.
namespace LoggingExample
{
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.Extensions.Logging;
public class Startup
{
public void Configure(
IApplicationBuilder app,
ILoggerFactory loggerFactory)
{
loggerFactory
.AddConsole(minLevel: LogLevel.Verbose)
.AddProvider(new MyLoggingProvider());
app.Run(async (context) =>
{
var logger = loggerFactory.CreateLogger("CatchAll");
logger.LogInformation("Hello logger!");
await context.Response.WriteAsync("Hello world!");
});
}
}
}
MyController.cs
Anywhere that supports dependency injection can now receive an ILogger that will log to all of the providers that we registered in the Startup.Configure method.
namespace LoggingExample
{
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.Logging;
public class MyController : Controller
{
public MyController(ILogger logger)
{
logger.LogInformation("Logging from my controller");
}
}
}
Log4Net
Use Log4Net. Its a common framework for logging that everyone who follows up on your code will understand, and it lets you do things like attach a new log "destination" on the fly just by editing your config file. It already covers most of the things you'll want to do (like create a separate file for each "day"), and most of the log mining tools out there will be able to read the files l4n creates.
Setting it Up
There are tutorials online for how to get started, but they basically require a few simple steps:
Download the Log4Net nuget package.
Adjust the log settings in your web.config file
Create a static instance of the logger object
Log Stuff wherever you need to. If you decide you want your logger to write to a file, it will. If you add a database writer, it will write to the db too. Want your log entries to show up in console, just add that logger in your default (debug) config.
Once you get it setup, logging is as simple as this code:
...
} catch(SystemException ex) {
logger.Error("This error was thrown by the XXX routine", ex);
}
Hope that's helpful.
Edit: Config File + Core
As #auga points out in his oh-so-helpful comment, config for ASP.Net 5 may require you to read carefully the link I added under step #2 above (configuring your logger). Instead of re-writing someone else's blog post, I'll just link to the article I used to set this up in our ASP.NET 5 environment. Works really well.
If you're reading this post to learn (instead of skimming it to critique), I'd suggest following the links...

Custom Exception Filter not being hit in asp.net MVC

I have a custom exception filter that I'm using to catch a custom exception that I wrote but for some reason when I throw my exception, it's not ever getting to the filter. Instead I just get an error that my exception was not handled by user code. Can anyone please provide some advice/assistance as to how I should have this set up? Relevant code is below:
// controller
[CustomExceptionFilter]
public class SomeController : Controller
{
public SomeController()
{
}
public ActionResult Index()
{
SomeClass.SomeStaticMethod();
return View();
}
}
that's the controller with the customexception attribute
// some class (where exception is being thrown)
public class SomeClass
{
public static void SomeStaticMethod()
{
throw new MyCustomException("Test");
}
}
that's the class (for my test) that throws the exception (I've also tried throwing it directly on the controller).
// Custom exception filter (want this to catch all unhandled exceptions)
public class CustomExceptionFilter : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (filterContext.Exception.GetType() == typeof(MyCustomException))
{
// do stuff
}
}
}
that's the custom exception filter...it's never being reached when the code is executed and the exception is thrown. Instead I get the error mentioned above. Everything I've read indicates that this is the proper way to set this up, but when I put breakpoints in my custom filter, it's never being hit....
What am I missing here?
TIA
Once you've handled your error, you need to let the filter context know it has been handled. Like this:
filterContext.ExceptionHandled = true;
This should be in your '// do stuff' section.
I've copied your code, and the filter is getting called fine. The only difference I made was I added the exceptionHandled code and adding my breakpoint at that line.

Resources