My blog has moved!

You should be automatically redirected in 6 seconds. If not, visit
http://www.f5todebug.wordpress.com
and update your bookmarks.

Showing posts with label SharePoint. Show all posts
Showing posts with label SharePoint. Show all posts

Tuesday, 16 June 2009

Best Practice: Using the JQuery dialog widget in a custom web part

0 comments

If you have played around with the dialog widget in JQuery UI you may have noticed a couple of things.






  1. Like a lot of javascript libraries it messes with the DOM (Document Object Model) at what might be unexpected times and therefore it does not play well with SharePoint.



  2. It breaks the web part verb menu (the 'edit' drop down menu)





Actually it (like a lot of the JQuery UI widgets) is an incredibly powerful tool to your client side arsenal, and as long as you adhere to some best practice it will work perfectly happily within SharePoint, or any other ASP.Net site.



1. It messes with the DOM.



Specifically it does not play well with the ASP.Net page post back model. This is fairly well documented across the interweb (although the actual solution is not).



The dialog widget is initiated via code similar to this:



$('#dialog').dialog();





When JQuery sees this it initiates the widget and actually moves your entire div tag to the root of the DOM (see screenshot below). Therefore outside of the form tag. So any ASP.Net controls which you may have in this div will not be included in any post backs therefore none of their events will fire.



Never fear however as this is easily fixed by moving the parent element of your div, which will be another div which is created by JQuery and putting this at the root of the form instead (see code sample below).


2. It breaks the web part 'edit' menu.






Actually it doesn't. But if you have followed some code examples that are out there then it might. Essentially it may mess with this if your call to initiate the dialog is happening before the page has entirely loaded.






Fortunately JQuery has a handy way of ensuring that no matter where your code is defined on the page it will only run when the page has loaded up. This is simply accessed using:



$(document).ready();




Any function supplied to this method will be loaded in memory and run when the page has finished loading. How great is that!



As long as you follow these two items of best practice you should have no problems using the JQuery dialog widget from within SharePoint.



Code



The following code example is how I would use the dialog widget. At some point you need to run the initiateModalDialog method passing in the id of the div to use as a dialog. This will then run when the page is loaded and will initiate your dialog.




When you want to show it then call openModalDialog and optionally (because JQuery will render a nice close button in the top tight hand corner) you could call closeModalDialog to close it.



Note: If you are using this within a web part then make sure your selector (the id of your div) is unique to your web part in case you have multiple web parts on the same page.



function initiateModalDialog(selector) {







//initiates the dialog when the page has finished loading



$(document).ready(function() {



$('#' + selector).dialog({



autoOpen: false,



bgiframe: true,



draggable: false,



width: 600,



resizable: false,



modal: true,



show: 'slide'



});



});



}







//Opens the selected div as a modal dialog



function openModalDialog(selector) {







//Opens the dialog



$('#' + selector).dialog('open');







//Appends the dialog to the ASP.Net form to allow postbacks



$('#' + selector).parent().appendTo($("form:first"));







}













//Closes the selected div dialog



function closeModalDialog(selector) {



$('#' + selector).dialog('close');



}





Obviously the options which are passed to the initiation method such as 'draggable' and 'resizable' are up to you, but for this to work you must set autoOpen to false otherwise your dialog will open straight away (unless that is what you intended of course).

Links

JQuery UI dialog widget documentation









Tuesday, 7 April 2009

Inside the European SharePoint Best Practices Conference

0 comments

I am currently attending the European SharePoint Best Practices Conference at the Queen Elizabeth Conference Centre in London. So far I have attended several of the sessions on the developer track and have been surprised by the quality of both the presenters and the quality of advice on offer.

The web part development session, hosted by Todd Bleeker served as a good reminder of the topics covered in his course (which I took last year), but also he covered off some new issues and points of best practice.

The SharePoint Cowboy (Eric Shupps) and Andrew Connell have also given fascinating and insightful sessions on Custom Site Definitions and Field Controls/Web Parts respectively, both highlighting do's and dont's and areas that are likely to trip you up.

The 'rose tinted' views of the presenting MVPs and experts is one thing, but to actually get to share issues and problems with others dealing with the realities of trying to develop and deploy custom applications in SharePoint is much more revealing and insightful.

