Thursday 31 March 2011

Google +1

If you like the "Like" function that sites like Facebook​ implement then you may be interested to know that Google will be launching its own version over the coming weeks in an attempt to make their search results more social.

From what I understand at present, you need to have a Google profile to be able to use the facility, but you'll be able to recommend sites that appear in search results - and at some point in the future offer the same functionality within your public-facing websites.

Read more about it here: http://googlewebmastercentral.blogspot.com/2011/03/introducing-1-button.html?utm_source=feedburner&utm_medium=email&utm_campaign=Feed%3A+blogspot%2FamDG+%28Official+Google+Webmaster+Central+Blog%29

Tuesday 22 March 2011

SharePoint 2010 - Reducing Page Load Size

Having gone round-and-round in circles looking to disprove (and prove to myself) Chris O'Brien's blog article about removing unwanted and unnecessary JavaScript files from SharePoint 2010 when a public-facing website is accessed anonymously, I've basically satisfied myself that there doesn't appear to be any better way to do this.

As Chris explains, SharePoint 2010 includes a whole host of JavaScript files which can bloat a page quite considerably.  In a content author scenario, this isn't so much of a problem as the website will be accessed within an local and closed environment, more-often-than-not, and over the larger bandwidth that usually accompanies this it doesn't always pose a problem.  As soon as a website becomes public-facing, there are many more considerations which not only include bandwidth, but also client capabilities.

Any work that can be done to reduce page size is always worthy of consideration.  In light of this, referring to Chris here again, Microsoft introduced the Script On Demand framework in SharePoint 2010 to attempt to mitigate the page size.  Problem is the scripts still get downloaded, and quite a few, despite this. 

To solve it, Chris came up with a way to remove unnecessary JavaScript files from the list of registered files (which are stored in the HttpContext) but has had to use reflection to achieve this....it's not nice, but seems to be the only way to make it possible.

Here's his article explaining how - definitely worth consideration if performance is a concern.
Continuing on from what Chris has said, another way to reduce the number of server requests is to use the ASP.NET ScriptManager which gets added to the masterpage and combine your own scripts into a single one. for instance you may be loading the base jQuery library as well as one or more plug-ins, plus your own custom JavaScript.  Here's how:
 
<asp:ScriptManager id="ScriptManager" runat="server" EnablePageMethods="false" EnablePartialRendering="true" EnableScriptGlobalization="false" EnableScriptLocalization="true">
    <CompositeScript>
      <Scripts>
        <asp:ScriptReference Path="<%$SPUrl:~sitecollection/Style Library/Scripts/scriptfile_001.js%>" ScriptMode="Release" />
        <asp:ScriptReference Path="<%$SPUrl:~sitecollection/Style Library/Scripts/scriptfile_002.js%>" ScriptMode="Release" />
        <asp:ScriptReference Path="<%$SPUrl:~sitecollection/Style Library/Scripts/scriptfile_003.js%>" ScriptMode="Release" />
      </Scripts>
    </CompositeScript>
</asp:ScriptManager>
 
Remember that doing this removes your files from the list of files used by the ScriptLink control.

Monday 21 March 2011

JavaScript and CSS Combining

Well, there's always someone out there who's gone the extra mile...

If you want to know how to combine JavaScript and CSS into a single file and yuo're looking at performance of public-facing websites, this guy's written​ an article showing how it can be done - and not only that, it's without code:

http://blogs.msdn.com/b/shivap/archive/2007/05/01/combine-css-with-js-and-make-it-into-a-single-download.aspx

Nice idea but might make managing a little more complicated - okay if you have a small development team perhaps.

Friday 18 March 2011

Deploying SharePoint 2007 Solutions - Read-Only Attributes

If, for some strange and mystical reason, you have tinkered with the files delivered by a Solution Package to a server and set them to "read-only"​ [gasps with shock and horror] they will cause the Solution Package to fail when it's retracted, leaving artefacts effectively orphaned on the server.

It means you have to reset the files to remove the "read-only" attribute, redeploy the Solution and start again.

Just as a note, even when files are set to "read-only" when you're creating Solution Package (i.e. straight from TFS) the files are delivered with that attribute removed, probably for exactly the reasons above...

Thursday 17 March 2011

User Solutions (a.k.a Sandboxed Solutions), Web Parts and Web Controls

