tag:blogger.com,1999:blog-199063052024-03-14T13:16:24.117+01:00NielsVrolijk blog... about software development and other thingsNielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.comBlogger99125tag:blogger.com,1999:blog-19906305.post-23946294958535500252015-07-08T21:48:00.001+02:002015-07-08T21:51:50.411+02:00Provision additional lookup fields with CSOM<p>When you create a lookup field in SharePoint, you’ll have the option to add additional fields of the source list to your target list. When you create this from the UI, you check those fields on creation of the lookup field. But when you create this from your provision code, you can’t find any parameters on the lookup field itself.</p> <p>The key for doing this in the code is the method <a href="https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.client.fieldcollection.adddependentlookup.aspx" target="_blank">AddDependentLookup</a> on the Fields collection of the target list. To provision this lookup, I created the following method in my provisioner:</p> <script src="https://gist.github.com/Niels-V/4e5d8ecaa239def44ccf.js"></script> <code class="csharp" style="display: none"> private void AddDependantLookup(List parentList, List targetList, Guid lookupFieldId, Field primaryLookupField, string displayName) { Field toField = parentList.Fields.GetById(lookupFieldId); _clientContext.Load(toField); _clientContext.Load(targetList); _clientContext.ExecuteQuery(); Field dependantField = targetList.Fields.AddDependentLookup(displayName, primaryLookupField, toField.StaticName); FieldLookup dependantFieldLookup = _clientContext.CastTo<fieldlookup>(dependantField); dependantFieldLookup.LookupField = toField.StaticName; dependantField.UpdateAndPushChanges(true); _clientContext.Load(dependantField); _clientContext.ExecuteQuery(); }</code> <p>Please note that the lookupFieldId should be the fieldId of the field you want to add to your target list, and there should be another ‘primary’ lookup field configured between the two lists. The displayName is free to choose, this one will show up as column heading for instance in your target list. </p> Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-59694525375948547302014-08-15T11:59:00.000+02:002014-08-15T11:59:09.117+02:00SharePoint workflow variable [Current Item:Path]I needed some documentation what values the [Current Item:Path] workflow variable contains. I couldn't find any examples online, but wondered if this variable contained a server relative URL or a site collection relative URL to the path of an item.<br />
<br />
It turned out this path is server relative. Some examples:<br />
<br />
<dl><dt>http://site.local/Shared Documents/test.docx</dt><dd>/Shared Documents</dd>
<dt>http://site.local/Shared Documents/Folder/test.docx</dt><dd>/Shared Documents/Folder</dd>
<dt>http://site.local/sites/test/Shared Documents/test.docx</dt><dd>/sites/test/Shared Documents</dd>
<dt>http://site.local/sites/test/Shared Documents/Folder/test.docx</dt><dd>/sites/test/Shared Documents/Folder</dd>
</dl><br />
<br />
Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-25916549240088490022014-03-30T12:39:00.000+02:002014-03-30T12:45:07.813+02:00Development VM for SharePoint 2013 on Azure with MSDN<h4>SharePoint 2013 – Hardware needs</h4> <p>To run a SharePoint 2013 development environment, you need a machine with decent specifications. SharePoint 2013 needs at least 12 GB of RAM to run properly, and multiple cores to keep the stuff going. As my current laptop lacks this kind of specifications, but fortunately I currently have a MSDN Premium subscription, which includes a monthly credit of €75 for Windows Azure. Besides this credit, Microsoft made some MSDN specific images available, which give you a fly start because all the needed software is already installed (SQL Server, SharePoint, Visual Studio).</p> <p>There is some information available <a href="http://blogs.msdn.com/b/sharepointdev/archive/2013/09/26/create-sharepoint-2013-development-environments-quickly-on-azure.aspx">on the web</a> about these Visual Studio images, but I found it was a bit out of date, so I wrote my own install guide. I want to create a simple development environment for SharePoint 2013, so I choose to setup a single machine farm without an AD (so I do not need another AD machine).</p> <h4>Configuration steps</h4> <h5>MSDN subscription with Azure</h5> <p>You need to create your VM in Azure with an account connected with MSDN. If you didn’t set up Azure with your MSDN account, start at <a href="https://msdn.microsoft.com/subscriptions/manage/">https://msdn.microsoft.com/subscriptions/manage/</a> to start your Azure MSDN benefit. </p> <h5>Set up a Virtual Machine</h5> <p>If you already set up this account, or after you set it up, go to the Windows Azure Management portal.</p> <h5>Create a new machine</h5> <p><a href="http://lh4.ggpht.com/-aSbyrcM7kMw/Uzf0NBhk7oI/AAAAAAAADUk/DQPj1MQjtGQ/s1600-h/clip_image002%25255B6%25255D.jpg"><img title="clip_image002" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image002" src="http://lh3.ggpht.com/-Xv_TBJ1qSDE/Uzf0Nl2hfuI/AAAAAAAADUs/ZRUsVw0oG5I/clip_image002_thumb%25255B3%25255D.jpg?imgmax=800" width="609" height="179" /></a></p> <p>Click New - Compute - VM - From Gallery to create a new Virtual Machine in your Azure environment. A wizard will guide you through the process for a new VM.</p> <h5>Choose an Image</h5> <p><a href="http://lh6.ggpht.com/-V-bS7yWZKGk/Uzf0ODjOY7I/AAAAAAAADU0/gt2IPjVyX4E/s1600-h/clip_image004%25255B4%25255D.jpg"><img title="clip_image004" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image004" src="http://lh3.ggpht.com/-ypb46L_c-l0/Uzf0OjUVSSI/AAAAAAAADU8/QZJLsGkYQAE/clip_image004_thumb%25255B1%25255D.jpg?imgmax=800" width="608" height="387" /></a></p> <p>As a MSDN specific image is needed, check MSDN in the left bottom. Now you can create a VM based upon a specific Visual Studio version. Choose the MSDN version eligible to your MSDN subscription (or downscale, as the lighter the version is, the lower the needed disk space will be, and the lower the costs will be).</p> <h5>Virtual Machine configuration</h5> <p><a href="http://lh6.ggpht.com/-tT6uWWCxgkg/Uzf0PGu6XMI/AAAAAAAADVE/bge2yOB8U4A/s1600-h/clip_image006%25255B4%25255D.jpg"><img title="clip_image006" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image006" src="http://lh6.ggpht.com/-gNRb3RmifHk/Uzf0PnM8WtI/AAAAAAAADVM/AfpmznzDOx8/clip_image006_thumb%25255B1%25255D.jpg?imgmax=800" width="609" height="387" /></a></p> <p>In this screen, you choose your computer name, administrator account name and password, and most importantly the size of the VM. Choose the Extra Large VM size.</p> <h5>Cloud configuration</h5> <p><a href="http://lh4.ggpht.com/-ife0Ge_mFEk/Uzf0QYB_omI/AAAAAAAADVU/Til_Z13mvBg/s1600-h/clip_image008%25255B4%25255D.jpg"><img title="clip_image008" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image008" src="http://lh3.ggpht.com/-TraWh03aOTA/Uzf0RNZ_zeI/AAAAAAAADVc/f_e8ckSW9Rc/clip_image008_thumb%25255B1%25255D.jpg?imgmax=800" width="609" height="389" /></a></p> <p>In the cloud configuration you specify the DNS name which you use to connect to the machine (RDP or HTTP). As this is my first VM in Azure, I created the cloud service and storage account automatically.</p> <h5>VM network configuration</h5> <p><a href="http://lh4.ggpht.com/-AsYedJwuE0s/Uzf0R_sNRUI/AAAAAAAADVk/-fng2vGzjGY/s1600-h/clip_image010%25255B4%25255D.jpg"><img title="clip_image010" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image010" src="http://lh5.ggpht.com/-bW2_9euD9OY/Uzf0SegI0XI/AAAAAAAADVs/DmOQvs0XxhY/clip_image010_thumb%25255B1%25255D.jpg?imgmax=800" width="609" height="388" /></a> </p> <p>In this last screen, you specify which ports will be mapped such that you can connect from the internet to your VM. As my company firewall blocks outgoing traffic on the RDP port, I map the RDP port to public port 443 (SSL). It can also be a good idea to add HTTP to this list, so you are able to use the SharePoint site from your browser without RDP.</p> <p>Finish the Wizard, and your VM will be created. This can take some time, but in the meantime take the time to change the created storage settings.</p> <h5>Change storage to locally redundant.</h5> <p>Go in the Management Portal to Storage, and select the storage account which was created in the last step. Choose configure, and change Geo Redundant to Locally Redundant such that you will cut your storage costs in half (as it is only a dev test environment, I do not need my VM stored in two different locations). Save your settings.</p> <p><a href="http://lh5.ggpht.com/-fBaycKacIcs/Uzf0S2ri76I/AAAAAAAADV0/spZvOnbHyyk/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-9x9BvCfAR0s/Uzf0TXA9e9I/AAAAAAAADV8/TOHgZG1iujc/image_thumb%25255B1%25255D.png?imgmax=800" width="609" height="266" /></a></p> <h5>Connect to your VM</h5> <p>Now your VM is up and running, as Azure starts it automatically. Keep in mind that you pay for the VM per minute from the moment it is running.</p> <p>RDP to the machine with your cloud service DNS name (and think about the port when you changed it from 3389 to something else). In this example, that is ‘mysharepointfarm.cloudapp.net’. Login with the credentials you set in step 2 of the wizard. You’ll have a nice SharePoint machine at your fingertips:<a href="http://lh5.ggpht.com/-0bHk3CTC_qw/Uzf0T4diqWI/AAAAAAAADWE/zWAlHsPiABo/s1600-h/clip_image014%25255B4%25255D.jpg"><img title="clip_image014" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image014" src="http://lh5.ggpht.com/-bfVxUdnKTic/Uzf0VmbHbdI/AAAAAAAADWM/DeYHRqyVp7c/clip_image014_thumb%25255B1%25255D.jpg?imgmax=800" width="609" height="554" /></a></p> <h5>Create the farm</h5> <p>Your VM is started, SharePoint is installed as you see the icons of Central Administration and the product configuration wizard on the desktop, but there is no farm created yet. But on the desktop you find a shortcut to the Configure Developer Desktop. Inside that folder you find a Scripts map with three different scripts. </p> <p><a href="http://lh4.ggpht.com/-28tvlxy5bxo/Uzf0WnXWm9I/AAAAAAAADWU/XDl_ohnEyf0/s1600-h/clip_image016%25255B4%25255D.jpg"><img title="clip_image016" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image016" src="http://lh3.ggpht.com/-L7k-t4p6aQs/Uzf0XL6r7LI/AAAAAAAADWc/axjQXsc8GlE/clip_image016_thumb%25255B1%25255D.jpg?imgmax=800" width="609" height="292" /></a> Start the PowerShell script ‘ConfigureSharePointFarm.ps1’ from the Shortcut found on the desktop to configure SQL and the SharePoint Farm. </p> <p>This script will ask for a localSPFarmAccountName and a localSPFarmAccount password. It will create those accounts on the computer, configure SQL server, install a SharePoint farm and provision a developer site on <a href="http://localhost">http://localhost</a>. This script will take some more time to run (I think it runs a complete SQL configuration on the background), so this is time to get some coffee. It will end with opening your newly created site collection.<a href="http://lh3.ggpht.com/-LhwvL-ESuDc/Uzf0XiGJEgI/AAAAAAAADWk/TIDp39p9Qlc/s1600-h/clip_image018%25255B4%25255D.jpg"><img title="clip_image018" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image018" src="http://lh6.ggpht.com/-jbg19uhL1fI/Uzf0Yd3F04I/AAAAAAAADWs/OKgskly0fMA/clip_image018_thumb%25255B1%25255D.jpg?imgmax=800" width="609" height="394" /></a></p> <h4>Costs</h4> <p>Again, keep in mind that you will pay your VM by the hour when it is running. So turn off your VM after use and power off the VM in the Management Portal when you’re done (otherwise your credits will be gone in a couple of days). I installed the Azure PowerShell tools, such that I can turn off your VM from my own computer with a simple Stop-AzureVM command.</p> <p>As a Premium MSDN subscription will come with a monthly credit of €75, I estimated you can run your VM for about 175 hours. <table cellspacing="0" cellpadding="0" border="1"><tbody> <tr> <td valign="top" width="151"> <p>Storage, first TB</p> </td> <td valign="top" width="198"> <p>€ 0.038 per GB per Month</p> </td> <td valign="top" width="104"> <p>127 GB</p> </td> <td valign="top" width="151"> <p>€ 5 per month</p> </td> </tr> <tr> <td valign="top" width="151"> <p>Transactions</p> </td> <td valign="top" width="198"> </td> <td valign="top" width="104"> <p>Per transaction</p> </td> <td valign="top" width="151"> <p>€ 0.04 per hour?</p> </td> </tr> <tr> <td valign="top" width="151"> <p>Compute hours</p> </td> <td valign="top" width="198"> <p>MSDN rate</p> </td> <td valign="top" width="104"> <p>Per hour</p> </td> <td valign="top" width="151"> <p>€ 0.36 per hour</p> </td> </tr> <tr> <td valign="top" width="151"> <p>Data Transfer, first 10 TB</p> </td> <td valign="top" width="198"> <p>€ 0.09 per GB, first five free</p> </td> <td valign="top" width="104"> <p>Not much, but assume 15 GB</p> </td> <td valign="top" width="151"> <p>€ 1 per month</p> </td> </tr> </tbody></table> </p> <p>I’m not sure about how much transactions are used per hour. After two hours of usage, my bill was only € 0.02, so I estimate it on the safe side to € 0.04 an hour. So this means a €6 month fee, and a rate of €0.40 per hour.</p> <h4>Conclusion</h4> <p>When you are in the possession of a MSDN account, the SP2013 VM option is an excellent way to start developing and learning SharePoint 2013 without the need of expensive hardware. The other major benefit is that you have an environment up and running within the hour. You do not need to download or upload installation media, or install the bits yourself, which is a real time saver. </p> Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com2tag:blogger.com,1999:blog-19906305.post-66121344111213607702014-02-19T22:48:00.001+01:002014-02-19T22:49:23.784+01:00Quickly update WebPart titles by CSOMWhile entering content for a new SharePoint section on a SharePoint 2010 publishing site, the content editors added a related articles webpart on about 100 pages. Too bad they didn't bother to change the webpart title, so I was asked to change change these titles, which had their default value, from a rather functional description of the webpart to something that makes a lot more sense in on the pages. As it should be possible to do it in CSOM, I created a small console application to achieve this. <br />
<br />
<script src="https://gist.github.com/Niels-V/9102200.js"></script>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-67733232658464576492013-12-20T21:57:00.000+01:002013-12-20T21:57:01.722+01:00Lightweight monitoring solution with PowerShellFor one of my projects, I needed a simple and lightweight monitoring and testing framework for the public website. As we tweaked SharePoint with some custom redirect functionality to improve SEO, and moved the Google Analytics code from one solution to one other, I wanted to make sure these functionalities still work after each release.<br />
As UI bugs will be noticed directly, those more technical features are hardly noticed directly on failure. So there was the need to script and monitor those features.<br />
<br />
As I wanted a simple, free and easy to expand solution (I worked with <a href="http://www.ks-soft.net/hostmon.eng/" target="_blank">HostMonitor </a>before, it's easy to write small tests there, but it isn't free), I decided to create my own PowerShell framework. Here it is. It is written for PowerShell 2.0, so webrequests are not executed with Invoke-WebRequest but with the C# System.Net variant.<br />
The script is basically executing tests found in one folder, format the results as HTML and sending it by email with a SMTP server. Things to improve are more test outcomes (now it is Success or Failure, but there might be a yellow inbetween warning or so), or possibly using a tool like Selenium to run tests inside a browser session as well.<br />
<br />
<script src="https://gist.github.com/Niels-V/8061137.js"></script>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-34258080578559562722012-12-11T14:16:00.003+01:002012-12-11T14:18:12.630+01:00No search results on anonymous SP2010 websiteLast week I had an issue with search on SharePoint 2010. It turned out that we didn't had any results on our public website with anonymous access. Results showed up in our authoring zone (with authenticated users). <br />
A lot of the suggestions Google came up with weren't applicable in this situation. It turned out the Anonymous policy on one of the zones of the web application was 'Deny all'. This zone wasn't crawled, but the policy was still propagated to the index and used on the other zone. This meant that, as the content had a deny all flag for anonymous users, security trimming didn't allowed the return of any results.<br />
Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-83138483496628552832012-06-05T09:50:00.000+02:002012-06-07T12:51:22.083+02:00Bug in Duet Enterprise NetWeaver configuration wizardWith Duet Enterprise FP1 came a wizard that lets you configure the settings for user mapping between SAP and SharePoint users. Duet Enterprise is using SAML tokens of SharePoint to single sign on these users to SAP. You can configure this mapping on the NetWeaver machine, but as described in the <a href="http://blogs.msdn.com/b/duetsupport/archive/2012/05/18/no-mapping-for-saml-authentication-found.aspx">Duet Enterprise support blog</a>, this mapping is case sensitive based on the values in the SAML token. <br />
<br />
What turns out is that you can specify the user name prefix in the Configuration wizard, but the wizard always turns the characters to uppercase. So the wizard step is quite pointless, as you need to delete the user mapping and recreate it again with the proper casing with SPRO, SAP Reference IMG - SAP NetWeaver - Gateway - Configuration - Connection Settings - SAP NetWeaver Gateway to Consumer - Define Consumer Issuer Certificate & Map SAP User Names to Consumer.<br />
<br />
<b>Update:</b> this behavior is addressed in SAP Note 1688843.Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-40183043689187232052012-03-01T22:34:00.002+01:002012-03-01T22:34:50.911+01:00MSOCAF false positivesI've been struggling with <a href="https://caf.sharepoint.microsoftonline.com/">MSOCAF</a> lately. It turns out that validation of the developed SharePoint solution is quite hard. And it turns out that the validation of the tools still has a lot of errors.<br />
A couple of examples:<br />
<ul><li>The tool implements SPDispose check. It is a fantastic tool to detect the right disposal of SharePoint objects, but sometimes it can't determine the context right. These errors are taged with 'could be false positive'</li>
<li>MSOCAF implements a couple custom FxCop rules, but these are the quite problematic ones. For example, it detects the usage of deprecated classes and members. It uses the list found on MSDN with <a href="http://archive.msdn.microsoft.com/sps2010deprecated">deprecated members</a>. But in the notes added, there is the source of errors: <blockquote>Note: Types and methods in the Microsoft.SharePoint.Portal namespace are not included in these lists because, with a few exceptions, the entire namespace has been made obsolete.</blockquote>What it means, the Microsoft.SharePoint.Portal namespace? If you look at the MSDN documentation, you see that all classes directly in this namespace are deprecated or internal. But the FxCop rule is implemented as (thank you Reflector): <blockquote>if (fullName.Equals(str3) || fullName.Contains("Microsoft.SharePoint.Portal"))</blockquote>. And here disaster strikes. My code use a new SP2010 class <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.portal.webcontrols.averageratingfieldcontrol.aspx">AverageRatingFieldControl</a>. But as this one is in the Microsoft.SharePoint.Portal.WebControls namespace, it is marked as a deprecated class (see FxCop rule). And now I need time to justify the use of a deprecated method.<br />
</li>
<li>MSOCAF does like logging to ULS, no problem with that. It checks a couple of rules: <ol><li>detects if Unified Logging Service (ULS) logging is performed in every catch block.</li><li>SPDiagnosticsService should be called at start and end of Timer Jobs, Event Receiver, Feature Receiver, and Web Services functions.</li><li>Any errors happening in the Feature Receiver upon activation and deactivation should be logged to the ULS and the exception must be reported back to SharePoint.</li></ol>But as with logging in code, developers like to create a generic method for that, where my custom application categories will be set. But no, MSOCAF keeps complaining that your ULS is not filled with data. And again, inspecting the FxCop rules turns out that it expect you to directly call the SPDiagnosticsService.Local.WriteTrace method. As it checks the IL generated code, sometimes this won't check right in debug mode. Also, using properties as parameters in the WriteTrace function will mess with the callstack, and probably influence the outcome of the FxCop rule negatively. <br />
</li>
</ul><br />
Too bad that the rules used in MSOCAF still need some tweeking.Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-4281747191109052462011-12-04T21:07:00.001+01:002011-12-04T21:09:56.572+01:00Remove BDC Models in PowerShellI needed a PowerShell script to enumerate over all the installed BDC Models (and delete them), but couldn't find the example on TechNet or MSDN. After trying some things, I found the following script:<br />
<br />
<code><br />
$context = "http://sharepoint.local"<br />
$bdc = Get-SPBusinessDataCatalogMetadataObject -BdcObjectType Catalog -ServiceContext $context<br />
foreach ($model in $bdc.GetModels("*") ) {<br />
Remove-SPBusinessDataCatalogModel –Identity $model<br />
}<br />
</code>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com1tag:blogger.com,1999:blog-19906305.post-32754835202529300422011-08-11T11:38:00.000+02:002016-08-11T11:40:19.351+02:00SharePoint File UploadFor some little functionality, I wanted to do a file upload to a document library by some custom .NET only code:<br />
<br />
<code><br />
ListsSoapClient client = new ListsSoapClient();<br />
XElement result = client.GetListItems("{642DF480-74CB-4EDC-865C-CA009054998F}", null, null, null, null, null, null);<br />
XNamespace rs = "urn:schemas-microsoft-com:rowset";<br />
XNamespace z = "#RowsetSchema";<br />
var data = result.Descendants(rs + "data").Descendants(z+"row");<br />
<br />
CopySoapClient copyClient = new CopySoapClient();<br />
FieldInformation[] fields;<br />
byte[] output;<br />
uint result2 = copyClient.GetItem(Uri.EscapeUriString("http://example.hostname/"+"Documents/Report.xls"), out fields, out output);<br />
<br />
string destinationUrl = "http://example.hostname/Documents/Test.xls";<br />
string[] destinationUrls = { Uri.EscapeUriString(destinationUrl) };<br />
List<fieldinformation> fieldsList = new List<fieldinformation>();<br />
<br />
CopyResult[] copyResults;<br />
<br />
uint result3 = copyClient.CopyIntoItems("+", destinationUrls, fieldsList.ToArray(), output, out copyResults);<br />
WebRequest request = WebRequest.Create(destinationUrl);<br />
request.Method = "PUT";<br />
request.Credentials = CredentialCache.DefaultCredentials;<br />
// Write the contents of the local file to the request stream.<br />
using (Stream stream = request.GetRequestStream())<br />
{<br />
//Load the content from local file to stream<br />
stream.Write(output, 0, output.Length);<br />
}<br />
WebResponse response = request.GetResponse();<br />
response.Close();<br />
</code>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-25552648985350040102011-08-05T10:44:00.000+02:002011-08-05T10:44:29.228+02:00Tips while working with SharePoint projects in VS2010<ul>
<li>Install the <a href="http://cksdev.codeplex.com/">CSKDev tools</a></li>
<li>Use quick deploy on the project to test small changes in markup and code</li>
<li>Page layouts don't support Intellisense when double clicking the aspx (VS2010 opens the file in textmode). Right-click and use 'View Code' or 'View Markup' will open the file as a webpage, with fill Intellisense support.</li>
<li>To start with already filled page layouts based on the content type, use the CSKDev 'Create page layout' on the content type in the Server Explorer. <img border="0" height="96" width="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6kbWOKYBCn8nI_LcP8TBxOPDhElpFaQSUl_x5m3NyogZsw4k_7Akzs_YNX_pB2JLjSc4ysXV4NYey-FxEXefeh9UNdlxgBvNzErb2ENFlQjccy_8ZfU5LSzWO9VLlUoCjATmKEA/s200/Create-page-layout.png" /></li>
</ul>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-85565798517562731332011-08-04T22:22:00.003+02:002011-08-05T08:53:00.027+02:00Get Taxonomy terms from the user while configuring a WebPart<!-- code formatted by http://manoli.net/csharpformat/ -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>
In my current SharePoint 2010 project we make use of Managed Metadata terms a lot. We want to be able to select taxonomy terms while configuring WebParts, but the setup of the taxonomy field isn't quite straightforward.
For the configuration of WebParts with exotic controls, you need to implement a custom ToolPart and link it to your WebPart. Because I think we will create a lot of custom ToolParts, I created a base class for displaying these taxonomy fields.
</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="rem">/// <summary></span></pre>
<pre><span class="lnum"> 2: </span><span class="rem">/// This class makes it easier to work with Taxonomy data in a <see cref="Microsoft.SharePoint.WebPartPages.ToolPart">ToolPart</see></span></pre>
<pre class="alt"><span class="lnum"> 3: </span><span class="rem">/// </summary></span></pre>
<pre><span class="lnum"> 4: </span><span class="kwrd">public</span> <span class="kwrd">class</span> TaxonomyToolPart : ToolPart</pre>
<pre class="alt"><span class="lnum"> 5: </span>{</pre>
<pre><span class="lnum"> 6: </span> <span class="rem">/// <summary></span></pre>
<pre class="alt"><span class="lnum"> 7: </span> <span class="rem">/// Gets or sets the name of the term store.</span></pre>
<pre><span class="lnum"> 8: </span> <span class="rem">/// </summary></span></pre>
<pre class="alt"><span class="lnum"> 9: </span> <span class="rem">/// <value></span></pre>
<pre><span class="lnum"> 10: </span> <span class="rem">/// The name of the term store.</span></pre>
<pre class="alt"><span class="lnum"> 11: </span> <span class="rem">/// </value></span></pre>
<pre><span class="lnum"> 12: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> TermStoreName { get; <span class="kwrd">protected</span> set; }</pre>
<pre class="alt"><span class="lnum"> 13: </span> <span class="rem">/// <summary></span></pre>
<pre><span class="lnum"> 14: </span> <span class="rem">/// Gets or sets the name of the term group.</span></pre>
<pre class="alt"><span class="lnum"> 15: </span> <span class="rem">/// </summary></span></pre>
<pre><span class="lnum"> 16: </span> <span class="rem">/// <value></span></pre>
<pre class="alt"><span class="lnum"> 17: </span> <span class="rem">/// The name of the term group.</span></pre>
<pre><span class="lnum"> 18: </span> <span class="rem">/// </value></span></pre>
<pre class="alt"><span class="lnum"> 19: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> TermGroupName { get; <span class="kwrd">protected</span> set; }</pre>
<pre><span class="lnum"> 20: </span> <span class="rem">/// <summary></span></pre>
<pre class="alt"><span class="lnum"> 21: </span> <span class="rem">/// Gets or sets the name of the term set.</span></pre>
<pre><span class="lnum"> 22: </span> <span class="rem">/// </summary></span></pre>
<pre class="alt"><span class="lnum"> 23: </span> <span class="rem">/// <value></span></pre>
<pre><span class="lnum"> 24: </span> <span class="rem">/// The name of the term set.</span></pre>
<pre class="alt"><span class="lnum"> 25: </span> <span class="rem">/// </value></span></pre>
<pre><span class="lnum"> 26: </span> <span class="kwrd">public</span> <span class="kwrd">string</span> TermSetName { get; <span class="kwrd">protected</span> set; }</pre>
<pre class="alt"><span class="lnum"> 27: </span> <span class="rem">/// <summary></span></pre>
<pre><span class="lnum"> 28: </span> <span class="rem">/// Gets or sets a value indicating whether multiple terms can be selected.</span></pre>
<pre class="alt"><span class="lnum"> 29: </span> <span class="rem">/// </summary></span></pre>
<pre><span class="lnum"> 30: </span> <span class="rem">/// <value></span></pre>
<pre class="alt"><span class="lnum"> 31: </span> <span class="rem">/// <c>true</c> if multiple terms can be selected; otherwise, <c>false</c>.</span></pre>
<pre><span class="lnum"> 32: </span> <span class="rem">/// </value></span></pre>
<pre class="alt"><span class="lnum"> 33: </span> <span class="kwrd">public</span> <span class="kwrd">bool</span> MultiSelect { get; <span class="kwrd">protected</span> set; }</pre>
<pre><span class="lnum"> 34: </span> </pre>
<pre class="alt"><span class="lnum"> 35: </span> <span class="kwrd">private</span> TaxonomyWebTaggingControl TaxonomyControl { get; set; }</pre>
<pre><span class="lnum"> 36: </span> </pre>
<pre class="alt"><span class="lnum"> 37: </span> <span class="rem">/// <summary></span></pre>
<pre><span class="lnum"> 38: </span> <span class="rem">/// Called by the ASP.NET page framework to notify server controls that use composition-based </span></pre>
<pre class="alt"><span class="lnum"> 39: </span> <span class="rem">/// implementation to create any child controls they contain in preparation for posting back or rendering.</span></pre>
<pre><span class="lnum"> 40: </span> <span class="rem">/// </summary></span></pre>
<pre class="alt"><span class="lnum"> 41: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> CreateChildControls()</pre>
<pre><span class="lnum"> 42: </span> {</pre>
<pre class="alt"><span class="lnum"> 43: </span> <span class="rem">// create a panel that will hold all of our controls </span></pre>
<pre><span class="lnum"> 44: </span> Panel toolPartPanel = <span class="kwrd">new</span> Panel();</pre>
<pre class="alt"><span class="lnum"> 45: </span> </pre>
<pre><span class="lnum"> 46: </span> <span class="rem">// create the actual control </span></pre>
<pre class="alt"><span class="lnum"> 47: </span> SPContext context = SPContext.Current;</pre>
<pre><span class="lnum"> 48: </span> SPSite site = context.Site;</pre>
<pre class="alt"><span class="lnum"> 49: </span> TaxonomySession session = <span class="kwrd">new</span> TaxonomySession(site);</pre>
<pre><span class="lnum"> 50: </span> TermStore termStore = session.TermStores[TermStoreName];</pre>
<pre class="alt"><span class="lnum"> 51: </span> Group group = termStore.Groups[TermGroupName];</pre>
<pre><span class="lnum"> 52: </span> TermSet productsTermSet = group.TermSets[TermSetName];</pre>
<pre class="alt"><span class="lnum"> 53: </span> </pre>
<pre><span class="lnum"> 54: </span> </pre>
<pre class="alt"><span class="lnum"> 55: </span> TaxonomyControl = <span class="kwrd">new</span> TaxonomyWebTaggingControl();</pre>
<pre><span class="lnum"> 56: </span> TaxonomyControl.ID = <span class="str">"taxonomyControl"</span>;</pre>
<pre class="alt"><span class="lnum"> 57: </span> TaxonomyControl.SspId.Add(termStore.Id);</pre>
<pre><span class="lnum"> 58: </span> TaxonomyControl.TermSetId.Add(productsTermSet.Id);</pre>
<pre class="alt"><span class="lnum"> 59: </span> TaxonomyControl.IsAddTerms = <span class="kwrd">false</span>;</pre>
<pre><span class="lnum"> 60: </span> TaxonomyControl.AllowFillIn = <span class="kwrd">true</span>;</pre>
<pre class="alt"><span class="lnum"> 61: </span> TaxonomyControl.IsMulti = MultiSelect;</pre>
<pre><span class="lnum"> 62: </span> </pre>
<pre class="alt"><span class="lnum"> 63: </span> TaxonomyControl.Text = GetTextFromWebPart(<span class="kwrd">this</span>.ParentToolPane.SelectedWebPart);</pre>
<pre><span class="lnum"> 64: </span> </pre>
<pre class="alt"><span class="lnum"> 65: </span> toolPartPanel.Controls.Add(TaxonomyControl);</pre>
<pre><span class="lnum"> 66: </span> </pre>
<pre class="alt"><span class="lnum"> 67: </span> <span class="rem">// finally add the panel to the controls collection of the tool part </span></pre>
<pre><span class="lnum"> 68: </span> Controls.Add(toolPartPanel);</pre>
<pre class="alt"><span class="lnum"> 69: </span> </pre>
<pre><span class="lnum"> 70: </span> <span class="kwrd">base</span>.CreateChildControls();</pre>
<pre class="alt"><span class="lnum"> 71: </span> }</pre>
<pre><span class="lnum"> 72: </span> </pre>
<pre class="alt"><span class="lnum"> 73: </span> <span class="rem">/// <summary></span></pre>
<pre><span class="lnum"> 74: </span> <span class="rem">/// Gets the textual representation of the selected terms from the WebPart and sets it on the Taxonomy control.</span></pre>
<pre class="alt"><span class="lnum"> 75: </span> <span class="rem">/// </summary></span></pre>
<pre><span class="lnum"> 76: </span> <span class="rem">/// <param name="webPart">The web part.</param></span></pre>
<pre class="alt"><span class="lnum"> 77: </span> <span class="rem">/// <returns>a value from the webpart to select in the TaxonomywebTaggingControl</returns></span></pre>
<pre><span class="lnum"> 78: </span> <span class="rem">/// <remarks>Override this method in your child class to link the webpart property with the taxonomy field.</remarks></span></pre>
<pre class="alt"><span class="lnum"> 79: </span> <span class="rem">/// <example>the term string has a value like 'Term 1|db61b704-cf1d-490d-bfc3-4cbcd8d2f453;Term 2|66b5696d-94a2-4299-ae34-63d3072ca357</example></span></pre>
<pre><span class="lnum"> 80: </span> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> GetTextFromWebPart(WebPart webPart) { <span class="kwrd">return</span> <span class="kwrd">string</span>.Empty; }</pre>
<pre class="alt"><span class="lnum"> 81: </span> </pre>
<pre><span class="lnum"> 82: </span> <span class="rem">/// <summary></span></pre>
<pre class="alt"><span class="lnum"> 83: </span> <span class="rem">/// Sets the textual representation of the selected terms from the Taxonomy control to the WebPart.</span></pre>
<pre><span class="lnum"> 84: </span> <span class="rem">/// </summary></span></pre>
<pre class="alt"><span class="lnum"> 85: </span> <span class="rem">/// <param name="webPart">The parent web part.</param></span></pre>
<pre><span class="lnum"> 86: </span> <span class="rem">/// <param name="selectedTerms">The selected terms.</param></span></pre>
<pre class="alt"><span class="lnum"> 87: </span> <span class="rem">/// <remarks>Override this method in yout child class to link the taxonomy filed with the webpart property</remarks></span></pre>
<pre><span class="lnum"> 88: </span> <span class="rem">/// <example>the term string has a value like 'Term 1|db61b704-cf1d-490d-bfc3-4cbcd8d2f453;Term 2|66b5696d-94a2-4299-ae34-63d3072ca357</example></span></pre>
<pre class="alt"><span class="lnum"> 89: </span> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> SetTextToWebPart(WebPart webPart, <span class="kwrd">string</span> selectedTerms) { }</pre>
<pre><span class="lnum"> 90: </span> </pre>
<pre class="alt"><span class="lnum"> 91: </span> <span class="rem">/// <summary></span></pre>
<pre><span class="lnum"> 92: </span> <span class="rem">/// Called when the user clicks the OK or the Apply button in the tool pane.</span></pre>
<pre class="alt"><span class="lnum"> 93: </span> <span class="rem">/// </summary></span></pre>
<pre><span class="lnum"> 94: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> ApplyChanges()</pre>
<pre class="alt"><span class="lnum"> 95: </span> {</pre>
<pre><span class="lnum"> 96: </span> WebPart webPart = <span class="kwrd">this</span>.ParentToolPane.SelectedWebPart;</pre>
<pre class="alt"><span class="lnum"> 97: </span> SetTextToWebPart(webPart, TaxonomyControl.Text);</pre>
<pre><span class="lnum"> 98: </span> }</pre>
<pre class="alt"><span class="lnum"> 99: </span>}</pre>
</div>
<p>This base class can now be used in a new class, where the configuration of the ToolPart and the linking with the WebPart needs to be implemented:</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">public</span> <span class="kwrd">class</span> TestToolPart : TaxonomyToolPart</pre>
<pre><span class="lnum"> 2: </span>{</pre>
<pre class="alt"><span class="lnum"> 3: </span> <span class="kwrd">public</span> TestToolPart()</pre>
<pre><span class="lnum"> 4: </span> {</pre>
<pre class="alt"><span class="lnum"> 5: </span> <span class="kwrd">this</span>.TermStoreName = <span class="str">"Managed Metadata"</span>;</pre>
<pre><span class="lnum"> 6: </span> <span class="kwrd">this</span>.TermGroupName = <span class="str">"NL"</span>;</pre>
<pre class="alt"><span class="lnum"> 7: </span> <span class="kwrd">this</span>.TermSetName = <span class="str">"Brand"</span>;</pre>
<pre><span class="lnum"> 8: </span> <span class="kwrd">this</span>.MultiSelect = <span class="kwrd">true</span>;</pre>
<pre class="alt"><span class="lnum"> 9: </span> <span class="kwrd">this</span>.Title = <span class="str">"Taxonomy Example"</span>;</pre>
<pre><span class="lnum"> 10: </span> }</pre>
<pre class="alt"><span class="lnum"> 11: </span> </pre>
<pre><span class="lnum"> 12: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">string</span> GetTextFromWebPart(Microsoft.SharePoint.WebPartPages.WebPart webPart)</pre>
<pre class="alt"><span class="lnum"> 13: </span> {</pre>
<pre><span class="lnum"> 14: </span> <span class="kwrd">return</span> ((TestWebPart)webPart).Text;</pre>
<pre class="alt"><span class="lnum"> 15: </span> }</pre>
<pre><span class="lnum"> 16: </span> </pre>
<pre class="alt"><span class="lnum"> 17: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> SetTextToWebPart(Microsoft.SharePoint.WebPartPages.WebPart webPart, <span class="kwrd">string</span> selectedTerms)</pre>
<pre><span class="lnum"> 18: </span> {</pre>
<pre class="alt"><span class="lnum"> 19: </span> ((TestWebPart)webPart).Text = selectedTerms;</pre>
<pre><span class="lnum"> 20: </span> }</pre>
<pre class="alt"><span class="lnum"> 21: </span>} </pre>
</div>
<p>
The only thing you need to do is override the <code>GetToolParts()</code> in your WebPart to inject your custom ToolPart in the ToolPart array, and your ToolPart should work. </p>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-90577966806769015962011-01-23T16:04:00.010+01:002011-04-01T12:42:58.574+02:00Enhanced ASP.NET input sanitation with AntiXSS<h4>Need for input sanitation</h4> <p>The applications you build for the internet can have quite a big audience. It is possible for the whole connected world to visit your website and use the app you built on it. But with these visitors, you will attract dark forces who can misuse your application for their own agenda. It is therefore needed to harden your application, and be sure no-one can send email, inject custom HTML and javascript and hijack user information. It is needed you built secure code and protect yourself.</p><p>The main characteristic of an application is that it needs input data from the end user. With this input data, something is done. If this data is sent back to the user, is can be displayed on the screen. In it most simple form, this looks like:</p> <br /><pre class="csharpcode"><span class="kwrd"><</span><span class="html">div</span><span class="kwrd">></span><br /> <span class="kwrd"><</span><span class="html">asp:TextBox</span> <span class="attr">ID</span><span class="kwrd">="inputBox"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="attr">TextMode</span><span class="kwrd">="MultiLine"</span> <span class="kwrd">/></span><br /> <span class="kwrd"><</span><span class="html">br</span> <span class="kwrd">/></span><br /> <span class="kwrd"><</span><span class="html">asp:Button</span> <span class="attr">ID</span><span class="kwrd">="submitButton"</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="attr">Text</span><span class="kwrd">="Submit"</span> <br /> <span class="attr">onclick</span><span class="kwrd">="submitButton_Click"</span> <span class="kwrd">/></span><br /> <span class="kwrd"><</span><span class="html">br</span> <span class="kwrd">/></span><br /> <span class="kwrd"><</span><span class="html">asp:Label</span> <span class="attr">runat</span><span class="kwrd">="server"</span> <span class="attr">EnableViewState</span><span class="kwrd">="True"</span> <span class="attr">AssociatedControlID</span><span class="kwrd">="resultLiteral"</span> <span class="attr">Text</span><span class="kwrd">="Html output:"</span> <span class="kwrd">/></span><br /> <span class="kwrd"><</span><span class="html">asp:Literal</span> <span class="attr">ID</span><span class="kwrd">="resultLiteral"</span> <span class="attr">runat</span><span class="kwrd">="server"</span><span class="kwrd">></</span><span class="html">asp:Literal</span><span class="kwrd">></span><br /><span class="kwrd"></</span><span class="html">div</span><span class="kwrd">></span></pre><br /><style type="text/css"><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br /><br /><p>With the following button_click code:</p><br /><code class="csharp">protected void submitButton_Click(object sender, EventArgs e)<br />{<br /> string input = inputBox.Text;<br /> string output = input;<br /> resultLiteral.Text = output;<br />} </code><br /><br /><p>With this example code, it is possible to inject javascript into the response. Try pasting <script language="javascript">alert('Hello World!');</script> in the input box and see.</p><h4>Out of the box ASP.NET functionality</h4><p>With the standard ASP.NET setup, the last script example didn’t worked, but threw an exception with the message ‘A potentially dangerous Request.Form value was detected from the client (inputBox="<script language="ja...").’. This is because out of the box, ASP.NET will scan each input parameter to dangerous characters. But don’t let this filter mislead you. The default characters will be the less than character (<) and some ampersand-hash encoded characters. There are also scenario’s you will be switching off the request validation. Simply because some business scenario (maybe you want some html from your user). </p><p>You can switch your validation off for all your pages in ASP.NET in the web.config, or specify ValidateRequest="false" in the page directive for the specific page you want to disable this check (note that in ASP.NET 4, there are some additional steps needed). But don’t rely on request validation to heavily, because there are situations in can’t detect malicious input.</p><h4>Shortcomings of Request Validation</h4><p>Think about the following situation. You want the user of your site to specify the background color of an element on your page, and you use the following submit event:</p><code class="csharp">protected void submitButton_Click(object sender, EventArgs e)<br />{<br /> string color = inputBox.Text;<br /> string output = "<div style=\"width:200px;height:200px;background-color:" + color + ";\">Colored Box</div>";<br /> resultLiteral.Text = output; <br />} </code></p><br /><p>Because the input is directly pasted into an attribute of the div tag, you don’t need HTML directly to inject javascript. The following line will pass through input validation, and inject the page with some potentially evil javascript:<em><br />red;" onclick="alert('Hello World!');" "</em>/</p><br /><br /><h4>Filtering input</h4><p>The first thing to prevent the injection of those unwanted code, is to filter the user input if used for generating output. Standard built-in in ASP.NET is the HttpUtility class with some Encoding methods. They can help with the above two attacks, but it is still possible to inject URL backgrounds in the second example. Because these filters are limited in usage, Microsoft started a new library quite some time ago.</p><h4>AntiXSS library</h4><p>The two main features in the AntiXSS library are the Encoder and Sanitizer classes. Like the HttpUtility, the encoder class has several specific Encoding methods. These methods are a lot more specific than HttpUtility though. In the second example, it is possible filter the color input with a call to Encoder.CssEncode. The output will be CSS encoded into ‘red\00003B\000022\000020onclick\00003D\000022alert\000028\000027Hello\000020World\000021\000027\000029\00003B\000022\000020\000022’. </p><p>The Sanitizer class is even more powerful. It can strip certain HTML tags out of the input. It can transform <em><script language="javascript">alert('Hello World!');</script><strong>bla</strong><img src="bla.gif" /><ul><li>one<li>Two<li>Three</ul></em> into <em><strong>bla</strong><img src="bla.gif"> <ul> <li>one</li><li>Two</li><li>Three</li></ul> </em></p><br /><h4>Install AntiXSS with NuGet</h4><p>AntiXSS used to be a very hidden gem somewhere deep on Microsoft Download or CodePlex. But with the new NuGet, it is on page one of packages. First you need to install NuGet into your Visual Studio. After that, right click your project and choose ‘Add Library Package Reference’. </p><br /><br /><p><a href="http://lh6.ggpht.com/_ZWHxGFTVlMU/TTxDZxKaAJI/AAAAAAAAC3A/H8I-yHrnbKE/s1600-h/image%5B4%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_ZWHxGFTVlMU/TTxDaTkl0BI/AAAAAAAAC3E/yqQ_UbhAyEY/image_thumb%5B2%5D.png?imgmax=800" width="238" height="383" /></a><a href="http://lh4.ggpht.com/_ZWHxGFTVlMU/TTxDa3nEvQI/AAAAAAAAC3I/yP7-9rstWxQ/s1600-h/image%5B8%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_ZWHxGFTVlMU/TTxDbTVJJpI/AAAAAAAAC3M/r-g_79px7mo/image_thumb%5B4%5D.png?imgmax=800" width="566" height="379" /></a></p><br /><p>As of today, AntiXSS is the eighth package in the list. If you click install, all assemblies for AntiXSS will be automatically downloaded and added to your solution. So it won’t be very hard anymore to write really secure code! </p>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com1tag:blogger.com,1999:blog-19906305.post-16416920434962246902010-12-15T22:19:00.002+01:002010-12-15T22:33:11.222+01:00Conversion of a RTF document to PDF with C#In my current project, I need to convert in an easy way RTF documents to PDF from managed code. I don't want to rebuild these documents in PDF, because the RTF's still have some need in the application.<br /><br />After google-ing around for possible solutions, I tried two components: the last version of <a href="http://sourceforge.net/projects/itextsharp/">iTextSharp</a> with RTF support (from version five on, the RTF support is split into a new project and removed from iTextSharp) and <a href="http://www.aspose.com/categories/.net-components/aspose.words-for-.net/default.aspx">Aspose.Words</a>. <br /><br />After a quick conversion with iTextSharp, I understand why RTF support was dropped. The produced PDF was one piece of garbage. The code I used was:<br /><code class="csharp"><br />using (FileStream outstream = File.Create(outFile))<br />{<br /> Document docText = new Document();<br /> PdfWriter writer = PdfWriter.GetInstance(docText, outstream);<br /> docText.Open();<br /> RtfParser rtf = new RtfParser(null);<br /> using (FileStream rtfStream = File.OpenRead(inFile))<br /> {<br /> rtf.ConvertRtfDocument(rtfStream, docText);<br /> }<br /> docText.Close();<br />}<br /></code><br /><br />Aspose.Words worked like a charm, while using only two lines of code:<br /><code class="csharp"><br /> Aspose.Words.Document doc = new Aspose.Words.Document(inFile);<br /> doc.Save(outFile, SaveFormat.Pdf);<br /></code><br />The only drawback is iTextSharp is OpenSource and Aspose.Words isn't. But I guess there isn't another reliable OS alternative.Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-17874030658192515482010-08-19T15:39:00.005+02:002010-08-19T15:48:05.810+02:00VBScript to detect if there is a COM+ application instance runningI had to figure out how to query the COM Administration catalog to detect if there is a specified COM+ application running.<br />Here is the quickly written vbscript:<br /><code class="vbscript"><br />running = False<br />Dim oCatalog<br />Set oCatalog = CreateObject("COMAdmin.COMAdminCatalog")<br />sName = "Tridion Content Manager"<br />Dim result<br />set apps = oCatalog.GetCollection("Applications")<br />apps.Populate<br /><br />For Each app In apps<br /> If app.Name = sName Then<br /> Set objAppInst = apps.GetCollection("ApplicationInstances",app.Key)<br /> objAppInst.Populate<br /> for each inst in objAppInst<br /> pId = inst.Value("ProcessID")<br /> running = not ( inst.Value("IsPaused") or inst.Value("HasRecycled"))<br /> if running then<br /> Exit For<br /> end if<br /> Set objAppInst = nothing<br /> Next<br /> Exit For<br /> End If<br />Next <br />set apps = Nothing<br />set oCatalog = nothing<br />MsgBox pid & " " & running<br /></code>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-6982345244277384652010-08-11T11:34:00.000+02:002016-08-11T11:39:40.942+02:00Migrating Tridion templates from 5.2 to 2009<p>Upgrading a Tridion environment from Tridion 5.2 SP1 to Tridion 2009 SP1 isn’t a straightforward procedure, especially when you have to cope with a lot of custom functionalities. In this post, I write down some experience whith the upgrade of the old templating framework to a new one.</p><br />
<h4>Tridion 5.2 situation</h4><br />
<p>The templating framework used in 5.2 (pre-compound templating) was we built as a ScriptExtension in C#, and this ScriptExtension was registered one in the Tridion MMC snap-in. All the present VBScript based templates call this ScriptExtension with some templating parameters. This templating setup is very easy to deploy (register one dll and you're ready to go),</p><br />
<p>The drawback of this solution was the usage of the Tridion COM API, and the managed to native interop issues you have to deal with (like releasing your references to COM objects), but with Tridion 5.2 (and before that, with Tridion 5.1SP4) it worked. </p><br />
<h4>First try, migrating this solution to 2009 SP1</h4><br />
<p>While building our solution with Tridion 5.1SP4 and 5.2SP1, you had to built the Interop assemblies yourself. With version 2009, Tridion delivered these in the bin\client folder of the Tridion installation. Linking the existing solution to these new assemblies, fixing small API changes and recompiling the whole worked like a charm. But testing the code gave some major issues. The internals of the deployment packages changed for binaries and was killing the custom metadata for indexing purposes. But the whole publishing process became a large memory hog. So it was needed to rewrite the solution (or restart the TDSE process once in a short while). That was basically what was done, the legacy rendering and publishing was ditched for the new way of publishing and rendering content. </p>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-64009027117226656312010-07-05T22:54:00.004+02:002010-07-05T23:00:32.970+02:00Upgraded Certification<img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 236px; height: 80px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhXtC3sMP4N9_jNhAWVtRPby3ru64FaQv7CacRWRyRjn1jH8u0Y7H1ihd1z0QIrp07hT2_R6VI69BAuTaH98DrxAG8KjhBslrsQurcfwkP1i_b4GkneFPRlFVk5XUHILpr0fPZlg/s320/MCPD(rgb)_1372.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5490529561539187858" /> <br />With the new version of the .NET Framework, I needed to upgrade my .NET Certifications to this new version. A couple of months ago, I did the beta versions of these exams, and last week I got the results. I passed all the exams I did. They were not easy, so I was quite surprised to receive all the results positively back.Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-86015253193817608692010-01-18T13:57:00.005+01:002011-08-04T22:29:06.052+02:00Updated XSLT for CC.NET in SharePointJust modded my <a href="http://gruntbuggly.blogspot.com/2008/04/show-your-ccnet-dashboard-in-sharepoint.html">XSLT for viewing the CC.NET status</a> of the buildserver in the XML Webpart of Sharepoint 2007:<br /><br /><code class="xslt" style="color: black; background: white; font-family: Consolas; font-size: 10pt;"><br /><span style="color: blue;"><?</span><span style="color: #a31515;">xml</span><span style="color: blue;"> </span><span style="color: red;">version</span><span style="color: blue;">=</span>"<span style="color: blue;">1.0</span>"<span style="color: blue;"> </span><span style="color: red;">encoding</span><span style="color: blue;">=</span>"<span style="color: blue;">utf-8</span>"<span style="color: blue;">?></span><br /><span style="color: blue;"><</span><span style="color: #2b91af;">xsl:stylesheet</span><span style="color: blue;"> </span><span style="color: red;">version</span><span style="color: blue;">=</span>"<span style="color: blue;">1.0</span>"<span style="color: blue;"> </span><span style="color: red;">xmlns:xsl</span><span style="color: blue;">=</span>"<span style="color: blue;">http://www.w3.org/1999/XSL/Transform</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:output</span><span style="color: blue;"> </span><span style="color: red;">method</span><span style="color: blue;">=</span>"<span style="color: blue;">xml</span>"<span style="color: blue;"> </span><span style="color: red;">encoding</span><span style="color: blue;">=</span>"<span style="color: blue;">utf-8</span>"<span style="color: blue;"> </span><span style="color: red;">indent</span><span style="color: blue;">=</span>"<span style="color: blue;">yes</span>"<span style="color: blue;"> </span><span style="color: red;">omit-xml-declaration</span><span style="color: blue;">=</span>"<span style="color: blue;">yes</span>"<span style="color: blue;"> /></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:template</span><span style="color: blue;"> </span><span style="color: red;">match</span><span style="color: blue;">=</span>"<span style="color: blue;">/</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">table</span><span style="color: blue;"> </span><span style="color: red;">border</span><span style="color: blue;">=</span>"<span style="color: blue;">0</span>"<span style="color: blue;"> </span><span style="color: red;">cellpadding</span><span style="color: blue;">=</span>"<span style="color: blue;">0</span>"<span style="color: blue;"> </span><span style="color: red;">cellspacing</span><span style="color: blue;">=</span>"<span style="color: blue;">0</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">thead</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-viewheadertr</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">style</span><span style="color: blue;">=</span>"<span style="color: blue;">text-align:left;</span>"<span style="color: blue;"> </span><span style="color: red;">scope</span><span style="color: blue;">=</span>"<span style="color: blue;">col</span>"<span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> </span><span style="color: red;">nowrap</span><span style="color: blue;">=</span>"<span style="color: blue;">nowrap</span>"<span style="color: blue;">></span>Project<span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> ></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">style</span><span style="color: blue;">=</span>"<span style="color: blue;">text-align:left;</span>"<span style="color: blue;"> </span><span style="color: red;">scope</span><span style="color: blue;">=</span>"<span style="color: blue;">col</span>"<span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> </span><span style="color: red;">nowrap</span><span style="color: blue;">=</span>"<span style="color: blue;">nowrap</span>"<span style="color: blue;">></span>Status<span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> ></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">style</span><span style="color: blue;">=</span>"<span style="color: blue;">text-align:left;</span>"<span style="color: blue;"> </span><span style="color: red;">scope</span><span style="color: blue;">=</span>"<span style="color: blue;">col</span>"<span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> </span><span style="color: red;">nowrap</span><span style="color: blue;">=</span>"<span style="color: blue;">nowrap</span>"<span style="color: blue;">></span>Last buildtime<span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> ></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">style</span><span style="color: blue;">=</span>"<span style="color: blue;">text-align:left;</span>"<span style="color: blue;"> </span><span style="color: red;">scope</span><span style="color: blue;">=</span>"<span style="color: blue;">col</span>"<span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> </span><span style="color: red;">nowrap</span><span style="color: blue;">=</span>"<span style="color: blue;">nowrap</span>"<span style="color: blue;">></span>Buildlabel<span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> ></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">th</span><span style="color: blue;"> </span><span style="color: red;">style</span><span style="color: blue;">=</span>"<span style="color: blue;">text-align:left;</span>"<span style="color: blue;"> </span><span style="color: red;">scope</span><span style="color: blue;">=</span>"<span style="color: blue;">col</span>"<span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vh2-nograd</span>"<span style="color: blue;"> </span><span style="color: red;">nowrap</span><span style="color: blue;">=</span>"<span style="color: blue;">nowrap</span>"<span style="color: blue;">></span>Activity<span style="color: blue;"></</span><span style="color: #a31515;">th</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #a31515;">thead</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">tbody</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:apply-templates</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">/CruiseControl/Projects/Project</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:sort</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">@name</span>"<span style="color: blue;">/></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:apply-templates</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #a31515;">tbody</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #a31515;">table</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:template</span><span style="color: blue;">></span><br /> <br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:template</span><span style="color: blue;"> </span><span style="color: red;">match</span><span style="color: blue;">=</span>"<span style="color: blue;">Project</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">tr</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:if</span><span style="color: blue;"> </span><span style="color: red;">test</span><span style="color: blue;">=</span>"<span style="color: blue;">position() mod 2 != 1</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">class</span>"<span style="color: blue;">></span>ms-alternating<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:if</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">td</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vb2</span>"<span style="color: blue;"> </span><span style="color: red;">align</span><span style="color: blue;">=</span>"<span style="color: blue;">top</span>"<span style="color: blue;"> </span><span style="color: red;">nowrap</span><span style="color: blue;">=</span>"<span style="color: blue;">nowrap</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:element</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">a</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">onfocus</span>"<span style="color: blue;">></span>OnLink(this)<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">href</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:value-of</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">@webUrl</span>"<span style="color: blue;">/></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">onclick</span>"<span style="color: blue;">></span>GoToLink(this);return false;<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">target</span>"<span style="color: blue;">></span>_self<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:value-of</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">@name</span>"<span style="color: blue;">/></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:element</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:element</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">td</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">class</span>"<span style="color: blue;">></span>ms-vb2<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">align</span>"<span style="color: blue;">></span>top<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">style</span>"<span style="color: blue;">></span>padding-bottom: 3px;<br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:choose</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;"> </span><span style="color: red;">test</span><span style="color: blue;">=</span>"<span style="color: blue;">@lastBuildStatus='Failed'</span>"<span style="color: blue;">></span><br /> color:red;<br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;"> </span><span style="color: red;">test</span><span style="color: blue;">=</span>"<span style="color: blue;">@lastBuildStatus='Exception'</span>"<span style="color: blue;">></span><br /> color:red;<br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;"> </span><span style="color: red;">test</span><span style="color: blue;">=</span>"<span style="color: blue;">@lastBuildStatus='Unknown'</span>"<span style="color: blue;">></span><br /> color:yellow;<br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;"> </span><span style="color: red;">test</span><span style="color: blue;">=</span>"<span style="color: blue;">@lastBuildStatus='Failure'</span>"<span style="color: blue;">></span><br /> color:red;<br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:otherwise</span><span style="color: blue;">></span><br /> color:green;<br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:otherwise</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:choose</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:value-of</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">@lastBuildStatus</span>"<span style="color: blue;">/></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:element</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">td</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vb2</span>"<span style="color: blue;"> </span><span style="color: red;">style</span><span style="color: blue;">=</span>"<span style="color: blue;">padding-bottom: 3px;</span>"<span style="color: blue;"> </span><span style="color: red;">align</span><span style="color: blue;">=</span>"<span style="color: blue;">top</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:value-of</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">substring-before(@lastBuildTime,'T')</span>"<span style="color: blue;">/></span><span style="color: red;">&#160;</span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:value-of</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">substring-before(substring-after(@lastBuildTime,'T'),'.')</span>"<span style="color: blue;">/></span><br /><span style="color: blue;"> </</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">td</span><span style="color: blue;"> </span><span style="color: red;">class</span><span style="color: blue;">=</span>"<span style="color: blue;">ms-vb2</span>"<span style="color: blue;"> </span><span style="color: red;">style</span><span style="color: blue;">=</span>"<span style="color: blue;">padding-bottom: 3px;text-align:right;</span>"<span style="color: blue;"> </span><span style="color: red;">align</span><span style="color: blue;">=</span>"<span style="color: blue;">top</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:value-of</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">@lastBuildLabel</span>"<span style="color: blue;">/></span><br /><span style="color: blue;"> </</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><span style="color: red;">&#160;</span><span style="color: blue;"></</span><span style="color: #a31515;">td</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:element</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">td</span>"<span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">class</span>"<span style="color: blue;">></span>ms-vb2<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">align</span>"<span style="color: blue;">></span>top<span style="color: blue;"></</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">style</span>"<span style="color: blue;">></span><br /> padding-bottom: 3px;<br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:choose</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;"> </span><span style="color: red;">test</span><span style="color: blue;">=</span>"<span style="color: blue;">@activity='Building'</span>"<span style="color: blue;">></span><br /> color:red;<br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;"> </span><span style="color: red;">test</span><span style="color: blue;">=</span>"<span style="color: blue;">@activity='CheckingModifications'</span>"<span style="color: blue;">></span><br /> color:yellow;<br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:when</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:otherwise</span><span style="color: blue;">></</span><span style="color: #2b91af;">xsl:otherwise</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:choose</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:attribute</span><span style="color: blue;">></span><br /><span style="color: blue;"> <</span><span style="color: #2b91af;">xsl:value-of</span><span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">@activity</span>"<span style="color: blue;">/></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:element</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #a31515;">tr</span><span style="color: blue;">></span><br /><span style="color: blue;"> </</span><span style="color: #2b91af;">xsl:template</span><span style="color: blue;">></span><br /><span style="color: blue;"></</span><span style="color: #2b91af;">xsl:stylesheet</span><span style="color: blue;">></span><br /></code>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-91622468570170876452009-10-24T12:00:00.004+02:002009-10-24T12:10:33.992+02:00Getting Hippo Site Toolkit demo to workWhile figuring out Hippo and its architecture, I found some annoying errors in the documentation. While the documentation at http://www.onehippo.org/site-toolkit/home reads: <br /><quote>1. Download the wars, drop them in your Tomcat servlet container and start Tomcat (see in_servlet_container, but with different wars).<br />2. Checkout the HST2 project, start the cms and the site of the demosuite in the buildin Jetty servlet container.<br /></quote><br />So I use Tomcat, and its saying in another page to rename the cms war to cms.war, there is no mention of renaming the site war to site.war. But in the rest of the documentation the assumption is made to use the /site URL. I'm no Tomcat guru, so how should I know that the webapp wars are used as URI shortcuts ;).<br /><br />But that's the main pain in the ass with OSS documentation, it's mostly incomplete. How hard should it be to test your HOWTO for a plain and simple demo. Adding a simple step 1.5: "rename the cms war to cms.war and the site war to site.war" isn't a big deal, but makes a difference of about 1 hour for a Hippo n00b figuring out what's going on!Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com1tag:blogger.com,1999:blog-19906305.post-1266406341969959462009-09-30T10:41:00.005+02:002009-09-30T10:58:12.090+02:00Demo Parallel Extensions .NET 4.0Yesterday I a gave a <a href="http://cid-3ac7786dfaaf4364.skydrive.live.com/self.aspx/Public/VS2010-demo.pptx">presentation/demonstration</a> about the upcoming .NET 4.0 framework release. Unfortunately, there wasn't enough time to show the complete parallel demo. Here I show a couple of ways to display all integers between 0 and 100 that are dividable by 10.<br /><br /><code class="csharp"><br />class Program<br />{<br /> // objects for classic parallel code<br /> static object locker = new object();<br /> static Queue<int> integers;<br /> //with concurrent Queue, we don't need a locker<br /> static ConcurrentQueue<int> concurrentIntegers;<br /><br /> static void Main(string[] args)<br /> {<br /> int steps = 100;<br /> steps.WriteOnConsole(); //extension method to display an integer on the console<br /> Classic(); //classic for loop, no parallel code<br /> ClassicParallel(); //classic parallel invocation<br /><br /> New(steps); //parallel for loop<br /> NewMoreLikeClassic(steps); //parallel the new way, but looks like classic parallel<br /><br /> Linq(steps); //old LINQ way<br /> PLinq(steps); //new Parallel LINQ <br /> }<br /><br /> private static void Classic(int steps = 100)<br /> {<br /> for (int i = 0; i < steps; i++)<br /> {<br /> if (i % 10 == 0)<br /> {<br /> i.WriteOnConsole();<br /> }<br /> }<br /> }<br /><br /> private static void ClassicParallel(int steps = 100)<br /> {<br /> integers = new Queue<int>(steps);<br /> // fill the queue with all integers<br /> for (int i = 0; i < steps; i++)<br /> {<br /> integers.Enqueue(i);<br /> }<br /><br /> int workerCount = 5; //arbitrary number for workercount. <br /> Thread[] workers = new Thread[workerCount];<br /> // Create and start a separate thread for each worker<br /> for (int i = 0; i < workerCount; i++)<br /> {<br /> workers[i] = new Thread(Consume);//.Start();<br /> }<br /> foreach (Thread worker in workers)<br /> {<br /> worker.Start();<br /> }<br /> }<br /><br /> private static void Consume()<br /> {<br /> while (true)<br /> {<br /> int i;<br /> lock (locker)<br /> {<br /> if (integers.Count == 0) return; // run until the queue is empty<br /> i = integers.Dequeue();<br /> }<br /> if (i % 10 == 0)<br /> {<br /> i.WriteOnConsole();<br /> }<br /> }<br /> }<br /><br /> private static void New(int steps)<br /> {<br /> ParallelLoopResult result = Parallel.For(0, steps, (i, loop) =><br /> {<br /> if (i % 10 == 0)<br /> {<br /> i.WriteOnConsole();<br /> }<br /> //With the LoopState, we can break and terminate the processing of the loop<br /> if (i == 50)<br /> {<br /> loop.Break();<br /> }<br /> }<br /> );<br /> Console.WriteLine("Completed: {0}, Breaked at iteration {1}",<br /> result.IsCompleted,<br /> result.LowestBreakIteration);<br /> }<br /><br /> private static void NewMoreLikeClassic(int steps = 100)<br /> {<br /> concurrentIntegers = new ConcurrentQueue<int>(Enumerable.Range(0, steps));<br /> Parallel.Invoke(() =><br /> {<br /> ConsumeQueue();<br /> }<br /> );<br /> }<br /><br /> private static void ConsumeQueue()<br /> {<br /> // note: there is no locking used here, because we use a ConcurrentQueue<br /> int i;<br /> bool success = concurrentIntegers.TryDequeue(out i);<br /> if (success && (i % 10 == 0))<br /> {<br /> i.WriteOnConsole();<br /> }<br /> }<br /><br /> private static void Linq(int steps)<br /> {<br /> Enumerable.Range(0,steps).Where(i => i % 10 == 0)<br /> .ToList<int>().ForEach(i=>i.WriteOnConsole());<br /> }<br /> <br /> private static void PLinq(int steps)<br /> {<br /> Enumerable.Range(0, steps).Where(i => i % 10 == 0).AsParallel()<br /> .ToList<int>().ForEach(i => i.WriteOnConsole());<br /> }<br />}<br /></code>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-32850181418886129532009-09-16T16:36:00.005+02:002009-09-16T16:50:23.324+02:00ASP.NET favicon.ico routing to deep linkAfter seeing some errors in my application log complaining about a non existing business object with id favicon.ico, and being sure that I had a <link href="/resources/images/favicon.ico" rel="shortcut icon" /> tag in my header section, I realized that old non-standard-compliant browsers do a request for the hard-coded /favicon.ico url. So I wanted to add a route in my route table to redirect these requests to the proper icon location. Unfortunately, there is no public StaticFileHandler available with a virtual path in its constructor, so I had to built them myself. The following couple of lines do the trick:<br /><br />Registering the routes in the application startup:<br /><code class="csharp"><br />routes.Add(new Route("favicon.ico", new StaticFileRouteHandler("~/Resources/images/favicon.ico")));<br />// generic, catch-all rule, caused the error for favicon.ico<br />routes.Add(Routes.BusinessObject, new Route(<br /> string.Format("{{{0}}}", RouteParameters.BusinessObjectIdentifier), <br /> new CustomRouteHandler("~/Pages/BusinessObjectDetails.aspx")));<br /></code><br /><br />The StaticFileRouteHandler to serve the the static file from the request.<br /><code class="csharp"><br />public class StaticFileRouteHandler : IRouteHandler<br />{<br /> public string VirtualPath { get; set; }<br /> public StaticFileRouteHandler(string virtualPath)<br /> {<br /> VirtualPath = virtualPath;<br /> }<br /><br /> #region IRouteHandler Members<br /> public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext)<br /> {<br /> HttpContext.Current.RewritePath(VirtualPath);<br /> return new DefaultHttpHandler();<br /> }<br /> #endregion<br />}<br /></code>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com2tag:blogger.com,1999:blog-19906305.post-51666033865838995722009-09-02T22:57:00.000+02:002009-09-02T23:01:26.769+02:00New VS2010 / .NET 4.0 featuresI already love the new <a href="http://msdn.microsoft.com/en-us/library/dd264741%28VS.100%29.aspx">dynamic</a> keyword in VS2010, and missing it in my day to day work with Tridion COM objects. Although the drawback is no IntelliSense in VS on the object, see the following code to get the item title from a Tridion TOM item:<br /><br /><strong>Old code</strong><br /><code class="csharp"><br />object obj = tdse.GetObject(tcmUri, EnumOpenMode.OpenModeView, null, XMLReadFilter.XMLReadAll );<br />string title = null;<br />if (obj is Component)<br />{<br /> Component component = (Component) obj; <br /> title = component.Title;<br />}<br />if (obj is Folder)<br />{<br /> Folder folder = (Folder) obj; <br /> title = folder.Title;<br />} <br />if (obj is Page)<br />{<br /> Page page = (Page) obj; <br /> title = page.Title;<br />}</code><br /><br /><strong>New code</strong><br /><code class="csharp"><br />dynamic tridionItem = tdse.GetObject(tcmUri, EnumOpenMode.OpenModeView);<br />string title = tridionItem.Title;<br /></code><br /><br />Another long-missing-but-finally-added feature is the support of optional COM Interop parameters in C#. Before 4.0, you needed to specify all optional parameters in Interop method calls, even if you wanted to use the default values, leading to extremely long method calls (maybe not in Tridion, but infamous in Office Interop with Type.Missing). These method parameters do now have the block parentheses around them in IntelliSense:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRtnfa3cEqlITpMhjYXM86E6_LNrz87xJ59VGsGH7snypNKzoz57ccs3-dxMdc0jrvj3bVuWv1beFb-UdsTr-EgpUv8vodkkaH7g9MlJLT_eBwbZzLejSbTyf_bVWclX0Mp64ew/s1600-h/VS2010-is.PNG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 676x; height: 24px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRtnfa3cEqlITpMhjYXM86E6_LNrz87xJ59VGsGH7snypNKzoz57ccs3-dxMdc0jrvj3bVuWv1beFb-UdsTr-EgpUv8vodkkaH7g9MlJLT_eBwbZzLejSbTyf_bVWclX0Mp64ew/s800/VS2010-is.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5376971904474434610" /></a>Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-3325510720307707152009-07-15T22:26:00.004+02:002009-07-16T00:02:47.019+02:00Using MySQL Providers with ASP.NET<img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 114px; height: 68px;" src="http://dev.mysql.com/common/logos/logo_mysql_sun_a.gif" border="0" alt="MySQL Logo" /><br />I'm figuring out how to use MySQL with Visual Studio and ASP.NET. The first thing to install (besides MySQL Server) is the <a href="http://dev.mysql.com/downloads/connector/net/6.0.html">MySQL Connector for .NET</a>, currently at version 6.0.4.<br />After installing this connector, you've all the .NET providers and entity framework stuff to go. One thing I should mention is that the .NET Connectors will install MySql providers which you can use in your website, MySql won't popup in the Express editions of Visual Studio. So you can't connect to a MySQL database with your server explorer with these versions.<br /><br />So installing the MySQL connector on your server will modify the server's machine.config and add the provider config in it. Not installing the connector on your server means you need to configure the providers in the system.web section of the web.config of the site (and bin deploying the MySql dll's of course):<br /><code class="xml"><br /> <membership defaultProvider="MySQLMembershipProvider"><br /> <providers><br /> <remove name="MySQLMembershipProvider" /><br /> <add connectionStringName="MySqlServer" enablePasswordRetrieval="false"<br /> enablePasswordReset="true" requiresQuestionAndAnswer="true"<br /> applicationName="/" requiresUniqueEmail="false" passwordFormat="Clear"<br /> maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7"<br /> minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10"<br /> passwordStrengthRegularExpression="" name="MySQLMembershipProvider"<br /> type="MySql.Web.Security.MySQLMembershipProvider, MySql.Web, Version=6.0.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" /><br /> </providers><br /> </membership><br /> <profile><br /> <providers><br /> <remove name="MySQLProfileProvider"/><br /> <add name="MySQLProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.0.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="MySqlServer" applicationName="/" /><br /> </providers><br /> </profile><br /> <roleManager defaultProvider="MySQLRoleProvider"><br /> <providers><br /> <remove name="MySQLRoleProvider" /><br /> <add connectionStringName="MySqlServer" applicationName="/" name="MySQLRoleProvider"<br /> type="MySql.Web.Security.MySQLRoleProvider, MySql.Web, Version=6.0.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" /><br /> </providers><br /> </roleManager><br /></code><br /><br />These new providers need a connection string, so add to your connectionString section:<br /><code class="xml"><br /><connectionStrings><br /> <add name="MySqlServer" providerName="MySql.Data.MySqlClient" connectionString="server=mysql1;user id=webuser;password=xxxxxx;persist security info=True;database=website" /><br /> </connectionStrings><br /></code><br />Next you need the schema. The docs will say they will be created automatically, but I didn't saw a single table created. By looking at the connector source code, I distilled the following script to create the schema in your database:<br /><code class="mysql"><br />CREATE TABLE `my_aspnet_applications` (<br /> `id` int(11) NOT NULL AUTO_INCREMENT,<br /> `name` varchar(256) DEFAULT NULL,<br /> `description` varchar(256) DEFAULT NULL,<br /> PRIMARY KEY (`id`)<br />) ;<br /><br />CREATE TABLE `my_aspnet_membership` (<br /> `userId` int(11) NOT NULL DEFAULT '0',<br /> `Email` varchar(128) DEFAULT NULL,<br /> `Comment` varchar(255) DEFAULT NULL,<br /> `Password` varchar(128) NOT NULL,<br /> `PasswordKey` char(32) DEFAULT NULL,<br /> `PasswordFormat` tinyint(4) DEFAULT NULL,<br /> `PasswordQuestion` varchar(255) DEFAULT NULL,<br /> `PasswordAnswer` varchar(255) DEFAULT NULL,<br /> `IsApproved` tinyint(1) DEFAULT NULL,<br /> `LastActivityDate` datetime DEFAULT NULL,<br /> `LastLoginDate` datetime DEFAULT NULL,<br /> `LastPasswordChangedDate` datetime DEFAULT NULL,<br /> `CreationDate` datetime DEFAULT NULL,<br /> `IsLockedOut` tinyint(1) DEFAULT NULL,<br /> `LastLockedOutDate` datetime DEFAULT NULL,<br /> `FailedPasswordAttemptCount` int(10) unsigned DEFAULT NULL,<br /> `FailedPasswordAttemptWindowStart` datetime DEFAULT NULL,<br /> `FailedPasswordAnswerAttemptCount` int(10) unsigned DEFAULT NULL,<br /> `FailedPasswordAnswerAttemptWindowStart` datetime DEFAULT NULL,<br /> PRIMARY KEY (`userId`)<br />) COMMENT='2';<br /><br />CREATE TABLE `my_aspnet_profiles` (<br /> `userId` int(11) NOT NULL,<br /> `valueindex` longtext,<br /> `stringdata` longtext,<br /> `binarydata` longblob,<br /> `lastUpdatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,<br /> PRIMARY KEY (`userId`)<br />) ;<br /><br /><br />CREATE TABLE `my_aspnet_roles` (<br /> `id` int(11) NOT NULL AUTO_INCREMENT,<br /> `applicationId` int(11) NOT NULL,<br /> `name` varchar(255) NOT NULL,<br /> PRIMARY KEY (`id`)<br />) ROW_FORMAT=DYNAMIC;<br /><br />CREATE TABLE `my_aspnet_schemaversion` (<br /> `version` int(11) DEFAULT NULL<br />) ;<br /><br />CREATE TABLE `my_aspnet_users` (<br /> `id` int(11) NOT NULL AUTO_INCREMENT,<br /> `applicationId` int(11) NOT NULL,<br /> `name` varchar(256) NOT NULL,<br /> `isAnonymous` tinyint(1) NOT NULL DEFAULT '1',<br /> `lastActivityDate` datetime DEFAULT NULL,<br /> PRIMARY KEY (`id`)<br />) ;<br /><br />CREATE TABLE `my_aspnet_usersinroles` (<br /> `userId` int(11) NOT NULL DEFAULT '0',<br /> `roleId` int(11) NOT NULL DEFAULT '0',<br /> PRIMARY KEY (`userId`,`roleId`)<br />) ROW_FORMAT=DYNAMIC;<br /><br />INSERT my_aspnet_SchemaVersion (version) VALUES (4);<br /></code><br /><br />Finally, you can use the ASP.NET Configuration website to configure users. To get only the providers working, it took a whole blog post. The .NET connector for MySQL is still a little bit rough on the edges, but after figuring the above things out, it will work!Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-20595465706527346832009-07-10T17:03:00.004+02:002009-07-10T17:33:09.753+02:00Combining XML documents into one big one with XIncludeI needed to figure out how to include transparently some xml documents into another xml last week. We store our site navigation in one XML, but due to a decentralized management of this file, I need to cut this navigation into different file parts.
<br />
<br />For this, the <a href="http://www.w3.org/TR/xinclude/">W3C XInlude standard</a> was developed. Unfortunately, there is still no support for this in the .NET Framework. The solution is the use the <a href="http://www.codeplex.com/MVPXML">Mvp.Xml library</a> from codeplex, which includes XInclude support. A strong point of XInclude is the fallback possibilities of this standard, so when the included file isn't present, the output is predictable.
<br />
<br />With XInclude, a XML fragment can be included from the original document:
<br /><code class="xml">
<br /><topic name="External Topic" path="/external-topic" id="18442">
<br /> <xi:include href="../../external-topic/navigation.xml"
<br /> xmlns:xi="http://www.w3.org/2003/XInclude"
<br /> xpointer="xpointer(/navigation/*)">
<br /> <xi:fallback>
<br /> <subject name="Fallback Subject" pad="/external-topic/FB"
<br /> id="19672" />
<br /> </xi:fallback>
<br /> </xi:include>
<br /></topic>
<br />
<br /></code>
<br />Where the included XML fragment will be:
<br /><code class="xml">
<br /><?xml version="1.0"?>
<br /><navigation name="External Topic" path="/external-topic"
<br /> id="18442" xmlns:xi="http://www.w3.org/2001/XInclude">
<br /> <subject name="Poll" path="/external-topic/poll" id="19670" />
<br /> <subject name="Text" path="/external-topic/text" id="19671" />
<br /> <subject name="Links" path="/external-topic/links id="19672" />
<br /></navigation>
<br /></code>
<br />While XInclude describes the format of the XML document, we still need a XInclude aware XmlReader. There is one within the Mvp.Xml package. The old XML reading code:
<br /><code class="csharp">
<br /> mXmlDoc = new XmlDocument();
<br /> mXmlDoc.Load(mXmlFile.FullName);
<br /></code>
<br />should be changed to:
<br /><code class="csharp">
<br /> mXmlDoc = new XmlDocument();
<br /> using (XmlReader reader = new XmlIncludingReader(mXmlFile.FullName))
<br /> {
<br /> mXmlDoc.Load(reader);
<br /> }
<br /></code>
<br />The resulting mXmlDoc document representations are equal in both situations. Only the XInclude result includes extra xml:base attributes.
<br />
<br />The resulting XML is:
<br /><code class="xml">
<br /><code style="xml">
<br /><topic name="External Topic" path="/external-topic" id="18442">
<br /> <subject name="Poll" path="/external-topic/poll" id="19670" xml:base="../../external-topic/navigation.xml" />
<br /> <subject name="Text" path="/external-topic/text" id="19671" xml:base="../../external-topic/navigation.xml" />
<br /> <subject name="Links" path="/external-topic/links id="19672" xml:base="../../external-topic/navigation.xml" />
<br /></topic>
<br /></code>
<br />These xml:base attributes can be used to add extra CacheDependencies for the storage of the resulting XML document to the application cache, so the cache will be invalidated as one of the included XML documents change.
<br />Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com0tag:blogger.com,1999:blog-19906305.post-77542030936905119982009-05-04T14:19:00.003+02:002009-05-04T14:23:24.813+02:00Cleanup artifacts in CC.Net with artifactcleanupI got an email from the system admin that the CC.Net buildserver used a lot of diskspace. It turned out that I got 1000 buildlogs for one project on the server...<br /><br />The solution was to configure a artifactcleanup in the cc.config. See the <a href="http://confluence.public.thoughtworks.org/display/CCNET/Artifact+Cleanup+Publisher">CC.Net documentation</a>.Nielshttp://www.blogger.com/profile/11485174861674260723noreply@blogger.com1