Diary of a Software Developer

SharePoint, ASP.NET MVC, Silverlight, ...

  • Contact

Add custom action in Site Actions Menu at a specific location

Posted by GillouX on November 22, 2011
Posted in: Custom Action, Sharepoint 2010. 2 comments

In this article, I am going to show you how to add a new menu item into the Site Actions menu.

In order to do that, you must use a Custom Action.

Here is example of Custom Action:

source : http://msdn.microsoft.com/en-us/library/bb418728%28v=office.12%29.aspx

This Custom Action adds a new item menu called “Hello World Application Page”. When a user clicks on this menu item, he is redirected to a /LitWare/ApplicationPage1.aspx

Something that I would like to point out, is the Sequence property. It’s supposed to allow the developer to choose where he wants to put the menu item. It does make that but only among your custom menu items. So you get to set the order of your menu items, those will be appended at the end of the menu. You can try to set it at 1, it will be still added at the end.

What I am going to show you, it’s to actually work around this limitation and explain how you can actually add a new menu item wherever you want to.

This technique will use two different properties : ControlClass and ControlAssembly

In ControlClass we will define the control which needs to be rendered when the menu item get displayed while ControlAssembly defines the assembly which contains this class.

Check out the following sample:

The Code of the Class, note that the class inherits from WebControl (System.Web)

As you can see, I even didn’t provide any sequence in my Custom Action, the important thing here is the MenuGroupId.

It refers in this case to already existing locations that you can find in the v4.master

By setting a MenuGroupId and a Sequence, you can add your Custom Action within the existing menu and not only at the end.

SharePoint and Acrobat X integration

Posted by GillouX on October 1, 2011
Posted in: PDF, Sharepoint 2010. 25 comments

!<UPDATE>!

A fix for the bug described at the end of this article has been published by Microsoft.

You can find here the related KB.

This is the scenario that refers to our particular issue:

You create a French site collection in SharePoint Foundation 2010.
You upload a .pdf file to a document library in the French site collection.
You check out and edit the file.
You try to check in the file.

It describes the issue with a French site collection but it applies to all non-english site collection.

!<UPDATE>!

In this article, I will show you how to set up the integration SharePoint 2010/Acrobat X.

About Acrobat X

This is not the porn version of Acrobat but the last drop of the Acrobat family made by Adobe.

The great thing with this version is that it comes with an ActiveX which holds a special class to deal with PDF and make the integration nicer and easier.

PDFs and SharePoint

To tell SharePoint and Internet Explorer what they must do when they see a PDF file, you must add a new mapping into the 14/TEMPLATE/XML/DOCICON.XML

but instead of using the old traditional SharePoint.OpenDocuments ActiveX, we will use a brand new feature of the new ActiveX provided by the Acrobat X.

<Mapping Key=”pdf” Value=”pdfIcon.gif”  Text=”Adobe Pro” OpenControl=”AdobeAcrobat.OpenDocuments“/>

Once this is done, you just need to make a small recycle of your Application Pools or a IISRESET.

For every PDF uploaded into a document library, you will have the PDF icon in the type column and a new item “Edit in Adobe Pro” in the ECB (Edit Control Block).

Result

Here is what you get if you have followed me until now. I made my printscreens in French, sorry for that : x

if you click on Modifier dans Acrobat Pro (Edit in Acrobat Pro),  you get the following

Let’s check out the file, modify something and check-in it back.

Common issues

“The URL you have provided could not be reached. Please verify that the URL is correct and that the network location is reachable.”

This one is WebDav related.

1. Check that the client has the WebClient Service enabled in Windows

It should be enabled by default but you never know, especially if you are working in a highly secured environment.

2. Check that the user have the Use Remote Interfaces permission.

“Acrobat cannot access the network”

I came across this issue when doing some working with Acrobat and SharePoint on a French site. Indeed, I did not have this issue on English site.

We got the official word from Microsoft, it’s a bug. They are working on a fix as I speak but they have provided us a workaround in the meantime.

So here it is, let’s the magic happens : you need to recreate 57 fields in English in order to make this working. My guess is that French is not the only buggy version so it should apply to all non-English sites.

Here is the list of fields that you must add to your list.