It's kind of disheartening when you look at User Solutions​ (which is how I'll refer to Sandboxed Solutions), especially if you're looking to use User Solutions to deliver some components that you're intending to hard-bake into a page layout (for instance).

Before I go any further explaining why, here's a nice short article giving a very brief overview of User Solutions from Wictor Wilen:

http://www.wictorwilen.se/Post/Understanding-the-SharePoint-2010-Sandbox-limitations.aspx

Ok, so off we go...

Recently I had an opportunity to look into User Solutions in more detail and found quite a few harsh limitations. My foray into this world came about while I was trying to add a Web Control into a page layout - i.e. hard-baked into the HTML. I had given myself the brief to use User Solutions to deliver all the code to see just how it could be achieved. Needless to say, after trying to add the assembly references into the page layout I tested the page, only to get an error stating that the assembly couldn't be found. Curious, I thought - so I tried and checked and re-checked my code and references to make sure I hadn't got it wrong but it was all to no avail. Then I read Wictor's article and found another article (http://www.elumenotion.com/Blog/Lists/Posts/Post.aspx?ID=109) which is when I had a moment of clarity and understanding.

It was an "of course" moment: user solutions run in their own process - the User Code Worker Process (a.k.a Sandbox Worker Process) outside of the IIS worker process. Pages are initially parsed by the IIS worker process and therefore any references to assemblies are also parsed at this point. Due to the way User Solution assemblies are used, the IIS worker process doesn't really know about them and therefore cannot resolve them - hence the error I was getting.

So that was that: but how can I add a Web Control that's delivered by User Solution into a page layout? Is it even possible? Well, in stepped the SPUserCodeWebPart. To be honest, despite doing the SharePoint 2010 exams, there was no mention of this component - nothing during my revision came up and highlighted this Web Part and yet, to me, it appears to be a fundamental part of the User Solution architecture.

Any way, putting that to one side, I implemented a test Web Part I had written: very simple "Hello world" example and added the necessary properties (Solution ID, Assembly Full Name, and the Type Full Name) to the SPUserCodeWebPart wrapper and there it was - it worked. The reason is works is because of the way the SPUserCodeWebPart makes a call out to the User Code Worker Process which loads DLLs from a separate location to those loaded by the IIS worker process. Each User Code assembly comes with its own web.config file declaring it as a Safe Control (which is why you cannot reference the assembly directly on the page as the IIS worker process knows nothing about these files). The wrapping SPUserCodeWebPart asks the User Code Worker Process to load the declared assembly and type from the specified solution: the work process looks to check the information and then loads the type against the subset of the Microsoft.SharePoint framework. Any errors it encounters, it pumps back up the pipeline.

But what about properties?, I thought. Well, these can also be passed as follows using the SPUserCodeProperty class:




In my Web Part I exposed a string property called "MyValue" and using the SPUserCodeProperty I set that to be "Some text". My Web Part then used that to output in HTML. Simple. Trying a more complex type I tried a custom enumeration passing in the value as my enumeration name and that also worked.

