Archive

Archive for the ‘Development’ Category

Finding out if SharePoint Objects are Disposed Correctly

February 27th, 2009 RichardWillis No comments

Everyone should know by now that certain SharePoint objects, including SPSite and SPWeb need to be disposed of when you have finished with them or you will get a memory leak. If you want to refresh your memory have a look at the MSDN white papers Best Practices: Using Disposable Windows SharePoint Services Objects on MSDN and Best Practices: Common Coding Issues When using the SharePoint object model.

What you may not know is that there are a couple of tools/techniques which can help you find areas in your code where you are not disposing of objects correctly.

  1. SPDisposeCheck. This is a tool which will analyze your assemblies to search for coding patterns which lead to objects not being disposed correctly. It’s a great tool and worth running regularly on your assemblies.
  2. SPRequestStackTrace registry value. Creating the registry key

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings
SPRequestStackTrace: DWORD = 1

Will cause the SharePoint runtime to log a stack trace everytime a SPRequest object is not disposed of correctly. This will actually pick up all the types of objects not being disposed of as internally the problem with not disposing of them is that they contain a reference to SPRequest.

At this point I have to say thank you to Jared Kahlil who pointed out a memory leak in the SLK by using the second method above and started my research into both of these methods. Unfortunately we can’t use SPDisposeCheck on SLK as it checks to see if the file name begins with Microsoft and if there are any namespaces beginning with Microsoft, and if so ignores the assembly.

Categories: Development, SLK, SharePoint Tags:

WCF – WSHttpBinding and Clock Skew

January 28th, 2009 RichardWillis 2 comments

I was deploying a WCF service and when testing it started to get the following error:

The security timestamp is invalid because its creation time (’2009-01-28T16:18:26.625Z’) is in the future. Current time is ‘2009-01-28T16:11:40.173Z’ and allowed clock skew is ‘00:05:00′.

A quick search of the internet threw light on what the problem was, by default in WCF the clocks on the client and server have to be within 5 minutes of each other. Now this can be controlled if all the machines involved are on the same network, but as soon as you start having clients on other networks, you will get them with bigger time differences than this. After another bit of searching I found that you can control the size of the allowed clock skew. However, you can’t do this with the WSHttpBinding, you have to create a custom binding.

The problem then is that the documentation about doing this in web.config is pretty poor. With a custom binding you start with nothing about your connection set up and have to build it from scratch, which given the complexity of the possble binding is really difficult. I found several posts in newsgroups asking about it, but for a long time couldn’t find a decent answer. Then I stumbled across http://social.msdn.microsoft.com/forums/en-US/wcf/thread/6554776e-4b05-427f-ad6f-5d72c6579746/ and discovered that you could programmatically create the binding, convert it to a custom binding and save it to a configuration file, which will then contain all the settings you need to duplicate your original binding, but within a custom binding where I could then set maxClockSkew.

The code I used is:

