Sharepoint, 64-bit Office and Datasheet view

by Martin 25. november 2011 10:55

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

Tags: , ,

General | MOSS | SP2010

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

by Martin 17. oktober 2011 08:15

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"]);
                             }
               }
}

Tags: , , , ,

SP2010

MCTS: 70-573 Microsoft SharePoint 2010 Application Development passed

by Martin 22. juni 2011 09:49

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.

Tags: , , ,

SP2010

Page List

About

Take a look at my LinkedIn-profile.

DISCALIMER: The content on this blog is in NO way affiliated with my employer. The opinions expressed on this blog are solely my own and in NO way endorsed by my employer.

Recent comments

Comment RSS

Month List