logging abstraction in .net framework class library - c#

I'd like to create a .net framework (4.72) class library to be used inside a different project (also .net framework 4.72) that has Serilog as it's current logger.
In my class library my ctor has the following lines :
var loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory();
var logProvider = loggerFactory.CreateLogger<TcpServer>();
logProvider.LogDebug("Tcp Logger Init");
My 2nd project has a windows forms app with the following ctor :
Log.Logger = new LoggerConfiguration()
.WriteTo.File("log.txt").CreateLogger();
if I log directly from my windows forms project it works fine :
Log.Information("Test Info");
But I dont see the logs from the library I referenced into my windows forms project.
Any help is much appreciated on figuring out how to link between them
or any other project that I'll be using with the logging .

Related

When to use Microsoft Extensions Logging and Application Insights Asp NETCore in Azure Functions

I am so confused while enabling logging in azure functions in .NET Core 6 using application insights. I had explored lot of sites but still in dilemma what exactly the difference between the nuget packages and when to use at which situations.
microsoft.extensions.logging.applicationinsights
microsoft.applicationinsights.aspnetcore
I had understand that if we want custom telemetry, we should use microsoft.applicationinsights.aspnetcore
I had created separate azure functions with separate nuget packages and I am able to see logs.
With microsoft.extensions.logging.applicationinsights package and used ILogger in function classes.
I added below piece of code in azure function startup
builder.Services.AddSingleton(new TelemetryConfiguration { ConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING")});
with Microsoft.ApplicationInsights.AspNetCore package , I injected Di and used ITelemetryClient in function classes
I added below piece of code in azure function startup
var options = new ApplicationInsightsServiceOptions { ConnectionString = SharedMethods.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING") };
builder.Services.AddApplicationInsightsTelemetry(options);

Adding a WCF IPC service to an existing App that access an SQLite DB through EntityFrameworkCore

I'm looking for some help.
I have a Mono application for Mac, developed in VS for Mac, using the currently latest updates in the VS for Mac, which include Mono Framework MDK 5.16.0.221. The app is targeting .NET Framework 4.7.1
The app accesses an SQLite DB throught EF Core, all latest packages, the problem is that things brakes if I try to add a WCF service to the app. Apparently the order between the service start and the DB context initialization is making the app to crash.
I have created this example project, which include a test case for the issue.
It works fine as it is, but if the IPC initialization is done before the DB context (Moving this line to be after this one), the failure can be reproduce.
Edit:
The issue i have detected is the order between the WCF ServiceHost is started, and the initialization of the EF DbContext is affecting the application behavior.
Initializing the ServiceHost first:
serviceHost = new ServiceHost(singletonInstance);
...
serviceHost.AddServiceEndpoint(typeof(S), new NetTcpBinding(), serviceAddress);
serviceHost.Open();
then the DbContext
var databaseProvider = new DatabaseProvider(DB_FILE);
DatabaseContext databaseContext = databaseProvider.GetConnection();
Results into an exception like System.NotSupportedException : Specified method is not supported., when using the databaseContext to access information from the DB.
Thank you

Porting System.Configuration to .NET Core via POCOs?

We've got a .NET Framework .dll that we're porting to .NET Core. Currently we're inheriting from ConfigurationElement and ConfigurationSection from System.Configuration to create custom configuration sections in the app.config (or it's .NET Core equivalent)
Questions:
It appears the .NET Core way is Microsoft.Extensions.Configuration. Is that correct? Because it lives on ASP.NET Core's github project instead of .NET Core's github project. We have no ASP parts.
If so, any .NET Core examples on creating and loading custom configuration sections not relying on startup.cs ? Ideally we'd like to read from a text source (XML or JSON) directly into a POCO object graph for strongly typed benefits.
With .NET Core 2.0, will there be any support for the traditional ConfigurationElement and ConfigurationSection negating the need for any such porting efforts to begin with ? Reason I ask is the .NET Core 2.0 Roadmap says
.NET Core gain over 5,000 APIs from .NET Framework as part of this work making it a broader platform.
I am not aware of app.config and System.Configuration support in .NET Core. Probably, no, but that's just a guess. You can setup configuration for .NET Core application in Main method:
class Program
{
static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var poco = new Poco();
configuration.Bind(poco);
Console.WriteLine(poco);
Console.ReadKey();
}
}
class Poco
{
public bool Enabled { get; set; }
public Sort Sort { get; set; }
public override string ToString()
{
return $"Enabled={Enabled}, SortOrder={Sort.Order}";
}
}
class Sort
{
public int Order { get; set; }
}
appsettings.json is following:
{
"enabled": true,
"sort": {
"order": 2
}
}
Outputs:
Enabled=True, SortOrder=2
You need to reference Microsoft.Extensions.Configuration.Json and Microsoft.Extensions.Configuration.Binder packages.
No dependency on ASP.NET Core.
Microsoft.Extensions.Configuration is quite extensible, it can use different settings providers like environment variables, command line arguments, etc. So it is possible to implement custom provider for ConfigurationSection-like configuration if needed.
Based on this comment they are not going to bring System.Configuration to NetStandard 2.0.
With the dust settling down from .NET Standard 2.0 release it is possible to use your usual System.Configuration even in .NET Core 2.0 on Linux!
Here is a test example:
Created a .NET Standard 2.0 Library (say MyLib.dll)
Added the NuGet package System.Configuration.ConfigurationManager v4.4.0. This is needed since this package isn't covered by the meta-package NetStandard.Library v2.0.0
All your C# classes derived from ConfigurationSection or ConfigurationElement go into MyLib.dll. For example MyClass.cs derives from ConfigurationSection and MyAccount.cs derives from ConfigurationElement. Implementation details are outof scope here but Google is your friend
Create a .NET Core 2.0 app (e.g. a console app, MyApp.dll). .NET Core apps end with .dll rather than .exe in Framework.
Create an app.config in MyApp with your custom configuration sections. This should obviously match your class designs in #3 above. For example:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="myCustomConfig" type="MyNamespace.MyClass, MyLib" />
</configSections>
<myCustomConfig>
<myAccount id="007" />
</myCustomConfig>
</configuration>
That's it - you'll find that the app.config is parsed properly within MyApp and your existing code within MyLib works just fine. Don't forget to run dotnet restore if you switch platforms from Windows (dev) to Linux (test).
Besides described way of migration to Microsoft.Extensions.Configuration (which totally makes sense) as it should (at least I hope) be possible to use the same types from System.Configuration on .NET Core 2.
Here's System.Configuration types in corefx:
https://github.com/dotnet/corefx/tree/master/src/System.Configuration.ConfigurationManager
I can't tell you that they are fully compatible with the ones from full .NET. But at least it's something that takes us a hope )
So it looks like .NET Core 2 will have that old System.Configuration stuff but not netstandard2. Probably it's because MS doesn't want to share these types among other platforms (Xamarin).

