Second Life of a Hungarian SharePoint Geek

November 24, 2015

NullReferenceException in the Content Editor Web Part when Trying to Upload Images

Filed under: CEWP, SP 2013 — Tags: , — Peter Holpar @ 23:16

Recently a user complained, that when he tries to upload a photo in a Content Editor Web Part (CEWP)…

image

… an error is displayed.

image

We found the following relevant line in the ULS logs:

11/16/2015 12:46:45.29     w3wp.exe (0x21FFC)                          0x2185C    SharePoint Foundation             Runtime                           tkau    Unexpected    System.NullReferenceException: Object reference not set to an instance of an object.    at ASP._layouts_15_upload_aspx.__Render__control29(HtmlTextWriter __w, Control parameterContainer) in c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS\upload.aspx:line 81     at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)     at Microsoft.SharePoint.WebControls.ScriptBlock.Render(HtmlTextWriter writer)     at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)     at ASP._layouts_15_upload_aspx.__Render__control27(HtmlTextWriter __w, Control parameterContainer) in c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS\upload.aspx:line 61     at Sy…    b324429d-5597-507f-40b1-b3a2b68192e5

In upload.aspx at line 81 there is a reference for CurrentList.ID:

function LaunchOpenInExplorer()
{
    vCurrentListID = "<%= CurrentList.ID %>";
    vCurrentListUrlAsHTML = "<%= Web.Url + "/" + (CurrentList.RootFolder.Url.Length > 0 ? CurrentList.RootFolder.Url + "/" : "") %>";

}

We got the NullReferenceException, because the CurrentList object is null.

In our case, the CurrentList was null, because somebody has deleted all document libraries from the site where the page with the CEWP was located, so there was no place the user could upload the image.

However, we should not delete all of the libraries if you want to reproduce the issue. The GetActionableDocumentLibraries method of the Microsoft.SharePoint.ApplicationPages.UploadPage class is responsible for populating the list of document libraries of the upload page that are candidates for image upload. We can find the following loop and conditions in this method:

List<SPDocumentLibrary> list = new List<SPDocumentLibrary>();
foreach (SPList list2 in web.Lists)
{
  …
  SPDocumentLibrary item = list2 as SPDocumentLibrary;
  if ((((item != null) && !item.Hidden) && ((SPBaseType.DocumentLibrary == item.BaseType) && (SPListTemplateType.WebPageLibrary != item.BaseTemplate))) && (!item.IsCatalog && (!requireAddListItemsPermissions || (requireAddListItemsPermissions && list2.DoesUserHavePermissions(SPBasePermissions.AddListItems, false)))))
  {
    list.Add(item);
  }

}

As you can see, the library should not be a hidden one, should not be the Site Pages library or any of the standard catalog libraries (like Web Part Catalog), and the user must have the permission to add items to the list. For example, if there are no document libraries the user is allowed to add items to, we have the same issue with the CEWP.

Re-creating the deleted document library solved the issue for the user.

Advertisements

March 5, 2014

August 22, 2013

Strange error Saving changes of the Content Editor Web Part

Filed under: CEWP, Fiddler — Tags: , — Peter Holpar @ 23:01

A few days ago I just worked with the Content Editor Web Part (CEWB) when I received the following alerts after editing the HTML source of the web part:

"Cannot retrieve properties at this time” and “Cannot save your changes"

I found several references for this error on the web, but none of the proposed solutions (like AAM, trusted sites, etc.) solved my issue. After a short research I found the culprit: it was Fiddler, on of my favorite tools that intercepted the communication between SharePoint and my browser. Strange, that it did not helped when I turned off capturing of network traffic, only after shutting down the application disappeared the symptoms, and I was able to save the changes.

Autocomplete textbox for site groups

Filed under: CEWP, jQuery, jQuery UI, SP 2010, SPServices — Tags: , , , , — Peter Holpar @ 22:44

Recently I had to provide a solution that supports selecting SharePoint site groups through an HTML autocomplete textbox.

The solution was built on JavaScript-based components, like jQuery (version 1.8.3), Autocomplete widget of jQuery UI (version 1.10.3) and jQuery Library SharePoint Web Services (aka SPServices, version 2013.01). The JavaScript code was injected into the page using the Content Editor Web Part (CEWP).

In the code (see below) we get the list of groups through the GetGroupCollectionFromSite method of the UserGroup web service, and attach the autocomplete feature to a HTML textbox, filtering the matching groups by a simple RegExp based on the text entered into the textbox.

  1. <script src="/_layouts/jQuery/jquery-1.8.3.min.js"></script>
  2. <script src="/_layouts/jQuery/jquery-ui-1.10.3.custom.min.js"></script>
  3. <script type="text/javascript" src="/_layouts/jQuery/jquery.SPServices-2013.01.min.js"></script>
  4. <link rel="stylesheet" type="text/css" href="/_layouts/jQuery/css/ui-lightness/jquery-ui-1.10.3.custom.min.css">
  5.  
  6. <input id="autocomplete">
  7.  
  8. <script language="ecmascript" type="text/ecmascript">
  9.  
  10. $(document).ready(startScript);
  11.  
  12. function startScript() {
  13.   $().SPServices({
  14.         operation: "GetGroupCollectionFromSite",
  15.         async: true,        
  16.         completefunc: AttachAutoComplete,
  17.     webURL: "/"
  18.     });
  19. }
  20.  
  21. function AttachAutoComplete(xmlResponse) {
  22.   var domElementArray = $.makeArray(xmlResponse.responseXML.getElementsByTagName("Group"));
  23.   var data = $.map(domElementArray , function(node) {
  24.         return node.getAttribute("Name");
  25.     });   
  26.  
  27.   $( "#autocomplete" ).autocomplete({
  28.     source: function( request, response ) {
  29.       var matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
  30.       response( $.grep( data, function( item ) {
  31.         return matcher.test( item );
  32.       }) );
  33.     }
  34.   });     
  35. }
  36.  
  37. </script>

