Running code analysis on a custom stsadm command gives errors CA0052 and CA0055

When you want to implement a custom stsadm for SharePoint, all you realy have to do is implement the Microsoft.SharePoint.StsAdmin.ISPStsadmCommand interface. Because I develop on a machine with no SharePoint installed, I (only) copy the assemblies I need to develop locally. For the stsadm command I was working on recently (more on this in a future post) I only needed the Microsoft.SharePoint and Microsoft.Office.Server assemblies. Or at least I thought so…

After implementing the functionality I tried running code analysis, and I got two errors:

CA0052 : No targets were selected.
CA0055 : Could not load AssemblyName.

After trying several ways to fix this, I finally compiled the project on a machine with SharePoint installed. At that point, compiling and running code analysis both worked fine. Code analysis then gave a warning that pointed me to the solution of the problem:

CA2123 : Microsoft.Security : Add the following security attribute to ‘ClassName.MethodName(string)’ in order to match a LinkDemand on base method ‘ISPStsadmCommand.GetHelpMessage(string)’:  [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)].

Apparently the attribute requires an extra reference. When I copied that assembly (Microsoft.SharePoint.Security) to my non-SharePoint development machine, all worked correctly. FYI: I did add the attribute code analysis suggested by the way.

A not so clear Visual Studio code analysis message (CA1308)

While writing a custom stsadm command for SharePoint (more on that in a future post) and having to do something based on the command the user typed in, I used ToLower(CultureInfo.InvariantCulture) on the command string to be able to check without the hassle of differences in casing. When I ran code analysis on my project, I got this somewhat cryptic message:

CA1308 : Microsoft.Globalization : In method ‘CommandParser.Run(string, StringDictionary, out string)’, replace the call to ‘string.ToLower(CultureInfo)’ with String.ToUpperInvariant().

So in order to solve a code analysis warning I should change lowercasing a string to a call to ToUpperInvariant? That seems a bit strange, right? Because I was almost sure this could not be a typo, I searched around a bit. When you search for the error number, you get an explanation from Microsoft through the MSDN article Normalize strings to uppercase [1]. Apparently there’s an issue with a small group of characters which are unable to round trip when converted to lowercase. For more information: have a look at Michael Kaplan’s post Get off my (lower) case! (or: Casing, the 1st) which explains it pretty well [2].

Hope this helps some of you ;)

[1] http://msdn.microsoft.com/en-us/library/bb386042.aspx
[2] http://blogs.msdn.com/michkap/archive/2004/12/02/273619.aspx

Unable to connect publishing custom string handler …

After developing a custom Web Service to be hosted in SharePoint (based on this HowTo article on MSDN) and deploying it on a testing environment, I got some entries in the EventLog over there, stating:

Unable to connect publishing custom string handler for output caching. IIS Instance Id is ‘xxxxxxxxx’, url is ‘http://internalsharepointserver/somesubfolder/services.asmx

The PublishingHttpModule trying to cache an unmanaged path seems to be the problem here. When enabled for a custom web application (such as my web service), it causes the eventlog entry each time certain requests like web service calls or static CSS files are made.

The quick solution is to simply remove the PublishingHttpModule for the custom web application. You can do so by editing the web.config file:
<httpModules>
    <remove name=PublishingHttpModule/>
    …
</httpModules>

To completely switch back to all default ASP.NET modules, use these settings in the web.config file:
<httpModules>
    <clear/>
    <add name=OutputCachetype=System.Web.Caching.OutputCacheModule/>
    <
add name=Sessiontype=System.Web.SessionState.SessionStateModule/>
    <add name=WindowsAuthenticationtype=System.Web.Security.WindowsAuthenticationModule/>
    <add name=FormsAuthenticationtype=System.Web.Security.FormsAuthenticationModule/>
    <add name=PassportAuthenticationtype=System.Web.Security.PassportAuthenticationModule/>
    <
add name=UrlAuthorizationtype=System.Web.Security.UrlAuthorizationModule/>
    <add name=FileAuthorizationtype=System.Web.Security.FileAuthorizationModule/> 
    …
</httpModules>

First release: Microsoft SharePoint Administration Toolkit

It’s here: the Microsoft SharePoint Administration Toolkit. This first release contains two tools, both supported on WSS 3.0 and SharePoint Server 2007.

Batch Site Manager
From the “Move, Lock, and Delete Site Collections” page on Applications Management you can schedule bulk operations against site collections in the farm—including moving site collections between content databases (!!).

stsadm extension: UpdateAlert
This command will refresh all alert URLs in a specific site collection, which is extremely important should you change the URL of a web application or after an upgrade.

For more information and links for downloads, have a look at the original article on MSDN: Announcing the First Release of the Microsoft SharePoint Administration Toolkit.

DropDownList SelectedIndexChanged doesn’t trigger UpdatePanel in SharePoint 2007 SP1