So far this has been an enjoyable experience. I hope to post more detail later, but for now its fair to say I am suitably impressed. Obviously the free beer and casino last night helped! Hats off to Steve and the guys at Combined Knowledge for stepping up and organising this to ensure that the UK has a decent SharePoint conference which delivers great value for money.

Follow the updates from the conference on twitter by tracking the #spbpc hashtag.

Monday, 16 March 2009

Documenting SharePoint - Visio Stencils

0 comments

Have you ever needed to create some SharePoint technical diagrams, that look as good as the ones produced by the SharePoint documentation team? Well now you can as they have been kind enough to release them for all to use and abuse.

You can view the documentation teams original blog post here.

Alternatively you can get the download package from here.

Monday, 2 February 2009

SPDispose Tool

2 comments

If you often use the SP object model to write code then odds are that you have probably already had to deal with a memory leak of some kind. If you do not correctly dispose of some of the objects that you create (SPWeb amongst others) then you can get memory leaks.

SPDisposeCheck is a tool to allow you to check your compiled assemblies for poor use of the SharePoint OM with regard to disposal of objects.

Paul Andrew has just published a blog post announcing the release of v1.3.1 of this tool and I recommend you download it and use it as part of your development cycle.

See Paul's blog post or download it from this page.

Thursday, 29 January 2009

Hyperlink Columns

0 comments

In SharePoint if you are using hyperlink columns there are some worthwhile things to bear in mind.
  1. If you are setting a hyperlink column value in workflow then the format is 'URL, Link Text', and the space after the comma is really important! Without it the link name will not get picked up.

  2. The column has to be 255 characters or less. If you are referring to an internal SharePoint URL using the 'Source' parameter* within it then you may easily hit this limit.

*Tip: You don't have to specify the fully qualified URL for an internal source you could just use a relative URL such as '?source=../../default.aspx'.


Just a quick post today, but I have been caught out by these issues in the past.

Tuesday, 27 January 2009

Good showing for SharePoint in top intranets

0 comments

Its great to see that exactly half of the intranets featured in the 10 best-designed intranets for 2009 from usability expert Jakob Nielsen (Nielsen Group - www.useit.com), are based on the SharePoint platform.

http://www.useit.com/alertbox/intranet_design.html

Friday, 16 January 2009

People Picker for SharePoint Designer Workflow Initiation

10 comments

Creating a workflow from SharePoint Designer is limiting in many ways, but it's also very quick and easy, and it covers a large majority of every day scenarios. One of the major flaws for me has always been the inability to select 'Person' as a data type for an initiation variable (assuming that this would render a nice people picker control in the initiation form and maybe pass back the UserID to the workflow).

In the last few days I have been determined to resolve this and have come up with a quick and easy fix using some bespoke client side code within the initiation form.

NOTE: In my workflow I actually want to send an email so I am doing a little more in the javascript. This only works because on this project UserID@domain.com is a valid email alias. However the techniques outlined here should assist anyone who needs people data into a workflow.

First of all create a new SPD workflow. Give it a name and select your list. Ensure that 'Allow this workflow to be started manually' is checked (so we get an initation form generated for us).



Select Initiation... and Add...

In the Add Field dialog enter a Field name, in my case 'email' and select 'Single line of text'.



Leave Default value blank and click on Finish. Then OK.

Back in your Workflow Designer click Next.

In this simple example I am just going to send an email, so click Actions and select Send an email. Click on 'this message' to define your email.

Click the address book on the To: line and in the Select Users dialog select Workflow Lookup... and click Add >>.

Define your workflow lookup as Source: Workflow Data and Field: Initiation: email (or whatever you called your initiation variable)



Click OK. Then OK again.

Enter a value in Subject: And also for the body text. Click OK.

Now click Finish as we are done creating this simple workflow.

If you open up the folder structure which SPD has created under Workflows you will see that there should be three files created:

  • the xoml file

  • an xml config file

  • an aspx page

The final one is the one we are interested in as this contains the initiation form for our workflow.

Double click on this so we can take a look.

