Wednesday, January 11, 2006

Validation Controls and Webparts

I'm currently working on a project that has a SharePoint webpart with an input form on it. The form has several ASP.NET validator controls on it. The problem begins when I want to modify a webpart's property (not just my webpart) with my webpart on my page. None of the submit buttons work, like 'Ok', 'Apply', 'Cancel', 'Upload', etc. I googled for awhile trying to find a nice easy way to detect that the page was in edit mode but I could not. I found a way to check if my webpart was in edit mode but the problem still would exist if I was editing another webpart or wanted to add another webpart to the page.


So I came up with a custom solution. I wrote a loop routine for all the controls loaded on the Page object and outputted those control IDs. After reviewing the controls loaded on a normal view and edit view of a page, I found that the control named MSOWebPartPage_MenuPostback is loaded to the page only if we are in edit mode. So I wrote a method that recursively searches all the controls loaded to the Page object for MSOWebPartPage_MenuPostback. If the control is found, then I set the validator control's EnableClientScript property to false, otherwise it is set to true. So now the clientside validation is active only when we are not in edit mode. If you do use this technique, you will have to always check that your validator controls validate correctly on the server-side.


Turns out that the above idea wasn't the greatest. Apparently anytime a SharePoint page does a postback, the MSOWebPartpage_MenuPostback control is added. So it does not do an effective job detecting if the page is in edit mode. I however did find the built-in webpart property BrowserDesignMode. This property successfully detects if the page is in edit mode (Modifying a webpart, adding/importing webparts, etc). The rest of the solution works fine with the BrowserDesignMode property replacing the search for the MSOWebPartpage_MenuPostback control.

Friday, January 06, 2006

Handy Tool

A coworker just pointed me to a recently released WinXP power toy. It's called SyncToy. It's nice because you can setup a folder pair (the source and destination folders) and choose the type of synchronization. There are five types of synchronization actions (copied from its own help file):
  • Synchronize: New and updated files are copied both ways. Renames and deletes on either side are repeated on the other.
  • Echo: New and updated files are copied left to right. Renames and deletes on the left are repeated on the right.
  • Subscribe: Updated files on the right are copied to the left if the file name already exists on the left.
  • Contribute: New and updated files are copied left to right. Renames on the left are repeated on the right. No deletions.
  • Combine: New and updated files are copied both ways. Nothing happens to renamed and deleted files.
These allow me to program on my laptop or desktop and keep my files up to date. I also created a shortcut that synchronizes the folder pair that I'm working on the most

"C:\Program Files\Microsoft\SyncToy\SyncToy.exe" -R "SyncPairName"

This will pop open the progress window and it will close again when it's all done syncing. It's a pretty good tool. The only complaint that I have is that there isn't an option to exclude files. It's possible to say that I want only jpg and gif files but not possible to say I want everything but jpg files. Hopefully in the next version...

An XML Serialization Epiphany

I have an object that I want to serialize so that my webapp (SharePoint) can use its properties later. The object (PropertyClass) has a custom collection property that holds objects of BaseClass. Adding the Serialization [Serializable] attribute to each of the class declarations being serialized (ie PropertyClass, CustomCollection, and BaseClass) let me serialize to my heart's content. The problem started when I added a derived class of the BaseClass to the custom collection. Everything would work until the serialization call and then I would get the following error:

The type DerivedClass was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

After a little googling I found that the problem was that the XMLSerializer did not know how to serialize the derived class. After an hour of googling I found that I needed to add an xml attribute to the BaseClass that tells it how to find the derived classes of the BaseClass. Here’s the xml attribute that I applied to the BaseClass:

[System.Xml.Serialization.XmlInclude(typeof(Class.DerivedClass))]
public class BaseClass
{
...

This seemed to allow me to do normal serialization to a file. However, I needed to serialize this class to custom property of a webpart in SharePoint. SharePoint still choked on the serialization call. After a day of googling I finally found a reference to the XML Schema Definition Tool (xsd.exe). By running the below command I was able to see the xml schema that my serialized PropertyClass would create.

xsd MyProject.dll /t: MyProject.PropertyClass

This command creates an xsd file that has the xml for the schema. After looking at the schema for awhile I found that the schema shows the CustomCollection class as an array. Once this epiphany occurred, I remembered from all the googling that I had already done the XmlArrayItem attribute. I added the following to the get/set property for my CustomCollection in the PropertyClass.

// This attribute enables the Collection to be serialized:
[System.Xml.Serialization.XmlArray( "MyCollection" )]
// Explicitly tell the serializer to expect the derived class so it can be properly written to XML from the collection:
[System.Xml.Serialization.XmlArrayItem( typeof(Class.DerivedClass)) ]
public CustomCollection MyCollection
{
get
{
return myCollection;
}
set
{
myCollection = value;
}
}

And voila, everything serialized beautifully. I have since added several other derived classes to the collection and it works wonderfully as long as you add the appropriate XmlArrayItem and XmlInclude attributes.

My First Post

My main purpose for this blog is to provide a place for me to record my ephiphanies/problems/issues with programming and technology issues. I'm a software engineer that works with .Net andMicrosoft SharePoint, so a lot of my posts will be geared to those subjects but I will have anything that tickles my fancy here as well.