SharePoint Automatic prefilling of lookup fields in insert forms using JQuery

At my last project I was working on a SharePoint online solution and one of the requirements is to prefill some values at one of the insert forms for a list. Since this is SharePoint online and the only tool you can use to customize is SharePoint Designer I had to do this with JavaScript.

I’ll explain how to build it by an example. for example you have a list of customers and a list of customer actions. What I wanted to build was a way to make it easier to add a customer action for a specific customer. To do this I added a custom column to the customer list containing a link to the edit form with the customer id as an url variable. Of course the out of the box you can’t create links or any other html with calculated fields so I added more javascript there.

to enable html as output of a calculated field just copy this piece of javascript and put it in a content editor webpart or paste it on your master page.

var theTDs = document.getElementsByTagName("TD"); 

var i=0; 

var TDContent = " "; 

while (i < theTDs.length)

{ 

  try

  { 

    TDContent = theTDs[i].innerText || theTDs[i].textContent; 

    if ((TDContent.indexOf("<DIV") == 0) && (TDContent.indexOf("</DIV>") >= 0))

    { 

      theTDs[i].innerHTML = TDContent; 

    } 

  } 

  catch(err){} 

  i=i+1; 

} 

Thanks Marijn Somers for this piece of code. original source: http://marijnsomers.blogspot.com/2010/01/write-html-code-in-sharepoint-via.html

so now my calculated field was a link in html. what did my calculated field look like?

="<DIV><a href=’../../Lists/CustomerActions/NewForm.aspx?Customer="&[Customer ID]&"’>Add Customer Action</a></DIV>"

First a DIV element since the javascript above only replaces elements starting with a <DIV> to html, then just a plain html link to the NewForm.aspx sending the customer id as an url parameter.

 

So now the changes in the customer list are done and we only need to add some more javascript at the NewForm.aspx or again just at your masterpage to get the parameter from the url and selecting the right lookup field value at the form.

I’ve created the following code  using Jquery:

var customer = $.getUrlVar("Customer");

 

if(customer != "")

{

  $("input[title='Customer']").val(customer);

  

  $("select[title='Customer']").children("option").each(function() {

    if($(this).text() == customer)

    {

      $(this).attr('selected', 'selected'); 

    }

  });

}

My customer actions list contained a Customer field which is a lookup to the Customer list by Customer ID. The script above gets the Customer ID from the url parameters first and then tries to set the lookup item. SharePoint renders lookup items in 2 different ways. as a select box when there are less then +/- 25 items and as a auto complete textbox when there are more then 25 items in the lookup list. Because of that I firs try to set the textbox to the right value and after that the select. I’m using the title attribute to locate the right input field because it gets the same name as the field from SharePoint by itself.

Now when I open the newform.aspx?customer=1234 my customer lookup field is automatically prefilled with 1234

 

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

Using the SPContext in HttpModules in SharePoint

When you are building custom HttpModules in SharePoint a common thing to do is to use the SPContext object to get acces to your SPSite, SPWeb, SPList or SPListItem. When doing this you have to be careful because the SPContext isn’t available everywhere because HttpModules can run early in the ASP.Net request pipeline so the SPContext object isn’t available yet.

if you try to acces the SPContext to early in the pipeline you’ll get a System.InvalidOperationException error.

The earliest you can use the SPContext is in the “PreRequestHandlerExecute” so don’t use it at the BeginRequest event what most people try to use when they want to add code as early in the pipeline as possible

code:

   1: public class RequestHandlingHttpModule : IHttpModule, IRequiresSessionState

   2: {

   3:  

   4:     public void Dispose() {}

   5:  

   6:     public void Init(HttpApplication application)

   7:     {

   8:         application.BeginRequest += application_BeginRequest;

   9:         application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute);

  10:     }

  11:  

  12:     void application_PreRequestHandlerExecute(object sender, EventArgs e)

  13:     {

  14:         string webUrl = SPContext.Current.Web.Url;

  15:     }

  16:  

  17:     void application_BeginRequest(object sender, EventArgs e)

  18:     {

  19:         // do not use SPContext here it will throw a System.InvalidOperationException 

  20:         // this event is fired before PreRequestHandlerExecute so code that doesn't uses SPContext goes here

  21:     }

  22:  

  23: }

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