Content Type ID
Approver Comments
Name
Document Modified By
Document Created By
File Type
HTML File Type
Source URL
Shared File Index
Title
Template Link
HTML File Link
Is Signed
Document ID Value
Document ID
Content Type
Created
Created By
Modified
Modified By
Has Copy Destinations
Copy Source
Approval Status
URL Path
File Size
Item Type
Sort Type
Effective Permissions Mask
ID of the User who has the item Checked Out
Is Checked out to local
Checked Out To
Unique Id
Client Id
Virus Status
Check In Comment
Edit Menu Table Start
Edit Menu Table End
Server Relative URL
Encoded Absolute URL
Property Bag
Level
Is Current Version
Item Child Count
Folder Child Count
Select
Edit
UI Version
Instance ID
Order
Workflow Version
Workflow Instance ID
Source Version (Converted Document)
Source Name (Converted Document)
Document Concurrency Number
Relink
Merge
Path

Here is a script which does that.

Note that each field Hidden property is set to true in order to keep a clean interface.

If none of these fixes have helped you, fire up Fiddler and locate the call to the Copy.asmx, have a look at the HTTP Response, it might reveal some really useful information.

That’s all folks.

Change “Choose Picture” Control in EditProfile.aspx

Posted by GillouX on June 6, 2011
Posted in: Delegate Control, Sharepoint 2010. 1 comment

When editing his profile in SharePoint, a user can (among other things) choose a profile picture.

He clicks Choose Picture and choose a file from his hard-drive disk.

The user experience could be better, maybe we could replace this control by our own?

This is possible using the Delegate Control feature of SharePoint.

I won’t explain what is a Delegate Control because there are already plenty of articles targeting this matter, here for instance.

if you read the article I referenced above, you should have understood by now that a Delegate Control allows you to replace a Control by another but in order to do that, you need to know the ControlId and the Scope

Anywhooo ….

I made myself some digging into the EditProfile.aspx (14/TEMPLATE/LAYOUTS)

You will see that the control responsible for displaying the editing profile section of the page is called ProfileEditor. Using Reflector, I looked ProfileEditor up and realized that it inherits from ProfilUI. If you look at the decompiled code of this abstract class, you will find that the “Choose Picture” Control is in fact a DelegateControl with the following ControlId : MySitePictureEditor and the following Scope : Farm.

Note: ProfilUI is located under the Microsoft.SharePoint.Portal.WebControls namespace in the Microsoft.SharePoint.Portal.dll assembly.

I created a base SharePoint Project which uses the information we have collected above to replace the OOTB MySitePictureEditor, you can download it here.

For demo purpose, I just put a nice I got you!! label.

You can use this project and implement whatever solutions you come up with:

  • a Silverlight Control (webcam photo capture, …)
  • an advanced picture editor allowing the user to resize, crop, …
  • …

If I have time, I’ll look myself to implement one of these solutions.

Hope it helps!

Move a file to a document set

Posted by GillouX on May 31, 2011
Posted in: Custom Action, Document Set, Sharepoint 2010. Leave a Comment

When I started using the Document Sets feature I was surprised to see that you can not move a file to an existing Document Set, at least not easily.

In fact, you have the same issue if you wish to move a document  into a folder. There is no easy way to do it. Well you have the Send To Other Location but how less user-friendly could it get? You do not get to select anything, you must know the destination URL…

…but anyway it’s not going to move the document but to copy it which is not what I want to do.

I came up with my own solution which will provide another menu item in the ECB (EditControlBlock) allowing the user to move a file to a document set.

the SharePoint project is made of 2 essentials things:

  • A Custom Action Move to Document Set
  • an Application Page ChooseDocumentSet which allows the user to select the document he wishes to move the document into.

1. Move to Document Set Custom Action

Sequence = “0″ sets the Custom Action at the top of the menu.

RegistrationType = “ContentType” and RegistrationId = “0×0101″ will make the Custom Action only visible for the Document.

Rights = “EditListItems” will make the Custom Action only visible for people who have Editing rights.

The rest of the Custom Action is pretty self-explanatory, I call our Application Page in a modal dialog using the Dialog capabilities of SharePoint.

2. ChooseDocumentSet Application Page

For the server side code, I’m using the MVP Pattern (model-view-presenter), so you will find the main logic of the code in the Presenter of the ChooseDocumentSet page.

Here are the two main methods:

- in the OnViewLoaded() method:

I check first if I am not already in a document set, if it’s the case, I get its name.

In the second part, I get recursively the list of document sets existing in the current list, I exclude the current document set if it’s the case.

Note that ParentFolderIsDocumentSet() and GetDocumentSets() are both Extensions Methods defined in a separate class that I will not explain here.

- in the OnSubmitClick() method:

This is where I actually move the document using the SPFile.MoveTo method. It’s the same method you would use to move document within a folder for instance.

In fact, a Document Set is an object which derived from a SPFolder.

You will find the Visual Studio Solution here.

