Friday, April 23, 2010

First win for Office 2010 (and first fail for office x64)

For some reason I cannot fathom, Word 2007 never jumped to the headers when I clicked them in my book documents. That means that when I opened the document map, and saw the headers I wrote, I could not click on them to navigate to them - which is a very useful function, and for some reason Word 2007 refused to do it for all documents for my book.

Word 2010 just installed, and solved this issue! now I can write more comfortably - thanks Microsoft!

Now for the fail...I installed Office x64 - in hope that it would work better on my Windows 2008r2 machine, utilizing whatever it needed from its 12GB RAM (ok, honestly - I don't actually need 64bit office. this version is meant for excel dark wizards who need more power when working on worksheets bigger than 2GB). However, I almost immediately regretted that choice, as now I cannot use the datasheet view in SharePoint (both 2007 and 2010). This technet article explains that this is because the 64bit version does not support the 32bit activeX that is used by the datasheet view:

"The Edit in Datasheet view functionality is not supported if you install 64-bit Office 2010. However, the functionality is available if you install 32-bit Office 2010. "

But...I am still curious to see how I go with 64bit office. so I will keep it on my 2008r2 server, and install the 32bit version on my windows 7 hyper-v machine (and take my screenshots of the datasheet view from there).

update (30 minutes later): it also appears that you cannot install SharePoint designer (since it is 32bit) on the same machine. lucky my win7 virtual machine is so snappy!

Thursday, April 22, 2010

Error downloading prerequisites for SharePoint 2010

When installing SharePoint 2010 (which I am doing now), if you get an error when installing the prerequisites that it couldnt download the components, make sure your firewall is configured to allow it to download.

I don't know which firewall rule specifically blocks the installer, so I just turned the firewall off, let it finish downloading and installing all prerequisites, and then turned the firewall back on. Done!

Sunday, April 18, 2010

SharePoint 2010 How To book is ready!

If you were worried that you'r pre-ordered book will not arrive on time, you can now relax. I have just sent the first complete draft to the publisher, and seeing how Microsoft is due to release the RTM version of SharePoint 2010 this week or the next, I only have to wait for that to be able to add the images, check what changed and what was fixed, and send my publisher the final draft.
Then it may take a few weeks to go over the entire editing process, but I hope this time it will be faster, and then the book is ready to be bought by you!

Monday, April 12, 2010

Book update and MVP status

8 Chapters down...only 6 to go. I intend to finish the book this weekend - wish me luck!. I am finding out a lot of small things that got changed (improved) in 2010 for the end user, and it is slowing me down - but every such thing only boosts my fondness for this version. If I get some time I will blog about those nice little things.
Also - In case you wondered, My MVP award was renewed again this April. Thank you Microsoft for thanking me!

Thursday, March 25, 2010

A new internet site using SharePoint - indigenous.gov.au

Take a look at the new site - an external facing internet site created for the Australian goverment to spread news about the Indigenous Australian related projects. My company, Extelligent Design, helped build the site which includes such features as tagging (with a custom built tag cloud), content query web parts and jquery picture library slide show components. I have helped write some of the components above as part of my day job.

Update: I was asked what the slide show component is - the answer is not flash, nor sliverlight - but a jquery script called galleryview (http://www.spaceforaname.com/jquery/galleryview/) that we customized for our needs (different CSS, do not show descriptions and so on) and then embedded in a web control that pulls information from a picture library, formats it as a UL list, and then uses script to show it as a slide show. Easy, and accessible - because even if you don't have javascript enabled you see the picture as a UL list (which is shown anyway at the bottom to make it accessible for other people).

Sunday, March 14, 2010

My SharePoint 2010 book available for pre-order

I just noticed that Amazon UK is making my 2010 book available for pre-order.
This is a bit stressful for me, since I have only written 5 chapters so far (out of 14 planned) - I guess I'd better start typing faster!
If you are interested in a end user, how to book that covers all the basics for your end users, have a look at the link, and keep a close watch - I will be posting updates. I can tell you that the book will be very similar in structure to the 2007 book I have already published.

Friday, March 12, 2010

Adding the "Sort by modified date" option to SharePoint 2010 search

By default in SharePoint 2010, the search actions link web part does not show the option to change the sorting order to sort by modified date. However, it is easily added back through the web part's properties. Note that it is now shown as a dropdown and not as a link as it did in SharePoint 2007...

SharePoint Foundation - forcing a search index

If you have SharePoint foundation and you want it to index your sites NOW, all you have to do is go to the service job definitions page and tell the timer job to start.
To do it - open central administration > monitoring>review job definitions>"sharepoint foundation search refresh" and click the "run now" button at the bottom.

SharePoint Foundation - no indexer error

If you have installed just SharePoint Foundation (SPF) and created a site collection before turning search service on (which is off by default when you install SPF), you will get an error "your search cannot be completed because this site is not assigned to an indexer.".
After starting the service it still did not resolve the issue, so I tried to find where to assign the indexer to the site. Before long, I realized that it is not on the site collection settings, nor on the web application settings but instead on the content database setting.
Just go to the manage content databases screen in central management, click on the content database in question (usually WSS_Content) and in the middle of the page there is the option to select a search server.

PS - is anyone else finding it puzzling that the default name for a SPF database starts with WSS? Maybe MS will change that before release?

Friday, February 26, 2010

Web Part architecture - what I had to fix in ChartPart

An important aspect of web part architecture is "redeploy-ability".
Redeploy-ability is when you want to use the web part as part of a site template. When you develop a web part, you need to think of redeployment - since the web part will need to be deployed with a set of pre-configured settings into a new site - the web part's properties. If those properties cannot be set as part of the site template, the web part cannot be redeployed.

Let me use ChartPart as an example.
If you don't already know, there is a project called "ChartPart" in codeplex, that shows lists as charts:
chartpart2-1.png
The web part needs to store a lot of information in its properties when it gets configured. For example, it needs to store the X axis and the Y axis columns. For this, the developer created a property called "XAxisSourceColumns", of type "List<string>". That allowed him to add column names to the list easily in the code.
The problem with this, is that this property has to be stored with the web part, and is required for the web part to work - that means if I export the web part, then I expect that when I import it again, all the settings will be there. With a property of type "List<string>", this will not happen - because the web part system does not know how to serialize a "List<string>" object into XML (a .webpart file) and doesnt export those settings. Then, if you import the web part you just exported, you lost those settings. I recommend storing the information as a simple type (defining the properties as strings for example) for serialization purposes.

A second problem, and one that you can see with a lot of Microsoft web parts as well as ChartPart (for example the Content Query Web Part) is that when a web part is connected to a list, the property stores the list's ID - a GUID, instead of the list name. This is smart - because someone may rename the list, and the ID will remain the same, so the web part will keep working. On the other hand - using an ID means that you lose "redeploy-ability" - since a list's ID gets generated randomly every time the site gets created, if your template has the web part set with a specific ID, then when you create a new site off that template, the web part will be broken - since it will not find a list with that ID in the site.
I recommend you store in the web part both the list's ID and the list's name. This way, if there is a list with the ID that was specified, the web part uses it, and therefore does not break when the list's title changes. But if there is no list with that ID (or no ID was set - which is what we will do in a template), the web part will look for a list with the name that was set - which means it will support redeploy-ability.

Finally, a problem with many web parts that allow linking to objects in other sites is that the site url property often expects a value - and does not support a "this site" option (which I like to add as a blank value). This means again that we lose "redeploy-ability" - since there is no way to configure the web part to look in this new site that was created from the template - the web part expects a link to a site...
I recommend supporting a "leave site url empty for current site" as a minimum requirement for a web part, and if you want to be real good, add support for relative URLs.

So how do we resolve this?


Usually we implement "redeploy-ability" when we start writing the web part - we create properties of type string that are not browse-able, and then create ToolParts that populate them using a good user interface - that gets the list of columns (in this example) from the user, then serializes it into a string that gets saved in the web part. It does mean a bit more effort to serialize the list and deserialize the string - but the end result is that when you export the web part you get what you expected - the serialized property gets stored in the .webpart file.

Supporting "blank" as current site url
In ChartPart to make this change was easy - I looked for all the places that SiteUrl property was used, and changed the code to check if the siteurl property is empty then to use the current site url. This is not as effective as you can make it (a function that gets a SPWeb object would have done it better) but it saved me a lot of refactoring:

string url = this.SiteUrl;
if (string.IsNullOrEmpty(url))
   url = SPContext.Current.Web.Url;
using (SPSite site = new SPSite(url)) 
{
   ...
}

Supporting list names as well as IDs
In ChartPart I added a property called ListName and then made the following modifications to all locations that referred to the list ID:

if(this.ListId != null && this.ListId != Guid.Empty)
   list = web.Lists[this.ListId];
else if(!string.IsNullOrEmpty(this.ListName))
   list = web.Lists[this.ListName];
I also changed the toolpart so that when a user picks a list from the dropdown, both the list ID and the list name gets stored.

Serializing complex type properties

In ChartPart for example, since it was already developed and I had to keep supporting existing web parts that store the information as a list, I couldnt remove the existing properties. However, what I did is add a string property for each one of the "List<T>" properties, that return the serialized value of the "List<T>" property it reflects, and when set it sets the "List<T>" property. Here is an example:

//the original property
[Personalizable(PersonalizationScope.Shared)]
public List XAxisSourceColumns
{
    get;
    set;
}
//this is for supporting exporting and importing the web part (which does not serialize List)
//we will have these as pipe seperated strings.
[Personalizable(PersonalizationScope.Shared)]
public string XAxisSourceColumnNames
{
    get
    {
        if (this.XAxisSourceColumns != null)
        {
            string ret = "";
            foreach (string xAxisColumn in this.XAxisSourceColumns)
            {
                if (!string.IsNullOrEmpty(ret))
                    ret += "|";
                ret += xAxisColumn;
            }
            return ret;
        }
        else
            return "";
    }
    set
    {
        this.XAxisSourceColumns = new List();
        if(!string.IsNullOrEmpty(value))
        {                 
            string[] values = value.Split('|');
            this.XAxisSourceColumns.AddRange(values);
        }                
            
    }
}