How do you update FX_schema.xml file in IIS 7? - asp.net

We are deploying our ASP.Net MVC application to a windows 2008 R2 server, running IIS 7.5.
After deployment, we get this error in the event log (we also get an email) :
"Unrecognized element 'providerOption'" on line x in c:\wwwroot\web.config
which is:
<providerOption name="CompilerVersion" value="v3.5">
located in the system.codedom compiliers section of our standard web config. I investigated the problem a bit. (I also checked the namespace details on msdn to find out abit about it). Amongst many other solutions, I found this post recommending updating the FX_Schema.xml file on our server. (I think this is where the problem is, please correct me if I'm mistaken)
I looked through fx_schema file, and, as defined in the event viewer, the attribute "providerOption" is not in this schema! Here is the copy of the system.codedom section from the FX_schema.xml
<sectionSchema name="system.codedom">
<element name="compilers">
<collection addElement="compiler" removeElement="remove" clearElement="clear">
<attribute name="language" type="string" isCombinedKey="true" />
<attribute name="extension" type="string" isCombinedKey="true" />
<attribute name="type" type="string" />
<attribute name="warningLevel" type="int" />
<attribute name="compilerOptions" type="string" />
</collection>
</element>
</sectionSchema>
I am sure that I can not be the the only person who has this problem, but has anyone else anyone come across this before and found a solution?
EDIT: Another way to produce this quickly is (on IIS 7 in Windows 7)
In IIS Managment console, open your MVC website, in the website home. You should see ASP.NET, IIS, and Managment groups. Under Management, open the "Configuration Editor". I get the error message popping up here!
EDIT: My copy of the web config:
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"
type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4"
type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="OptionInfer" value="true"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
</compilers>
</system.codedom>

I've managed to recreate the error in IIS by simply going to the system.codedom section of the configuration manager.
I don't get any error using either a .net3.5 or .net4.0 app but these are very basic test apps, also only .net3.5 test apps put a system.codedom section in the web.config file by default.
.net4.0 simplified the web.config file and moved out a lot of options
I've found some information here about possible config conflicts which may be of use
It recomends
The workaround for the second scenario
is to delete or comment out all the
system.web.extensions configuration
section definitions and configuration
section group definitions from the
application-level Web.config file.
These definitions are usually at the
top of the application-level
Web.config file and can be identified
by the configSections element and its
children.
For both scenarios, it is recommended
that you also manually delete the
system.codedom section, although this
is not required
Not exactly the same problem but similar

I had an issue very similar to this that I posted and then solved myself and posted the solution I came up with. My solution: I made my own file and placed it in with the schema files. I called it the inventive name ThreeFive.xml and placed it at C:\Windows\System32\inetsrv\config\schema. The entire contents of the file are as follows:
<configSchema>
<sectionSchema name="system.codedom">
<element name="compilers">
<collection addElement="compiler" removeElement="remove" clearElement="clear">
<attribute name="language" type="string" isCombinedKey="true" />
<attribute name="extension" type="string" isCombinedKey="true" />
<attribute name="type" type="string" />
<attribute name="warningLevel" type="int" />
<attribute name="compilerOptions" type="string" />
<collection addElement="providerOption">
<attribute name="name" required="true" isUniqueKey="true" type="string" />
<attribute name="value" required="true" type="string" />
</collection>
</collection>
</element>
</sectionSchema>
</configSchema>
I then published a 3.5 site that retrieved information from an appconfig setting and did some LINQ to make sure the config and the 3.5 were in effect. The config file was not blanked and the LINQ is working as expected so I am tempted to call this a solution.

Related

Trying obfuscating Dot Net Core applications

I am trying to obfuscate a Dot Net Core application but I am having no success. I am using ConfuserEx, managed to get it to work with a Net Framework, but no luck when trying it out with a Net Core Console Application or Net Core DLL.
I get the error:
Object reference not set to an instance of an object.
Did anyone managed to obfuscate a Net Core application? If not is there any other tool that can do it?
You can try Obfuscar. Its free and open source.
Binaries can be loaded at https://www.nuget.org/packages/Obfuscar/
Project sample:
<Obfuscator>
<Var name="InPath" value=".\" />
<Var name="OutPath" value=".\output" />
<Var name="HideStrings" value="true" />
<Var name="UseKoreanNames" value="true" />
<Var name="ReuseNames" value="true" />
<Var name="RenameFields" value="true" />
<Var name="RenameProperties" value="true" />
<Var name="RenameEvents" value="true" />
<Var name="OptimizeMethods" value="true" />
<Var name="SuppressIldasm" value="true" />
<Var name="KeepPublicApi" value="false" />
<Var name="HidePrivateApi" value="true" />
<Module file="$(InPath)\YourApplication.dll" />
</Obfuscator>
Running obfuscation:
Obfuscar.Console.exe your_project.xml
I saw this error when I tried to obfuscate EXE file. DLLs do not yield this error.
But I need to add that at the moment ConfuserEx does not really support .NET Core assemblies, because it does not handle metapackages; all dependent assemblies must be explicitly specified in the main DLL, which makes it quite a hassle.

NLog & GrowlNotify, added assembly can't be found after deploying

I'm using NLog and Growl. It works fine locally. When I deploy the website, I get the error that :
Exception: NLog.NLogConfigurationException: Exception when parsing E:\Websites\SPECIFICATION\NLog.config. ---> System.ArgumentException: Target cannot be found: 'NLog.Targets.GrowlNotify'
But this dll does exist in my bin directory. I added all the required files via nuget.
And my config file:
<?xml version="1.0" encoding="utf-8"?>
<nlog xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd" autoReload="true" throwExceptions="false" throwConfigExceptions="true" internalLogToConsole="true" internalLogLevel="Trace" internalLogFile="E:\Websites\SPECIFICATION\App_Data\log.txt" xmlns:p1="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<variable name="myvar" value="myvalue" />
<extensions>
<add assembly="NLog.Targets.GrowlNotify" />
</extensions>
<targets>
<target name="db" xsi:type="Database" connectionString="Data Source=AA;Initial Catalog=BB;User ID=SA;Password=BBBB" connectionStringName="SC" commandType="StoredProcedure" commandText="[dbo].[NLog_AddEntry_p]">
<parameter name="#machineName" layout="${machinename}" />
<parameter name="#siteName" layout="${iis-site-name}" />
<parameter name="#logged" layout="${date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#username" layout="${aspnet-user-identity}" />
<parameter name="#message" layout="${message}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#properties" layout="${all-event-properties:separator=|}" />
<parameter name="#serverName" layout="${aspnet-request:serverVariable=SERVER_NAME}" />
<parameter name="#port" layout="${aspnet-request:serverVariable=SERVER_PORT}" />
<parameter name="#url" layout="${aspnet-request:serverVariable=HTTP_URL}" />
<parameter name="#https" layout="${when:inner=1:when='${aspnet-request:serverVariable=HTTPS}' == 'on'}${when:inner=0:when='${aspnet-request:serverVariable=HTTPS}' != 'on'}" />
<parameter name="#serverAddress" layout="${aspnet-request:serverVariable=LOCAL_ADDR}" />
<parameter name="#remoteAddress" layout="${aspnet-request:serverVariable=REMOTE_ADDR}:${aspnet-request:serverVariable=REMOTE_PORT}" />
<parameter name="#callSite" layout="${callsite}" />
<parameter name="#exception" layout="${exception:tostring}" />
</target>
<target name="growl" xsi:type="GrowlNotify" password="" host="192.168.1.10" port="23053"/>
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="*" minlevel="Trace" writeTo="db" />
<logger name="*" minLevel="Trace" writeTo="growl" />
</rules>
</nlog>
I'm not sure why it works locally but not on the deployed version. They're the same. And the dll exists on both. Any ideas?
Update:
After enabling binding logging I get these log messages:
Assembly manager loaded from:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable c:\windows\system32\inetsrv\w3wp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c
(Fully-specified)
LOG: Appbase = file:///E:/Websites/SPECIFICATION/
LOG: Initial PrivatePath = E:\Websites\SPECIFICATION\bin
Calling assembly : NLog.Targets.GrowlNotify, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: E:\Websites\SPECIFICATION\web.config
LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/specification/f65047fd/2d5397dc/NLog.DLL.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/specification/f65047fd/2d5397dc/NLog/NLog.DLL.
LOG: Attempting download of new URL file:///E:/Websites/SPECIFICATION/bin/NLog.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Major Version
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
Is this something to do with nuget not being able to download the latest packages on the production server? But if the error is with NLog.dll why does NLog log to my database just fine, and only growl doesn't work?
NLog.Grow is build to NLog 2. Because NLog is strong named, the strong names should match.
NLog.Web is using NLog 4 and the strong name for all NLog 4.x versions is 4.0.0.0.
To fix these problems, you need a bindingRedirect in your .config:
<dependentAssembly>
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
But please note this isn't 100% safe, as breaking changes could lead to method mismatch errors.

Deploying ASP.NET application on IIS 7; got compilerVersion issue

I am trying to deploy two ASP.NET Application onto IIS 7. The first application I copied and pasted under wwwRooT folder and set Application Pool as Asp.NET 4.0 Integrated. For the second one, I created one virtual directory and set the Application Pool the same as the first application.
The first one works well, but the second one got exception:
The value for the 'compilerVersion' attribute in the provider options
must be 'v4.0' or later if you are compiling for version 4.0 or later of the .NET
Framework. To compile this Web application for version 3.5 or earlier of the .NET
Framework, remove the 'targetFramework' attribute from the element of
the Web.config file.
I had a similar problem and had to tell ASP.NET in configuration to use the 3.5 compiler as follows by modifying Web.config.
I've copied and pasted the following from my code. You have to change value="v3.5" to value="v4.0". The compiler type strings might also change.
<configuration>
<!-- ... other configuraiton stuff ... -->
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="OptionInfer" value="true"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
</compilers>
</system.codedom>
</configuration>
In my case the 2.0 compiler was being used instead of 3.5. I was working in an IIS 7, ASP.NET Website project.
You might glean additional insight from:
http://msdn.microsoft.com/en-us/library/system.codedom.aspx
http://msdn.microsoft.com/en-us/library/a15ebt6c%28VS.80%29.aspx

.NET Web Deployment Tool with log4Net: Not overwriting logs

I'm using the Web Deployment Tool to build and release an MVC site from VS 2010 to a server running IIS. I also have log4net logging to a subdirectory off of the root of the web application I'm deploying to. I already figured out how to keep write permissions intact when deploying with this tool on that directory, but now I'm running into the problem that I'd rather not lose the logs when deploying, and also, the deploy is failing because the log file that log4net is using is "used by another process" (presumably w3wp) and won't let the deploy continue.
So, I'd like to preserve the log files and not delete or overwrite them, for auditing purposes. Is there a way to do that within the confines of the Web Deployment Tool?
EDIT: Here's the applicable bits of the log4net configuration, in Web.Config.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net" />
</configSections>
<log4net>
<appender name="RollingLog" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Logs\Log.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="20" />
<maximumFileSize value="10MB" />
<datePattern value="yyyyMMdd" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="{%level}%date{MM/dd HH:mm:ss} - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingLog" />
</root>
</log4net>
</configuration>
Found it by hunting around: there is a "skip" parameter you can tack on to the command when you call the pre-packaged deploy script. You HAVE to use a regular old CMD prompt for this; Powershell's crazy escaping of quotes makes it near-impossible to get right, so I gave up. Anyway, here's the end result I came up with:
.\MyProject.deploy.cmd /Y /M:MyServerName "-skip:skipAction=Delete,objectName=filePath,absolutePath=Logs"
"MyProject.deploy.cmd" being the name of the prepackaged deploy command, "MyServerName" being the name of the server I was deploying to, and "Logs" being the name of the folder I wanted to skip. This command seems to leave alone that Logs directory and deploy anything else that matters.
Source where I started to hone in on things: http://blogs.iis.net/msdeploy/archive/2009/04/23/what-has-changed-about-skip-replace-rules-in-rc.aspx
Set locking model of your appender to minimal lock and everything will be fine:
<appender name="RollingLog" type="log4net.Appender.RollingFileAppender">
...
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
...
</appender>
log4net.Appender.FileAppender (see remarks)

Edit config custom section in IIS

I am working on big ASP.NET project(we using ASP.NET 3.5) which comprised of 5 different WebSites and some shared assemblies. Recently I added custom section into web.config files for each site. When I deploy all these applications, each site is deployed separately under same app pool.
Is there any way to make this section editable in IIS on site level, just like you can edit ConnectionString section for each site?
Sections I added all look like this:
<sectionGroup name="RegistriesCustomSettings">
<section name="RegistriesSettings"
type="Registries.Business.Utilities.RegistriesConfigurations"/>
</sectionGroup >
<RegistriesCustomSettings>
<RegistriesSettings ContextCommandTimeout="30"
logLinq="true" DisplayUser="true" BaseReportPath="/DDD/"
ReportingServer="http://patriot-regdev:8000/ReportServer"
TopInstitution="1000001" />
</RegistriesCustomSettings>
We using are IIS 7.0, 2008 RC 2.
Yes there is a way to do this by extending the IIS configuration schema.
Create a file called RegistriesSchema.xml and copy and paste the following XML:
<configSchema>
<sectionSchema name="RegistriesCustomSettings">
<element name="RegistriesSettings">
<attribute name="ContextCommandTimeout"
type="int"
validationType="integerRange"
validationParameter="1,600"
allowInfinite="true"
defaultValue="30" />
<attribute name="logLinq"
type="bool"
defaultValue="True" />
<attribute name="DisplayUser"
type="bool"
defaultValue="True" />
<attribute name="BaseReportPath"
type="string"
validationType="nonEmptyString" />
<attribute name="ReportingServer"
type="string"
validationType="nonEmptyString" />
<attribute name="TopInstitution"
type="string"
validationType="nonEmptyString" />
</element>
</sectionSchema>
</configSchema>
Grab a copy of a tool called IisSchema.exe from here:
IISSCHEMA.EXE - A tool to register IIS7 configuration sections
Unzip and make sure both the exe and the xml schema file are in the same folder.
From an administrator command line (i.e. open cmd.exe using "Run As Administrator"):
IISSCHEMA.EXE /install RegistriesSchema.xml
This will do two things:
drops the schema file into %systemroot%\system32\inetsrv\config\schema
adds the following XML to applicationHost.config:
<section name="RegistriesCustomSettings"
overrideModeDefault="Allow"
allowDefinition="Everywhere" />
4 . Launch IIS Manager and open the feature settings for your website and open the Configuration Editor:
5 . Select the Section drop down list:
If all is good you should see "RegistriesCustomSettings", select this item.
6 . You can now edit these settings and they'll be added to your site's web.config file:
This is just a demonstration so the schema settings may not be quite right and will probably need some fine tuning.
What To Do With <sectionGroup name="RegistriesCustomSettings">?:
You will still need to add the configSection/sectionGroup xml to your web.config file for each site or you could add it to the root machine.config file for whatever version of ASP.NET you're using, i.e.:
For .NET Framework 2.0 (which also applies to .NET3.0 and 3.5):
%systemroot%\Microsoft.NET\Framework\v2.050727\CONFIG\machine.config
%systemroot%\Microsoft.NET\Framework64\v2.050727\CONFIG\machine.config
For .NET Framework 4.0:
%systemroot%\Microsoft.NET\Framework\v4.0.30319\CONFIG\machine.config
%systemroot%\Microsoft.NET\Framework64\v4.0.30319\CONFIG\machine.config
If you put your assembly's configSection/sectionGroup in your machine.config file(s) then you don't need to declare it in every site's web.config. If quite a few sites are going to be using this assembly then this may be good timesaver.
Update:
There seems to be a bug or limitation in the IIS7.5 Configuration Editor. It appears that if you have your own custom configSections <sectionGroup> or <section> declarations in your site's web.config file this breaks the IIS7.5 Configuration Editor. I'm trying to get to the bottom of this:
ASP.NET custom configuration section declaration breaks IIS Manager Configuration Editor
Update 2:
I think the MS docs on this are a bit bogus particularly where your custom config section needs to be consumable by ASP.NET and editable in the IIS Manager Configuration Editor. The trick seems to be to declare the schema as follows in the RegistriesSchema.xml file:
<configSchema>
<sectionSchema name="RegistriesCustomSettings/RegistriesSettings">
<attribute name="ContextCommandTimeout"
type="int"
validationType="integerRange"
validationParameter="1,600"
allowInfinite="true"
defaultValue="30" />
<attribute name="logLinq"
type="bool"
defaultValue="True" />
<attribute name="DisplayUser"
type="bool"
defaultValue="True" />
<attribute name="BaseReportPath"
type="string"
validationType="nonEmptyString" />
<attribute name="ReportingServer"
type="string"
validationType="nonEmptyString" />
<attribute name="TopInstitution"
type="string"
validationType="nonEmptyString" />
</sectionSchema>
</configSchema>
Also, and importantly, remove the section reference from applicationHost.config:
<section name="RegistriesCustomSettings"
overrideModeDefault="Allow"
allowDefinition="Everywhere" />
This is not required.
Additionally, you don't actually need to use the iisschema.exe tool, just grab a copy of NotePad2 (it's a 64bit editor, you need this to edit anything in inetsrv\config) and create the RegistriesSchema.xml file directly in inetsrv\config\schema.
You can find out more about extending the IIS7 schema here:
Extending IIS 7.0 Schema and Accessing the Custom Sections Using MWA
You can poke about the existing schema files to learn more about how to construct these settings. They can be found in:
%systemroot%\system32\inetsrv\config\schema
Caveat: The example above was tested on IIS7.5 x64 RTM on Windows 7 x64 Ultimate. You mention that you're running a release candidate so your mileage may vary because of that.

Resources