Changing SQL port on SharePoint installations

Scenario:

Our QA environment had been installed and configured. Working fine with a DB alias connecting to standard port 1433. The RFC though stated that port xxxx was to be used. No biggie: we changed the port on the SQL listener in our AlwaysOn setup. Changed the port in DB Alias config on the SharePoint servers. It didn't work.

Resolution:

Make sure that when you change something in cliconfg.exe (SQL Server Client Network Utility) it is correctly configured to use the appropriate network library. We use TCP/IP but the Utility somehow (read: human error) made a switch to Named Pipes (which was not setup on the SQL side.
Morale: Make sure to tick of the appropriate Network Library.

SharePoint eventreceivers and Nintex workflow

Been working on a project utilising Nintex Workflow 2010 and custom event receivers.
These two components should in theory not have impact on each other but in the real World; they do!

My project contains a custom Nintex Workflow containing simple actions, one being the "Wait for item to be checked in". The workflow would crash randomly not specifically around the aforementioned Nintex action. So we looked at our simple eventreceiver.

Our eventreceiver was simple: took a value from one field, did some computation, and then wrote the new value back to another field. We did this in the asynchronous events (ItemAddED and ItemUpdatED). After doing the deed we updated the listitem and went on.

This seems to have caused confusion with the workflow. So we changed the event hook to be on the synchronous events instead (ItemAddING and ItemUpdatING).
This seems to have solved the problem relating to the workflow. But the code has to be somewhat different. In the synchronous events you have to persist the changes to the properties.AfterProperties and NOT update the ListItem (if does exist; it does not exist in the ItemAdding-event). In a asynchronous event the listitem has been created and you persist your changes to properties.ListItem and call the Update (or SystemUpdate) method on the ListItem.

Just a little reminder :)

Content databases, version numbers and upgrades / mounting

Doing a new project I faced the challenge to mount a copy of a production content database from my customer to my SharePoint DEV "rig" (my sturdy Lenovo W520).

The steps should be fairly simple:

  1. Get the .bak file from the customer
  2. Bring to my lab
  3. Restore it in SQL Management Studio
  4. Dismount the current content database of the web-app in question
  5. Mount the new content database

NOTE to the above steps: in real life production scenarios one should ALWAYS use a scripted and tested approach!

