Archive

Kategorien

Links

Andere Blogs




ITaCS GmbH

May 162013

SPQuery for my tasks

Developing solution with multiple languages (or a language which is not English) sometimes can be a bit painful. To configure a Webpart to display only my tasks, I would filter for [Me] or [Ich].

image

To achieve the same via code / CAML, you can filter by UserID and not the string “Me”.

  1: <Where>
  2:   <Eq>
  3:     <FieldRef Name="AssignedTo" />
  4:     <Value Type="Integer">
  5:       <UserID />
  6:     </Value>
  7:   </Eq>
  8: </Where>
  9: <OrderBy>
 10:   <FieldRef Name="Status" />
 11:   <FieldRef Name="Priority" />
 12: </OrderBy>
This is just a reminder for me, so I can find the information more quickly. But maybe this is useful for some of you as well Smile

Published: 5/16/2013  1:29 PM | 0  Comments | 0  Links to this post
Tagged as: Development, SharePoint, SPQuery

Apr 122011

Empty Admin Recycle Bin items

What is it?

Usually the size of the recycle bin is not relevant. But on development machines, you don’t want lots of files in there, which make your databases grow without actually used data.

What do you do? Go to the recycle bin, click on “Site Collection Recycle Bin”. The two stages of the recycle bin can be managed independently.

image

The two views on the left let you switch between the first- and second stage. All items from the first stage can be moved to the second stage with one click (+ 1 confirmation). But if the items are in the second stage, you can only delete 200 items at a time by selecting all and delete them in batches. An option to delete all items is missing (in the GUI).

image

My solutions adds this option for the second stage recycle bin. A link for deleting all items at once is displayed in the toolbar. If you click it, a modal dialog – I love SharePoint 2010 Smile - is displayed, and you can delete all items at once.

image

 

How does it work?

A feature (farm-scoped) activates a delegate control. It references jQuery/JavaScript code to add the button “Empty Recycle Bin”, as shown in the second picture, and to open a modal dialog.

This modal dialog is a custom application page, which will query the recycle bin for statistics (as shown in the second picture) and delete items in batches via SPRecycleBinQuery which is similar to the SPQuery.

New link in the toolbar

jQuery was my choice to add an additional button the the toolbar of the second stage recycle bin. The developer tools from the Internet Explorer helped me to find the right table by its ID. The content of it is modified, so the button is injected via JavaScript. That way there is not server code required to add the button directly to the page.

jQuery(document).ready(function () {
   // the Toolbar2 is used for the second stage recycle bin
   var row = jQuery("#ctl00_PlaceHolderMain_Toolbar2 > tbody > tr");
   
   // find last cell
   var lastTD = $(row).find('td:last');

   // add seperator
   lastTD.before('<TD class=ms-separator>|</TD>');

   // change content of the last cell
   var content =
   '<TABLE border=0 cellSpacing=0 cellPadding=1>' +
      '<TBODY>' +
         '<TR>' +
            '<TD class=ms-toolbar noWrap><A class=ms-toolbar title=' + emptyRecycleBin + ' href="javascript:openEmptyAdminRecycleBinDialog()">...</A></TD>' +
            '<TD class=ms-toolbar noWrap><A class=ms-toolbar title=' + emptyRecycleBin + ' href="javascript:openEmptyAdminRecycleBinDialog()">' + emptyRecycleBin + '</A>...</TD>' +
         '</TR>' +
      '</TBODY>' +
   '</TABLE>';
   lastTD.html(content);
});

Modal Dialog

The modal dialog is opened with JavaScript:

function openEmptyAdminRecycleBinDialog() {
   var options = {
      url: "../../_layouts/RH.EmptyAdminRecycleBin/EmptyAdminRecycleBin.aspx",
      width: 400,
      height: 130,
      title: "Empty Admin RecycleBin",
      dialogReturnValueCallback: onDialogClose
   };
   SP.UI.ModalDialog.showModalDialog(options);
}

function onDialogClose(dialogResult, returnValue) {
   if (dialogResult == SP.UI.DialogResult.OK) {
      // refresh the page to reflect changes
      SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK)
   }
   if (dialogResult == SP.UI.DialogResult.cancel && returnValue != null) {
      alert(returnValue);
   }
}

With the callback function, a page refresh is triggered. Otherwise the deleted items would still be visible on the recycle bin page.

Recycle Bin

Querying recycle bin items is achieved with a dedicated object. The SPRecycleBinQuery. It takes parameters like the RowLimit. If you don’t specify the RowLimit, only 50 items will be returned. The ItemState defines if items from the first, or second stage will be returned. The query is executed multiple times, to get all items.

private void GetRecycleBinStorageInfo(out int itemCount, out long overalSize)
{
   itemCount = 0;
   overalSize = 0;
   SPRecycleBinItemCollectionPosition itemcollectionPosition = null;
   do
   {
      SPRecycleBinQuery query = CreateQuery(itemcollectionPosition);
      SPRecycleBinItemCollection recycleBinItems = Site.GetRecycleBinItems(query);
      itemcollectionPosition = recycleBinItems.ItemCollectionPosition;
      // get itemCount
      itemCount += recycleBinItems.Count;
      // get overalSize
      overalSize += recycleBinItems.Cast<SPRecycleBinItem>().Sum(item2 => item2.Size);
   } while (itemcollectionPosition != null);
}

