My Top 10 tests when testing custom SharePoint webparts

1. Logging in with a Visitor only profile

Often, developers work on development environments where they have full permissions. Because of that, they might not notice some permission issues. Having a test account with lower permissions helps identify such problems before going further in the deployment cycle.

Here are a few scenarios when a visitor role would encounter problems:

  • Somewhere during its the execution, the webpart accesses a list with unique permissions on which visitors have no permission.
  • The webpart tries to write some data but the visitor role has of course no such permission

While this test sounds obvious, it is necessary to think of it at any time. This is also valid for other types of components.

2. Adding the custom webpart several times on the same page

Again, this might sound obvious but not every developer thinks that a webpart can be added several times to the same page. According to the nature of the webpart, this scenario has to be considered seriously. If for instance, your custom webpart has a property specifying a list of the current web and performs specific work based on that list, it’s obvious that it might be added multiple times in the same page but pointing to different lists.

The type of errors that could be encountered often relate to javascript/html code generated by the webpart. If your webpart needs to perform some client side coding on specific HTML markup generated by the webpart, if you forgot to ensure your HTML markup (div, span…) have unique IDs and/or unique javascript variables, you might end up with some unexpected behavior because the multiple instances of the same webpart residing on the same page will generate the HTML DOM objects with the same IDs and therefore the javascript associated with it will likely fail to play its role correctly…

To illustrate the above statements, here is a short example that would just not work correctly if the webpart is added several times on the page.

Say you have a webpart exposing a list property in order to bind it to a given list. The webpart displays the number of items for the given list asynchroneously via ECMAScript.

Given that scenario, we know that when using ECMAScript, we will have to query our list, specify a callback method and treat the results in order to display them with our rendering logic.

To make this very simple, I’m not going to implement the entire code. But, say you create a visual webpart and in the user control part, you implement this:

01 <script type="text/javascript">
02     ExecuteOrDelayUntilScriptLoaded(GetItems, "sp.js");
03     function GetItems() {
04         this.ClientContext = SP.ClientContext.get_current();
05         if (this.ClientContext != undefined && this.ClientContext != null) {
06             this.ReturnedList = this.ClientContext.get_web().get_lists().getByTitle('<%= ListName %>');
07             this.ClientContext.load(this.ReturnedList);
08             this.ClientContext.executeQueryAsync(
09              Function.createDelegate(this, this.Success),
10              Function.createDelegate(this, this.Failure));
11         }
12     }
13     function Success(sender, args) {
14         document.getElementById("NonUniqueIDDivElement").innerText = this.ReturnedList.get_itemCount();
15     }
16     function Failure(sender, args) {
17         document.getElementById("NonUniqueIDDivElement").innerText = "nok";
18     }
19 </script>
20 <div id="NonUniqueIDDivElement"></div>

You get the name of your list via a webpart property that you can configure in the webpart properties:

2011-09-20-TopTenTests-01.png

When you add the webpart only once into the page, you get the expected result:

2011-09-20-TopTenTests-02.png

If you add another instance of this webpart into the page and you bind it to the “docs” library containing one item, you’ll get this as a result:

2011-09-20-TopTenTests-03.png

The second webpart bound to the “docs” list displays its result within the first webpart. The reason is obvious : this is because the div element in which the results are displayed has the same IDs for both webparts…

When there is only one webpart on the page, you will never notice this problem but when adding another one, you’ll start having troubles. That’s why, as a habit, I always add the webpart a few times to the same page to see how it behaves when it makes sense functionally speaking.

Not only should you make your DIV element unique but you should also isolate your javascript context in order to make sure that the different instances do not interfeer with each others. An easy way to do that is to work with the ClientID of the user control.

3. Checking if the webpart file is correctly deployed/removed from the webpart gallery

Seasoned SharePoint developers know that when deploying the .webpart or .dwp file into the webpart gallery declaratively via a site collection feature works fine at activation time but the file never gets removed from the gallery when deactivating the feature.

In order to prevent this behavior, a feature receiver can help to clean things up.

4. Checking the relationship between the webpart and its associated feature

Some webparts have a very wide functional scope and can potentially be deployed anywhere in SharePoint.

As you know, when a webpart gets deployed, it must target one or more web applications so that the corresponding web.config file gets modified to add a SafeControl entry making sure the webpart can be used.

Most of the times, a site collection feature is used to deploy the .webpart or .dwp file into the webpart gallery.  This gallery is later used as a datasource by SharePoint when adding a webpart to a page.

So, if you have two site collections (A) and (B) and if you activate the feature for A, you will by default not see the webpart when adding a webpart to a page of site B. However, any user with enough permission (site owner is enough) could just upload the webpart file himself in the webpart gallery, thus making this webpart available although the site collection feature was not activated for site collection B.

Therefore, for business sensitive/specific webpart, I tend to add a code check in the webpart that verifies whether the feature is activated or not. Something like this:

1 if(SPContext.Current.Site.Features[new Guid(“..”)] == null)
2    Error.Text = “This webpart cannot be used, ask your administrator…”;

That way, you make sure your webpart will never be used/reveal unattended things if it was not explicitely allowed by a site collection administrator.

5. Checking the property validation in custom editorpart

If the webpart exposes custom properties, I make sure that the data type is correctly validated. Not only for scalar types such as int, string etc..but also for links.

6. Checking CAS/Trust Level

If the WebPart is deployed to the BIN folder of the SharePoint Web Application, I want to make sure that it works correctly when the trust level is set to WSS_Minimal in the web.config. So, I reset it to that level if it’s not the case.

7. Checking its resuability in a SandBoxed Solution