But I found out my rig hadn't been updated since I created it a year ago, so it didn't even have SP1 installed. The mount-spcontentdatabase cmdlet threw an error stating the schema version of the database being attached wasn't the same as the farm it was being attached to. Now, I didn't know at that time which patchlevel the customer is on (I've just started the work yesterday and haven't had a chance to read the entire documentation and history Foot in mouth). I dug around the new contentDB and found the table dbo.Version. It contained a row stating which patchlevel was used. It seemed to be the June 2011 CU, which is post-SP1. I reckoned, that I would just install SP1 and see where it would take me… Same result as the first try. This was actually expected. So instead of downloading the June 2011 CU, mount the contentDB and then AGAIN upgrade to the latest available CU (atm it is Feb 2012 CU, April 2012 CU has been pulled) I just patched my farm the latest available hotfix package (being Feb 2012 CU). I had my doubt if this path would work. But eventually it came through (took aorund 75 minutes total (SP1 + Feb2012CU) and the contentdatabase mounted successfully, and the sitecollection seems to respond.

So, morale is:

You can upgrade to a later CU than the contentDB is on. And why shouldn't this work?! Wink But remember: this is a DEV rig. It does prove just one thing: it is possible to perform this maneuver, but in real-life production environments I recommend using the CU necessary and test it thoroughly in your own environment before putting it on production servers.

Sharepoint, 64-bit Office and Datasheet view

Some times you want to edit a list in datasheet view:

But you get an error, if you've installed the 64-bit version of Office:

This is resolved by installing 2007 Office System Driver: Data Connectivity Components

Creating Notes://-links in SharePoint 2010's Rich Text Editor (RTE)

I've been working on a project where we have migrated a customer from Lotus Notes to Exchange and SharePoint. On the SharePoint side a requirement arose to be able to link to document in the old Notes database. (Notes-links starts with notes:// in the URL and requires Lotus Notes to be installed on the client to be intepreted correct) We found out, that the Rich Text Editor in SP2010 won't allow notes://-links : they are banned by javascript in core.js (it only allows http, ftp, \\, and similar normal protocols). So, when creating a notes://-link in the RTE you are left with an empty a-tag with no href. No matter what you do! Either the client side javascript removes the link or the serverside when posting (if you manually have created the link in HTML-view).

So, the solution for us was actually not that easy. Some forums on the WWW suggests that you edit your core.js to contain the notes:// protocol in the array of allowed protocols. BUT, this will actually leave you in an unsupported state if you upgrade your farm (SP or CU's). That does not fly. So the solution for us kinda three-fold;

  1. Create an easy way for the editors to cvreate links by "mimicking" the normal RTE "Insert Link" (external) in SharePoint
  2. Create a "redirect service" on the server that transferred the user to Notes
  3. Make sure for max usability to get the user back to page they came from

The way I made the mimicking of the standard RTE "Insert Link" was to

  1. Create a button which was placed the same place as the other "Insert Link" shortcuts.
  2. Create a dialog that displayed the same interface as the standard "Insert Link". This was done by completely copying the existing dialog .aspx and changing a few lines
  3. Make this dialog return a url which was not truncated or cut out by the server side execution.

To create the button, the following Elements.xml was produced:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
               <CustomAction
                             Id="Intranet.CustomActions.NotesLink"
                             Location="CommandUI.Ribbon">
                             <CommandUIExtension>
                                            <CommandUIDefinitions>
                                                          <CommandUIDefinition
                                                                         Location="Ribbon.EditingTools.CPInsert.Links.InsertLink.Link.Menu.Link.Controls._children">
                                                                         <Button 
                                                                                        Id="Intranet.CustomActions.InsertNotesLink"
                                                                                        Command="RTE.RichTextEditor.insertNotesLink"
                                             Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-160" Image16by16Left="-224"
                                                                                        Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-160" Image32by32Left="-448"
                                                                                       Description="Inserts notes://-link"
                                                                                       LabelText="Insert link poiting to Notes"
                                                                                       Sequence="30"
                                                                                       TemplateAlias="o1"
                                                                                       ToolTipTitle="Indsæt notes link tool tip"
                                                                                       ToolTipDescription=""/>
                                                                                                      />
                                                          </CommandUIDefinition>
                                            </CommandUIDefinitions>
                                            <CommandUIHandlers>
                                                          <CommandUIHandler
                                                                         Command="RTE.RichTextEditor.insertNotesLink"
                                                                         CommandAction="javascript:RTE.RichTextEditor.insertNotesLink();"
                                                                         />
                                            </CommandUIHandlers>
                             </CommandUIExtension>
               </CustomAction>
</Elements>

The changes in the aspx where minor (some lines removed for readability, just copy (and rename to customerrtedialog.aspx) the existing rtedialog.aspx and replace the lines validating the protocol with this):

function OkButtonClick()
                                            {
                                                          var arr = new Array();
                                                          var valid = 1;
                                                          if ((document.getElementById(">")) != null)
                                                          {
                                                                         arr[0] = (document.getElementById("")).value;
                                                          }
                                                          if ((document.getElementById("")) != null)
                                                          {
                                                                         arr[1] = "/_layouts/Customer.Intranet/Customer.LotusNotesRedirect.aspx?target=" + encodeURIComponent((document.getElementById("")).value);
                                                          }
                                                          if (document.pageName == "SharePointLink")
                                                          {
                                                                         if (arr[0] == null || typeof(arr[0]) == 'undefined' || arr[0].trim().length == 0 ||
                                                                                       arr[1] == null || typeof(arr[1]) == 'undefined' || arr[1].trim().length == 0)
                                                                         {
                                                                                       alert("You must specify a list and an item.");
                                                                                       valid = false;
                                                                         }
                                                          }
                                                          if (document.pageName == "InsertTable")
                                                          {
                                                                         if (arr[0] < 1 ||
                                                                                        arr[1] < 1 ||
                                                                                       isNaN(Number(arr[0])) ||
                                                                                       isNaN(Number(arr[1])))
                                                                         {
                                                                                       alert("");
                                                                                       valid = 0;
                                                                         }
                                                                         if (valid && arr[0] * arr[1] > 625)
                                                                         {
                                                                                       alert("");
                                                                                       valid = 0;
                                                                         }
                                                          }
                                                          if (document.pageName == "CreateLink")
                                                          {
                                                                         valid = true;
                                                          }
                                                          if (valid)
                                                          {

                                                                         commonModalDialogClose(1 , arr);

                                                                         window.returnValue = arr;
                                                                         window.close();

                                                          }
                                            }

In the masterpage i added an EditMode-panel at the very bottom to reference the following javascript, which extends the existing functionallity. The javascript is put in a seperate .js-file.

RTE.RichTextEditor.insertNotesLink = function () {
               ULSkay: ;
               RTE.SnapshotManager.takeSnapshot();
               RTE.ObjectCommands.insertNotesLink();
               RTE.SnapshotManager.takeSnapshot();
}

RTE.ObjectCommands.insertNotesLink = function () {
               ULSkay: ;
               var $v_0 = RTE.Cursor.get_range();
               if (!$v_0.get_isEditable()) {
                             return;
               }
               if (!$v_0.$EP()) {
                             return;
               }
               var $v_1 = new RTE.InsertNotesLinkDialog();
               $v_1.show();
}


RTE.InsertNotesLinkDialog = function () {
               ULSkay: ;
               this.$85 = Function.createDelegate(this, this.$Dq_0);
}
RTE.InsertNotesLinkDialog.prototype = {

               show: function () {
                             ULSkay: ;
                             var $v_0 = new RTE.InsertLinkDialogArguments();
                             $v_0.allowRelativeLinks = false;
                             $v_0.text = RTE.Cursor.get_range().get_text();
                             RTE.DialogUtility.$5Q('CustomerRteDialog.aspx', 'CreateLink', true, true, $v_0, null, this.$85, false, 400);
               },

               $Dq_0: function ($p0, $p1) {
                             if ($p0 === 1) {
                                            var $v_0 = $p1;
                                            var $v_1 = $v_0[0];
                                            var $v_2 = $v_0[1];
                                            if (RTE.RteUtility.$9H($v_2, false)) {
                                                          var $v_3 = RTE.Cursor.get_range();
                                                          var $v_4 = $v_3.parentElement();
                                                          if (!$v_4) {
                                                                         return;
                                                          }
                                                          var $v_5 = $v_4.ownerDocument.createElement('A');
                                                          $v_5.href = $v_2;
                                                          if ($v_3.isEmpty()) {
                                                                         SP.UI.UIUtility.setInnerText($v_5, ($v_1.trim() !== '') ? $v_1 : $v_2);
                                                                         $v_3.insertBefore($v_5);
                                                          }
                                                          else {
                                                                         if ($v_1.trim() !== '') {
                                                                                       $v_3.replaceHtml($v_1);
                                                                         }
                                                                         $v_3.wrapRange($v_5);
                                                          }
                                                          $v_3.moveToEndOfNode($v_5);
                                                          RTE.Cursor.update();
                                                          RTE.RteUtility.showRibbonTab('Ribbon.Link', 'LinkTab');
                                            }
                             }
               }
}
RTE.InsertNotesLinkDialog.registerClass('RTE.InsertNotesLinkDialog');

What this script does is to prefix the given notes://-link with a valid http-link and encode the querystring (the notes url). When saving the page, SharePoint API won't be the wiser than to allow the url.
When the user clicks the link he/she is taken a to page on the SharePoint server which creates a "javascript-redirect" by using the window.location and setting it to the Notes://-url. After waiting 3 seconds, the user is then taken back to the page they came from (this is while Notes is opening up to show the document the link was pointing to.
ASP.Net code:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Customer.LotusNotesRedirect.aspx.cs" Inherits="Customer.Intranet.LAYOUTS.Customer.Intranet.LotusNotesRedirect" DynamicMasterPageFile="~masterurl/default.master" %>

<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<script type="text/javascript" language="JavaScript">
<!--
               function goBack() {
                             history.go(-1);
               }
               window.location = '<asp:Literal ID="uiLitRedirectLocation" runat="server" />';
               setTimeout(goBack, 3000);
//-->
</script>
</asp:Content>

Codebehind:

using System;


namespace Customer.Intranet.LAYOUTS.Customer.Intranet
{
               public partial class LotusNotesRedirect : Microsoft.SharePoint.WebControls.LayoutsPageBase
               {
                             protected void Page_Load(object sender, EventArgs e)
                             {
                                            if (string.IsNullOrEmpty(this.Page.Request["target"]))
                                            {
                                                          Microsoft.SharePoint.Utilities.SPUtility.TransferToErrorPage("Kan ikke omdirigere, da link ikke er angivet i \"target\"-querystring");
                                            }

                                            this.uiLitRedirectLocation.Text = System.Web.HttpUtility.HtmlDecode(this.Page.Request["target"]);
                             }
               }
}

Lenovo ThinkPad noisy fan

I've been equipped with a state of the art Lenovo ThinkPad W520. A powerhouse! Runs smoothly with 6 Hyper-V guests running :)

It had one minor flaw; the fan was running at full speed for no apparent reason.

I found out that a tool exists to aid you to control the fan speed: TPFanControl (ThinkPadFanControl).

It's available here (at your own risk) for the vast majority of ThinkPads: http://www.staff.uni-marburg.de/~schmitzr/donate.html

IE9 adblocking

For a while I've been using Simple Adblock to get rid of ads on webpages. Simple Adblock blocks ads in IE9 which has several advantages:

  • Less loading time for pages; the browser doesn't waste bandwidth to get the ads
  • The intrusive ad corps don't get their money
  • I get a much cleaner looking page with the important content in focus

BUT, Simple Adblock comes in 2 flavors, one free which blocks 200 ads a day (which means 1 visit to berlingske.dk and 1 visit to eb.dk...) or a paid version for 29$ (which of course blocks all ads 'indefinetly'). I don't want to pay money to get rid of ads!

Enter TPL (Tracking Protection Lists), a new feature in IE9. Simply put it's a built-in adblocker in IE9. From this blogpost I got a link to how to easily configure the TPL in IE9. Essentially, one goes to http://www.quero.at/adblock_ie_tpl.php and add Quero's TPL to your browser: Poof, ads-be-gone!

MCPD and MCITP

I've now passed all the SharePoint 2010 exams.

Sooooo, know I'm a MCITP and a MCPD:

YEAH Cool

MCTS: 70-573 Microsoft SharePoint 2010 Application Development passed

A couple of days ago I passed the MCTS exam, 70-573 Microsoft SharePoint 2010 Application Development. Sooooo, I can now use this logo:

I just wanted to let any interested candidates know how it was. I've using the web search engines to find information on how to pass this exam, but there isn't much info out there. The only good info was from Becky Bertram: http://blog.beckybertram.com/Lists/Exam%2070573%20Study%20Guide/AllItems.aspx

The preperation was a LOT of hands on experience with SharePoint 2010 development (countless projects). Futhermore I used the book "Professional SharePoint 2010 Development" by mulitple authors. It was a great help! Especially regarding workflow development where I did not have any hands on experience...

The exam itself was just as all the other Prometric exams; some easy questions, some hard and some tricky. There is a lot of guidance on how to complete the exam, but my advice is to choose "Mark for review" on the questions where you are in doubt. Revisit them later and read the question carefully once again, you might have missed something in the wording of the question.

Site column messing up Document Information Panel (DIP)

I've been doing a project which requires custom site columns (who hasn't!?). These site columns where then added to document libraries. But the site columns didn't show in the Document Information Panel in Word 2010... Frown And it messed up all subsequent columns added after my custom columns (the columns added afterwards wasn't displayed either) They did show in the document properties in the SharePoint UI though...
The trouble seemed to be in the CAML for my site columns: I've forgotten that the StaticName-property doesn't allow spacings... Embarassed Correcting the spacings by either removing them (making the staticname-prop camel-cased) or replacing with _x0020_ did the trick! Now my custom columns show in the DIP! Laughing

Strange that the column works except for in the DIP... If somebody has an explanation, please comment on this post

Calendar

<<  July 2016  >>
MoTuWeThFrSaSu
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

View posts in large calendar

RecentComments

Comment RSS