And here is the feature in action:

image

July 23, 2013

Creating a Flash Video Player For SharePoint using the built-in web parts – Version 1

Filed under: CEWP, jQuery, REST, SP 2010 — Tags: , , , — Peter Holpar @ 20:51

Recently I had to provide our users a way to display a list of Flash video files (FLV) with the ability to play the selected one. I found a similar solution on CodePlex, however, I did not like the idea to install a custom web part just to fulfill this requirement, and implemented instead my custom lightweight solutions using the standard SharePoint web parts. In this post I show you the implementation based on the Content Editor Web Part (CEWP), in a later post I publish another version based on the Content Query Web Part (CQWP).

It’s common in the implementations that they utilize Flowplayer version 3.2.16. I created a folder called flowplayer on the SharePoint server at 14\TEMPLATE\LAYOUTS, and from the flowplayer folder in flowplayer-3.2.16.zip copied the following files into the new folder:

flowplayer.controls-3.2.15.swf
flowplayer-3.2.12.min.js
flowplayer-3.2.16.swf
style.css
(from the example subfolder)

The Flash video files are stored in this case in a document library called “VideoLib1”. I set the Title property of the files to provide a short description of the content beyond the file name (Name property).

image

Additionally, I needed jQuery version 1.8.3, json2.js (to support JSON.parse in the Quirks document mode of Internet Explorer, like the WSS 3.0 compatible master page of SharePoint 2010) and the LINQ for JavaScript (ver.3.0.3-Beta4) library (version is important due to the incompatible syntax of former versions). All of these JavaScript libraries were located – for the sake of simplicity – in the jQuery folder in Layouts.

I’ve created a new web part page, added a new CEWP to the page, and set the source code of the web part according to the sample below:

Code Snippet
  1. <script src="/_layouts/Flowplayer/flowplayer-3.2.12.min.js"></script>
  2. <script src="/_layouts/jQuery/jquery-1.8.3.min.js"></script>
  3. <script src="/_layouts/jQuery/json2.js"></script>
  4. <script src="/_layouts/jQuery/linq.js"></script>
  5. <script src="/_layouts/jQuery/linq.jquery.js"></script>
  6.  
  7. <link rel="stylesheet" type="text/css" href="/_layouts/Flowplayer/style.css">
  8. <span><a style="display:block;width:520px;height:330px" class="myPlayer"></a></span>
  9. <div class="videoList" style="text-align:left;"></div>
  10.  
  11. <script language="ecmascript">
  12.  
  13.     function startClip(src, title) {
  14.         flowplayer().play([
  15.     { url: src, title: title }
  16. ]);
  17.     }
  18.  
  19.     $(document).ready(startScript);
  20.  
  21.  
  22.     function startScript() {
  23.         // initialize FlowPlayer in the 'myPlayer' anchor (A) HTML tag
  24.         flowplayer("a.myPlayer", "/_layouts/Flowplayer/flowplayer-3.2.16.swf");
  25.  
  26.         // ctx assumes a ListViewWebPart (it might be even hidden) on the same page
  27.         var siteUrl = ctx.HttpRoot;
  28.  
  29.         // clear the video list DIV (videoList)
  30.         $('.videoList').empty();
  31.  
  32.         $.ajax({
  33.             type: 'GET',
  34.             contentType: 'application/json;odata=verbose',
  35.             // get the (file)Name and Title property of each .FLV file
  36.             url: siteUrl + "/_vti_bin/listdata.svc/VideoLib1?$filter=endswith(Name,'.flv')&$select=Name,Title",
  37.             headers: {
  38.                 "Accept": "application/json; odata=verbose"
  39.             },
  40.             dataType: "json",
  41.             complete: function (result) {
  42.                 var response = JSON.parse(result.responseText);
  43.                 if (response.error) {
  44.                     alert("Error: " + response.error.code + "\n" + response.error.message.value);
  45.                 }
  46.                 else {
  47.                     var videos = response.d.results;
  48.                     Enumerable.from(videos).forEach(function (x) {
  49.                         // on click event will be the video clip started
  50.                         var link = '<p><a href="javascript:void(0)" title ="' + x.Name.substring(0, x.Name.length – 4) + '" onclick="startClip(\'' + x.__metadata.media_src + '\', \'' + x.Title + '\')">' + x.Title + '</a></p>';
  51.                         // append video link to the video list DIV (videoList)
  52.                         $('.videoList').append(link);
  53.                     });
  54.                 }
  55.             },
  56.             error: function (xmlHttpRequest, textStatus, errorThrown) {
  57.                 alert(errorThrown);
  58.             }
  59.         });
  60.     }
  61. </script>

 

In this script we request the Name and Title properties of the .flv files from our document libraries through the REST API, and add the required links to the play list. Alternatively one could use the Client OM as well, but in this case I found REST to be simpler.

To be able to send the REST request, we need the URL of the current SharePoint web. The JavaScript variable ctx referred to in my script is available only we have at least one ListViewWebPart on the same page. If you don’t have any, you can add a dummy  one (for example, the movie document library itself), and set it to be hidden, as illustrated below:

image

If you don’t like this hack, you can get the URL through the Client OM as well, through an extra asynchronous call.

The image below illustrates the end result rendered by the CEWP:

image

Clicking on the title of the movie will start the video playback.

You can read about a similar solution utilizing CQWP here.

Blog at WordPress.com.