Before this success (which hadn't come about until the tail-end of my investigations) I had decided to try to get a Web Control to work. By it's name alone you can determine that the SPUserCodeWebPart is for use with Web Parts. I did some looking around and reflection and found no alternative for Web Controls and so I tried to use the SPUserCodeWebPart control to wrap a Web Control. To ensure you don't go down the same route, this doesn't work - it appears that you can only use classes that inherit from WebPart and anything else simply won't work.

If I do come across a way to do it, I'll be back.

Thursday 10 March 2011

Using the Xslt List View Web Part for Cross-site Views

As you know, if you try to add a web part to a page, some of the options for web parts allow you to add a view of the lists contained​ in the current site. That's great, but what if you need to add a view of a list that exists elsewhere in the site?

Well, fortunately, this is possible in SharePoint 2010 with the aid of the new Xslt List View Web Part. This web part is a change from the old List View Web Part or Data View Web Part in that it uses XSLT to generate the view you see of columns and headers etc. It's also less hassle to create a view of a list that exists elsewhere in the site.

This is how...

  1. Go to the site where the list you want to use exists and add the web part for it to a page in that site
  2. In SharePoint Designer (SPD) open the page and, using the ribbon, select Web Part Options. On the right you will see an option for "Site Gallery" which saves the web part file to the Web Part Gallery (you cannot export it directly through the UI)
  3. You will be prompted with a question about whether you want the web part view of the list to be relative to the site in which the web part exists or to remain fixed on the current list it is set up to view. Make sure you make the choice that means the web part file is saved and remains fixed to the current list
  4. You can now safely remove the web part from the page and go to the site in which you want to add the view
  5. Using SPD (it must be SPD), open the page you want and add the saved web part from the Web Part Gallery
  6. Check in....your work is done

One note is that the view you get doesn't appear to get updated if you change the source list view.

Anonymous Access and SharePoint

I've recently done some work creating a some public-facing websites using SharePoint 2010. Needless to say, in the scenario of a website that anyone can access we have to obviously rely on anonymous access rather than forcing every user to somehow register and log in.

As a result of this doing work and experiencing some of the pain involved, it's safe to say that there are some areas of SharePoint 2010 that don't quite deliver what you would expect - in fact, one could go so far as to use the word "flake-y" in hushed tones.

Let me set the scenario of Problem One:

In SharePoint 2007, one aspect of content management is how content should be displayed to a content author as opposed to a content viewer. On one hand, the content author may want to see everything in the same way the viewer should see it, however, this is not always true or possible. A content author may have to configure any number of additional options and choices that the viewer of a page will never have sight of so therefore, the balance between author and viewer is slightly skewed.

In light of this skewed balance, we have often implemented different views for an author of a page and a viewer. How we do this in a single page layout, fortunately, has become quite simple by using the misnamed Edit Mode Panel that comes with SharePoint. The Edit Mode Panel has a Page Display Mode property which can be set to Edit or Display and it's this very important control that helps us out and works perfectly.

Moving on to SharePoint 2010 and the same situation, we start to put the Edit Mode Panel in everywhere to help us out - CSS, Field Controls, maybe a bit of JavaScript etc. Everything looks fine until we start looking in anonymous mode. Where's everything gone?

Well looking here: http://svengillis.blogspot.com/2010/06/inconvenient-editmodepanel-control.html and here: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.webcontrols.editmodepanel.aspx (at the comments) quickly tells us there's a problem. Oh dear.

So, moving on to the Problem Two:

One new aspect of SharePoint 2010 is the ability to use LINQ to SharePoint. You un-wrap SPMetal and generate your classes based on your site structure and libraries, and start writing your LINQ queries. Off you go creating your code without a care in the world. And then, anonymous mode again and you start getting some errors. You have a search and dig up some interesting links:

http://blog.mastykarz.nl/sharepoint-2010-linq-doesnt-support-anonymous-users/ and http://jcapka.blogspot.com/2010/05/making-linq-to-sharepoint-work-for.html

So what do you do? Go back to CAML or hack your way around the problem by storing, destroying and then reinstating the HttpContext. Oh dear.

Another one to chalk up, Problem Three:

You want to use the Client Object Model to get some list items back. Fortunately, this isn't something we've had to commercially deploy yet - although perhaps only a matter of time, but is none-the-less another anonymous-mode quirk. I wrote a blog article explaining the issue here:


http://whats-the-sharepoint.blogspot.com/2011/03/anonymous-access-using-sharepoint-2010.html and how to work around it. But once again, it's an anonymous-related issue that unless you do some digging you enter into blindly.

Oh dear, Microsoft.

Here's a more recent one, Problem Four:

Take a Content Query Web Part and use it to display items from a Picture Library or Document Library. Everything is fine. Swap into anonymous mode and suddenly the page is littered with errors and Correlation IDs. “What's going on?”, I hear you ask.

Waldek Mastykarz to the rescue again: http://blog.mastykarz.nl/inconvenient-sharepoint-2010-content-query-web-part-anonymous-access/ on the basis of a find by Paul Galvin here: http://www.mstechblogs.com/paul/sp-2010-cqwp-document-libraries-and-anonymous-users

Now, obviously, you have to add two additional fields to the Common View Fields property of the Content Query Web Part to resolve it, and they are SetDocumentIconUrlAndOnClickString and DocumentIconImageUrl, of course.


Thanks again, Microsoft, and oh dear again.

Last of all, Problem Five:

This isn't so much a problem as a question about how to work around an issue that appears to have been inherited from SharePoint 2007. As you already know there were multiple JavaScript files required in 2007, and with the added Ribbon, there are many more. In anonymous mode, the Ribbon isn't display and therefore its supporting JavaScript doesn't need to be included either. Enter the Script-on-demand framework (SOD). As Chris O'Brien points out, this doesn't resolve everything (and perhaps doesn't resolve "anything"):