Combined power of SharePoint and JQuery part 2: Changing the SharePoint webpart edit menu position

Have you ever had the problem using SharePoint 2007 that when you create small webpart zones that the edit button disappeared because the title of the webpart was to long? I ran into this problem at my current project and instead of shortening down the titles i came up with the idea of changing the position of the edit button to be on the left of the title. when the button is on the left and the title is on the right the title will be trimmed automatically since the webpart zones have a fixed length.

In your server side code it’s really hard to change these kinds of things because this is standard SharePoint functionality and you can’t change it server side. So the solution is to fix it using javascript and to make that easier I’m using JQuery.

first I’ll show you the results below and then how I did it using a small JQuery script.

before:

sharepointjquery1

after:

sharepointjquery2

Below is the JQuery script to change the position of the edit menu to the left. the only thing you have to do is save this code to a js file, include the reference to the js file and a reference to the JQuery library js file on your masterpage and you’re done.

   1: $(document).ready(function() {

   2:     SPEditMenuFix();

   3: });

   4:  

   5: function SPEditMenuFix() {

   6:     $(".ms-WPHeader").each(function() {

   7:         var first = $(this).children("td:first").clone(true);

   8:         var last = $(this).children("td:last").clone(true);

   9:         $(this).children("td:first").replaceWith(last);

  10:         $(this).children("td:last").replaceWith(first);

  11:     });

  12: }

Enjoy!

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

Combined power of SharePoint and JQuery part1: Changing the SharePoint Image Picker

Wow… long time since i blogged. Thank god I’m going to the Dutch DevDays to see Scott Hanselman’s session called “How to make your blog suck less” :)

So here is an update of mine about how to use JQuery in SharePoint to do some fancy tricks. I’ll post some more of these tricks later on and I’ll try to be more active as a blogger again. (In which I’ll probably fail)

Have you ever tried to change some of SharePoint’s default controls like the image picker?

Well I have. My customer wanted a image picker that worked exactly like the normal one except for 1 change. It shouldn’t show the selected image as an image but it should only show the URL of the selected image. I tried to change this at server side first by inheriting from the default SharePoint image picker control. This was a rather annoying job as i didn’t seem to get the right result this way. you cannot extend the rich image picker from sharepoint but only the default image picker that doesn’t have the image library function behind it.

When i was looking at the html that was rendered by SharePoint i thought it would be easier to change the html with jquery as with serverside code and this is the result. just save this source to a .js file and include it into your masterpage or aspx page and all selected images in the image picker will be changed to only show the url of the image.

///<reference path="jquery-1.3.2.min-vsdoc.js" />

 

$(document).ready(function() {

    HideImages();

});

 

function HideImages() {

    $("span[id $= '_RichImageField_ImageFieldDisplay']").each(function() {

        var url = $(this).find("img").attr("src");

        $(this).find("a").hide();

        $(this).append("<span class='imgurl'>" + url + "</span>");

        $(this).find("a").each(function() {

            $(this).find("img").each(function() {

                $(this).load(function() {

                    $(this).parent().hide();

                    var imgurl = $(this).attr("src");

                    $(this).parent().parent().find(".imgurl").text(imgurl);

                });

            });

        });

    });

}

It’s as easy as that.

More JQuery fun to post in the future.

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

Set file level permissions in SharePoint using Workflow Foundation

Hello Everyone, 

On my current project we are building a customer facing SharePoint application which has to store files. These files are uploaded with biztalk so we have to set the permissions manually so only the user who the file belongs to has rights to open te file.

We are storing the username of the owner of the file in the metadata of the sharepoint item and we are going to use this to set the permissions after the file is uploaded to sharepoint by Biztalk.