You will note that essentially this is a standard SharePoint page with a DataFormWebPart which is set up to pass the initiation data to our workflow. In this case we should have a single text box for our initiation variable.

If you look at the code view you will see that various assemblies and namespaces have been included within this page already. Including the Microsoft.SharePoint.WebControls namespace which contains the PeopleEditor control. This is the key to getting people data from the users.

In code view if you put some spaces above the DataFormWebPart definition then we can include this control on the page. Just copy the code below:

<sharepoint:peopleeditor id="pplPicker" runat="server" allowempty="False" validatorenabled="True" onvaluechangedclientscript="SetPeopleValues()" allowtypein="False"></sharepoint:peopleeditor>

Essentially this is adding the control to the page and setting some properties. The really important properties here are:

OnValueChangedClientScript
This property allows us to specify some client side javascript which we wish to run every time the value in the people picker is changed.

AllowTypeIn
This property restricts the user from manually typing into the people picker and forces them to use the Browse dialog to select users. See final note.

Next we need to add the javascript to our page.

At the very top of your page after all the Page and Register tags you will notice the opening <asp:content> tag for PlaceHolderMain. We need to place the following code above this control on the page:

<asp:Content id="Content1" runat="server" contentplaceholderid="PlaceHolderAdditionalPageHead">
<script type="text/javascript">

function SetPeopleValues()
{
//Retrieve the semi-colon separated list of user id's
var people = document.getElementById('ctl00_PlaceHolderMain_pplPicker_downlevelTextBox').value;
document.getElementById('ctl00_PlaceHolderMain_InitiationForm_ff1_1').value = people;
if (people=='')
{
alert('No people selected');}
else
{
//Split the list by ; to get an array of domain user names
var arrPeople = new Array();
arrPeople = people.split(';');

//Create an empty string to hold the email addresses
var strEmails = '';

//Loop through the array of usernames
var arrEndIndex = arrPeople.length - 1;
var i=0;
while (i <= arrEndIndex)
{
//Strip the domain name off and append the email address elements
var person = String(arrPeople[i]);
person = person.toLowerCase().replace('DOMAIN\\','');
var email = person + '@domain.com';

//Add this email address to our string
strEmails = strEmails + email;

//If this is the final email then add this value to the text box in our initiation form control
//Otherwise add the semi-colon
if (i == arrEndIndex)
{
document.getElementById('ctl00_PlaceHolderMain_InitiationForm_ff1_1').value = strEmails;
} else
{
strEmails = strEmails + '; ';
}

i=i+1;
}
}
}

</script>
</asp:Content>


This uses the PlaceHolderAdditionalPageHead place holder to 'inject' some javascript into the head of the html page.

Essentially this code is retrieving the value from our people picker and inserting it into the text box held on the DataFormWebPart. In my case I am doing some additional processing (to generate a semi-colon separated list of email addresses).



NOTE: By default the PeoplePicker control (that is the TextArea html control that is rendered by the PeopleEditor SharePoint control) contains a semi-colon separated list of user names, of the form DOMAIN\UserName, so if you wanted to ignore the string parsing and processing elements of the javascript you could just set this value to the textbox straight away and then do any text processing on these values within your workflow. Like this:

function SetPeopleValues()
{
//Retrieve the semi-colon separated list of user id's
var people = document.getElementById('ctl00_PlaceHolderMain_pplPicker_downlevelTextBox').value;
document.getElementById('ctl00_PlaceHolderMain_InitiationForm_ff1_1').value = people;
}

To tidy up the look and feel of your form select the <tr> tag that contains the textbox control from within your DataFormWebPart and set the style tag to:

style="visibility: hidden"

This will mean that the end user does not see the data being passed to this textbox they just select their users and click Start.

If you save all the changes you have made to this form then try and initiate your workflow you will see that you should be able to select your users using the Browse button and then click start, an email containing the details set out in your workflow should be emailed to the users selected in your People Picker.

And that's it.



NOTE: If you don't declare the PeopleEditor control with AllowTypeIn set to false then your end users could manually type in any name regardless of whether nor not it exists or can be resolved. In this scenario clicking start will not cause the people picker to resolve the names first and the value of your textbox will be empty as our javascript will not run. If anyone has any ideas on this could they please post comments as I would like to get this working.

