Wednesday, August 4, 2010

Measuring performance from the user's point of view

Check this javascript, boomerang.

In their own words:

"boomerang is a piece of javascript that you add to your web pages, where it measures the performance of your website from your end user's point of view. It has the ability to send this data back to your server for further analysis. With boomerang, you find out exactly how fast your users think your site is."

Sounds like a great tool for performance check.

Tuesday, June 29, 2010

SharePoint 2010 + ADFS 2.0

A client wants us to provide them with an intranet site, in which several organizations are able to work together, but without adding any trust between their independent AD's.

The solution was to use ADFS 2.0. There is a lot of information going on, but I found it quite hard to find exactly what I wanted, in an easy and fast manner.

Here it is for you:

Friday, June 25, 2010

Send custom Response on Page_Load

Ever had a scenario where you'd like to stop the current Response and give an entirely different one?

From ASP.Net 2.0++, you'll have to not only do a Response.End(), but before that a HttpContext.Current.ApplicationInstance.CompleteRequest();

Why? Because Response.End() no longer stops the page processing, so if you, for instance, are sending a file to the response stream, for some reason, it will get the page's HTML in the end of the file's contents.

Special thanks to a post by Rick Strahl, here.

Monday, May 17, 2010

First error on SharePoint 2010

...wasn't in the instalation!! :)

I got several "File Not Found" exceptions while acessing system pages. The reason: webapp was created with the hostname being the server name and did not include the domain (which was being used in the external access).

Just add the URL with the domain to the AAM and it's solved!

Monday, March 22, 2010

SharePoint Variations

Lots of bad things can happen with variations. The main point is: you can, for some reason, move or delete a site/page in one of the labels and the system will get corrupted.

The most typical cases I found were: deleting a site in a secondary label, then later trying to recreate that label variation of the site (which has subsites). Some of the subsites wouldn't be created, since there was still some garbage in the Relationships List from the previous entries (that got deleted).