A week ago I had a nice page that was hosted in SharePoint and, among others, contained an updatepanel with a dropdownlist in it. Everything worked, and all was well. Because our testers had found some issues we had delivered two newer versions to our development environment. In the last version they found an issue that wasn’t there before: selecting a different value in the dropdown did not only update the updatepanel, but resulted in a complete postback. My first idea was: that’s an easy one, I’ll check the triggers. Boy, was I wrong…

A few hours later, we had everything working again. But rebuilding the entire usercontrol didn’t solve the issue, and neither did changeing all available settings for all controls ;). Weird thing was it did work when outside of a SharePoint environment. After some extensive searching, I found a post on Brian H. Madsen’s blog, called Using DropDownList with an UpdatePanel in MOSS 2007. As it turns out, SP1 introduces a bug for working with dropdownlists, making that the SelectedIndexChanged event isn’t captured by the update panel. Brian’s post contains the code below which, if placed in the page_load, solves this issue:

if (this.Page.Form != null)
{
    if (this.Page.Form.Attributes[“onsubmit”] == “return _spFormOnSubmitWrapper();”)
    {
        this.Page.Form.Attributes[“onsubmit”] = “_spFormOnSubmitWrapper();”;
    }
}

ScriptManager.RegisterStartupScript(this, this.GetType(), “UpdatePanelFixup”,
    “_spOriginalFormAction = document.forms[0].action;_spSuppressFormOnSubmitWrapper=true;”, true);

ModalPopupExtender in SharePoint – part II

As I said earlier, we didn’t test our solution to using the ModalPopupExtender in SharePoint in all situations. Today we made a start to do so. To indicate our successrate: we now use window.showModalDialog with some extra pages…

Lets go through some of the problems we encountered.

  • Placing an UpdatePanel around the entire UserControl (with default settings) makes that the entire UserControl is posted back, even when it is a control inside a nested UpdatePanel that posts back. The ASP.NET controls have no problem with this, but the SharePoint InputFormTextBox set to RichText does. The toolbars are not rendered, and the entire HTML is shown. Setting ChildrenAsTriggers would disable this behaviour (it does with default ASP.NET controls), because in that case only the nested UpdatePanel is posted back. Unfortunately we didn’t get to test that.
  • The SharePoint page layout doesn’t render properly when using the XHTML Transitional doctype. Probably nothing a redesign of the masterpage (and maybe some controls) can’t handle, but it seems you need time and budget for that. ;)
  • The background wasn’t always completely grayed out using the BackgroundCssClass. Sometimes a ribbon of say 10 pixels was shown normal, sometimes the entire background was displayed normal. And clickable! That’s not what we would like to use a modal popup for.

Especially the last problem made us eventually switch back to an oldskool JavaScript solution, although we did mix it with some UpdatePanels. The Ajax modal popup sometimes did its job, but not all of the time. We couldn’t quite put our finger on it. When a solution doesn’t feel stable and there isn’t much time, you should / sometimes have to revert to proven technology. The problems we encountered are solvable, or at least I think so. We didn’t have time to prove they are. At least not this time… ;)

Getting the ModalPopupExtender to work in SharePoint 2007

Getting the ModalPopupExtender from the Ajax Control Toolkit to work (decently) in SharePoint was not exactly a walk in the park. With a default SharePoint installation, the modal popup is partly positioned ‘outside’ of the page (you only see the bottom right part of the popup in the top left corner of the browser). Postbacks are not executed or executed poorly and the page gets garbled up. A possible solution for the positioning of the popup is to set the X and Y property of the ModalPopupExtender. Downside is you never know (for sure) if the popup is positioned inside the visible part of the browser because of things like non-maximized browser, different resolutions and so on.
Today we seem to have solved our issues with the ModalPopupExtender in SharePoint. We haven’t tested it in all scenario’s yet, but we’ll get to that. At this point everything looks the way it is supposed to. And it seems to work, too… ;).

The extra steps we took to make these two play together the way we wanted them to, besides the usual steps to make Ajax work in ASP.NET 2.0, are:

* Because of our setup with close-images that postback (because we have to clear controls and that sort of stuff) and more, we couldn’t use the TargetControlID property for the ModalPopupExtender. Well, we could, but that would result in the background not being displayed properly half the time ;). This can be solved by setting the TargetControlID to a dummy control (like a hidden one) and showing the popup from code.

** We have a usercontrol with several usercontrols in it. This one usercontrol (the parent) was added to a page. The normal (postback) controls on the usercontrols didn’t work after one of the modal popups was shown. And I can image neither would any other ‘normal’ controls on the page, but we didn’t encounter this scenario. The problem was the page would freeze with a message in the taskbar stating ‘The page is busy submitting data to the server’ directly after an Ajax postback. The controls that performed a ‘normal’ postback did nothing: the serverside code just was not executed. We solved this by putting an updatepanel around everything inside the usercontrol. That way the normal controls would postback in an ajaxy way too, apparently solving the ‘The page is busy’ message.

We’ll be testing this solution over the next few days. If any problems pop up, I’ll keep you posted.