ASP.NET Core targeting full framework with EF6 and Identity

I currently have a .NET Core Web App targeting the full .NET Framework and a .NET 4.6.1 class library project that contains my EF6 implementation.
I have these two currently working together.
Now I need to add Identity, but I need to customize the implementation. (If it matters, I'm building against an existing user table and only care about local logins)
So in the 4.6.1 class library project I've created the customized Identity classes/stores/managers using this guide: https://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity
The part I am stuck on is how to configure the .NET Core App to use the non-Core version of Identity.
All the tutorials have configs similar to
services.AddIdentity<ApplicationUser, ApplicationRole>(config => { })
.AddEntityFrameworkStores<ApplicationDbContext>();
and
app.UseIdentity();
However both those methods only exist in Microsoft.AspNetCore.Identity and not Microsoft.AspNet.Identity.Core, which is what the class library is using.
What frameworks should the .NET Core App be referencing? And what should the Startup.cs configuration look like?
To keep things simple, all my custom Identity code is exactly what's in the article linked above.
The Startup.cs code looks like this (with AspNetCore.Identity referenced)
services.AddIdentity<ApplicationUser, CustomRole>(config => { /* config */ })
.AddUserManager<ApplicationUserManager>()
.AddUserStore<CustomRoleStore>()
.AddDefaultTokenProviders();
Sample Controller
public AccountController(ApplicationSignInManager signInManager)
{
_signInManager = signInManager;
}
Error when trying to run it
InvalidOperationException: Type ApplicationUserManager must derive from UserManager.
However both those methods only exist in Microsoft.AspNetCore.Identity and not Microsoft.AspNet.Identity.Core, which is what the class library is using.
You should strictly distinct two api : ASP NET Identity https://github.com/aspnet/AspNetIdentity and ASP NET Core Identity https://github.com/aspnet/Identity
What frameworks should the .NET Core App be referencing?
ASP NET Core Identity (Microsoft.AspNetCore) should be referenced.
And what should the Startup.cs configuration look like?
Since you want to use EF6 you will need to port "Microsoft.AspNetCore.Identity.EntityFrameworkCore" (https://github.com/aspnet/Identity/tree/master/src/EF) to your own realization that uses EF6. After this you would need to provide your own .AddEntityFrameworkStores<TDbContext>(); extension method. Therefore Startup.cs should left the same (except using, to reference AddEntityFrameworkStores you will need to point your ported lib namespace).

Do I need a Global.asax.cs file at all if I'm using an OWIN Startup.cs class and move all configuration there?

Let's say for example in a brand new ASP.NET MVC 5 application made from the MVC with Individual Accounts template, if I delete the Global.asax.cs class and move it's configuration code to Startup.cs Configuration() method as follow, what are the downsides?
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureAuth(app);
}
}
The upsides for me is that when upgrading ASP.NET 4 applications to ASP.NET 5 and using pieces that now must be configured in the Startup.cs class, I'm not doing dependency injection and other configuration in two different classes that seem related to starting up, and configuration.
Startup.Configuration gets called slightly later than Application_Start, but I don't think the difference will matter much in most cases.
I believe the major reasons we kept the other code in Global.asax are:
Consistency with previous versions of MVC. (That's where everybody currently expects to find this code.)
Ability to add other event handlers. In Global.asax, you can handle other methods like Session_Start and Application_Error.
Correctness in a variety of authentication scenarios. The Startup.Configuration method is only called if you have Microsoft.Owin.Host.SystemWeb.dll in your bin directory. If you remove this DLL, it will silently stop calling Startup.Configuration, which could be hard to understand.
I think the third reason is the most important one we didn't take this approach by default, since some scenarios don't include having this DLL, and it's nice to be able to change authentication approaches without invalidating the location where unrelated code (like route registration) is placed.
But if none of those reasons apply in your scenario, I think you'd be fine using this approach.
For those looking for the complete steps: If you are looking to create a OWIN based, IIS hosted web API, these steps should get you there:
File -> New -> Project
In the dialogue, Installed -> templates -> Other Project types -> Visual Studio Solutions -> Blank Solution targeting .NET 4.6
On the solution, right click, add Project -> Web -> ASP.NET Web Application (targeting .NET 4.6)
3.1 Now In the ASP.NET 4.5 templates, choose Empty as the template
3.2 This creates a blank solution with two nuget packages:
Microsoft.CodeDom.Providers.DotNetCompilerPlatform v 1.0.0
Microsoft.Net.Compilers v 1.0.0
Install the following packages:
Install-Package Microsoft.AspNet.WebApi.WebHost -Version 5.2.3
Install-Package Microsoft.AspNet.WebApi -Version 5.2.3
Install-Package WebApiContrib.Formatting.Razor 2.3.0.0
For OWIN:
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Then add Startup.cs with Configuration method:
[assembly:OwinStartup(typeof(namespace.Startup))]
public class Startup
{
/// <summary> Configurations the specified application. </summary>
/// <param name="app">The application.</param>
public static void Configuration(IAppBuilder app)
{
var httpConfiguration = CreateHttpConfiguration();
app
.UseWebApi(httpConfiguration);
}
/// <summary> Creates the HTTP configuration. </summary>
/// <returns> An <see cref="HttpConfiguration"/> to bootstrap the hosted API </returns>
public static HttpConfiguration CreateHttpConfiguration()
{
var httpConfiguration = new HttpConfiguration();
httpConfiguration.MapHttpAttributeRoutes();
return httpConfiguration;
}
}
Now add a class that inherits from ApiController, annotate it with RoutePrefix attribute and the action method with Route + HttpGet/PutPost (representing the Http verb you're after) and you should be good to go
This is my understanding of how starting/hosting a web application evolved as it's all pretty confusing to follow. A small summary:
1. Classic ASP.NET: Write only the application code to run in the last step of the mandatory IIS pipeline
2. ASP.NET with OWIN: Configure a .NET webserver and write your application code. No longer directly coupled to IIS, so you're no longer forced to use it.
3. ASP.NET Core: Configure both the host and the webserver to use and write your application code. No longer mandatatory to use a .NET webserver if you target .NET Core instead of the full .NET Framework.
Now I'll go a bit more into detail of how it works and which classes are used to start the application:
Classic ASP.NET
Classic ASP.NET applications have the Global.asax file as entry point. These applications can only be run in IIS and your code gets executed at the end of the IIS pipeline (so IIS is responsible for CORS, authentication... before your code even runs). Since IIS 7 you can run your application in integrated mode which integrates the ASP.NET runtime into IIS. This enables your code to configure functionality which wasn't possible before (or only in IIS itself) such as url rewriting in the Application_Start event of your Global.asax file or use the new <system.webserver> section in your web.config file.
ASP.NET with OWIN
First of all OWIN is not a library but a specification of how .NET web servers (for example IIS) interact with web applications. Microsoft themselves have an implementation of OWIN called project Katana (distributed through several different NuGet packages). This implementation provides the IAppBuilder interface you encounter in a Startup class and some OWIN middleware components (OMC's) provided by Microsoft. Using IAppBuilder you basically compose middleware in a plug-and-play way to create the pipeline for the webserver (in addition to only the ASP.NET pipeline in IIS7+ as in the point above) instead of being tied to the IIS pipeline (but now you use a middleware component for CORS, a middleware component for authentication...). Because of this, your application is not specifically coupled to IIS anymore and you can run it on any .NET Webserver, for example:
The OwinHost package can be used to self-host your application with a Katana webserver.
The Microsoft.Owin.Host.SystemWeb package is used to host your OWIN application in IIS7+ in integrated mode, by subscribing your middleware to the correct lifetime events internally.
The thing that makes everything so confusing is that Global.asax is still supported together with the OWIN Startup class, while they can both do similar things. For example you could implement CORS in Global.asax and authentication using OWIN middleware which becomes really confusing.
My rule of thumb is to remove the Global.asax file alltogether in favor of using Startup whenever I need to add OWIN.
ASP.NET Core
ASP.NET Core is the next evolution and now you can target either .NET Core or the full .NET Framework. When you target .NET Core you can run your application on any host which supports the .NET Standard. This means you are no longer restricted to a .NET webserver (as in the previous point), but can host your application in Docker containers, a linux webserver, IIS...
The entry point for an ASP.NET Core web application is the Program.cs file. There you configure your host and again specify your Startup class where you configure your pipeline. Using OWIN (by using the IAppBuilder.UseOwin extension method) is optional, but fully supported.

Categories