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[]
{
"TRUE",
"FALSE",
"FALSE",
text,
text2,
text,
string.Empty,
string.Empty,
SPHttpUtility.EcmaScriptStringLiteralEncode(scriptLiteralToEncode),
text3,
text4,
(string)file.Item["IsCheckedoutToLocal"],
(string)file.Item["PermMask"]
});
}

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);
}
else
{
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;
}

Friday, July 26, 2013

Stay Modal, My Friends

I don’t often need to prevent a SharePoint 2010 modal dialog window from closing, but when I do I use the code below:

//step 1: check if we are in a dialog
var dlg = typeof (SP.UI.ModalDialog.get_childDialog) == "function" ? SP.UI.ModalDialog.get_childDialog() : null;

if (dlg != null && dlg.$5_0) {
//step 2: hide close button
dlg.$5_0.style.display = "none";
}



Then, when you want to allow the dialog to be closed again, the code is:



//step 1: check if we are in a dialog
var dlg = typeof (SP.UI.ModalDialog.get_childDialog) == "function" ? SP.UI.ModalDialog.get_childDialog() : null;

if (dlg != null && dlg.$5_0) {
//step 2: show close button
dlg.$5_0.style.display = "inherit";
}

Wednesday, June 5, 2013

SPSite.MakeFullUrl Lies To You and Me!!

Today we are complaining about this method of SPSite: MakeFullUrl

The complaint is this: In SharePoint 2010, it always returns the root web url, no matter what site collection instance it is used upon.

Here is the example: Given the following code block, what would you expect the resulting output to be when used in different site collection contexts:

Code
Response.Write(SPContext.Current.Site.MakeFullUrl("/Lists/Tasks"));
 
Test 1
Hitting the code at http://sharepoint/_layouts/test.aspx – the ROOT site collection - results in the output:
http://sharepoint/Lists/Tasks

Test 2
Hitting the code at http://sharepoint/sites/AnotherSiteCollection/_layouts/test.aspx – the AnotherSiteCollection site collection - results in the output:
http://sharepoint/Lists/Tasks

Conclusion
Since MakeFullUrl is an instance method of an SPSite object, you would think the result URL would take the SPSite into consideration. It does not, and therefore it sucks.
Thursday, March 28, 2013

RPC Server is Unavailable in Windows 8 App running in Windows Server 2012

 

Problem: This was an annoying problem – but I guess I have never encountered a non-annoying problem: Was working with a Windows App Store app on my Windows Server 2012 dev server. The app contained some media – mp3 and mp4 files – stuff that required audio. Whenever the app would attempt to stream one of these files into Windows Media Player (unimportant side note: Was using the Microsoft Media Platform Player Framework), the app would crash with the error “RPC Server is unavailable’.

Solution: After ensuring the Remote Procedure Call service was running (that would have been WAY too easy), and checking the event logs – which was a dead end – I noticed that the Windows Audio service was NOT running – and set to manual startup.  Starting the Windows Audio service resolved the issue.

I get why the Windows Audio service is not set for automatic start by default for Windows Server 2012 – so when it comes to this particular problem, I feel no anger towards Microsoft or the Windows Server team. In fact, I really like Windows Server 2012 so far – and still even hold Windows Server 2008 in high regard!

MetroPivot Web Part released on Codeplex

Finally got off my ass and published a side project I had around for a while. Get it on CodePlex at http://metropivotwebpart.codeplex.com/.

What is it? If you are familiar with the EasyTabs web part, it is basically the same thing with a lot more style: Drop it in a Web Part zone, and it will ‘wrap’ all of the web parts in that zone into a fancy metro-styled pivot control. Check out the video demo:

metropivot demo from Chad Schroeder on Vimeo.

Monday, February 18, 2013

People Picker Plus for SharePoint 2010

A no-touch replacement for the horrid built in people picker control

Finally finished it up! Get it on CodePlex: http://peoplepickerplus.codeplex.com/

The SharePoint 2010 People Picker has always caused problems for me. Either by not working in what it deems to be 'down level' browsers (Firefox and Chrome), showing red X's instead of user images, random script errors, or totally failing within an HTML5 doctype, the list of crap I have taken from it is extensive. So I finally had enough and developed a solution to bury it with a much more user-friendly and sensible component. Oh yeah, and it works the same under all BICA (Browsers I Care About), like IE 9+, Chrome, Firefox, and even poor little Safari. The major features of it include:
  • Activate 'n Go! Activate the site collection scoped feature and be done - all people pickers will be replaced within the site.
  • Cross-browser! Unlike the built in entity picker, which devolves into a textarea for non-IE browsers, the People Picker Plus works the same way no matter what browser is being used. Also, it is HTML5 friendly.
  • Autocomplete Searches!As the user types, search results are displayed, and even grouped by User, SharePoint group, and Security Group.
  • User Image ProxyUser images located on mysites usually cause an annoying extra authentication prompt within the default people picker dialog. Your users won't miss this!
  • Decent UI!The UI for the built in people picker is awful. Especially for 'down level' browsers like Chrome and Firefox. The UI for the People Picker Plus is better than awful! Plus it is touch-friendly, should your users be crazy enough to try to use SharePoint on a tablet.

Feedback is greatly appreciated, especially of the constructive kind. If you feel the need to hit me with anything negative, it better contain humor.

 
© I caught you a delicious bass.
Back to top