Global.asax equivalents

Hi,

A question, as I’m not able to find anything quickly about this:
What are the DotVVM equivalents of:
void Application_Start(object sender, EventArgs e)
void Application_End(object sender, EventArgs e)
void Application_Error(object sender, EventArgs e)
from Global.asax.cs in WebForms.

Thanks

PS:

And I need access to DotVVM’s context (IDotvvmRequestContext) for logging purposes.

I don’t see this happening inside DotvvmStartup.cs.

Is an ActionFilterAttribute the way to go?

If yes, which of its overrideables should I use to map the code from Global.asax ?

…It seems that I have to deal directly with IHttpContextAccessor.HttpContext by injecting as a service somehow in my methods that configure the Serilog logger.

I’m not sure what exactly do the Application_Start and End do. However, if you want to execute something during the application launch, you cannot access IDotvvmRequestContext, since there is no request running yet.

Why do you need a request for logging, isn’t access to IServiceProvider enough? If yes, you can get it from DotvvmConfiguration.ServiceProvider inside the DotvvmStartup or in the OWIN Startup class.

var config = app.UseDotVVM<DotvvmStartup>(...); 
config.ServiceProvider.GetRequiredService<ILogger>().LogWarning("blabla");

Also, as far as I remember, Serilog is configured a singleton instance, which you can access as Serilog.Log from anywhere. The configuration can be done Startup.Configure on OWIN, or just in Program.Main on AspNetCore.

When it comes to Application_End, I only remember that AspNetCore calls StopAsync method on all IHostedService (it also has asynchronous Start in case you’d need that). There are simpler events, though, AspNetCore: c# - How do I register code to run when shutting down an ASP.NET web application using the new .NET 6 format? - Stack Overflow, OWIN: asp.net - Is there Application_End from Global.asax in Owin? - Stack Overflow

Application_Error can most likely be replaced by the ActionFilterAttribute, it depends what exactly do you need, it’s perfect if you want to log error from DotVVM pages. Inherit the ExceptionFilterAttribute and override the OnPresenterExceptionAsync method.

There is also OnPageExceptionAsync and OnCommandExceptionAsync. Maybe the OnCommandExceptionAsync might be useful for you, since you might want to log the command binding which failed (actionInfo.Binding). The OnCommandExceptionAsync method is often used to handle the error and set some view model property to display an error message (Exception filters | DotVVM Documentation), if you do this, you’ll not see an exception in OnPresenterExceptionAsync. Otherwise, these events are just more specific - only called when GET / postback fails, and have the advantage of being called before view model is disposed.

Thank you, very useful as I’m still learning DotVVM…

My use case is very complex here and it will take me some time to properly describe. In a nutshell I am dealing with configuring the Serilog logger exactly once per application run, regardless of how many requests are made in the scope of the application running and the config uses enrichers who need access to HttpContext at the moment when Log.Error() is called inside OnPageExceptionAsync().

I am still working on it, and also I’m injecting the root ServiceProvider into the Serilog enrichers to get another service to work in that scope at runtime. And hopefully I’ll get all this mess to work properly then return here with a clear head. Thanks!

PS:

Yes, I’ve already managed to properly make the log entries in those two handlers. Thanks!

PS PS
I am in .NET 8 Blazor app (with Program.cs)

The log entry works (see red arrow):

But not the log entries are my problem now, instead the logger config is. Anyhow… this pretty much is outside of the DotVVM universe.

I’m also new to a lot of other things (DI, .NET Core etc.) so yeah, as I’ve been living under a WebForms rock until recently. …Suits me well to grasp at straws now…

1 Like

I ended up using:

  • app.Lifetime.ApplicationStarted.Register(() => {...}) for Application_Start(object sender, EventArgs e)
  • app.Lifetime.ApplicationStopped.Register(() => {...}) for Application_End(object sender, EventArgs e)
  • and ditching Application_Error(object sender, EventArgs e) altogether, as I’ve seen that leveraging OnCommandExceptionAsync and OnPageExceptionAsync was enough, for now, for centralizing logging for main source of exceptions… those coming from DotVVM pages.