ILSpy : Open Source Reflector-like

Posted by GillouX on April 30, 2011
Posted in: Reflector, Tools. 1 comment

For those who use Reflector, you might know that Reflector is no longer free…

Fortunately, there is a free open source alternative called ILSpy.

What you see is what you get:

I didn’t have enough time to make this post shorter ; )

Enjoy!

SharePoint 2010′s Upload Multiple Documents in Silverlight Part 2.

Posted by GillouX on March 24, 2011
Posted in: Client Object Model, Sharepoint 2010, Silverlight. 4 comments

Following the Part 1 of the Sharepoint 2010 s Upload Multiple Documents in Silverlight article, I had let some issues unsolved.

  1. When a user clicks on Upload Document, the standard upload page is loaded  but sill contains the link to the OOTB multiple upload page (uploadex.aspx)
  2. If a user does not have office installed, this link won’t appear.

1. When a user clicks on Upload Document, the standard upload page is displayed and contains the link to the standard multiple upload page (uploadex.aspx?Multipload=true) and not our custom MultipleUpload page developed in the Part 1 on this article.

2. The second issue is linked to the first issue, the link to the standard multiple upload page appears based on the same rule than the Upload Multiple Documents ribbon button, you need Office installed.

To overcome both issue, what I propose in this article, is to provide our own uploadex.aspx page.

This workaround(let s be honest and call it that way) will consist of two steps:

- create a custom version of the uploadex.aspx
- create a httphandler to redirect to this custom uploadex.aspx page

Create a custom version of the uploadex.aspx

To create a custom version of the uploadex.aspx, proceed as follows:

  • copy the standard uploadex.aspx (_layouts folder) page and rename it to CustomUploadex.aspx
  • create a class called CustomUploadex, this class must inherits from Microsoft.Office.RecordsManagement.PolicyFeatures.ApplicationPages.UploadExPage ( assembly : C:\inetpub\wwwroot\wss\VirtualDirectories\80\_app_bin\Microsoft.Office.Policy.Pages.dll)

In this newly created class, overrides the onload event to add the following code.

As you can see, we are setting a custom url for the UploadMultipleLink, this url points on the custom mutliple upload page created in the part 1.

Change the default inherits properties to point on your newly created class. Be sure this line figure at the top of the CustomUploadEx.aspx file.

<%@ Assembly Name=”SPMU, Version=1.0.0.0, Culture=neutral, PublicKeyToken=99a1297ff3a95a0c”%>

Create a httphandler to redirect to CustomUploadex.aspx page

do not fourget to put your feature a safecontrol  if you do not do that, the HttpModule will not be attached

Your must add the following line under <modules runAllManagedModulesForAllRequests=”true”> into the web.config also to wire our httpmodule, this could be done using a feature and the SPWebConfigModification API but it’s out of the scope of this article.

<add name=”MyHttpModule” type=”SPMU.MyHttpModule, SPMU, Version=1.0.0.0, Culture=neutral, PublicKeyToken=99a1297ff3a95a0c” />

Now when requesting the original upload page, our custom page will be called.

Here are the full source of both part 1 and 2.

gl & hf

SharePoint 2010′s Upload Multiple Documents in Silverlight Part 1.

Posted by GillouX on February 21, 2011
Posted in: Client Object Model, Sharepoint 2010, Silverlight. 1 comment

A lot of people are asking why the Upload Multiple Documents button is greyed out.

The reason is simple, the component used for the Upload Multiple Documents is a ActiveX which comes with the installation of Office. So if you do not have
office installed, you do not get to use this awesome feature.

In this post I’ll explain how to integrate your own Upload Multiple documents feature. This feature will be made of a Silverlight Control integrated into SharePoint.

But before starting anything, let’s create our SharePoint solution in Visual Studio 2010.

In Visual Studio 2010, create an Empty SharePoint Project.
In the same solution, create a Silverlight Project, choose not to Host the Silverlight application in a new Web site as SharePoint will do that.

We will also add a List Instance called XAPLib (for later use).

Here is the structure of the solution we have created so far.

SPMU : SharePoint project which will contain all SharePoint stuff (customization, packaging)
SPMU.Client: Silverlight project which will contain the Multiple Upload control

Now that we have our SharePoint project ready, here is in short what needs to be done:

  • override the Upload Multiple Documents button to add our own and implement the logic behind our new button to call a modal dialog
  • implement the Application Page that the modal dialog will host
  • implement the Silverlight Control (responsible for the multiple upload) that the Application Page will host

Override the Upload Multiple Documents button