Be very careful when messing with this hidden list. After deleting some wrong entries of the subsite/pages, I managed to recreate it. A tip: look for the name of the page specifically, since I found entries that were misplaced in the Pages library of the parent site. Apparently because of the first failure, when the procedure failed to create the variation of the subsite (I'm not sure about this one, but I doubt the page was ever created in that place).

There is also a great program, by Tim Dobrinski, called Variations Editor, available here on CodePlex and described here by him. It will check for problems with variations through your portal. It seems very efective. After detecting the errors, it also makes suggestions on how to fix it and can directly apply the fixes on your portal. It doesn't seem to detect the above situation (list entries of pages that no longer exist), but it will detect any incoherent behaviour in the data found about existent pages.

Great tool!

Wednesday, March 17, 2010

Re-activating a feature with scope Web

Ever had a feature activated in several subsites, needing to be re-activated?

Uninstall / install feature will not work. But this command from Gary Lapointe will: gl-activatefeature (more information here).

It will perform the deactivate and activate in all subwebs, if you provide the command with the base site collection url. You can also define that only the webs with the feature already activated will have this re-activation done (using -ignorenoactive).

(Yet another) great command!

ErrorWebPart instead of SummaryLinkWebPart

I was working with some custom development where I needed to import some webpart from a top level page. This was done in 2 stages:

  1. it would start as the execution of a user button's action, i.e. the user would have a page to explicitly execute some code, including the webpart import.
  2. some event handlers would also trigger this same action, i.e. whenever someone checked in a pre-determined page.
In the first case, everything went fine. The webparts were successfully imported.

In the second case, the SummaryLinkWebPart would not be imported. Actually, the SPLimitedWebPartManager would not return a SummaryLinkWebPart, but a ErrorWebPart. It was a customized SummaryLinkWebPart, with a non-default MainXslLink, ItemXslLink and so on...

Apparently, the SPLimitedWebPartManager (or the SummaryLinkWebPart) need to have a request/context set in order to create/return the correct WebPart. Since in an Event Handler (or Timer Job) those objects are not created by default, it would return you that error object.

To make things worse, my code would return a "No parameterless constructor" exception on that ErrorWebPart, which got me in the wrong way to start with.

How to solve it? Just create the necessary objects, before getting the webparts from the SPLimitedWebPartManager:

HttpRequest request = new HttpRequest("", destinationWeb.Url, "");
HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
HttpContext.Current.Items["HttpHandlerSPWeb"] = destinationWeb;

where destinationWeb is the web where the page you are importing webparts to is located (and perhaps it can actually be any web).

Don't know what really happens inside the Microsoft code to cause this behaviour, but I'm guessing it is some use of SPContext.Current to get a SharePoint object (like CurrentWeb).

Best SharePoint links

Highlighted content: STSADM/PowerShell Commands

(currently being edited with my favorite resources)

Friday, March 12, 2010

Stupid things in SharePoint 2007 API

For future reference:
  • ItemDeleted event receiver has no information whatsoever on the item that was deleted (quite useful then!)
  • SPWeb.GetFile(string) returns a SPFile object without the correct data (namely Exists and Length properties); using SPWeb.GetFileOrFolderObject(string) on the other hand, after instantiation, does return a valid and correct SPFile object
  • Also on the previous topic, you should always use the web where your file is! Using RootWeb may or may not work well (I have experienced this!). In my case, I was using RootWeb.GetFileOrFolder() / RootWeb.GetFile() and then file.OpenBinary() would return as exception of File Not Found. Using FileWeb.GetFileOrFolder() worked perfectly! As a confirmation of the strange behaviour, in an external console app, RootWeb.GetFileOrFolder() was working!
  • Event Handlers and Timer Jobs do not have request/context objects, that can sometimes be needed so that API methods work correctly and return what you expect (see this post)

(updated everytime I find "funny" things)

TechDays 2010 Lisbon, Road to SharePoint 2010, and more!

I will attend TechDays 2010 Lisbon, 20-22 April. I will try to attend every SharePoint session, and some Visual Studio ones too.

Another great initiative (that unfortunatelly I have not been attending), also for portuguese people, is Road to SharePoint 2010. Some good presentations already have their slides there. Not close to being in the presentation itself, but worth looking into.

There is also a great portuguese community site, Portuguese SharePoint Community, recommended to all portuguese SharePoint developers/architects out there!

Thursday, March 11, 2010

Google maps tips

Getting the current langitude and latitude of the map center while in Google Maps is always useful, just put in your browser's location url: javascript:void(prompt('',gApplication.getMap().getCenter()));

I have also been using clustering to show a set of gmarkers on the map, so that zooming in/out still gives us interesting information, instead of just a bunch of markers all over the place. The library we used was this one: Really good!


Monday, March 8, 2010

SharePoint 2010 oficial release - May 12th

Microsoft has announced the official release of the new SharePoint version, in the Microsoft SharePoint Team Blog, in this post by Arpan Shah.

This should be a very interesting landmark.

I've been quite busy in a MOSS 2007 project, but I'm planning to get my hands on 2010 in the next few weeks and also attend TechDays 2010, here in Lisbon. From what I've seen, it seems like another huge step for SharePoint, both from the user point of view, but also (this time) for the developer too. Let's hope everything is as nice as it seems at first look.

I only saw some webcasts from Microsoft people, so I think that it might be in fact a great improvement for developers, but I'm guessing (like in 2007) there will still be many tricks to learn, not before some hours of pain. Let's pray for me to be wrong.

Monday, February 22, 2010

Anonymous access - login prompt

All SharePoint developers building WCM sites have probably run into this problem: anonymous access being prompted for login. Usually the SharePoint tools (namely Manage Content and Structure) should be enough to find the "offending" objects (with no published version), but sometimes they just tell you there are no drafts in the portal (although you do know there are).

The plausible reason I found for this is when you define specific permissions per web. Even if your user is site admin, apparently SharePoint does not crawl those webs searching for items matching that view.

The scenario where I got this behaviour was a multilingual site with several first level sites, each with specific permissions, since each one represented a company's unit, each with different editors.

Goggling it, I also found a page that provided me with a very useful way of finding them:


Monday, January 25, 2010

Performance optimizations

In the last days, I have been working on the final optimizations of a WCM site that will be released soon.

It's never late to remember two of the most important optimizations, in my opinion:

1. Assure that all images, CSS's, JS's and other static content have their cache definitions correct. The client browser should receive the information of the expire date correctly (and set to something like 365 days).

How to check this? Use Fiddler or Firebug (Net tab). If you refresh a page and still get requests sent to the server regarding static content (that receive 304 Not Modified replies) then you have a problem.

The more static content your page loads, the bigger the problem is, since your browser will check changes with the server for every file (therefore, 1 useless request per file).

This is probably the most important checkup you must do, since by default, for example, SharePoint will NOT cache the files in the Styles Library (known bug). Regarding this, I suggest you read a post by Chris O'Brien here.

2. Avoid loading SharePoint files in a fully customized frontend anonymous site

Anonymous users usually don't need the core.js/core.css/etc. These files are heavy and should be avoided

Webpart maintenance

If you are having trouble with some webparts or just want to perform some maintenance actions like closing or re-opening a webpart, you should check the webpart maintenance page, acessible everywhere by addint "?contents=1" to your page URL.

Can also be used for page layouts that have built-in webparts.