private static SPRecycleBinQuery CreateQuery(SPRecycleBinItemCollectionPosition page)
{
   var query = new SPRecycleBinQuery
                  {
                     RowLimit = 200,
                     ItemState = SPRecycleBinItemState.SecondStageRecycleBin,
                     OrderBy = SPRecycleBinOrderBy.Default,
                     ItemCollectionPosition = page ?? SPRecycleBinItemCollectionPosition.FirstPage
                  };
   return query;
}

The method returns the itemcount and size of all items in the second stage recycle bin.

To delete all items, I’ve used this code:

using (var operation = new SPLongOperation(this))
{
   operation.Begin();

   try
   {
      // delete all items in pages of 200 items
      SPRecycleBinItemCollectionPosition itemcollectionPosition = null;
      do
      {
         SPRecycleBinQuery query = CreateQuery(itemcollectionPosition);
         SPRecycleBinItemCollection recycleBinItems = Site.GetRecycleBinItems(query);
         itemcollectionPosition = recycleBinItems.ItemCollectionPosition;
         for (int i = 0; i < recycleBinItems.Count; i++)
         {
            recycleBinItems[i].Delete();
         }
      } while (itemcollectionPosition != null);

      operation.End("/_layouts/RH.EmptyAdminRecycleBin/CloseModalDialog.html", SPRedirectFlags.Default, Context, null);
   }
   catch (Exception ex)
   {
      UlsLogging.Write(TraceSeverity.Unexpected, ex.ToString());
      SPUtility.TransferToErrorPage(ex.Message);
      return false;
   }
   return true;
}

The SPLongOperation shows the nice animation during processing the code. Just make sure you end the operation to hide the animation.

Exception Handling

Usually my classes have a method HandleException, as the WSPBuilder does Smile. This class will write the exception to the SharePoint ULS log.

private void HandleException(Exception ex)
{
   try
   {
      UlsLogging.Write(TraceSeverity.Unexpected, ex.ToString());
      Controls.AddAt(Controls.Count, new Label {CssClass = "ms-error", Text = ex.Message});
   }
   catch (Exception e)
   {
      Trace.Write(e.ToString());
   }
}

internal class UlsLogging
{
   internal static void Write(TraceSeverity traceSeverity, string message)
   {
      var uls = SPDiagnosticsService.Local;
      if (uls != null)
      {
         SPDiagnosticsCategory cat = uls.Areas["SharePoint Foundation"].Categories["Web Controls"];
         uls.WriteTrace(1, cat, traceSeverity,message, uls.TypeName);
      }
   }
}

If you want to use an area or category which is not a default one, you’ll need administration permissions to create it. The use of RunWithElevatedPrivilegues is not enough!

You can download the sourcecode here: RH.EmptyAdminRecycleBin(Sourcecode).zip

The compiled solution as WSP file can be downloaded here: RH.EmptyAdminRecycleBin.wsp

And before you ask: The solution is for SP 2010! SharePoint Services 3 lacks the modal dialog. But you can take the source code, and modify it to fulfill your needs.


Published: 4/12/2011  4:09 PM | 2  Comments | 0  Links to this post
Tagged as: Development, SharePoint, SPQuery

Mar 112011

PortalSiteMapProvider.GetCachedListItemsByQuery

With MOSS 2007 or SharePoint Server 2010 you can use the PoraltSiteMapProvider of the Microsoft.SharePoint.Publishing.dll assembly to retrieve cached listitems.

   1: PortalSiteMapProvider ps = PortalSiteMapProvider.WebSiteMapProvider;
   2: var pNode = ps.FindSiteMapNode(web.ServerRelativeUrl) as PortalWebSiteMapNode;
   3: var query = new SPQuery
   4:                {
   5:                   Query = "<Where><Neq><FieldRef Name='ID' /><Value Type='Counter'>0</Value></Neq></Where>"
   6:                };
   7: SiteMapNodeCollection quoteItems = ps.GetCachedListItemsByQuery(pNode, "Top Seiten", query, web);

In my case, I didn’t need any special where clause. I wanted to retrieve all items, so I left the Query property  empty. And because I needed only three columns, I specified the ViewFields property of the SPQuery object.

Bad idea. The query failed hard and fast Sad smile

Conclusion:

If you use the GetCachedListItemsByQuery method, do not specify the ViewFields property of the SPQuery and configure a query. Even if it returns all items of the list!


Published: 3/11/2011  5:56 PM | 0  Comments | 0  Links to this post
Tagged as: SharePoint, Development, SPQuery

Jun 042009

SPQuery with lookup columns returns no data

An SPQuery for lookup columns should be easy. Start the famous U2U Caml Editor, configure your query, and query the list.

image

This query will get a result if the lookup column stores something like “1;#1”. But if its value is e.g. “1;#Title”, the query will not return an item.

So what can we do about it?

Add a LookupId='TRUE' to your query, so it will look like this:

   1:  <Where>
   2:     <Eq>
   3:        <FieldRef Name='LookupField' LookupId='TRUE'/>
   4:        <Value Type='Lookup'>2</Value>
   5:     </Eq>
   6:  </Where>

Remember to omit the Query tags from the U2U Caml Editor when pasting the query into your Visual Studio source code!


Published: 6/4/2009  8:21 PM | 1  Comment | 0  Links to this post
Tagged as: Development, SharePoint, SPQuery