Exception Handling in Azure Mobile App Service - asp.net-mvc

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);
}

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);
//}

Exception logging in ASP.NET MVC Application

Currently I log exceptions as follows-
public ActionResult Login()
{
try
{
throw new Exception("test");
}
catch (Exception ex)
{
LogException(ex);
}
return View();
}
I can get a clear & detail information about the exception from LogException() method here. See below-
Created on: 27-Dec-2016, 06.34.33 PM
Type: System.Exception
Error Description: test
Source File: ...\Controllers\LoginController.cs
Method: Login
Line: 20
Column: 17
I tried the same method in -
public class MyCustomAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
Exception ex = filterContext.Exception;
LogException(ex)
}
}
public class MyCustomAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
Exception ex = filterContext.Exception;
LogException(ex)
}
}
I also tried overloading OnException method-
public abstract class BaseController : Controller
{
public BaseController() {}
protected override void OnException(ExceptionContext filterContext)
{
Exception ex = filterContext.Exception;
filterContext.ExceptionHandled = true;
LogException(ex);
}
}
In all three abose cases I am getting no information about Source File, Method, Line and Column-
Created on: 27-Dec-2016, 06.44.45 PM
Type: System.Exception
Error Description: test
Source File:
Method: <BeginInvokeAction>b__1e
Line: 0
Column: 0
This is my method to log exception-
public static void Create(Exception exception, String rootDirectoryPath)
{
try
{
StackTrace st = new StackTrace(exception, true);
StackFrame frame = st.GetFrame(st.FrameCount - 1);
string fileName = frame.GetFileName();
string methodName = frame.GetMethod().Name;
int line = frame.GetFileLineNumber();
int col = frame.GetFileColumnNumber();
//Other code .....
}
catch (Exception)
{
//do nothing.
}
}
My question is, is it possible to retrieve Source File, Method, Line and Column information from those three cases?
I would not like to handle exceptions by writing try .. catch.. every time.
I have heard about ELMAH & Log4Net. But not sure whether those library able to supply my desired information from exceptions.
Sorry for the long question.
I'm the author of Coderr which also takes care of tracking exceptions for you.
the problem with your solution is that the exception filter (and the ASP.NET framework calls to invoke it) will be part of the stack trace, thus getting frames from the stack trace object wont work.
Also note that if the .PDB file is not included when you put your web site in production you wont get file numbers.
The most common approach is just to log exception.ToString() which will include line numbers in the stack trace (if there is a PDB file).
Why do you want to use your custom approach?
You are reinventing the wheel as ELMAH will do the job just fine. Did you give it a try? Just a Nuget package and some configuration to be fully set.
You can read more about it from Scot Hanselman or read the tutorial.

System.Net.Primitives.dll Cannot find the file

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

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...

Silence FullAjaxExceptionHandler

So after being confronted with the dreaded javax.faces.application.ViewExpiredException, I had to go look around the internet to find the proper solution. Fortunately, the solutions are readily available and I went ahead and adopted the OmniFaces FullAjaxExceptionHandler.
Enough said, as with pretty much everything from OmniFaces, it worked wonders. But, every time I have a view expiring I am getting :
SEVERE: WebModule[/myModule]FullAjaxExceptionHandler: An exception occurred during processing JSF ajax request. Error page '/WEB-INF/errorpages/test.xhtml' will be shown.
javax.faces.application.ViewExpiredException: viewId:/my/page.xhtml - View /my/page.xhtml could not be restored.
...
This is fine as it is handled as expected, but is there anyway to silence this exception from being printed to the server.log? This would crowd the log pretty quickly.
I am running :
Mojarra 2.1.23
PrimeFaces 4.0-SNAPSHOT
OmniFaces 1.6-SNAPSHOT-2013-07-01
on
Glassfish 3.1.2.2
As per OmniFaces 1.6, you can extend it and override the method logException() as below to skip the stack trace for ViewExpiredException.
public class YourAjaxExceptionHandler extends FullAjaxExceptionHandler {
public YourAjaxExceptionHandler(ExceptionHandler wrapped) {
super(wrapped);
}
#Override
protected void logException(FacesContext context, Throwable exception, String location, String message, Object... parameters) {
if (exception instanceof ViewExpiredException) {
// With exception==null, no trace will be logged.
super.logException(context, null, location, message, parameters);
}
else {
super.logException(context, exception, location, message, parameters);
}
}
}
Create a factory around it:
public class YourAjaxExceptionHandlerFactory extends ExceptionHandlerFactory {
private ExceptionHandlerFactory wrapped;
public YourAjaxExceptionHandlerFactory(ExceptionHandlerFactory wrapped) {
this.wrapped = wrapped;
}
#Override
public ExceptionHandler getExceptionHandler() {
return new YourAjaxExceptionHandler(getWrapped().getExceptionHandler());
}
#Override
public ExceptionHandlerFactory getWrapped() {
return wrapped;
}
}
In order to get this to run, register it as factory in faces-config.xml the usual way (don't forget to remove the original registration for FullAjaxExceptionHandlerFactory):
<factory>
<exception-handler-factory>com.example.YourExceptionHandlerFactory</exception-handler-factory>
</factory>

Resources