public static void Main(){     //Create the custom binding based on your original binding     WSHttpBinding binding = new WSHttpBinding();     binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;     binding.SendTimeout = new TimeSpan(0, 15, 0);     binding.MaxReceivedMessageSize = 65536000;     CustomBinding custom = new CustomBinding(binding);     //Set up the config file to save     Configuration machineConfig = ConfigurationManager.OpenMachineConfiguration();     ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();     fileMap.ExeConfigFilename = "out.config";     fileMap.MachineConfigFilename = machineConfig.FilePath;     Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);     config.NamespaceDeclared = true;     //Save the binding in the config file     ServiceContractGenerator scg = new ServiceContractGenerator(config);     string sectionName;     string configName;     scg.GenerateBinding(custom, out sectionName, out configName);     config.Save();}So from my original binding specification

<wsHttpBinding>    <binding name="SalamanderBinding" receiveTimeout="00:15:00"            maxReceivedMessageSize="65536000">            <security mode="Message">                <message clientCredentialType="UserName"/>            </security>       <readerQuotas maxArrayLength="65536000"/>     </binding></wsHttpBinding>

I got the following custom binding

<customBinding>    <binding name="SalamanderBinding">        <transactionFlow transactionProtocol="WSAtomicTransactionOctober2004" />        <security defaultAlgorithmSuite="Default" authenticationMode="SecureConversation"            requireDerivedKeys="true" securityHeaderLayout="Strict" includeTimestamp="true"            keyEntropyMode="CombinedEntropy" messageProtectionOrder="SignBeforeEncryptAndEncryptSignature"            messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"            requireSecurityContextCancellation="true" requireSignatureConfirmation="false">            <localClientSettings cacheCookies="true" detectReplays="true"                replayCacheSize="900000" maxClockSkew="00:05:00" maxCookieCachingTime="Infinite"                replayWindow="00:05:00" sessionKeyRenewalInterval="10:00:00"                sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="false"                timestampValidityDuration="00:05:00" cookieRenewalThresholdPercentage="60" />            <localServiceSettings detectReplays="true" issuedCookieLifetime="10:00:00"                maxStatefulNegotiations="128" replayCacheSize="900000" maxClockSkew="00:05:00"                negotiationTimeout="00:01:00" replayWindow="00:05:00" inactivityTimeout="00:02:00"                sessionKeyRenewalInterval="15:00:00" sessionKeyRolloverInterval="00:05:00"                reconnectTransportOnFailure="false" maxPendingSessions="128"                maxCachedCookies="1000" timestampValidityDuration="00:05:00" />            <secureConversationBootstrap defaultAlgorithmSuite="Default"                authenticationMode="UserNameForSslNegotiated" requireDerivedKeys="true"                securityHeaderLayout="Strict" includeTimestamp="true" keyEntropyMode="CombinedEntropy"                messageProtectionOrder="SignBeforeEncryptAndEncryptSignature"                messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"                requireSecurityContextCancellation="true" requireSignatureConfirmation="false">                <localClientSettings cacheCookies="true" detectReplays="true"                    replayCacheSize="900000" maxClockSkew="00:05:00" maxCookieCachingTime="Infinite"                    replayWindow="00:05:00" sessionKeyRenewalInterval="10:00:00"                    sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="true"                    timestampValidityDuration="00:05:00" cookieRenewalThresholdPercentage="60" />                <localServiceSettings detectReplays="true" issuedCookieLifetime="00:15:00"                    maxStatefulNegotiations="128" replayCacheSize="900000" maxClockSkew="00:05:00"                    negotiationTimeout="00:01:00" replayWindow="00:05:00" inactivityTimeout="00:02:00"                    sessionKeyRenewalInterval="15:00:00" sessionKeyRolloverInterval="00:05:00"                    reconnectTransportOnFailure="true" maxPendingSessions="128"                    maxCachedCookies="1000" timestampValidityDuration="00:05:00" />            </secureConversationBootstrap>        </security>        <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"            messageVersion="Default" writeEncoding="utf-8">            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"                maxBytesPerRead="4096" maxNameTableCharCount="16384" />        </textMessageEncoding>        <httpTransport manualAddressing="false" maxBufferPoolSize="524288"            maxReceivedMessageSize="65536000" allowCookies="false" authenticationScheme="Anonymous"            bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"            keepAliveEnabled="true" maxBufferSize="65536000" proxyAuthenticationScheme="Anonymous"            realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"            useDefaultWebProxy="true" />    </binding></customBinding>

and I just needed to change the maxClockSkew values.

You do need to set the clock skew on the client and server sides.

Easy when you know how.

Categories: Development Tags:

Support to Preview Extra File Types in Outlook 2007 or Vista

January 27th, 2009 RichardWillis No comments

If you use Outlook 2007 you probably already know that you can preview attachments from within Outlook. However, the built in support in fairly limited, being restricted to common types like office files, video and audio files.

However, this list is extensible using custom preview handlers. If you search on the internet for Outlook 2007 file previewers there’s a lot of hits. I’ve just downloaded some sample ones from a MSDN magazine article. Now I can preview files such as xml and pdf from within Outlook without saving them to disk and then re-opening them.

There’s more information at My Digital Life.

Windows Explorer in Vista can also take advantage of the same handlers if you turn on the Preview pane under Organize | Layout. I’ve now got this turned on and am finding it really useful as I generally have a lot of xml files which I need a quick look into.

So an example of previewing an xml file in Outlook is:

Categories: Development Tags:

Screen Capture in Vista and Server 2008

December 18th, 2008 RichardWillis No comments

Windows Vista and Windows Server 2008 come with a very handy utility for capturing the screen shots and saving them. It’s called the Snipping Tool and can capture almost any region you want. You’re not just limited to the whole screen and the current window like you are with the Print Screen button, you also have the options of rectangular select (the one I use most) and free-form snip.

It’s also got a couple of basic editing tools such as pens and highlighter.

I use it all the time when I need screen shots. Just type snip into the start menu and it will appear in the list at the top.

Enjoy.

Categories: Development Tags:

Take Ownership and Full Control of Folders in Vista

December 18th, 2008 RichardWillis No comments

Every now and then an automatic update fails and leaves a directory in the c: drive with a Guid for a name, along the lines of C:\3baf1f42abd933d331f0d49f. The most annoying thing about these is that you can’t delete them, even when running as administrator. This is because the SYSTEM account owns them and no-one else has any permissions on them.

To manually delete them, you need to take ownership and then give yourself permission on every folder and file individually. This obviously would take forever, so a scripting solution is required. I finally came up with this solution:

1.    Run PowerShell as administrator.
2.    Navigate into the root of the folder to process.
3.    Take ownership of all the files and folders by running

gci -r | %{takeown /f $_.FullName}
This gets all files and folders below the current directory, then for each one runs takeown filename. Takeown is a utility which comes with Vista.

4.    Once you have ownership you need to run icacls on all the files to get permissions on them. icacls is the Vista and Server 2008 replacement for xcacls. The command to run is:

gci -r | %{icacls $_.FullName /grant:r username:F}
username is either you log on name on a stand-alone machine or domain\accountname in a domain.

5.    Once you have permissions you can then run del -r

I found most of this information from Christopher Atkins blog.

Categories: Development Tags:

Adding a CSS Stylesheet to a Web Part

December 10th, 2008 RichardWillis No comments

This is something that you would think would be really easy, after all you should always separate the styles out from your code. However, I had great difficulty finding anything on the web about it. I finally managed to crack it and am posting it here for others to find.

Basically you can add an HtmlLink control to the Headers collection of the page.

        ///<summary>Adds the stylesheet to the page.</summary>
        void AddStyleSheet()
        {
            string url = “~/_layouts/misWebParts/misWebParts.css“;
            foreach (Control control in Page.Header.Controls)
            {
                HtmlLink link = control as HtmlLink;
                if (link != null)
                {
                    if (link.Href == url)
                    {
                        //Already added
                        return;
                    }
                }
            }
            HtmlLink cssLink = new HtmlLink();
            cssLink.Href = url;
            cssLink.Attributes.Add(”type“, “text/css“);
            cssLink.Attributes.Add(”rel“, “stylesheet“);
            Page.Header.Controls.Add(cssLink);
        }

The code is for the School MIS web parts I’m working on. The stylesheet is deployed to the layouts directory so we can reference it via the url above. You need to check to see if the link has already been added as usually there’s going to be more than one MIS web part on the page.

Categories: Development, Web Parts Tags:

Easily add a dll to the GAC

December 8th, 2008 RichardWillis No comments

Sometimes you need to quickly add a dll to the Global Assembly Cache (GAC) – usually when you need it to run with full trust rather than limited trust in an ASP.net or SharePoint setting. The quickest way to do this from any computer is just to drag and drop the assembly onto c:\windows\assembly which will automatically install it in there. You’ll need to do this from two instances of Windows Explorer for some reason. Open one at c:\windows\assembly, then find the dll in another one and drag and drop it. You’ll need to restart IIS (iisreset at the command line) if it’s for ASP.net or SharePoint.

If the assembly is already in there you’ll need to delete it first – right-click and Uninstall or highlight and press delete, as it won’t automatically overwrite an existing one.

Categories: Development Tags:

IIS7 – The request filtering module is configured to deny a request that exceeds the request content length.

November 12th, 2008 RichardWillis 1 comment

While testing some SCORM content in the Basic Web Player which comes with SLK I came across this error when trying to upload a large file.

Error Summary

HTTP Error 404.13 – Not Found

The request filtering module is configured to deny a request that exceeds the request content length.

Detailed Error Information

Module RequestFilteringModule
Notification BeginRequest
Handler PageHandlerFactory-ISAPI-2.0
Error Code 0×00000000
Requested URL http://localhost:80/basicwebplayer/UploadPackage.aspx
Physical Path C:\working\slk\Samples\BasicWebPlayer\UploadPackage.aspx
Logon Method Not yet determined
Logon User Not yet determined

Most likely causes:

  • Request filtering is configured on the Web server to deny the request because the content length exceeds the configured value.

Things you can try:

  • Verifytheconfiguration/system.webServer/security/requestFiltering/requestLimits@maxAllowedContentLengthsetting in the applicationhost.config or web.config file.

It’s actually a nicely detailed error message. The problem is that be default IIS7, certainly on Vista, blocks large files at the web server level as well at the application level as part of the request filtering chain. This overrides the maxRequestLength value in the applications web.config file.

To resolve this you need to add the following to your web.config file directly under your configuration node:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength=”2147483648″/>
</requestFiltering>
</security>
</system.webServer>
However, by default you cannot change this on a per application basis,and so need to modify the application.config file in%Windows%\System32\inetsrv\config. The easiest way to do this is torun, in a command prompt running as administrator,
%windir%\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/security/requestFiltering

Categories: Development Tags: