Using NLog with asp-net layout renderers in AspNet vNext (MVC 6) - asp.net

I am trying to integrate NLog in AspNet 5 (or using the new name AspNet Core 1.0) web app. Not sure if it is possible at all but I want to log the currently logged in user.
This is my NLog config file.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true">
<targets>
<target name="logfile"
xsi:type="File"
fileName="file.txt"
layout="${longdate}|${message}|${identity}|${aspnet-user-identity}" />
</targets>
<rules>
<logger name="WebApplication2.*" minlevel="Info" writeTo="logfile" />
</rules>
</nlog>
The thing is that I get
System.ArgumentException: LayoutRenderer cannot be found: 'aspnet-user-identity'
My project.json file looks like:
"dependencies": {
.....
"NLog.Framework.logging": "1.0.0-rc1-final",
"NLog": "4.4.0-alpha1",
"NLog.Config": "4.3.0-beta1",
"NLog.Extended": "4.0.0-rc",
"NLog.Web": "4.1.0"
},
Maybe I am missing something, or it is not yet supported by NLog ?
EDIT: I found out that auto load of extensions is not currently supported. So, I have to modify my NLog.config like:
<extensions>
<add assembly="NLog.Web"/>
<add assembly="NLog.Extended"/>
</extensions>
But now I get blank input for the current user. Any ideas ?

The internal log will give some more info why loading the extension failed.
There are also other ways to load the extensions, the assemblyFile attribute and programmatically:
//target
ConfigurationItemFactory.Default.Targets
.RegisterDefinition("MyFirst", typeof(MyNamespace.MyFirstTarget));
//layout renderer
ConfigurationItemFactory.Default.LayoutRenderers
.RegisterDefinition("hello-world", typeof(MyNamespace.HelloWorldLayoutRenderer ));
Edit: did some tests. This works in loading the assembly:
<extensions>
<add assembly="NLog.Web" />
</extensions>
But too bad NLog.Web isn't ASP.NET 5 compatible, yet. We can't use HttpContext.Current there.
edit: an ASP.NET 5 compatible version of NLog.Web is now available! See NuGet

Related

disable 8.3 name creation in web.config file

i use asp .net core version 3.1.
i know that for disabling 8.3 name creation i can set NtfsDisable8dot3NameCreation vaule to 1 on below path.
"HKLM\SYSTEM\CurrentControleSet\Control\FileSystem"
but my problem is that i dont know how i can set this configuration in web.config file.
actualy i want to use web.config XMl code for solving this issue.
and i try below setting in webconfig but get error when run project.
<configuration>
<HKLM>
<SYSTEM>
<CurrentControleSet>
<Control>
<FileSystem>
<add key="NtfsDisable8dot3NameCreation" value="1"/>
</FileSystem>
</Control>
</CurrentControleSet>
</SYSTEM>
</HKLM>
</configuration>

ASP.Net Website - publishing doesn't move all files

When publishing my ASP.Net Website (not a Web Application), the publisher does not include the Web.ConnectionStrings.config file that is next to the web.config. This is required since my web config looks like this:
<connectionStrings configSource="Web.ConnectionStrings.config"/>
How can I get a File System Publish to include files that Visual Studio seems to be ignoring. Please note that this is a website created using [File] > [New Website] in Visual Studio, not a [File] > [New Project] ASP.Net site so Content=Include will not work.
Steps to reproduce:
In Visual Studio: File > New > Website..
Create the Web.ConnectionStrings.config xml document (see ConnectionStrings.config code below).
In the web config link up the Web.ConnectionStrings.config file to the Web.Config file (see Web.config code below)
Publish the website to a folder on your file system, the Web.ConnectionStrings.config doesn't move with the rest of the files.
Web.config:
<configuration>
<connectionStrings configSource="Web.ConnectionStrings.config"/>
..
Web.ConnectionStrings.config:
<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
<add name="connString" connectionString="yourConnectionstringhere"/>
</connectionStrings>
The way you publish the website is OK.
But the name of the file into which the connectionstrings get stored must not start with the prefix web., just call it connectionstrings.config instead.
In web.config you put:
<configuration>
<connectionStrings configSource="connectionStrings.config"/>
In the renamed file connectionstrings.config you place:
<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
<add name="connString" connectionString="yourConnectionstringhere"/>
</connectionStrings>
I think this article will help
https://learn.microsoft.com/en-us/aspnet/web-forms/overview/deployment/visual-studio-web-deployment/deploying-extra-files
Basically you edit the picture .pubxml file to tell it to include additional files during deployment

NLog does not create log files on ASP.NET Core project