After adding the file we've set up a SharePoint Workflow to move the files to a specific location and we've come up with the idea to also change the permissions in this workflow. How we did this? here's the code to change the permissions of a SharePoint SPItem in the workflow:

   1:  workflowProperties.Item.BreakRoleInheritance(false);
   2:   
   3:  workflowProperties.Item.File.MoveTo(currentFolder + "/" + workflowProperties.Item.File.Name);
   4:   
   5:  SPRoleDefinitionCollection rolecollection = web.RoleDefinitions;
   6:  SPRoleAssignmentCollection roleAssignments = workflowProperties.Item.RoleAssignments;
   7:   
   8:  SPUser user = web.EnsureUser("aspnetsqlmembershipprovider:"+workflowProperties.Item.Properties["Username"].ToString());
   9:  SPRoleAssignment roleAssignment = new SPRoleAssignment(user as SPPrincipal);
  10:  SPRoleDefinitionBindingCollection roleDefBindings = roleAssignment.RoleDefinitionBindings;
  11:  roleDefBindings.Add(rolecollection.GetByType(SPRoleType.Reader));
  12:  roleAssignments.Add(roleAssignment);

 

We are using an aspnetsqlmembershipprovider to store the external users so thats why we add this to the sharepoint username.

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

Add documents from a Base64Binary xml element to SharePoint with Biztalk 2006

On my current project we wanted to add documents which come in as attachment through a webservice to a sharepoint document library to store them.

We used Biztalk 2006 to receive the file, get the different files from the xml and then send them to SharePoint. In this blogpost I’ll explain how to do this with a small POC I made.

First off we started with a receive port which is able to receive the xml message (the binary port on the picture) we receive this message into a BinaryMessage message which is linked to the following schema