With SharePoint 2010, webparts can be easily deployed in SandBoxed solutions but this is usually not what developers chose as default deployment.

However, it’s worth the effort required to convert a farm webpart into a sandboxed one in case, sooner or later, it would need to migrate to Office 365 or any other SharePoint Online system.

8. Monitoring the webpart execution with the Developer Dashboard

Since WebParts are encapsulated into pages, there are two good reasons to monitor their performance :

  • they are directly impacting the overall page payload and thus, the visitor experience
  • if the site expects a lot of visits, the overall impact on the server(s) might be high

Enabling the Developer DashBoard helps identifying poor performance without the need to perform a full code review.

9. Checking the behavior in Edit Mode

When editing the page containing the webpart or the webpart properties, it is sometimes surprising to see unexpected side effects…

A good example is when the webpart contains some ASP.NET validators.  Say, for instance, a good old RequiredFieldValidator. In that case, when editing another webpart on the same page, your RequiredFieldValidator will complain that your text fields are not filled in correctly because the editing of the other webpart causes some postbacks… as shown below:

2011-09-20-TopTenTests-04.png

While editing the content editor webpart, my custom webpart complains that my required field is empty.

In the case of this visual webpart, if I modify the CreateChildControls method like this:

1 protected override void CreateChildControls()
2         {
3             if (this.WebPartManager.DisplayMode == WebPartManager.BrowseDisplayMode)
4             {
5                 Control control = Page.LoadControl(_ascxPath);
6                 Controls.Add(control);
7             }
8         }

The user control will not be loaded in edit mode and therefore, the validators will not apply. You could, of course, manage it more precisely in order to act only on the validators but I’m taking the shortcut here2011-09-20-TopTenTests-05.png

10. Testing the usual operations such as delete/close

Usually, this is not likely to crash but since these are very common operations, it’s always worth your time to give it a try.

Happy Coding & Testing!

Advertisements

How To: Working SharePoint 2010 modals

When working with custom SharePoint modals, you’ve got to be able to collect the user data and then allow them to close the modal.
Page Content

When working with custom SharePoint modals, you’ve got to be able to collect the user data and then allow them to close the modal.

In my last post, we looked at how you can create a new modal rendering your custom page right from the context menu of the SharePoint list item.

This time I’d like to show you how you can close your modals once users are done with them.

There is no magic to closing modals, there is a button as you’d expect. The thing to keep in mind is that your modals are part of the context of the entire page and JavaScript is used to either show them or hide them. The whole superimposed modal UI is just a visual trick.

The close/cancel button is easy, you just close the modal DIV. There is even an out-of-the-box function for that.

All you need to do in the page that renders in modal is to assign OnClientClick event as follows:

1 <asp:Button Text="Cancel" ID="CancelButton" runat="server"
2   OnClientClick="window.frameElement.cancelPopUp(); return false;" />

The commit and close modal logic is a bit different since you need to run to the server first, execute any server events, and only then execute a client script.

The idea here is to execute a client script on the post-back when your custom server side code has run.

In our example, our server side context executes on a button click. We would add the following after the click has executed its server events:

1 this.Context.Response.Write("");
2 this.Context.Response.End();

The difference here is that we call commitPopup JavaScript function and we write this statement only when the page has posted back after our server code has executed.

As a result your users will see a modal dialog refresh and disappear.

How To Create SharePoint 2010 custom visual webpart properties

If you’ve created SharePoint 2010 classic web parts before, you know that you can easily define custom web part properties which your web part code-behind can consume.
Page Content

If you’ve created SharePoint 2010 classic web parts before, you know that you can easily define custom web part properties which your web part code-behind can consume.

2011-11-29-CustomWebpartProperties-01.png

With the popularity of SharePoint 2010 Visual Webpart, you’re probably interested in having custom properties defined there too.

There are few things different about exposing your custom properties in a Visual Web part.

Let’s see the steps involved:

    1. Add new or use existing Visual Web Part to your project, in our case called Webpart1
    2. Open the Webpart1.cs file which will look something like this:
01 [ToolboxItemAttribute(false)]
02     public class Webpart1: WebPart
03     {
04         private const string _ascxPath = @"~/_CONTROLTEMPLATES/[your ASCX].ascx";
05         protected override void CreateChildControls()
06         {
07             Control control = Page.LoadControl(_ascxPath);
08             Controls.Add(control);
09         }
10     }

and add your custom property definition right below the CreateChildControls method, in our case the property will look something like this:

1 [WebBrowsable(true),
2         Category("Configuration"),
3         Personalizable(PersonalizationScope.Shared),
4         WebDisplayName("Friendly Display Name"),
5         WebDescription("Values: Whatever value you need)]
6         public string PropertyValue { get; set; }

In here, the PropertyValue is the actual variable which will be later consumed by your web part user control.

    1. Update your CreateChildControls logic to look like this:
1 protected override void CreateChildControls()
2         {
3             Control control = Page.LoadControl(_ascxPath);
4             if (control!= null)
5             {
6                 ((Webpart1UserControl)control).WebPart = this;
7             }
8             Controls.Add(control);
9         }

This piece here will pass in the properties every time the control is reloaded. In here, the only change you’ll need to make is to rename Webpart1UserControl to the [name of your webpart]UserControl. This will reference the ASCX used for the Visual Webpart.

    1. Switch to your user control … Webpart1UserControl.ascx.cs

and define public variable right below the class declaration:

1 public Webpart1 WebPart { get; set; }

Here the Webpart1 is referencing the actual web part class file (not ASCX).

That’s all, in your code you can get a hold of the web part property value by using this: this.WebPart.PropertyValue, where the PropertyValue is the name of the variable we’ve chosen earlier.