Thursday, 8 January 2009

What do SharePoint developers want from a blog post?

0 comments

I'm just interested in seeing and hearing what other people searching for blog posts on SharePoint are interested in?

If there is a particular SharePoint development area that you are interested in then let me know and I will try to put together a post on my experience (or lack of it) in that area.

Monday, 22 December 2008

Initiate a SharePoint workflow from a button on the list view.

0 comments

I came across a scenario recently where a project required that a list of items could have a button or link on a list view, which would cause the workflow to start.

Essentially the users involved were not happy using the OOB way that SharePoint (WSS 3.0) allows users to manually initiate workflows. They believed there were too many steps involved.

After a bit of searching and Googling, I discovered a method involving the use of a hyperlink column on the list in question, coupled with a very simple workflow. I will outline the steps involved in this process below. This is not the most graceful solution I am sure, but it is a simple solution to what can be a tricky problem.

How was it done?

Note: I am assuming that you have a simple workflow attached to a list, if not then please create a simple SharePoint Designer workflow. You can see how to do this here.

1. Add a new hyperlink column to your list, this is going to represent the button which users click on to start the workflow, so give the column an appropriate name.



2. Click on the list settings for your list and select 'Advanced settings', ensure that 'Allow management of content types' is set to 'Yes'. This will allow us to hide the hyperlink column from the forms involved, if your list is a custom list then you may be able to go to 'Form settings' within list settings and make more detailed amendments to what appears on the new, display and edit forms.



3. In the 'Content Types' section of the 'List Settings' page, click on the content type for your list. Then click on the name of your column. On the 'Change List Content Type Column' page click on the radio button for 'Hidden'. Click 'OK'and return to your list, you should see an empty space for your new column. However if you click on 'New' or try to edit an existing item your column should not display.



