Using Web.Config Transforms to Change the "size" element in a log4net "parameter" - asp.net

I'm working on an ASP.NET project which uses log4net. In the Development environment, I want the size element of the #stackTrace parameter to be set to a higher value than in other environments.
The structure of the log4net.config file is:
<?xml version="1.0"?>
<configuration>
<log4net debug="true">
<appender name="SQLServerAppender" type="log4net.Appender.AdoNetAppender">
<parameter>
<parameterName value="#stackTrace"/>
<dbType value="String"/>
<size value="1000"/>
<layout type="log4net.Layout.RawPropertyLayout">
<key value="stackTrace"/>
</layout>
</parameter>
<!-- More parameters -->
</appender>
</log4net>
</configuration>
I would like to change the value attribute of the size element to 2000.
I tried the following transform file, but it didn't change anything:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<log4net>
<appender name="SQLServerAppender" type="log4net.Appender.AdoNetAppender">
<parameter xdt:Locator="XPath(configuration/log4net/appender[#name='SQLServerAppender']/parameter[parameterName[#value='#stackTrace']])"
xdt:Transform="Remove">
</parameter>
</appender>
</log4net>
</configuration>
The "Remove" was a last resort to try to get something to happen!
What should I do to perform the desired transform? It's not clear to me how to combine xdt:Locator with xdt:Transform in this case.

After the answer by Eric.Y.Fan didn't work, I played around a bit to find out why not.
I first put back the <connectionString> value (I left it out of my post for clarity), and it did work. That proved that the correct <appender> had been found, but that the correct <parameter> was not being found. "Found", or "located". That was a hint.
I looked at the XPath expression, and realized that it was attempting to locate the <parameter> which had a <parameterName> with a value attribute with the value #stackTrace. So I tried using Condition:
<parameter xdt:Locator="Condition([parameterName[#value='#stackTrace']])"
xdt:Transform="Replace">
</parameter>
This worked!
So the final transform is:
<parameter xdt:Locator="Condition([parameterName[#value='#stackTrace']])">
<size value="2000" xdt:Transform="Replace" />
</parameter>

I could be mistaken but I don't think Web.config transforms can be applied to other arbitrary xml files.
For that purpose I usually use SlowCheetah:
http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5
It's a great tool, very easy to use (similar to web.config transforms, but can be applied to anything), and also integrates very well with automated builds and deployments.
Here's a guide from Scott Hanselman:
http://www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx

Try this:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<log4net>
<appender name="SQLServerAppender" type="log4net.Appender.AdoNetAppender">
<parameter>
<size value="2000" xdt:Locator="XPath(configuration/log4net/appender[#name='SQLServerAppender']/parameter[parameterName[#value='#stackTrace']])" xdt:Transform="SetAttributes"/>
</parameter>
</appender>
</log4net>

Related

How do you enable document function in XSLT (called from ASP.NET)?

