Idera Acquires Sonar from BinaryWave BinaryWave Announces SharePoint Performance Optimization Service
|
|
|
|
|
|
Home > Blogs > Eric Shupps
|
|
The new home of The SharingPoint blog. Refer to the previous URL(http://sharingpoint.blogspot.com) for older posts.
|
|
|
2/9/2010We're now only a couple of months away from the upcoming SharePoint Evolution 2010 conference in London, England. Last year's Best Practices event was one of the best conferences I've ever attended or spoke at. The venue is fantastic – right across from the Houses of Parliament and Westminster Abbey. The Combined Knowledge crew does a great job of organization and production. Best of all, there's tons of content from speakers who come from every corner of the globe.
I'll be presenting two sessions at the conference. The first,
Customizing the Visual Studio 2010 SharePoint Deployment Process, is a repeat of my talk at SharePoint Conference 2009. The second, Unit Testing SharePoint, is a highly anticipated slugfest on Unit Testing between myself and the always-entertaining Andrew Woodward. I'm teasing a bit – Woody and I are good friends and share a lot of the same views on Unit Testing (as in, do it, no matter which camp you're in). It's going to be a lot of fun to share the stage with Woody and banter about SharePoint testing. Believe me, you don't want to miss this one!
As with last year, I will be conducting an unofficial "Redneck Tour of London" for all the US folks who've never been to London before (and anyone else who wants to tag along). As my adopted second home city, I'm pretty familiar with all the tourist spots in London, along with a few off-the-beaten-path locations that most folks never get to see. We'll be doing some of the standard attractions, including Parliament, Westminster Abbey, Buckingham Palace, The Tower of London, St. Paul's Cathedral, Horse Guard's Parade, Tower Bridge, Trafalgar Square, and the like, but we'll also branch out and do some other fun stuff, like the Jack the Ripper Ghost Walk, the HMS Belfast, Covent Garden, Shakespeare's Globe Theater, Benjamin Franklin House and the London Dungeon. Or anywhere else we all feel like going on a whim. Not to mention all the pubs and restaurants I'm well acquainted with J It'll be two full days of fun in London after the conference, so if you're planning on coming over be sure to stay through the end of the week. Trust me, nothing is quite so entertaining as watching a gaggle of tourists follow a redneck in big black hat around town. It's worth coming along just to watch the locals react!
Be sure to hit the conference site and register if you plan on attending. This event WILL sell out and you don't want to miss it.
See you in London!
2/2/2010
Part One of this series gave a general overview of SharePoint 2010 code deployment using Visual Studio 2010. Part Two described the creation and use of SharePoint Commands. In this installment we will explore SharePoint Deployment Steps and their relationship with both SharePoint Commands and SharePoint Deployment Configurations.
Introduction
A Deployment Step defines the order in which custom commands are called and which commands are associated with the required CanExecute and Execute methods. As with SharePoint Commands, a Deployment Step may be referenced by numerous Deployment Configurations and are surfaced in the SharePoint configuration page of the project properties. They can be explicitly defined as part of an immutable configuration or mixed and matched within design-time configurations specified by the developer.
Continuing the previously established scenario, in which we created custom SharePoint Commands to remove orphaned List Instance objects from a site after updating the associated List Template, the next step in the process is to create a SharePoint Deployment Step which calls the custom commands. For all intents and purposes, a custom Deployment Command is simply a pointer which allows users to select a specific piece of functionality in the configuration settings and bundle one or more sets of functionality into a packaged Deployment Configuration. In our example, the new Deployment Step will call our DeploymentCommands.SPCommand.ListExists and DeploymentCommands.SPCommand.DeleteLists custom commands when the developer adds it to a configuration and deploys the solution within Visual Studio 2010.
Setting Up the Project
As mentioned previously, SharePoint Commands must be compiled using the .NET 3.5 Framework since they reference the core SharePoint 2010 assemblies; however, Deployment Steps and Deployment Configurations both require .NET Framework 4.0. In order to account for the different platform requirements, we must add a new project to the solution which will contain classes for both steps and the configuration. The final VSIX package, which will be created in a third project, will bundle both sets of assemblies together for activation within Visual Studio.
Begin by opening the Contoso.CustomDeployment solution and adding a class project with a namespace of Contoso.DeploymentSteps (the project should default to the .NET 4.0 Framework):
Writing the Code
The Deployment Step performs two functions: 1) Calling the DeploymentCommands.SPCommand.ListExists method to determine if any lists of the specified type in the target site exist, and 2) If any do exist, executing the code contained in the DeploymentCommands.SPCommand.DeleteLists method to remove them before re-deploying the solution. Deployment steps must include an ExportAttribute of Type IDeploymentStep and reference the Microsoft.VisualStudio.SharePoint.Deployment and System.ComponentModel.Composition namespaces. Furthermore, each Deployment Step has a collection of IDeploymentStepInfo parameters which describe the step, specify its display name and provide a message to be displayed in the Visual Studio IDE status bar while executing.
Attributes and Naming Conventions
As with SharePoint Commands, Deployment Steps are referenced by their literal string name which is defined as part of an attribute decoration on each class. There are no explicit rules pertaining to naming conventions; however, as the use of custom Deployment Steps grows within a development team it may be necessary to enforce some kind of explicit notation. For this example we will use a dotted hierarchy which includes the namespace but this is simply an arbitrary choice and has no bearing on the overall functionality.
Methods
Begin by creating the RemoveListInstances class and include the necessary attributes. Bear in mind that the name applied in the DeploymentStep attribute will be used later in the Deployment Configuration to reference the step:
|
using System; using Microsoft.VisualStudio.SharePoint; using Microsoft.VisualStudio.SharePoint.Deployment; using System.ComponentModel.Composition;
namespace Contoso.DeploymentSteps { [Export(typeof(IDeploymentStep))] [DeploymentStep("Contoso.DeploymentSteps.RemoveListInstances")] class RemoveListInstances : IDeploymentStep {
} } |
Before moving on to the actual methods, it will be necessary to define a variable for the Feature ID of the List Template Feature created in the Contoso.CustomLists project (refer to the code samples in Part Two of this series). The GUID for the Feature can be located by opening the Contoso.CustomLists.Orders.Feature and clicking on the "Manifest" option in the Feature Explorer – this exposes the underlying XML from which the ID may be copied. In addition, we will also define the IDeploymentStepInfo parameters:
|
…
class RemoveListInstances : IDeploymentStep { private string definitionFeatureId = "2190859b-344a-4e97-8ba9-f59537e202f6";
public void Initialize(IDeploymentStepInfo stepInfo) { stepInfo.Name = "Remove List Instances"; stepInfo.StatusBarMessage = "Deleting lists..."; stepInfo.Description = "Removes all list instances associated with the specified list template."; } }
… |
The first method to be defined invokes the DeploymentCommands.SPCommand.ListExists method within the custom Deployment Command class by its attributed name and passes in the value stored in the definitionFeatureId variable. Execution of the command is achieved by utilizing the ExecuteCommand of the IDeploymentContext and ISharePointProject.SharePointConnection interfaces:
|
…
public bool CanExecute(IDeploymentContext context) { bool b = false;
b = context.Project.SharePointConnection.ExecuteCommand<string, bool>("DeploymentCommands.SPCommand.ListExists", definitionFeatureId);
if (!b) { string message = ("No lists of the specified type exist in target web."); context.Logger.WriteLine(message, LogCategory.Warning); }
return b; }
… |
The above code returns a Boolean value indicating whether or not any List Instances associated to the specified Feature ID exist within the target site. If they do, the Execute method can be called; if not, a message is logged to the IDE as a Warning and the step terminates.
The final Execute method is quite simple: it logs a status message indicating that it is running and calls the DeploymentCommands.SPCommand.DeleteLists method of the Deployment Command class, passing in the definitionFeatureId value as a parameter:
|
…
public void Execute(IDeploymentContext context) { context.Logger.WriteLine("Removing list instances...", LogCategory.Status); context.Project.SharePointConnection.ExecuteCommand("DeploymentCommands.SPCommand.DeleteLists", definitionFeatureId); }
… |
Building and Packaging
As with the Deployment Command project, at this stage there is nothing more to be done other than to build the project and insure it compiles correctly. Later, in the VSIX portion, we will discuss how to include the resultant assemblies in the final deployment package.
Testing
While the custom command methods were easily testable, the same cannot be said for the Deployment Steps or Deployment Configuration. This is primarily due to the fact that the steps are designed to run as part of the Visual Studio host process and rely upon context information only available at runtime. It may be possible to mock or Mole the containing processes to derive state and context information but the code required to do so is well beyond the scope of this tutorial. Refer to the TypeMock forums and PEX/MOLES documentation for more information on this topic.
Conclusion
SharePoint Deployment Steps build upon SharePoint Commands by providing a method for referencing custom commands and a functional element which the developer can select as part of a custom deployment solution. They can be used individually or packaged together in a custom Deployment Configuration. In Part Four of this series we will discuss the creation of a custom configuration that utilizes the step defined in our example code. In Part Five, the final article in this series, we will investigate how the commands, steps and configurations are activated within Visual Studio 2010 and their effects on the deployment of our List Template solution.
SharePoint 2010 Code Deployment, Part One
SharePoint 2010 Code Deployment, Part Two
1/15/2010
A lot of people have noticed that I've ditched my MacBook Pro in favor of a Dell Latitude. I've posted a lot about my trials and tribulations with the MacBook here, here, here and here. I loved my MBP but there are a number of reasons why I had to ditch it in favor of a true Wintel machine:
- Drivers. The BootCamp drivers on the pre-Unibody MBP's were pretty darn good – I had no trouble running Vista or Server 2003/2008 and Apple was one of the first to have native x64 drivers for both. I assumed – wrongly – that the same would apply to the Unibody MBP's but that was never the case. The switchable graphics on these machines made running Vista/Windows 7/Server 2008 a complete nightmare. The nVidia card would lock into high performance mode and the thing would get so hot you could fry an egg on it. Naturally, this led to horrible battery life and with the aluminum casing spreading the heat around it was almost impossible to use after a few minutes. The trackpad never worked quite right and Bluetooth was a complete joke. Perhaps worst of all, when connected to a projector the video card would lock into 640x480 and there was no way to increase the resolution. And did I mention using the Express Card slot to connect to an eSATA drive? Yeah, that doesn't work, either. No matter how much people complained in the support forums Apple never stepped up to the plate to fix the drivers (and still hasn't). I realize that nVidia is very much to blame in this situation but I'm pretty sure that if Apple had put pressure on them they would have released a fix.
- Ports. At first I didn't miss having a few extra USB ports but after it while it became a real hassle. It wasn't only having two ports that caused me grief – they are also positioned too close together. Anytime I put in my 3G dongle or any one of a number of other peripherals they blocked the other port and it was effectively useless. Just about the only things that plug into the FireWire ports are portable hard drives, which would have been fine except that the drivers never seemed to work right under Vista or Server 2008. So for all intents and purposes I was left with one USB port. That just ain't gonna cut it. And what on earth is with Apple's decision to replace the ExpressCard slot with an SD slot? That just makes no sense – there are a ton of peripherals which use the ExpressCard form factor – including multi-card readers so I can read and SD if I really need to – but you can't do much with just and SD slot. I'm still shaking my head over this one.
- Expansion. When you use a lot of virtual machines like I do you're forced to have a second (or third or fourth) drive to put them all on. Sure, you can use the FireWire or USB ports but both are pretty slow and there are a lot of situations where presenting with a drive hanging off your machine is difficult (some podiums leave you no room at all for peripherals). I've seen people attach portable drives to the lid of their machines but a) I really didn't want to mar the finish by sticking a Velcro strip on it, and b) the hinge on the Unibody MBP's isn't as tight as it could be so the weight of the portable drive would drag it down to the fully open position which can be hard to view (especially with the high-gloss screen). What I really needed was an expansion bay like the Dell's and Lenovo's had but the design of the MBP's won't accommodate one. This may sound trivial but it turned out to be a real hassle.
- VMWare Fusion. All the issues with running Vista and Server 2008 forced me to use Mac OS X. I don't really have any complaints about the OS, although there were things that seemed a whole lot easier to do in Windows, but what really got on my nerves was VMWare Fusion, which is a pale shadow of VMWare Workstation for Windows. I'm not sure why VMWare can't seem to figure out how to release a full-blown virtualization client for Mac – lack of support for snapshots and clones is just ridiculous. Not to mention the fact that Workstation is much faster than Fusion running the same VM's. This isn't Apple's fault but it is a primary reason why the Mac platform doesn't cut it for the way I work.
- DisplayPort. Ugh. This is a complete PITA. Offering the latest and greatest display connections is all well and good so long as you leave the old tried-and-true VGA connector intact. Plenty of PC manufacturers have figured this out but Apple appears to be clueless. This isn't just a Windows problem – I was forever trying to find the stupid adapter to allow me to connect to a projector or monitor in Mac OS. Heaven forbid you lose it, like I did on more than one occasion, and have to hope against hope that there's another Mac junkie around who has one. And I'm not the only one – I still keep a Display Port to VGA adapter in my bag in case I come across some poor soul in the same situation.
- Docking. Over the years I have come to rely upon the ability to dock my notebook and have instant access to a full keyboard, multiple monitors, and the range of peripherals I keep scattered across my desk. Except for the 13" versions, the MBP is no small machine – finding a place for it to be open yet out of the way can be a real problem. Worse, you can't even close the lid and tuck it under a monitor stand as the heat vents are on either side of the keyboard facing upwards. Try it and you'll have a fried hunk of aluminum in nothing flat.
The bottom line is that MacBooks, regardless of whether or not they put "Pro" in the title, are not designed for business use. It's a PC world out there and Apple isn't doing much to bridge the divide. Perhaps I shouldn't have had such high hopes for the platform but it seems to me that the folks in Cupertino would have gotten the message by now. Based on how many people I saw at TechEd and SharePoint Conference toting MacBooks, it seems there is a pretty substantial market for Windows running natively on Apple hardware. There are probably a large number of people like myself who love the form factor but just can't use the machines for day-to-day work tasks. And that's a real shame.
So, until I find a really good use for it, I've got a very expensive paper weight sitting on my desk just begging to be used for the good of mankind. Who knows, maybe I'll dream up a cool iPhone app at some point…anyone got a 57x57 glassy cowboy hat logo sitting around that they're not using? 1/13/2010
Part One of this series gave a general overview of SharePoint 2010 code deployment using Visual Studio 2010. Now it's time to dig deeper and take an in-depth look at how developers can customize the deployment process. We will begin at the lowest level by creating some custom SharePoint Commands, then move into creating Deployment Steps which utilize those commands and a Deployment Configuration that combines the Steps into a single deployment option. Finally, we will package it all together and use the Visual Studio Extensions and Managed Extensibility Framework to deploy our customizations as a VSIX package.
Introduction
The basic unit of work for 2010 code deployment is the SharePoint Command. This is how developers interact with the SharePoint Object Model during the deployment process. Due to the fact that SharePoint Commands must run in a separate process to bridge the 32-bit/64-bit divide, they must be created inside of a separate project. How the project is designed, the number of classes in each project, and which methods to include in each class, are decisions left entirely up to the developer. As I mentioned previously, there are as of yet no best practices relating to the composition of custom deployment projects, but for ease of maintenance and reusability I would recommend that each class function as a relatively self-contained unit with the minimum number of methods required to achieve the desired functionality. As time progresses, it may be useful to have a base utility class which implements helper methods used by various other classes, but for the time being we will assume that all the necessary code will reside within a single class.
The scenario for this example is pretty straightforward. We will create a List Definition and an associated List Instance. Upon deployment, the SharePoint Command will check to see if there are any existing List Instances associated with the List Definition Feature and remove them if it finds any before deploying a new version of the List Definition. This will insure that there are no orphaned lists which inherit from the previous Template.
Setting Up the Project
In order to implement a custom Deployment Configuration for our scenario, we will need two separate Visual Studio solutions – one for the List Definition/List Instance and one for the custom deployment. I won't go into detail on the first solution as it can easily be implemented using the new SharePoint Project Items and following the prompts for creation of a List Definition. The following graphic illustrates the solution:
Once this is in place we can move on to creation of the deployment solution. This solution will require three separate projects – one for the VSIX package, one for the Deployment Step and Deployment Configuration, and one for the SharePoint Commands. They are separated logically by type of functionality as well as.NET Framework requirements – the VSIX package and Deployment Step/Configuration projects require .NET 4.0 while the SharePoint Command project requires .NET 3.5. We will begin with the SharePoint Command project as it is at the bottom of the stack from a referential perspective (the Deployment Step references the SharePoint Commands, the Deployment Configuration references the Deployment Step, and the VSIX project references them all).
Begin by creating an empty solution and adding a class project for the SharePoint Commands. Be sure to set the .NET Framework version to 3.5 for the SharePoint Commands project, which in this example is using the Contoso.DeploymentCommands namespace:
Writing the Code
There are two distinct pieces of functionality in this command. First, it will be necessary to determine if any lists deriving from the List Definition Feature exist. This will enable the subsequent Deployment Step code to determine if it should continue executing or terminate and log a message to the IDE. Second, if any lists do exist, they will have to be removed from the list collection of the target site. There is no need to pass any state information back to the Deployment Step in this scenario; however, other command types may require success or fail messages to be transmitted, which can be achieved by setting the method type to 'string' and returning an appropriate value, or by using an integer count, or by other various means.
It will be necessary to reference the Micrsoft.VisualStudio.SharePoint.Commands namespace (which is included with the Visual Studio Beta 2 SDK) along with the standard Microsoft.SharePoint namespace. This is the only project within the custom deployment solution in which we can directly access the SharePoint object model due to the fact that Visual Studio is a 32-bit application while SharePoint 2010 is limited to only 64-bit execution.
Attributes and Naming Conventions
All SharePoint Commands are referenced by their literal string name which is defined as part of an attribute decoration on each method. There are no explicit rules pertaining to naming conventions; however, as the use of custom commands grows within a development team it may be necessary to enforce some kind of explicit notation. For this example we will use a dotted hierarchy which includes the namespace but this is simply an arbitrary choice and has no bearing on the overall functionality.
Methods
Begin by creating the SPCommand class (again, no explicit naming conventions are required and it may be necessary to come up with a more structured naming convention over time).
|
using System; using Microsoft.SharePoint; using Microsoft.VisualStudio.SharePoint.Commands;
namespace Contoso.DeploymentCommands { public class SPCommand { } } |
Next, we will add the first method which determines if a List Instance deriving from the specified List Definition Feature exists. We will decorate the method with an attribute which specifies a name for future reference by the Deployment Step.
|
using System; using Microsoft.SharePoint; using Microsoft.VisualStudio.SharePoint.Commands;
namespace Contoso.DeploymentCommands { public class SPCommand { [SharePointCommand("DeploymentCommands.SPCommand.ListExists")] public bool ListExists(ISharePointCommandContext context, string featureId) { Guid templateId = new Guid(featureId); bool bList = false; using(SPWeb web = context.Web) { SPListCollection lists = web.Lists; foreach (SPList list in lists) { if (list.TemplateFeatureId.ToString() == templateId.ToString()) { bList = true; break; } } } return bList; } } } |
Note that the method is invoking the new ISharePointCommandContext interface. This interface provides contextual information for the command which is passed in from the Deployment Step. We are also capturing the ID of the List Definition Feature as the code will need this ID to identify any derived List Instances. The method itself simply iterates the SPListCollection object and identifies any SPList objects whose TemplateFeatureId property matches the GUID passed in from the Deployment Step. We only need one match to satisfy our requirements, so a Boolean value is set when a match is found and this value is returned to the Deployment Step. If no match is found it returns the default value of 'false'. Also take note of the fact that the SPWeb object is already available to us via the context, much like an Event Receiver or Feature Receiver.
Now that we have code to determine if a list associated with the specified Feature exists, we can add a method to perform the task of removing such lists from the list collection. As with the previous method, begin by decorating the method with an attribute which specifies the name that will be used in the Deployment Step, then add code to iterate the list collection, match the TemplateFeatureId value, then remove the list object and update the SPWeb object.
|
…
[SharePointCommand("DeploymentCommands.SPCommand.DeleteLists")] public void DeleteLists(ISharePointCommandContext context, string featureId) { Guid templateId = new Guid(featureId); using (SPWeb web = context.Web) { SPListCollection lists = web.Lists; for (int i = lists.Count - 1; i >= 0; i--) { if (lists[i].TemplateFeatureId.ToString() == templateId.ToString()) { lists[i].Delete(); web.Update(); } } } }
… |
We now have two commands, DeploymentCommands.SPCommand.ListExists and DeploymentCommands.SPCommand.DeleteLists, which encapsulate the functionality required by the Deployment Step. As previously mentioned, you may wish to add error handling logic in the DeleteLists method and return a string, integer or Boolean value which can then be used by the Deployment Step to determine whether or not the lists were actually deleted, or even log a message with the list names or ID's that were removed.
Building and Packaging
At this stage there is nothing more to be done that to build the project and insure it compiles correctly. Later, in the VSIX portion, we will discuss how to include the resultant assemblies in the final deployment package.
Miscellaneous Considerations
It is worth pointing out that the deployment process and execution of SharePoint Commands is not an area in which much can be done to enhance performance. Certainly, if the commands being executed are enumerating list items or accessing external data sources, then best practices should be employed in order to avoid lengthy wait times, but beyond that there are very few options for reducing the overhead incurred by the necessity of invoking and terminating a separate process to execute the command code, the processing done by SharePoint itself, recycling of application pools, and any extensions or add-ons to the Visual Studio IDE. In other words, don't expect the deployment process to be exceptionally fast but do take measures to insure that the command code being executed doesn't exacerbate the problem.
Testing
It should be fairly obvious that the SharePoint Command code is just as testable as any other code running against the SharePoint Object Model. From a Unit Test perspective, developers can approach SharePoint Commands as stand-alone classes which are developed and tested outside of the deployment process using whatever methods they prefer – TypeMock, NUnit, XUnit, PEX/MOLES, etc. By structuring the projects in the manner suggested, the command methods may be fully tested prior to adding the dependencies upon the deployment interfaces (SharePointCommand, ISharePointCommandContext), which may then be added after the test cases are satisfied. Obviously, this means that subsequent testing will have to account for the integration issues brought about by including the deployment interfaces. One possible solution to this problem would be to abstract each of the core methods into a separate set of utility classes which receive the context objects and parameters from the command. This would permit the use of mock objects or parameterized tests without requiring the deployment framework dependencies.
To illustrate this, consider separating the code into two separate classes and abstracting the core functionality:
SharePoint Commands
|
using System; using Microsoft.SharePoint; using Microsoft.VisualStudio.SharePoint.Commands;
namespace Contoso.DeploymentCommands { public class SPCommand { [SharePointCommand("DeploymentCommands.SPCommand.ListExists")] public bool ListExists(ISharePointCommandContext context, string featureId) { bool bList = Contoso.DeploymentCommands.Utilities.VerifyListByTemplateId(context.web, featureId); return bList; } [SharePointCommand("DeploymentCommands.SPCommand.DeleteLists")] public void DeleteLists(ISharePointCommandContext context, string featureId) { int i = Contoso.DeploymentCommands.Utilities.RemoveListByTemplateId(context.web, featureId); if (i < 1) throw new System.Exception(); } } } |
Utility Class
|
using System; using Microsoft.SharePoint;
namespace Contoso.DeploymentCommands { public class Utilities { public bool VerifyListByTemplateId(SPWeb web, string TemplateId) { Guid templateId = new Guid(TemplateId); bool bList = false; using(web) { SPListCollection lists = web.Lists; foreach (SPList list in lists) { if (list.TemplateFeatureId.ToString() == templateId.ToString()) { bList = true; break; } } } return bList; } public int RemoveListByTemplateId(SPWeb web, string TemplateId) { Guid templateId = new Guid(featureId); int x = 0; using (web) { SPListCollection lists = web.Lists; for (int i = lists.Count - 1; i >= 0; i--) { if (lists[i].TemplateFeatureId.ToString() == templateId.ToString()) { lists[i].Delete(); web.Update(); x = x + 1; } } } return x; } } } |
Conclusion
SharePoint Commands provide a means for developers to interact with the SharePoint Object Model when creating custom deployment solutions. They run in a separate process in order to overcome the x86/x64 limitations of Visual Studio with SharePoint and are flexible enough to encapsulate any OM-related functionality. They also serve as the base building block for deployment customizations. In Part Three of this series we will explore the next link in the chain, Deployment Steps, how they relate to and reference SharePoint Commands, and how they are used within the Visual Studio IDE.
SharePoint 2010 Code Deployment, Part One
SharePoint 2010 Code Deployment, Part Three
12/31/2009Hard to believe that another year has come and gone. I've never been one for predictions and resolutions, which I'm no good at keeping anyway, but I think 2010 is going to be a big year in SharePoint land. For starters, SharePoint 2010 really will be a game-changer. I believe with this release that we will see SharePoint reach its potential in many organizations and adoption rates will be phenomenal. Developers finally have the tools they need to create killer applications and administrators have a much richer set of controls to manage their environments. Many of the almost-good-enough-but-not-quite features in 2007 (BDC, Records Management, Content Deployment, Excel Services, Search, and Shared Services, just to name a few) have been greatly improved and will generate a great deal of interest in using Enterprise features. Best of all, the reliance upon clunky web parts for content management and the slick new UI will make the end user experience a great deal better.
As AC
mentioned, there are a few areas that will demand more focus from developers in 2010. Silverlight will be huge and I anticipate that we'll see some very engaging and visually appealing solutions on that front. Creating service applications will also be a big area of interest. Lots of people will be getting on the VSIX bandwagon and extending Visual Studio 2010, especially in relation to one of my favorite new areas, code deployment. I also expect to see some cool extensions to the new SharePoint Project Items and Project Extensions. We'll all become more proficient with WCF and, despite their drawbacks and limitations, sandboxed solutions should be a big part of all our lives. I'm not sure if people will jump with both feet into Windows 7 development with the Client OM seeing as how there are so many new areas of server-level development but it's certainly an area to watch. I anticipate that the trend of vendors rushing into the space will continue and I'm looking forward to seeing some cool new solutions to fill gaps where the base product leaves off.
As usual, I'll be bouncing around the globe doing various events and conferences. There will be a lot of community action taking place, with expanded user group meetings in the UK and lots more SharePoint Saturdays and TechCons, not to mention the big get togethers like TechEd and SharePoint Conference. I'll be working hard with my ISPA compatriots to expand our value to the community and increase the number of user groups around the world (look for some big announcements on that front early on in the new year).
So here's to an exciting 2010. May it prove fruitful and fun. Happy SharePointing!
12/29/2009My initial post on the use of JQuery with SharePoint has generated a great deal of discussion (see here, here and here); so much so, that I felt some additional comments on the subject were merited. Let me begin by clarifying my position. I am not against the use of JQuery or any other particular technology. It has advantages and disadvantages and should be used where appropriate. What I am against is implementing something in an enterprise production environment without first thinking through all the ramifications.
I don't think this comes as much of a shock to anyone but SharePoint is not the most performant application right out of the box. The pages are weighty, the OOTB web parts are often inefficient, and the control hierarchy can be a downright mess (don't even get me started on the underlying data architecture). A lot of time and effort goes into making SharePoint perform at an acceptable level. Before making the problem worse by adding a bunch of Content Editor Web Parts which manipulate the DOM using client-side code, I think it's worth some additional time to consider what impact that code might have on overall performance.
A page which takes ten seconds to render still takes ten seconds regardless of whether code is executed on the server or on the client. At least on the server side we can baseline the execution time and optimize accordingly. But when the render time is complicated by code that runs on a variety of different client machines all with different configurations, connections, browsers, and so forth, it can be very difficult to isolate issues and correct them. If the baseline requirement is that all pages render in less than eight seconds, and tests indicate that it's taking ten seconds, something has to be done. There are lots of ways to go about this – modifying master and layout pages, adjusting caching and compression, adding hardware resources, distributing linked components into a content delivery network – but the first step is to eliminate as many variables as possible before determining a course of action. Javascript in CEWP's is the worst kind of uncontrolled variable – any user with sufficient permissions can throw a few onto a page and put the brakes on render time (hence the title of my original post). The same is true for list view and content query web parts. Strictly speaking, it's not the use of them that is the problem – it is the uninformed use of them that causes issues.
Before allowing this to happen in your environment, a discussion should be had on how and where this type of code is permissible. Users don't care about the technical details of how and where code is executed – all they know is that the page they're trying to access takes a long time to load. It's a perception issue and perception often defines reality. We can argue amongst ourselves about the size of the javascript libraries, where they are hosted, how much they add to the page payload, and so on until we're blue in the face but all the technobabble means nothing to the user – the page still takes longer to render then they expect it to. The key metric in this discussion is RENDER time – execution and load time are important to us but not to the user. The client-side code still must do its work before the page is finally displayed. Each CEWP adds to the overhead of the page and the code in them must be executed in serial before the page can be displayed. In most cases, this is probably negligible and not worth worrying about. But in situations where performance is paramount it is vitally important to deliver a consistent experience that meets the baseline requirements.
Another thing that's bothering me is the lack of understanding people seem to have regarding how JQuery really works. Granted, a lot of the people jumping on the bandwagon aren't true developers but that's part of the problem – it's dangerous to give someone a powerful tool and not teach them how to use it properly. One of the benefits I keep seeing people tout regarding JQuery is how simple the code is. This is often accompanied by an attestation along the lines of "it used to take me fifty lines to do this and now I can do it in three". No, you can't do it in three lines of code – those three lines are calling dozens, potentially hundreds, of lines of code in the script libraries you are referencing. Worse, many of those libraries are creating big fat arrays and iterating through them (multiple times, in some cases) to give you the results you want. There is no magic bullet here – just because the syntax is simple doesn't mean the work is any less complex. It still takes time to run all that script in the background BEFORE the page can be rendered to the user. What looks like a simple selector method could, in fact, be doing a whole bunch of heavy lifting behind the scenes.
It's time to get back to some basics. Javascript (or, more accurately, ECMAScript) is an interpreted language, meaning it must be retrieved, parsed, interpreted and executed with every page load (the browser does try to help by caching the files in memory when it can). The more of it you use, the more parsing, interpreting and executing are going on and, consequently, the longer the page takes to load. Unlike compiled server-side code like C# or VB, there is no multithreading in Javascript, meaning that each function must execute in serial (I know that many people are going to complain that most C#/VB code doesn't take advantage of multithreading but that's beside the point – it can be done in .NET, even though the developer may choose not to do it, but it absolutely cannot be done with Javascript). So, if you have three functions, each of which selects particular elements in the DOM, they must run in the order they are called to completion before the next one can execute. To further illustrate the issue, imagine that each of those functions makes a call to a web service – each one would have to instantiate the connection, make the call, get the response, release the connection, then parse the results before moving on to the next function, not to mention all the objects being created in memory and any operations that take place against the results of the web service call.
All of this back and forth, looping, iterating, recursing, and what not takes time and the page cannot be completely rendered until it's all done. The fact that the workload is happening on the client-side is COMPLETELY IRRELEVANT – THE PAGE STILL DOESN'T FINISH RENDERING UNTIL ALL THE PROCESSING IS COMPLETE. Asynchronous techniques like AJAX don't help, either – a page isn't finished until ALL the elements are rendered; AJAX really pays off on postbacks not on initial page loads. All that's being done by running the code on the client is to relieve the server of some of its workload – which may or may not be beneficial in your environment – but it doesn't change the amount of work that must be done. In fact, due to the granular control developers have over caching and memory management in ASP.NET, and the extra caching that SharePoint throws into the mix, it could be argued that the server can do the same unit of work less frequently and with greater efficiency than any client (I believe that argument breaks down when the server is under heavy load but it's certainly true under controlled conditions).
So what does all this mean? Should people avoid JQuery like the plague on SharePoint pages? Of course not. It is an elegant manner in which to accomplish common tasks and makes complex programming methods available to a wider audience. In cases where power users and/or developers don't have permissions to modify code directly or deploy their own custom controls, client-side scripting is often the only option for modifying the user interface, and the deployment methods are very easy and non-intrusive. Just don't go into it with blinders on – like all good things, it does come at a price. It has the potential to negatively affect performance, especially when employed by people who mean well but don't really understand what's going on behind the scenes, and it's easy to overdo it. By all means, use it where it makes sense, but do so with full awareness of the pitfalls and drawbacks. Remember the old rule that there is no free lunch – at some point, you always have to pay, and it's up to you to decide where the sweet spot is between functionality and performance within your environment.
12/28/2009
One of the most exciting aspects of Visual Studio 2010 is the tight integration it will have with SharePoint. The Visual Studio team has worked hard to make the SharePoint developer experience much more streamlined and less dependent upon manual configuration files and custom scripts. They have also made a tremendous investment into extensibility, allowing developers to move beyond the out-of-the box features and create their own custom extensions to fit their individual or team development environment. In this series, we will explore the new code deployment functionality in Visual Studio 2010 and take a deep dive into creating our own custom deployment extensions.
Introduction
In SharePoint 2007 developers were introduced to the solution packaging framework, which gave them the capability to package multiple assets, including Features, Assemblies, files, and other elements, into a single deployable artifact. This was a tremendous step forward in terms of deployment but it still left a lot to be desired. For one thing, there was no automated way to package the solution itself – developers were required to manually create the manifest, DDF and other packaging elements, then tie them into the build process. In addition, there was no method for automatically deploying the solution package in a development environment, requiring scripts to add the package into the solution store and run the necessary timer jobs. Finally, there was a lack of integration between Visual Studio and SharePoint, such that VS had no knowledge of SharePoint items within a project, leaving developers to manage changes and updates on their own. In practice, each element of packaging and deployment existed in isolation with no direct relationship to other elements.
Legacy Packaging and Deployment
For SharePoint 2010, the Visual Studio team tackled all the issues head on with the goal of providing developers with an integrated packaging and deployment process within the IDE (as opposed to third-party solutions which plugged into the environment, such as STSDEV and WSP Builder). At the same time, they sought to overcome the primary shortcomings of the VSeWSS extensions by insuring the automated processes would be both customizable and extensible. The main objectives of the Visual Studio SharePoint deployment framework can be summarized as follows:
- Implementation of packaged code in development environment
- Modification of deployment options and parameters
- Retraction of deployed solutions
- Elimination of repetitive manual processes which decrease productivity
- Single-click build/package/deploy process integrated into VS IDE
Although no solution is perfect, and some developers may choose to continue working with custom extensions or community tools, the packaging and deployment framework in Visual Studio 2010 does an admirable job meeting these objectives. It all begins with the introduction of SharePoint Project Items, already familiar to anyone who worked with the VSeWSS extensions, which are pre-defined SharePoint elements (such as Web Part, Workflow, List Definition, etc.) selectable from the Add New… menu within a SharePoint Project. Each SharePoint project includes a Package element which consolidates the various features, mapped folders, modules, and other project items into a WSP archive according to the directives within the Manifest.xml file (gone is the DDF file required for the MakeCab utility). The final stage, deploying the package to the local SharePoint server instance, is handled by the new Deployment framework within Visual Studio 2010.
SharePoint projects now contain a new 'SharePoint' tab within the project properties. This property page allows the developer to specify what type of deployment, known as a 'Deployment Configuration', they wish to execute. Each configuration (there are two that ship out of the box: 'Default' and 'No Activiation') consists of one or more Deployment Steps, and each step may execute one or more actions and/or SharePoint Commands. In addition, there are Pre- and Post-Deployment options for additional activities that may be required before and after the Deployment Configuration runs.
The Visual Studio 2010 SharePoint Deployment Framework
Each element – Project Items, Packaging, and Deployment – work together in a seamless process which can be automatically initiated simply by pressing F5 within the IDE. Just like ASP.NET development, Visual Studio will build, package, deploy, launch the web browser and wire-up the debugger to the worker process. This makes iterative development much easier and less fragile, eliminating a great deal of repetitive manual tasks and the potential for human error. It also lowers the rather high barrier to entry which had to be overcome by developers new to the SharePoint platform in previous releases.
SharePoint Project Items
The basic building block of all SharePoint 2010 projects is the SharePoint Project Item (SPI). Each SPI represents a specific type of SharePoint asset within the framework – web parts, workflows, list definitions, list instances, event receivers, application pages, site definitions, and so on. When a new solution is created Visual Studio automatically creates an empty feature to hold project items. If multiple items of the same type are added to a project, VS will attempt to add them to the same feature; if no features exists, it will create a new one for the selected SPI.
Visual Studio 2010 SharePoint Project Items
One critical aspect of SPI's that warrants further discussion is the concept of conflict resolution. During the deployment process it is necessary to determine if a particular element, such as a list instance, already exists in the target site and, of even greater importance, what to do with it in relation to the code currently being deployed. Each out of the box SPI contains its own conflict resolution logic which can be toggled on and off within the item properties. If, for example, a list definition already exists, the deployment process must eliminate any list instances associated with the definition before it can retract and re-deploy the solution, otherwise the target site will quickly become littered with orphaned objects. Each SPI has different requirements which necessitate different resolution actions (web parts, for example, must be removed from individual pages and the web part gallery before the feature can be deactivated cleanly) and this logic is already included with the default items. Even better, SPI's are fully extensible, allowing developers to define additional resolution logic or create their own logic for custom item types.
Solution Packaging
The packaging of SharePoint solutions is managed within the new visual Packaging Explorer. This utility allows developers to specify which features, mapped folders, and other assets should be included in the final WSP. By default, all SPI's in the project which are included in a Feature, along with any mapped folders, will be automatically added to the package. The Packaging Explorer also exposes a set of advanced properties which allow for inclusion of miscellaneous assemblies, setting of SafeControl entries, and so forth. It also allows developers to drop down to the underlying XML should they wish to control the packaging process manually.
Deployment Configurations
Once a project has been built and packaged it must be deployed to the target farm, site collection or site on the local development machine. Developers control how a solution is deployed by selecting a Deployment Configuration from the SharePoint tab in the project properties. A Deployment Configuration is a collection of Deployment Steps which occur in a specified order, such as 'Retract Solution', 'Recycle IIS Application Pool', 'Add Solution', and 'Activate Features'. Visual Studio ships with two Deployment Configurations out of the box – Default and No Activation. These configurations execute essentially the same set of steps with the primary difference being that the latter configuration doesn't attempt to activate any Features after the solution has been deployed to the farm.
Developers can create their own Deployment Configurations directly in the IDE by mixing and matching any of the available Deployment Steps. There are also provisions for Pre- and Post-Deployment Commands, which allow for scripts to be run before and after the deployment process is executed. Each project can have only one active Deployment Configuration at a time but multiple projects in the same Visual Studio solution can all use different Deployment Configurations. It's important to note that while all projects in a solution will be built and packaged, only the project marked as "Start Up" will be deployed (it is possible to have multiple startup projects within a single solution – see here).
Deployment Steps
Deployment Steps define the actual work to be done in the deployment process. In some cases, a Deployment Step has a one-to-one relationship to a pre-existing management command, such as "Add Solution", which is the same as invoking "stsadm.exe –o addsolution –filename [SolutionFilePath]" from the command prompt; however, Deployment Steps are not limited to a single activity – in reality they are task descriptors which invoke one or more commands. A Deployment Step may call an external script, invoke a custom assembly, or perform any number of assorted functions.
Visual Studio 2010 allows developers to specify which steps are included in a custom Deployment Configuration (the out of the box configurations are locked and cannot be edited) and the order in which they are to be executed during both the initial deployment process and retraction of the deployed solution. It is important to specify a valid order of execution when creating a custom Deployment Configuration, as steps which occur out of logical order can result in a failed deployment and potentially leave orphaned artifacts behind. Also, developers should be familiar with the behind the scenes actions which take place during deployment so as not to specify redundant or unnecessary steps. If, for example, a new solution is being added to the solution store using the 'Add Solution' Deployment Step, it is not necessary to run the 'Recycle IIS Application Pool' step after the solution has been added as SharePoint will automatically recycle the application pool if the solution is scoped for GAC deployment.
SharePoint Commands
Although Deployment Steps can perform any number of tasks, they are most often used to call code which interacts with the SharePoint object model. Due to the fact that SharePoint 2010 can only run on a 64-bit platform, and Visual Studio2010 is still a 32-bit application, a Deployment Step must reference a SharePoint Command assembly which is compiled against the 3.5 framework and runs in a separate process. Since they run in an isolated host process from the Visual Studio development environment, SharePoint Command assemblies can directly reference the object model and run any SharePoint-related code the developer wishes.
A SharePoint Command is executed when it is referenced explicitly by name within a Deployment Step. There are no limits on the number of SharePoint Commands that a Deployment Step can call, and a single set of commands can be shared by multiple Deployment Configurations. As such, it is important to think through the use of SharePoint Commands within a team environment. SharePoint Commands are referenced by name only, meaning that there are no type-safe restrictions in place – it is all too easy to create confusing or duplicate names for individual commands. In addition, because a SharePoint Command can run any object model methods, it will quickly become commonplace for duplicate functionality to exist in multiple commands. Although there are no "best practices" as such yet defined for the creation and use of SharePoint Commands within custom Deployment Configurations, it is probably wise to create many small classes which execute specific pieces of functionality (such as checking whether or not a solution is sandboxed or full trust, upgrading an existing solution, removing items from galleries, etc.). These commands can then be leveraged more effectively by calling them individually from within a Deployment Step.
Conclusion
Part One of this series introduces the concepts surrounding code deployment in Visual Studio 2010. In subsequent posts we will delve into how the deployment process can be customized programmatically so developers can create their own redistributable deployment extensions. Before continuing, it may be helpful for developers to learn more about the Managed Extensibility Framework in Visual Studio 2010 and Visual Studio Extensions. In order to compile and deploy the code samples, it will be necessary to install SharePoint 2010 Beta, Visual Studio 2010 Beta 2 and the Visual Studio SDK for Beta 2.
SharePoint 2010 Code Deployment, Part Two
SharePoint 2010 Code Deployment, Part Three
12/21/2009
For the better part of the last year I've been watching from the sidelines as nearly the entire SharePoint community jumped on the JQuery bandwagon. It seems like every year some new thing comes along which will make SharePoint sing and dance like a Broadway musical (remember 2007 – the year of AJAX?). Blog after blog has popped up with tips and tricks on how to do nearly everything with javascript, from fetching list items with web services to making pretty lightbox effects out of picture libraries. Ok, that's cool and all, but the one question nobody seems to be asking is: will it scale?
Putting aside the obvious shortcomings of doing all sorts of programmatic gymnastics with uncompiled, loosely-typed, client-side code, let's pause a minute to consider what impact JQuery may have on performance. There's nothing magic about JQuery itself; much like LINQ, it simply provides less-obtrusive language semantics in order to make common tasks more efficient. If you look into the source script you'll see that it's mostly a bunch of arrays being populated with getElementById calls and regular expression searches – not exactly rocket science.
In most of the examples I have seen, JQuery is being used to modify the user interface by changing elements of the document object model (DOM) after it has been sent down to the client by the server. The average SharePoint page has more than 1,000 elements in the DOM right off the bat before adding any web parts or publishing field content; add to that some of the really funky code that the OOTB web parts produce, along with a list view or two, and you can easily end up with pages that have thousands of DOM elements. That's a lot of stuff to process in client-side code. All that iterative selecting, searching and modifying that JQuery does in the background to manipulate these elements takes time – the bigger the page, the more work has to be done before the final content is rendered in the browser. Considering that SharePoint pages aren't exactly optimized for performance right out of the box, and how much time and effort is spent trying to shave a few seconds off of average page load times, is it really a good idea to start mucking around with the DOM just to produce some fancy visual effects?
I remember having a conversation over dinner at DevLink last August with Dennis Bottjer. Dennis was convinced that JQuery was the answer to many a developer's frustrations with the SharePoint UI and customizations in general. I conceded that he was probably right, it would catch on and spread like wildfire, but I was concerned that overuse would lead to performance problems. We went back and forth about it for a while then let the matter drop but the more I see it being used (you were right on that score, Dennis) the more I am troubled by its impact on high-volume sites, especially enterprise portals and public-facing web sites, and the lack of any substantive performance discussion in the greater community.
In order to validate my theory that even simple JQuery functions can put a damper on SharePoint performance (or, should the results prove positive, at least put my mind at ease), I set up a very simple test scenario. I created a web part page in a WSS site in SharePoint 2007 then added an out-of-the-box list view web part to the page which rendered a view of the first 500 items in a custom list. I then copied the JQuery scripts to a subfolder in the /_layouts directory and added a <script> link in the <head> tag of the master page. Finally, I added a content editor web part with a JQuery function that changed the background color of every other item in the list view to yellow, like so:
$(".ms-alternating").css("background-color","yellow");
I then fired up SharePoint Performance Manager to assess the render time of the page both with and without the JQuery CEWP. An empty CEWP had an average execution time of around four seconds (which is scary in and of itself – I need to look into it further and figure out why that particular web part is so slow even with no content); adding the function to change the row styling increased the execution time by about a second. I flipped it on and off twenty times using ten sample page loads for each configuration and the results were relatively consistent – in my test environment the JQuery took about a second on average to do its work. The overall effect on page render time was rather less due to multithreading, working out to about a third of a second. Ok, that confirmed my basic theory but there were no real surprises and a third of a second doesn't stop the world from spinning (although, to be fair, many dotcoms have spent millions of dollars in infrastructure for the sole purpose of reducing load times by a fraction of a second).
The next step was to set up a series of load tests to ascertain the impact of the JQuery operations when multiple simultaneous requests were involved. I configured a single-page web test in Visual Studio Team Test and dropped it into a load simulation of 100 concurrent users over a three minute period. This is when things got a bit more interesting. Overall page load time without the JQuery code went up from around six seconds to about eleven seconds (an 80% increase, which is to be expected on a single virtual machine with only 4GB of allocated RAM) but when I added the JQuery function to the CEWP it shot up to thirteen seconds – not at all what I was expecting. I ran the tests a dozen more times with similar results. While the base page load time increased by 80% the JQuery impact on page load went from a third of a second to two whole seconds – a 600% increase! That's more than statistically significant – that's downright worrisome.
So what gives? Admittedly, my test environment isn't anywhere close to "real world" – your mileage may vary depending upon the server and network infrastructure, client connection, amount of concurrent requests, and, of course, the exact nature of the JQuery methods being executed. But the results were pretty clear – under load the javascript performance was less than stellar. I would be very concerned about this type of code in a high-traffic environment; in fact, I would almost certainly call this out in a performance assessment as a critical blocking factor.
The takeaway here is to be very careful what kind of JQuery operations you are performing on your SharePoint pages. In most real-world scenarios I doubt whatever client-side functions are being performed would have a drastic impact on performance – typical enterprise portals just don't get that much simultaneous load. That being said, I would steer clear of JQuery in most high-traffic situations, especially home pages for popular WSS sites, shared application pages (like viewlsts.aspx) and any public-facing MOSS publishing pages. I'm especially troubled by JQuery inside of content editor web parts, as the CEWP by itself appears to be rather burdensome even without additional scripts, and would much prefer to embed the scripts directly (either in the master page or as a custom control) if I absolutely had to implement some fancy DOM-manipulation scripts.
Don't get me wrong – JQuery has a lot of benefits, not the least of which is the ability to write complex query logic with relatively little code; however, its use in performance-sensitive environments could be more trouble than it's worth. As with all things SharePoint, there's more than one way to skin the cat and other methods may achieve the same results while introducing less overhead. Use it if you must but test, test, test before going into production or you may get a nasty surprise when that fancy new MOSS portal goes live.
UPDATE
As expected, this topic has generated some discussions in the community, which is exactly what we need. Here are some links to related posts:
Marc Anderson - Putting the Brakes on SharePoint with JQuery - or not
Dennis Bottjer - Stop, Think, Dev SharePoint
Eric Shupps - Follow-Up on JQuery and SharePoint Performance
UPDATE 2
Many people have rightly pointed out that my load tests were not real world (whcih I did mention in the post) and not really applicable to client-side script processing. That's caused a lot of confusion and is fair criticism. I was going for the impact that the CEWP's and List Views had on each other under load and got distracted by the strange results I was getting from the CEWP's - I should have separated the two discussions. To that point, I have discovered some interesting things about how the CEWP's work and will be posting on it in the future as soon as I have a chance to compare them with the 2010 version. See my second post (linked above) for more discussion of render time performance as opposed to load time.
12/16/2009I'm in Houston today for the Houston SharePoint User Group holiday event. It's gonna be a great time with a panel of long-time SharePointers fielding all types of questions, lots of prizes from the sponsors, free food and drinks. If you're in the Houston area, space is limited so head on down to the Norris Conference Center early. We'll see you there! 12/2/2009As anyone who has ever heard me speak or had the misfortune to be cornered by me at a SharePint event knows, I'm a big proponent of implementing best practices for optimal SharePoint performance, both from an IT infrastructure perspective as well as custom development. Unfortunately, this is a tricky area with lots of gotchas – there are so many variables that impact SharePoint performance you almost need a roadmap to figure it all out. One of the most common issues we encounter in enterprise deployments is a default configuration that was installed way back when SharePoint was a departmental solution and, after growing and assimilating everything in its path like the Borg, has become an unruly monster that is slow and unresponsive.
Over the years we have seen just about every worst practice that you can imagine when it comes to poor performance – loading up a single server with tons of services, doing massive crawls within a single search scope, starving WFE's with minimal RAM, putting database servers on shared LAN segments – you name it, we've beat our head against it. Those of us who live this stuff day in and day out, and who have been around since the wild west days of SharePoint (which, in retrospect, was only about five to seven years ago even though it seems like several lifetimes), take for granted all the guidance that exists around this topic. But the truth is that most business don't have time to deal with all of SharePoint's nuances and intricacies – they just want it to work, and rightfully so. Despite all the best intentions of community contributors over the years, who have devoted countless hours to spreading the performance gospel, there still exists a deep divide between what should happen as a matter of course and what actually happens in practice.
As a means to bridge this divide, we at BinaryWave undertook the task of organizing our collective experience solving SharePoint performance into a set of repeatable practices that we feel represent the most common and easily solvable issues. Our first step was to create Sonar (since acquired by Idera and relaunched as SharePoint Performance Manager), as a means to objectively measure and isolate underperforming page objects. Although this had a tremendous impact on our thinking around some of the really difficult issues relating to the MOSS request processing pipeline and object model in general, we also realized that there are a number of issues which don't easily lend themselves to a product-based approach; in many cases you simply need an experienced set of eyes to look over everything and synthesize all the environmental factors into a targeted root-cause analysis. To this end, we conceptualized a service offering which would provide customers with hands-on guidance and optimization recommendations specific to their environment.
We have just announced the culmination of this effort as our SharePoint Performance Optimization service. The offering is primarily targeted at enterprise customers with a significant investment in SharePoint products and technologies but we hope to expand it down-market to SME customers as well. It is our hope that we can make an impact by reducing the amount of performance headaches that customers have endured by making it easy to identify, isolate and optimize their deployments.
I'd love to hear feedback from the community on the most common performance problems that people encounter in their day-to-day SharePoint existence. With any luck we'll be able to disseminate this information via public forums and keep this discussion in the forefront of everyone's mind. The more people who talk about performance the better off everyone will be. So feel free to comment, write a blog post, or otherwise publish your thoughts on this subject. I'll link to as many of them as I can and you can rest assured that I'll keep banging the drum whenever I get the chance. I might be a rhythmless Redneck but at least I can make some noise!
| Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/eshupps/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/eshupps/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/eshupps/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/eshupps/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blogs/eshupps/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blogs/eshupps/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blogs/eshupps/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blogs/eshupps/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blogs/eshupps/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|