It might sound stupid but when overriding Ribbons buttons, you need first to identify the good one to override.
The definition of the Ribbon can be found in the CMDUI.xml file that you will find in the C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\GLOBAL\XML folder.

What I need to know, it’s the ID of the button that I need to override, for this purpose I open the CMDUI.xml and I will search for Multiple.

You will find, at line 4091, a button with the following ID : Ribbon.Documents.New.AddDocument.Menu.Upload.UploadMultiple -> Sounds like the good one for us.
Now that we have identify the control to override, let’s do it.

In your SharePoint project, add a new Empty Element and add the following markup in the Elements.xml


What is important in this markup, is that we use as Location, the ID we have found before : Ribbon.Documents.New.AddDocument.Menu.Upload.UploadMultiple. For the others properties, I’ve just copied-past it from the default definition that you can find in the CMDUI.xml

I’ve added a CommandUIHandler to our new button. When the user clicks on this button, it opens a Modal Dialog with the Application Page MultipleUpload.aspx.

I’ve also added another Custom Action to integrate a script block used in the EnabledScript of our CommandUIHandler. This script checks if Silverlight is installed on the computer, return true if it’s the case and so set the our Ribbon button as enable.

Application Page that the modal dialog will host : MultipleUpload.aspx

First of all, create a new Application Page called MultipleUpload.aspx into your SharePoint project.
The mapped folder Layouts will be created and the MultipleUpload.aspx page will be  added inside. This page will be used as host for the Silverlight control.

Here is the code that I use in the MultipleUpload.aspx page to host the Silverlight:


The important things to look at is that I pass two initparams :

  • ListId which defines the list the upload should target
  • MS.SP.url which defines the client context in which the Silverlight control will be loaded, if you do not set this value, you will get a null reference for ClientContext.Current

As you can see the XAP will be stored in the XAPLib but I’ll come back on that later.

The Silverlight Control

We have created at the beginning a Silverlight Project, what we need to do now it’s to tell SharePoint what to do with the output (xap file) of this project.

For this purpose, create a new Module in your Sharepoint Project. In the elements.xml of your module add the following code:

When our solution will be deployed in SharePoint, this module will take the SLMultipleUpLoad.xap and push it in the Lists/XAPLib document library.
Further to this configuration file, we need to “link” our module with our Silverlight Project.

Click on Add, a new Member will appear and on the left, set the Deployment Type at ElementFile and in the Project Name, select your Silverlight Project.

I won’t add the code of the Silverlight Control because it’s a pretty standard code which use the Client Object Model to add the file into the current document library.

Here is how your final solution should look like:

Here you will find the Visual Studio 2010 of this project.

Don’t expect anything fancy in the Silverlight code, no MVVM, no waiting animation, no exception handling, does not support large uploads… the goal of this article was to describe how you can override a built-in feature by a Silverlight Control.

Issues

…because there is all the time some, especially with SharePoint.

These issues can be splitted in two parts:

  • When a user clicks on Upload Document, the standard upload page is loaded  but sill contains the link to the OOTB multiple upload page (uploadex.aspx)
  • If a user does not have office installed, this link won’t appear.

So what we should do,  it’s to find a way to override this page but this will be part of the Part 2 of this post.

If you have any question, feel free to let a comment.

Stay tuned

The Sharepoint SPAuditEntry.EvenData mistery

Posted by GillouX on February 18, 2011
Posted in: Audit, Sharepoint 2007. Leave a Comment

For those who had the crazy idea to extract audits information from SharePoint 2007, you might have face the same problem I had. I’ll just redefine the context before getting to the solution.

SharePoint and its audit

When a item is deleted in SharePoint, an SPAuditEntry of type Delete is logged into the audit and respects the following format:


source : http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spauditentry.eventdata(office.12).aspx

Note that beside the Delete type, the EventData object can have a lot of others information related to others types of events.

SharePoint and its audit… and its issues

I was working on a small console application to extract data from the SharePoint audit when I found two issues.

1. EventData is a XML string which is made of multiple root elements
2. Despite what msdn says, the real format for a Delete type of audit looks more like the following:


Note the absence of / in the end tag Recycle

So if like me, you thought that it would be a good idea to build a XDocument from it on which you could get crazy with LinQ…
then you are wrooooonnnng (cfr 1. et 2.)

Sharepoint and its audit… and its issues… and a solution

So here is a small workaround:

When you are looping through your SPAuditEntryCollection, integrate this piece of great and advanced technology.

It will just check the presence of Recycle, and in this case, insert a root element dummy
and add / before the last occurrence of Recycle to end correctly the tag.