I have a stylesheet using a for each loop over the XML doc but when it comes accross using the document() method it fails.
<td >
<xsl:value-of select="document('Departments.xml')/Departments/Department[#Id=dep]/Name"/>
</td>
The variable has a value each loop which prints out
Execution of the "document()" function was prohibited. Use the
"XsltSettings.EnableDocumentFunction" property to enable it.
I think if XslCompiledTransform is used by the asp:xml control instead of XslTransform it means that the environment you are working in has set aspnet:RestrictXmlControls to true (https://learn.microsoft.com/en-us/previous-versions/aspnet/hh975440(v=vs.120))
<appSettings>
<add key="aspnet:RestrictXmlControls" value="true" />
</appSettings>
so you might need to try/check whether your locale web.config can set it back to
<appSettings>
<add key="aspnet:RestrictXmlControls" value="false" />
</appSettings>
to have XslTransform being used where you are not restricted by default XsltSettings.

Extract form parameter in Extract Variables policy

I am trying to extract a form param in an Extract Variables policy without success. request.formparam.grant_type successfully extracts the form parameter value but when I do the following it doesn't work. I don't understand what I am doing wrong I have made the request with the header Content-Type set to application/x-www-form-urlencoded as specified in the documentation but nothing seems to work. I must be doing something really silly but cannot spot what.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-Variables-1">
<FormParam name="grant_type"/>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<Source clearPayload="false">request</Source>
<VariablePrefix>apigee</VariablePrefix>
</ExtractVariables>
Apigee Support helped me out and the following works:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-Variables-1">
<FormParam name="grant_type"><Pattern>{grantType}</Pattern></FormParam>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<Source clearPayload="false">request</Source>
<VariablePrefix>apigee</VariablePrefix>
</ExtractVariables>
You need to provide the variable in which to save the form parameter:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-Variables-1">
<FormParam name="grant_type">
<Pattern>{grantType}</Pattern>
</FormParam>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<Source clearPayload="false">request</Source>
<VariablePrefix>apigee</VariablePrefix>
</ExtractVariables>
Since you have set your VariablePrefix to "apigee", the form parameter grant_type will be saved in the variable apigee.grantType.

How can i remove the missing subpackage error in a phpcs ruleset?

I want to remove this because i dont need it on my project.
<rule ref="Squiz.Commenting.FileComment">
<properties>
<property name="subpackage" value="false"/>
</properties>
</rule>
See you
The way to exclude that specific error message in your ruleset.xml file is to use:
<exclude name="Squiz.Commenting.FileComment.MissingSubpackageTag" />
Use the -s command line argument to determine the code for a specific error message. You'll see something like this:
Missing #subpackage tag in file comment
(Squiz.Commenting.FileComment.MissingSubpackageTag)
If you want to exclude the whole sniff, you'd instead use:
<exclude name="Squiz.Commenting.FileComment" />
There are a lot of other things you can do in a ruleset file. See the docs for more examples: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml

What are appSettings keys valid characters?

This is strange. I thought I would easily find this information googling, but I haven't had much success. All I want to know is what are the valid characters that can be used for the keys in the AppSettings section of a Web.config file. Eg:
<add key="MySpeed" value="100" />
<add key="My.Speed" value="100" />
<add key="My Speed" value="100" />
<add key="Vélocité" value="100" />
Would all of the above keys be permitted?
The Microsoft documentation states only that the key is a String attribute. Nothing more. Their examples do show a key with spaces in the name.

Enrich message from within same message

Using Biztalk 2010 I have a incoming message with this structure:
<xml><blocks>
<block id="level">
<message id="code">100</message>
<message id="description">Some description</message>
</block>
<block id="level">
<message id="code">101</message>
<message id="description">More description</message>
</block>
</blocks>
<blocks>
<block id="change">
<message id="table">1</message>
<message id="oldvalue">100</message>
<message id="newvalue">101</message>
</block>
</blocks>
</xml>
I need to map the above to this structure:
<terms>
<termItem>
<code>100</code>
<description>Some description</description>
<deleted>false</deleted>
</termItem>
<termItem>
.....and so on with values from the above xml file, except that the item from the "change" block should be added as a new record to output, so the total output will be 3 items (<block>).
The map view is like this:
I need some help in choosing the right combination of either functoids to use, or maybe another approach to solve this challenge.
I'm able to either choose all blocks with the "level" value and filter out the "change" block, but unable to make a combination of the two.
Any hints, suggestions are very welcome.
Thanks
There seems to be more than meets the eye
The incoming xml seems to be nested (as per the schema in the visual mapper), so the example input xml structure might not quite be right?
Also, it might be that the schema on the RHS is debatched, i.e. one PaymentTerms message per company id, so unless you only need to map the first Company, you will need to create a wrapper schema for all mapped companies, with an arbitrary root node, and then debatch them before sending.
That said, it is relatively straightforward to get the general structure of the output by using a custom xslt instead of the visual mapper. I've assumed the RHS schema on your diagram for the real output schema (not your terms example).
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="xsl xsi">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<!--Outer template-->
<xsl:template match="/">
<PaymentTerms CompanyCode="Unsure">
<xsl:apply-templates />
</PaymentTerms>
</xsl:template>
<!--Root blocks only-->
<xsl:template match="block[#id='level']">
<PaymentTerm>
<Code>
<xsl:value-of select="message[#id='code']/text()"/>
</Code>
<Description>
<xsl:value-of select="message[#id='description']/text()"/>
</Description>
<Deleted>
<!--No idea how you want this populated-->
<xsl:value-of select="'false'"/>
</Deleted>
</PaymentTerm>
<xsl:apply-templates select="blocks/block"></xsl:apply-templates>
</xsl:template>
<!--Nested blocks only-->
<xsl:template match="block[#id='change']">
<PaymentTerm>
<Code>
NestedCode
</Code>
<Description>
NestedDescription
</Description>
<Deleted>
NestedDeleted
</Deleted>
</PaymentTerm>
</xsl:template>
</xsl:stylesheet>
You didn't provide much info on how the nested blocks are to be mapped, so I've provided placeholders in the meantime.
HTH!

Resources