Today I’m heading to the Agileee 2009 conference being held in Kiev on September, 18 – 19th. This is rather new field to me – I’ve never been practicing Agile or Scrum before. We’ll see how it goes. At least, I’m expecting to learn many new and interesting things and see how to apply this in the Modules team.
When you specify a WebDirProperties element to be used by the sites you install (configure) with WiX, you might also want to allow anonymous access to this site. Fortunately, there’s an attribute AnonymousAccess, which being set to ‘yes’ allows anonymous access to IIS web site.
NOTE: If you don’t address any property of “authorization” group (AnonymousAccess, BasicAuthentication, DigestAuthentication, PassportAuthentication or WindowsAuthentication) in your WebDirProperties, the site inherits those from w3svc root. If you set at least one explicitly, you need to set others the way you wish, because WiX defaults might not work for you.
The wix.chm states that “When setting this (AnonymousAccess) to ‘yes’ you should also provide the user account using the AnonymousUser attribute, and determine what setting to use for the IIsControlledPassword attribute.” But it turns out you are not forced to provide the AnonymousUser attribute and I suppose you never wanted to – you should provide a password as well, but who knows the password of IUSR on a target machine?
Instead, just omit the AnonymousUser attribute and this part of IIS metabase will stay untouched. The username/password will inherit from higher node (again, w3svc). And yes, don’t forget IIsControlledPassword=”yes”.
Hope this helps you tuning the website during the installation.
Avoid defining methods with default arguments!
Today I have been exploring the “Member design” chapter of a great book of Cwalina/Abrams “Framework Design Guidelines”, and found a guideline which shocked me a bit. No, the guideline itself is correct and valuable. I just was never thinking it works like this.
VB.NET has a language feature called default arguments. When you define a method in your class, you can specify default values to the optional parameters to be taken when this parameter is omitted. As far as I understand, this is a kind of alternative to the method overloading.
Consider the following code:
Public Class DefaultValues
Public Function Sum(ByVal a As Integer, Optional ByVal b As Integer = 100)
Sum = a + b
(I speak C# myself, so excuse me my poor VB ;-))
Let’s say we compile this code into a DLL and we have a client console application to utilize that library:
Dim df As DefaultValues.DefaultValues = New DefaultValues.DefaultValues()
Compile everything and run TestDefaultValues.exe. The result is predictable: 155.
Now change the default value from 100 to 200 and compile only the library. DO NOT recompile the client application. Run it again, and it is still 155!
This is why it is strongly not recommended to use default arguments instead of normal method overloading. And this issue is why C# doesn’t expose this technique.
Be careful, VB.NET developers! And long live C#! :-)
It’s not a secret that XSLT supports blocks of code, written in another language, to be used inside the stylesheet. It seems to have been there from the very beginning – at least, XSLT 1.1 understands it.
However, Microsoft enriched this option with their own element, msxsl:script. It offers pretty much the same functionality, but you can also write the code in C# or any other language of .NET platform. XSLT gurus might argue that it is superfluous stuff and it is unnecessary in 99% of cases. Well, as for me, XSLT lacks a number of useful functions in the standard library, such as ToLower/ToUpper, EndWith, etc. You never think about such low level things when programming C#, but you often have to invent a wheel trying to do the same with XSLT.
More details can be found in the official documentation, but here is a brief extract:
- guess an extra prefix and let XSLT processor know about it:
Also, pay attention how msxsl prefix is defined – it is required to use msxsl:script syntax.
- code your extension function:
<msxsl:script language="C#" implements-prefix="ext">
public string ToUpper(string inString)
- and finally use it:
Obviously, it is not a good idea to write lots of code this way. It makes the XSLT stylesheet larger and a bit harder to maintain. And, according to Microsoft, you should “avoid script blocks from XSLT files, because they require loading the script engine multiple times”. Actually, if you created an XSLT stylesheet to fill it with tones of .NET code, you’re definitely doing something wrong. But it seems to be good addition to small, but useful “one-line” operations.
Sitecore and msxsl:script
If you plan to take advantage of inline blocks of C# code in Sitecore XSL rendering, you’ll have to do one more step. By default, .NET API to handle the XSL transforms disables the possibility to use msxsl:script. It is probably done for security reason. But the web.config of your Sitecore solution contains the setting EnableXslScripts, which you can easily set to true and be happy:
<!– ENABLE XSLT SCRIPTS
Determine whether XSLT script support should be enabled.
If script support is not enabled, it will be an error if the XSLT file contains script blocks.
Default value: false.
<setting name="EnableXslScripts" value="true" />
The performance seems to be the same for this simple code either written in msxsl:script block, or wrapped into XSL extension. So, the choice is yours.
WiX and msxsl:script
The heat.exe utility of the WiX toolset has an option to run the harvested authoring against XSLT transform. This is a checkpoint when you can mutate the output before it is done. INHO, it is the most powerful extension option of Heat, because you can do anything with the XML fragment in XSLT.
However, it was a bit disappointing to find out the scripts are disabled by default, and it is not customizable, and the easiest way to fix this is to patch Heat itself and prepare custom WiX build. It would be great if this option is available one day in the base, either as a command line argument, or a configuration setting.
That’s it. If you have some experience with this trick, knowing its pros and cons deeper, share it here. And as usual, any comments are welcome.
P.S. this post was written with the help of Windows Live writer :-)
- The DatabaseName parameter is not validated, because Sitecore takes over this. Try specifying DatabaseName=nosuchdb, and press Save
- The parameter names are case-insensitive. This is because the parameters are extracted with the StringUtil.ExtractParameter() method, which ignores the case
- The TreeList field type doesn’t “tolower” the values of IncludeItemsForDisplay and ExcludeItemsForDisplay parameters. Hence, be sure to specify an item key instead of an item name here
- The content tree filter is built out of the “ForDisplay” parameters using ‘and’ operation. Thus, if IncludeItemsForDisplay contain items of other templates than those specified in IncludeTemplatesForDisplay, this results in an empty tree. This can also be a point of extension of this validator’s functionality
- LOGMSG_STANDARD, which is “write to log whenever informational logging is enabled”, which in most cases means “always”
- LOGMSG_TRACEONLY, which is “write to log if this WiX build is a DEBUG build” (is often used internally to dump CustomActionData contents)
- LOGMSG_VERBOSE, which is “write to log when LOGVERBOSE”
- Check if the LOGVERBOSE property is set (can be set in the command-line since it is public)
- Otherwise, check if the MsiLogging property is set (MSI 4.0+)
- Otherwise, check the logging policy in the registry
- search the registry for the app pool name as usual
- schedule a special action on unistall after AppSearch, which detects if this is the last instance being uninstalled, and if not, “breaks” the app pool name into something non-existent
- copy the MSI package
- use API to query and update the database with new GUIDs for each component
- generate a transform between the copy and original MSI
- drop the copy MSI
- repeat the steps about the number of times as many instances you plan to support
- embed all these transforms into the original MSI
- extract transform from the patch package
- change the original product code to this instance product code in summary info