You can now use XDocument.Parse(entryEventData)

Joie! (spécial dédicace à un ancien collègue)

Note that the malformed Recycle element was fixed in SharePoint 2010 but you will still have the issue of the multiple root elements.

Silverlight Validation with EF’s Code-First entities

Posted by GillouX on February 12, 2011
Posted in: Code-First, Entity Framework, Silverlight, Validation. Leave a Comment

Some months ago, I was developing a Silverlight application using the Entity Framework as data layer and a WCF service as the service layer. I came across a problem when doing the client validation.

Silverlight allows use of DataAnnotations which basically provides attributes classes, the ValidationException object belongs also to System.ComponentModel.DataAnnotations. This is what I want to use to do my validations.

Consider the following (and stupid) scenario:

We have a form that the user uses to add new movies in his database. The title field is required and should be between 6 and 12 characters.

We have a standard edmx file which contains a table of Movies.
We have a Silverlight-Enabled WCF Service for the Service Layer.

Our edmx file created for us the entity Movie. The definition of this object is defined in the designer file of our edmx file and this is our problem. To add some validation logic to this business object, we will need to modify this designer file meaning that whenever we will modify something in the edmx file, we will loose our modifications.

Well the Entity Framework Code-First answers this issue by allowing to define your model objects by simply writing “plain old classes” with no base classes required.

Now that you have full control on the model objects when can modify it easily and add whatever you want, validation for instance :D

In order to use this “server-side” objects on the client, here is what you must do:

- Create a Class Library which will contains your entities, let’s call it MyMovies.Service.Entities
- Create a Silverlight Library where will will add your entites classes as link ( Add existing item, Add-> Add as link), let’s call it MyMovies.Entities
- Add a reference to this Silverlight Library in your Silverlight Project

In your WCF Service Project, add a reference to the MyMovies.Service.Entities
Use Code-First to build your DbContext using the object defines in the MyMovies.Service.Entities assembly.

In your Silvelright Project, Add a service reference to your WCF Service Project and there the magic happens.

If you look the Reference.cs file into your WCF reference, you can see that the object used in this proxy file is the MyMovies.Service.Entities files.

So here you go, you can use your validation defined in your entities.

I won’t show any code here, you can download the following project which provides a sample of what I’ve explained before.

Download Project

ADO.NET Data Services returns 1000 items

Posted by GillouX on December 8, 2010
Posted in: ADO.NET Data Services, Sharepoint 2010. 3 comments

In this post, I explain the difference between the client.svc and the listdata.svc both services provided by SharePoint.

In this article I mention the fact that the ADO.NET Data Services can retreive only 1000 items at a time and somebody asked me some informations about this limitation.

Well after some investigations I have found out that it comes from the configuration of the listdata.svc on the SharePoint. Here is what I did.

I digged into the SharePoint body and I found that the assembly which runs underneath the listdata.svc is the Microsoft.SharePoint.Linq.DataService.dll (This dll can be found in the Global Assembly Cache). Then I use my friend Reflector to open up the dll and check what’s going on in there

and … I found an interesting line.

config.SetEntitySetPageSize(“*”, 0x3e8);

It means that the maximum results returns by page will be 3e8 = 1000

Ok we can retreive only 1000 items by page but we can go through the “pages” to get all the items.

For this we will use the DataServiceQueryContinuation which will be used as token that we will pass to the query to get the next results page.

If you have any question on the code, please feel free to comment this article.

Posts navigation

← Older Entries
  • A Twitter BadgeA Linkedin Badge
    mcts
  • Category Cloud

    ADO.NET Data Services ASP.NET Audit Client Object Model Code-First Custom Action Delegate Control Document Set Entity Framework FPRPC JQuery Office Search PDF Reflector Sharepoint 2007 Sharepoint 2010 Silverlight Tools Validation
  • Categories

  • Recent Posts

    • Add custom action in Site Actions Menu at a specific location
    • SharePoint and Acrobat X integration
    • Change “Choose Picture” Control in EditProfile.aspx
    • Move a file to a document set
    • ILSpy : Open Source Reflector-like
  • Blogroll

    • Benjamin Laffont
    • Maxime Legena's Blog
    • Notes For .NET
    • SharePoint – Stack Exchange Q&A
    • Xavier Vanneste's Blog
  • Meta

    • Register
    • Log in
    • Entries RSS
    • Comments RSS
    • WordPress.com
Blog at WordPress.com. Theme: Parament by Automattic.
Follow

Get every new post delivered to your Inbox.

Powered by WordPress.com