Tuesday, September 10, 2013

Using DispEx in a Link to a SharePoint Document

I needed to create a link to a document the same way SharePoint does it: using the DispEx client side function. The DispEx function performs all of the magic involved with opening an Office document directly in the appropriate Office app in a nice way, as long as you are using Internet Explorer of course. I believe it also uses ActiveX to do this, but that will be for another ran.. I mean blog post.

Searching for how to create such a link proved worthless. There are a few posts and Q&A’s on Stack Overflow out there, even at least one from one of those soon-to-be-extinct MVP’s – but they all hard coded most of the parameters for the function. It is true that the function has a plethora of parameters, but having them hard coded is not desirable – especially when the parameters are based on user-configurable settings, such as the ‘Force Checkout’ option in a document library.
Below is some code to create the ‘click’ script for the anchor element, gleaned via ILSpy and modified to accept an SPFile parameter. The DispEx  function (and dependencies) also require that the anchor element have an HREF attribute set to the server-relative URL of the file. In the case of an SPFile instance, this would be FIle.ServerRelativeURL.
        private string GetFileViewScript(SPFile file)
string text = SPUtility.MapToControl(SPContext.Current.Web, file.Name, string.Empty);
string text2 = (file.Item.ParentList.DefaultItemOpen == DefaultItemOpen.Browser) ? "1" : "0";
SPFieldLookupValue sPFieldLookupValue = file.Item["CheckedOutUserId"] as SPFieldLookupValue;
string scriptLiteralToEncode = (sPFieldLookupValue == null) ? string.Empty : sPFieldLookupValue.LookupValue;
string text3 = (SPContext.Current.Web.CurrentUser != null) ? SPContext.Current.Web.CurrentUser.ID.ToString(CultureInfo.InvariantCulture) : string.Empty;
string text4 = file.Item.ParentList.ForceCheckout ? "1" : "0";

return string.Format(CultureInfo.InvariantCulture, "return DispEx(this,event,'{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}','{11}','{12}')", new object[]

Friday, September 6, 2013

SendEmail from CurrentUser Caution in SharePoint 2010

This is a quick one I ran across, and yes: it was really annoying:

The SPUtility’s SendEmail method has several overloads. Check it out if you want to: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.utilities.sputility.sendemail(v=office.14).aspx

The most flexible overloads accept a StringDictionary. The dictionary allows us to specify any email headers we want to, most notably the ‘to’, ‘subject’, ‘cc’, and ‘from’ headers.

In the SendEmail overloads that are not taking a StringDictionary, notice there is no ‘from’ parameter. This is because the current Web Application’s outbound email address is automatically used as the ‘from’ address when using those methods.

When using on of the StringDictionary overloads, one would think leaving out the ‘from’ header would result in the same thing: the current Web Application’s outbound email address is used. This is NOT THE CASE.

What happens is that if the ‘from’ header is not in the StringDictionary or if it is null, the current user’s email address will be used as the FROM address in the email. If your email server has any type of security hardening this will result in the email being rejected since the app pool probably does not have the necessary rights to send an email on any old user’s behalf.

How to fix? Couldn’t be easier:

//email sendin code
StringDictionary headers = new StringDictionary();
headers.Add("to", toAddress);
if (!string.IsNullOrEmpty(fromAddress))
headers.Add("from", fromAddress);
headers.Add("from", GetFromEmailAddress(web));
headers.Add("subject", subject);
headers.Add("content-type", "text/html");

SPUtility.SendEmail(web, headers, body);

//get the FROM email address configured for the web app
internal static string GetFromEmailAddress(SPWeb web)
return web.Site.WebApplication.OutboundMailSenderAddress;

© I caught you a delicious bass.
Back to top