I am new to using NLog with ASP.NET Core, so I have followed the guide here:
https://github.com/NLog/NLog.Web/wiki/Getting-started-with-ASP.NET-Core-(project.json)
I have created the following nlog.config file at the root of the project directory:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Warn"
internalLogFile="c:\temp\internal-nlog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- define various log targets -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="allfile" fileName="${basedir}\nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId.Id}|${logger}|${uppercase:${level}}|${message} ${exception}" />
<target xsi:type="File" name="ownFile-web" fileName="${basedir}\nlog-own-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId.Id}|${logger}|${uppercase:${level}}| ${message} ${exception}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
<target xsi:type="Null" name="blackhole" />
</targets>
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile" />
<!--Skip Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>
Inside a controller, I call a line like this one:
_logger.LogInformation("Entered CustomerRange method");
which returns the following in the output window in Visual Studio:
CustomerMgmtAPI.Controllers.CustomerController:Information: Entered CustomerRange method
However, the actual log files are never created by NLog. I was wondering if someone can point out the error in the NLog configuration here, since I have been reviewing the documentation of NLog for ASP.NET Core project and I can't find the error myself.
So the actual fix to the problem was the remove the first line from the nlog.config file:
<?xml version="1.0" encoding="utf-8" ?>
I remove this line and everything started working as expected. I also noticed that Visual Studio was giving me these errors when that line was present:
Invalid token 'Text' at root level of document.
Unexpected XML declaration. The XML declaration must be the first node in the document and no white space characters are allowed to appear before it.
It seems in this case that the NLog tutorial is broken, as I just took over this file from the sample for ASP.NET Core. I am using VS2017, so perhaps there is an incompatibility with this version of VS?
The dirty little secret about using NLog with ASP.NET Core is that you can configure and create logs just as you did in ASP.NET and ASP.NET MVC. You just use the regular NLog Nuget package like you normally would.
Just create an NLog.config in your root, etc. You don't even have to make any extra configurations in the config or elsewhere to get it to work. You just reference NLog in your class and then create a logger with the LogManager.
What this means is that you don't have all of the wireup in Program.cs etc.

Publish is not transforming web.config?