4. I have a simple workflow attached to this list. This basic workflow merely adds an entry to the workflow history list saying 'Workflow started OK'. I assume your workflow is going to be slightly more complex, however the principle is the same. If you click on an item in your list (if you don't have one then create a quick test entry), and select the 'Workflows' icon from the item toolbar. Now click on the name of your workflow.



5. You should now be looking at the initiation page which SharePoint Designer has created for us, now this page can be cutomised to say whatever you wish via SharePoint Designer, but I am going to leave it as the default for now. The important part here is the URL and parameters.



The URL of this page will be something similar to:

http://SITE URL/List Name/Workflows/Workflow Name/Workflow Name.aspx

and it should have 4 URL parameters, these are as follows:

List
The guid which identifies the list involved. This will not change for each link required on our list.

ID
The numerical ID of the list item involved. This is the key to making this process work.

TemplateID
The guid of the workflow to be initiated. This will not change for each link required on our list. Note: This guid, unlike the list guid above requires the braces {}, though these may be url encoded (so don't be suprised to see the guid starting %7B which is { when URL encoded).

Source
The referring URL, responses will be redirected back to here once the workflow is succesfully started.

You can probably see that we could manipulate this URL to generate a link for our new hyperlink column by simply altering the ID parameter being sent to this page. How can we do this? We simply use another workflow!

6. Ensure you have copied the URL from step 5 to the clipboard. Open SharePoint Designer and create a new workflow for this site. This simple workflow should be set to 'Automatically start this workflow when a new item is created' only.



7. Click 'Next' and then add a 'Build Dynamic String' action click on 'dynamic string' and paste your URL into the 'String Builder' window. Find the ID parameter and delete the value which you had pasted in. Leaving the cursor in this location click on 'Add Lookup' and select the 'ID' column of the 'Current Item'.



Click 'OK'. Your URL should now look similar to that shown above. At the end of the URL add a comma (,) followed by the text which you want your hyperlink column to display in the list view. For example I have added ', Start my workflow'. There must be a space between your comma and your link text. Otherwise you will get the entire URL as the text for your hyperlink!

Click 'OK' again.

8. Add another action to 'Update List Item' and with Current Item selected click on 'Add'. The 'Value Assignment' dialog will allow you to assign your new hyperlink column to the value of the URL string we have just generated. Select your new hyperlink column from the 'Set this field:' list. Next to the 'To this value:' list select the 'fx' button. In the 'Source:' drop down select 'Workflow Data' and in the 'Field:' select your variable (probably named with the default 'Variable: variable')





Click 'OK' then 'OK' again on the 'Value Assignment' dialog. The 'Update List Item' dialog should now show this field and value in the list of items to be updated. Click 'OK' again.

9. We can now click 'Finish' to complete our simple workflow. SharePoint Designer will now generate the required files and bind this workflow to your list.

10. Go to your list and click on 'New' in the list toolbar, complete a test item (noting that your hyperlink column is not listed). Click 'OK' and you should return to your list view and your hyperlink column should be populated with the display value you entered in stage 7.



Clicking on this hyperlink should take you to the initiation page that SharePoint Designer created for you, but (crucially) the ID will be the ID for the item which the hyperlink column exists on.

Clicking 'Start' on this page will start your workflow as designed in SharePoint Designer.

So there you go! Wait for it...There are a few buts...

Issues

1. Document Libraries with check in/out enabled
This is the same as designing any workflow which is going to update these items, you must handle checking in/out. Because our workflow is only initiated on creation then this is not a major issue, but I did come across some problems in this scenario, but they were overcome by having the workflow check the item back in before updating.

2. Custom Workflow
This workaround is designed for dealing with either SharePoint Designer workflows or custom workflows which use an initiation form as SPD always creates a workflow initiation form anyway. It will not work for custom workflows that do not require an initiation form as there is no URL to link to (This is a scenario that I am interested in so if anyone has any recommendations then please post a comment). If your custom workflow uses an InfoPath form to initiate then you might want to look at creating links to the following URL:

http://SITE URL/_layouts/IniWrkflIP.aspx

This page takes similar parameters to the SPD generated page except you can supply an xsn location for your infopath form too. More information can be found here. The above technique should work perfectly well in this scenario, I just haven't tried it.

Credit: Thanks to Laura Rogers from the sharepointdiscussions Yahoo group for pointing me in the direction of this method.

Tuesday, 16 December 2008

Microsoft.SharePoint.SoapServer.SoapServerException whilst using the SharePoint web services

0 comments

Whilst trying out some development concepts using the SharePoint Lists.asmx web service I came across the above error message everytime I tried to call the GetList or GetListItems method. My code was simple:

Dim serLists as New myService.Lists
serLists.Credentials = System.Net.CredentialCache.DefaultCredentials
Dim myItems as XmlNode = serLists.GetListItems("MyList", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing)


However whenever I ran this through I got the mysterious error:

Microsoft.SharePoint.SoapServer.SoapServerException

Visual Studio debugging did not report any inner exceptions so I could not find out what the problem was.

The solution is a simple one. The Lists web service will execute methods on the root web (SPWeb as in site) on the Site Collection, even if your web service reference is to a site further down the site collection.

There is a URL property on the proxy class generated for the web service, you need to set this to the url of the web service within your sub site. This must be set BEFORE you use the service proxy class to call the method.

Example

'Set the Url property of the service for the path to a subsite.
'Not setting this property will return the lists in the root web site.
serLists.Url = http://Server_Name/Subsite_Name/_vti_bin/Lists.asmx


Hope this helps!

Tuesday, 8 July 2008

Keeping Up - SharePoint

0 comments

For those of you interested in the best ways of keeping up to date with information and developments with SharePoint then the SharePoint Product Team have posted a great blog article with links to a load of really useful RSS feeds.

Suck 'em up and keep updated!

Microsoft SharePoint Team Blog - A much easier way to keep track of new SharePoint content published on MSDN and TechNet

SharePoint Developer Training

0 comments

This post comes as I am undertaking a SharePoint developer course with Combined Knowledge. The training is being delivered by Todd Bleeker a SharePoint MVP from US firm Mindsharp. Todd's enthusiasm for SharePoint is infectious and the training is highly detailed and relevant.

I hope to post some articles on tips for SharePoint developers once the course is complete.

For further info see Combined Knowledge, Mindsharp, Todd Bleeker