http://www.sharepointnutsandbolts.com/2011/01/eliminating-large-js-files-to-optimize.html

It's a hack, an elegant one at that, and does get around the problem that is presented to us. Despite the scripts only being required "on demand" they are still loaded, even for anonymous users. So, hopefully, for the last time we utter: "oh dear, Microsoft".

In Conclusion

My advice is to watch out for anonymous access and go into it open eyed as it's an unavoidable part of public-facing websites. If you don't, you will see it as nasty and dirty and leave you with a feeling of being soiled, rueing the day you ignored my warning. Also, don't be fooled: there are five problems listed here, four of which will relate to every public-facing website we develop, however, there are more. I know of two more problems: one related to Style Library access in anonymous sites which causes the client browser to re-request resources instead of using its cache, and the second related to the Ribbon still being displayed in anonymous mode instead of being completely hidden. I wouldn't be surprised if there were more.

Anonymous Access using the SharePoint 2010 Client Object Model

One of the nice things about the client object model is the ability to ​retrieve items using ECMAScript and thereby making the UX of a public-facing website more dynamic and interesting. Items can be retrieved dynamically from lists within SharePoint 2010 and displayed in interesting ways, customisnig the whole interface if necessary with dynamic XHTML and CSS. However, this is all very well and good in a world of an Intranet / Extranet where users are authenticated, but in the world where you have Anonymous access enabled, the story is not quite the same.

While client-side object model calls do work, they do not work when your user is anonymous. The queries just do not run at all. The reason is quite simply because of a deliberate restriction applied to specific client object model calls in SharePoint 2010.

"What's the point of that?", I hear you say. Well, SharePoint rightly secures certain operations of the client object model to only allow authenticated users. I say "rightly so" because allowing the ability to query items in a list could pose a security threat or breach of data protection (for instance), especially if the list contains sensitive data. The client object model restrictions (of which there are more than one) are applied at a Web Application level which, admittedly, doesn't allow for a great deal of granularity, and can be viewed using the ClientCallableSettings.AnonymousRestrictedTypes property of an SPWebApplication which will display restrictions applied to SPList, SPWeb and SPSite client object model queries. Looking at a default installation of SharePoint you will see that there is a restriction imposed on the GetItems method of SPList objects - it's this that prevents the GetItems method from being used. You can get a list of the restrictions by running the following Powershell script:

param($Identity)
if(-not $Identity) { $Identity = read-host -prompt "Site Collection"}
$site = Get-SPSite -Identity $Identity
Write-Host "Processing..."
$wa = $site.WebApplication
$wa.ClientCallableSettings.AnonymousRestrictedTypes

Fortunately, the position is not untenable and SharePoint 2010, with the help of Powershell, allows us to remove the restriction and thereby allow any client object model calls by Anonymous Users to work successfully. Here's the Powershell script to remove the GetItems restriction:
param($Identity)
if(-not $Identity) { $Identity = read-host -prompt "Site Collection"}
$site = Get-SPSite -Identity $Identity
Write-Host "Processing..."
$wa = $site.WebApplication
Write-Host "Removing the GetItems restriction..."
$wa.ClientCallableSettings.AnonymousRestrictedTypes.Remove([Microsoft.SharePoint.SPList], "GetItems")
$wa.Update()
Write-Host "The operation was completed sucessfully"

It's useful that it's there, but does mean there is a need to balance security against required access. Allowing the GetItems is against all SPList objects across a single Web Application. This means that all client object model calls against any SPList will work within that single Web Application. While this is great it does mean that you do not have the granularity you may prefer in order to only allow a specific list the ability to be queried in this way (bit of a "sledge-hammer-to-crack-a-nut" approach). Therefore, when allowing this, bear in mind it is one-size-fits-all and you will need to ensure that a proper security model is followed for lists that contain sensitive data which may mean breaking inheritence in sites that allow access to anonymous users, in other words, being choosy about what you allow access to.