I made a web.config (full file, it doesn't show XML errors)
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
...
<location path="." inheritInChildApplications="false">
<connectionStrings>
<add name="ElmahLog" connectionString="data source=~/App_Data/Error.db" />
<add name="database" connectionString="w" providerName="System.Data.EntityClient"/>
</connectionStrings>
</location>
...
with a transform file (web.Staging.config)
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="database"
connectionString="c"
providerName="System.Data.EntityClient"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<customErrors defaultRedirect="error.aspx"
mode="RemoteOnly" xdt:Transform="Replace">
</customErrors>
</system.web>
</configuration>
I am publishing in Staging mode (right click website > Publish > Method: File System ...)
------ Build started: Project: Drawing, Configuration: Staging Any CPU ------
Drawing -> D:\Project\bin\Staging\Drawing.dll
------ Build started: Project: MySystem, Configuration: Staging Any CPU ------
MySystem -> D:\Project\bin\Staging\MySystem.dll
...
But when I look at the web.config in the output folder it isn't changed.
I found the following on the Build log:
D:\Project\Web.Staging.config(3,2): Warning : No element in the source document matches '/configuration'
D:\Project\Web.Staging.config(3,2): Warning : No element in the source document matches '/configuration'
D:\Project\Web.Staging.config(3,2): Warning : No element in the source document matches '/configuration'
Transformed web.config using Web.Staging.config into obj\Staging\TransformWebConfig\transformed\web.config.
What could be the problem? Am I doing this right?
Answering late but perhaps I can save someone a headache. In Visual Studio 2013, there are two places to select configuration for your build and deploy. The Configuration Manager and then again with Publish Web where the third step in the Wizard entitled Settings allows you to select Config you want to use. If you don't select your new configuration it will use the transform for the selected configuration instead of yours.
I found out two things:
You cannot set a namespace on the <configuration> tag (ex: for <location path="." inheritInChildApplications="false">)
You have to watch for the correct hierarchy in the transform file.
Like
<configuration>
<location>
<connectionStrings>
Instead of
<configuration>
<connectionStrings>
Ensure that in the properties of the Web.Config file Build Action is set to Content.
If the build action is set to None, it will not be transformed, even if it is being copied to the output directory.
Make sure to include InsertIfMissing if the section you are trying to add does not already appear in the output.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<location>
<system.webServer>
<security xdt:Transform="InsertIfMissing">
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
</location>
</configuration>
Don't forget to copy all the other attributes of "configuration" from the original "web.config", as it seems that VS2012 doesn't do it automatically and of course there will be no match...
Answering late as well, but this may help someone.
I realized that if you have two websites in the same solution, when you try to publish one of them the transformation might not work if you have one only configuration for both projects.
One of my websites was always transforming, but the other sometimes was and sometimes wasn't.
For example, I had the configuration "Auto" in the solution, and had web.Auto.config for both websites.
I resolved that by creating a new configuration with a different name - "AutoAdmin" - creating also its web.AutoAdmin.config file for the second project, and when I published it again the transformation finally occurred.
I followed the below steps to fix this issue. Thanks, #michaelhawkins for pointing in the right direction. You need to make sure you change the configuration to release in two places.
And right click on your project and select "Properties". IF not working try selecting x86 in CPU Architecture
#Karthikeyan VK your post resolved my issue. Although I was selecting Production configuration in my publish profile, in configuration manager it was set to dev therefore It didn't transform my settings.
Microsoft needs to fix this bug. Once you pick a configuration in the publishing profile it should automatically update the configuration manager as well.

using web.config variables within web.config

I would like to have a variable defined in my web.config that I can use in multiple places within my web.config file (and other config files). It's probably easier to explain by example ...
web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="AuthServiceEndPoint" value="any_old_name_i_like"/>
</appSettings>
<system.web>
...
<system.serviceModel>
<client>
<endpoint
address="net.tcp://localhost/AuthService"
binding="netTcpBinding"
contract="MyServices.Contracts.IAuthService"
name="#{AppSettings.AuthServiceEndPoint}"
bindingConfiguration="netTcpBindingConfig"
/>
</client>
</system.serviceModel>
</configuration>
windsor.config
<?xml version="1.0" encoding="utf-8" ?>
<castle>
<components>
...
<component
id="AuthProvider"
service="MyServices.Client.IAuthProvider, MyServices.Client"
type="MyServices.Client.AuthProvider, MyServices.Client"
lifestyle="transient">
<parameters>
<endpoint>#{AppSettings.AuthServiceEndPoint}</endpoint>
</parameters>
</component>
</components>
</castle>
Is this possible?
Edit (a bit more information)
I already have the ability to access the AppSettings from my windsor.config file (which is actually processed by castle windsor and a custom XmlInterpreter.
The real question is can I do this in my web.config?
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="AuthServiceEndPoint" value="any_old_name_i_like"/>
</appSettings>
<system.web>
...
<system.serviceModel>
<client>
<endpoint
address="net.tcp://localhost/AuthService"
binding="netTcpBinding"
contract="MyServices.Contracts.IAuthService"
name="#{AppSettings.AuthServiceEndPoint}"
bindingConfiguration="netTcpBindingConfig"
/>
</client>
</system.serviceModel>
</configuration>
ie - access variable in my <appSettings> from other parts of my web.config file.
Off the top of my head, I wonder if you might be able to do this with T4? I'm thinking that perhaps you could define a template which parses Web-Template.config and outputs Web.config? Of course, this only works for a single file.
You can use NAnt or MSBuild for this. You do need separate configuration files for both, but when you build your project they can automatically do transformations on your Web.config and other configuration files.
Not that I can think of. You could do your configuration in C# in global.asax.cs instead of the xml file.
Alternatively, have your web.config edited by your build process to replace all these values. FinalBuilder has a neato "Edit XML File" action that uses XPath quite well to do this, and FinalBuilder does have variables. Problem solved. This is how I do my builds at work.
Here I go answering my own question again :-S
I solved this by writing a NetTcpServiceLocator ...
public interface INetTcpServiceLocator
{
EndpointAddress GetAddress(Type serviceType);
}
... along with a custom config section handler which also implements the above interface and reads in the following config section ...
<services>
<service contract="My.Services.TestService.Contracts.ITestService" address="net.tcp://localhost/TestService" />
</services>
Then I created a proxy for each service ...
public class TestServiceProxy : ITestService
{
public SomeInformation GetSomeInformation(SomeParams #params)
{
using (var factory = new NetTcpServiceFactory<ITestService>())
{
var service = factory.Service;
return service.GetSomeInformation(#params);
}
}
}
My Controller has a dependency on a Service, which has a dependancy on ITestService. All this is glued together with Castle Windsor and by using property dependency injection.
So, my controller calls it's Service, which in turn calls the ITestService (in this case a proxy, which gets it's endpoint from the custom section handler).
The custom section handler (which is also the INetTcpServiceLocator) has a windsor lifestyle of "perWebRequest", so it gets called by the framework and web.config is read into an array in memory. When the service proxy is called, it then just pulls the relevant endpoint based on the contract type.
It's all driven by the type of the contract, so there is no need to have any variables in web.config anymore.
I've gone for a code based solution, as I don't use a build process locally, only when I submit my code to subversion does the build process kick in on our build server.

Resources