An example message is looking like this: (where the <document> should have the attachments as a base64binary string.

After receiving the message we want to loop through all the messages in the document so I created a foreach to read all the document elements from the xml.

The code to build the loop is the following:

InitializeLoop :

iteration = 1;

documentCount = xpath(BinaryFile,"count(/*[local-name()='BinaryFileToSharePointTest' and namespace-uri()='']/*[local-name()='Document' and namespace-uri()=''])");

first I set the iteration variable to 1 and I set the documentCount to the amount of document elements that are in the incoming xml file.

Message assignment

BinaryFileWithMetadata = BinaryFile;

binaryMessageCreator = new BinaryToSharePoint.Helper.BinaryMessageCreator();

selectXpath = "string(/*[local-name()='BinaryFileToSharePointTest' and namespace-uri()='']/*[local-name()='Document' and namespace-uri()='']["+ System.Convert.ToString(iteration)+"]/text())";

base64String = xpath(BinaryFile,selectXpath);

binaryMessageCreator.CreateBinaryMessage(BinaryFileWithMetadata,base64String);

configProperties = new VdCruijsenNet.Utilities.Sharepoint.ConfigPropertiesXML();

configProperties.AddProperty("Title","test");

BinaryFileWithMetadata(WSS.ConfigPropertiesXml) = configProperties.ToString();

BinaryFileWithMetadata(WSS.Filename) = "bestandsnaamTest "+System.Convert.ToString(iteration)+".pdf";

In the message assignment we first Create the new outgoing message for each of the documents in the incoming xml file. Then we select the base64binary string with an xpath expression and send it to the binaryMessageCreator.

The binaryMessageCreator creates a new System.Xml.Document (which isn’t a xml file but biztalk doesn’t know that :) from the base64binary string. For the source of the BinaryStreamFactory see below:

After creating the new Message of the type System.Xml.Document, which is actually a byte[] containing the file we add a filename and some metadata which can be stored in SharePoint we send the message with the send shape to sharepoint.

The SendPort is a “Windows SharePoint service” sendport which can automatically add the file to a sharepoint document library.

 

Sendport

Receiveport

As you can see it’s pretty easy to get the binary files from an xml file in Biztalk after you know how you can do it.

Happy Coding

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

MOSS workflow wont start because ‘The requested workflow task content type was not found on the SPWeb’

The last 2 days my MOSS environment was driving me crazy because an already existing workflow didn't want to start in a new document library in a new subsite. I made this workflow in Visual Studio 2005 and deployed it as a feature to my SharePoint Site. I connected the workflow to a content type and told it to run on new items of this type or whenever an item changes. This workflow worked fine for 2 months in this particular document library.

After 2 months my client asked for a new subsite with a new document library where this workflow should also run. I installed this workflow here and expected everything would go as planned. When I tried to test the workflow I didn't see anything happen so I tried creating new items, changing them, even manually starting the workflow. Nothing happened. The metadata field which contains the workflow status was staying empty. When checking the log files I didn't see anything either.

I tried to reinstall the workflow. Deleted and recreated the site nothing seemed to help. During all this the workflow still worked fine in the other subsite and document library. When I recreated the workflow and checked the logfile again I finally found an error. (it seems Sharepoint only logs this error the first time you start the workflow and after that it doesn't do anything)

The error message in the logfile was the following:

Workflow Infrastructure        72fv Unexpected AutoStart Workflow: System.ArgumentException: De aangevraagde werkstroomtaakinhoudstype is niet gevonden op SPWeb.     at Microsoft.SharePoint.SPList.PrepForWorkflowTemplate(SPWorkflowTemplate wt)     at Microsoft.SharePoint.Workflow.SPWorkflowManager.StartWorkflowElev(SPListItem item, SPFile file, SPWorkflowAssociation association, SPWorkflowEvent startEvent, Boolean bAutoStart, Boolean bCreateOnly)     at Microsoft.SharePoint.Workflow.SPWorkflowAutostartEventReceiver.AutoStartWorkflow(SPItemEventProperties properties, Boolean bCreate, Boolean bChange, AssocType atyp)

this Dutch error (I really hate Dutch errors. you can't look them up on Google/MSDN:( )translated in English is 'The requested workflow task content type was not found on the SPWeb'. I found the exact translation because I was lucky and when I had the English error this gave me new hope to find a weblog with the answer (since weblogs seem the primary documentation for SharePoint 2007 ;) )

I searched for the error and everything I could find was reinstalling the OffWFCommon feature. I tried this with the following commands but nothing changed. I also tried to uninstall and reinstall but this didn't help either

stsadm -o installfeature -filename OffWFCommon\feature.xml
stsadm -o activatefeature -filename OffWFCommon\feature.xml -url http://localhost/

This weblog told me the exact thing that was going on. the TaskListContentType wasn't installed on my tasks documentlibrary when I checked it by enabling content types chaning in the advanced settings of the tasks list. The ID of this content type is 0x01080100C9C9515DE4E24001905074F980F93160 which is the same as the OffWFCommon feature so it definitely had something to do with it. When I checked the content types of my task doclib that was working I noticed it had 2 content types attached. 1 called "Task" and 1 called "Workflow task content type" my Tasks library that wasn't working had a content type called "Tasks". I couldn't find any way how to add these content types because these are system content types and thus hidden.

Solution/Workaround:

Since I already wasted 1 and a half day on this problem my next try was to save the Tasks documentlibrary of the workflow that was working as a template. After that I deleted the workflow in the new document library and also deleted the Tasks list there. I added a new Tasks list by using the template I made and installed the workflow again for this documentlibrary. I tested it and guess what.. everything seemed to work fine. The solution isn't that pretty but I was glad it finally worked!

Hopefully someone with the same problem reads this before they waste to much time on this really awful problem. Also if you know  a better solution please let me know because I would really like to know how to really solve this problem.

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

SharePoint Workflow running in a different context as the host sharepoint site

On my current project I ran into a problem with a custom SharePoint workflow because the workflow sometimes failed to run and sometimes it worked like a charm. When I cancelled a workflow which gave an error and restarted it by hand it finished without any problems.

When I looked in the SharePoint logfiles what was causing my workflows to crash it showed that the workflow couldn’t find values for some settings in the web.config. I couldn’t think off any reason why the workflow couldn’t read these settings about 50% of the times a workflow was started.

The workflow I created is automatically started after the change of an item in a specific document library. After some testing I found out that all workflows that I started by changing the item with the sharepoint webinterface worked fine but the items that were changed by an external source (a custom webservice I created but also the biztalk SharePoint Adapter webservice) crashed with the error that they couldn’t read the web.config.

The webservices that are causing the workflow to crash are in a different sharepoint webapplication and thus use a different web.config. When I added my settings in the web.config of this webapplication the workflows stopped crashing.

So it seems that the WF workflows are running in the process which changed the item in the sharepoint list which caused the workflow to start instead of the standard w3p process of SharePoint which I thought always was the case.

Happy coding!

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

SharePoint BDC listview error: “An unhandled exception has occurred: There was an error in the callback”

So after my first month off having my own development blog I already start to slack on making new posts. Not a good sign ;) Well here’s an update again about a weird error I came across in SharePoint today. I'll try to make more posts in the near future but lately I didn't see any cool things to blog about. I also spend most of my free time to study for my MCPD exam next week.

I was working on a SharePoint Solution using the Business Data Catalog to retrieve data from a mssql database and to show this data in a BDC list view. On my development machine everything was working fine so I uploaded it to my test environment and what happened.

The following error came up: "An unhandled exception has occurred: There was an error in the callback"


I checked the trace log and the event viewer. Both didn’t show anything about any error involving the Business data catalog. Google didn’t result in anything useful either so I asked around at some colleagues. Finally one of them gave me the following link:

http://discuss.joelonsoftware.com/default.asp?dotnet.12.506335.2

The people at this page have a slightly different problem but I didn’t have any other solutions so I thought I might give it a try. And after I tried it I was stunned. The Data List view actually worked.

So what was the solution? Adding a Search box web part to the page containing the BDC data list view did the trick. You can set the search box to invisible if you don’t want it visible on your page.

I haven’t looked why this search box webpart is connected to the data list view yet but I would really like to know why. It took quite some time to figure this one out so in the end I was happy it worked.

For anyone of you who encounter the same problem as I did I hope you find this post faster as I found my answer today.

Enjoy!

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter

Searching Custom columns in SharePoint

The SharePoint Keywordquery and Fulltextsearch are good ways to search metadata programmatically. This option is only available for MOSS 2007 because you don’t have a server context object in WSS 3.0.


When you Create a keyword query instance the metadata properties that will be returned will only be the basic SharePoint metadata fields like name, title etc. When you want to get your own created columns in the results you’ll have to add the property names to the to the SelectProperties object from the keywordquery.

// Set result properties
kwq.SelectProperties.Add("ProductID");

To search custom SharePoint properties you’ll have to set these properties as Managed Metadata first. After you’ve done this it’s pretty easy. You can just put “propertyname:value” as QueryText and then the search will search the property “propertyname” which contain “value”. You’ll have to put quotes around the search value because otherwise the search will also show results where the value is only a part of the property value.

Below is a full example how to create a KeywordQuery in code for in example your custom webparts.

string SSP = ConfigurationManager.AppSettings["SSP"].ToString(); 
ServerContext context = ServerContext.GetContext(SSP);
KeywordQuery kwq = new KeywordQuery(context);

// Set properties for the query before executing
kwq.ResultTypes = ResultType.RelevantResults;
kwq.EnableStemming = true;
kwq.TrimDuplicates = true;

// Set result properties
kwq.SelectProperties.Add("ProductID"); 

kwq.QueryText = column + ":" + value;
// Fetch data
ResultTableCollection results = kwq.Execute();
ResultTable resultTable = results[ResultType.RelevantResults];

// Load data into a DataTable
DataTable tbl = new DataTable();
tbl.Load(resultTable, LoadOption.OverwriteChanges);

return tbl;

Hope this will help you building your own custom search webparts in MOSS 2007

Geert van der Cruijsen

Share on Facebook
Kick It on DotNetKicks.com
Shout it
Post on Twitter