Tuesday, July 31, 2012

HEY!!! Who changed my Helper.dll?

Ever want to share a class in Visual Studio without having the overhead of the good 'ol "Helper.dll"?

Try this instead...
Adding an Existing Item as a Link

It is a very rarely used and under appreciated feature of Visual Studio that I didn't know existed until recently.

Here is why this is good:
  • You have less DLL's
  • You still have the ability to share classes.
  • When you compile your code you always have the latest version of the class unlike a copy of the class.
  • Once you compile, that build will always have that version of the class until you build again.
  • Sharing Is Caring...OK, OK, I am done


Downfalls:
  • I can't think of one can you?

Thanks to my coworker and this blog post for helping me realize this possibility.

Friday, July 27, 2012

Ode to SharePoint Designer

Just a little fun here...
You have the right to use SharePoint Designer,
Anything you save or modify will not be backed up.
Some unexpected results are to be expected.
If you cannot afford a Developer, then you may not wish to proceed.
Do you understand these flaws as I have described them to you?
Just kidding SPD...but seriously, stop trying to help...if I wanted your silly __designer:Preview tags then i would ask for them.


If you got here via search looking for answers I am sorry...try these sites:
SharePoint Designer 2010 inserts "__designer:Preview" and "__designer:Values" attributes upon reopening of Master Pages
Sharepoint Designer 2010 adding/generating __designer preview tags – a fix to solve this issue

SharePoint 2010 Event ID 6482 Application Server Administration job failed for service instance Microsoft.Office.Server.Search.Administration.SearchServiceInstance

Have you ever seen this error in your ULS and wondered what it was?

SharePoint 2010 Event ID 6482 Application Server Administration job failed for service instance Microsoft.Office.Server.Search.Administration.SearchServiceInstance
I used to always ignore it because although it showed up once a minute in the logs SharePoint Search worked fine.


I got curious about it and decided to do some digging which lead me to this great article by Jeff DeVerter that explained what the issue was and how to resolve it.


And now thanks to Jeff, my ULS has been error free for 3 days!

Visual Studio build fails: unable to copy exe-file from obj\debug to bin\debug

My colleague fought this error for 2 days and finally found out what was causing this issue.


A little background is he was building a Console Application in Visual Studio to interact with SharePoint 2010.


He could rebuild this project many times over and work with it, debug it with no problems.


But, if he tried to run the .exe from windows explorer and then try to rebuild he would get the following error:
Error 4
Unable to copy file "obj\x64\Debug\Program.exe" to "bin\x64\Debug\Program.exe". 
Access to the path 'bin\x64\Debug\Program.exe' is denied.


After many failed attempts to narrow down the issue and trying many different solutions without avail finally he found a working solution.


It all has to do with a tiny little Windows Service called Application Experience.
The description of this service helps you understand why this service is important to what our issue is:
Processes application compatibility cache requests for applications as they are launched
Make its Startup Type Automatic and Start this service and you should be good to go.

Monday, July 16, 2012

SharePoint 2010: No Site Content Types Link

One of the most discuraging issues you will find when working with Content Types in SharePoint is a very simple issue. The Site Content Types link in the breadcrumb is not a link at all. Instead it is some grayed out text that irritates you every time you try an click on it.

So I got tired of trying to do this and thought I would take matters into my own hands.

Here is what I came up with:
function AddContentTypeLink() { 
   var spans = document.getElementsByTagName('h2'); 
   var stringToMatch = ' Site Content Types '; 
   for (var i = 0; i < spans.length; ++i) { 
     if (spans[i].innerHTML.indexOf(stringToMatch) != -1) { 
       spans[i].innerHTML = spans[i].innerHTML.replace(stringToMatch ,"<a href='/_layouts/mngctype.aspx'>" + stringToMatch + "</a>"); 
       break;
     }
   }
 }
 _spBodyOnLoadFunctionNames.push('AddContentTypeLink');

Add this to an existing JavaScript file you have on the go (or in a CEWP on the settings pages where it exists if you are desperate)

If all worked properly you should be left with this:

It may not be pretty but it works well...

If you are working in a different language you can change the string variable to whatever it translates to (French for example is " Types de contenu de site " (don't forget the leading and trailing space!)

Saturday, July 7, 2012

SharePoint 2010 Search Refinement Panel - Bad Border

If you have ever spent time customizing or even just using SharePoint's Search Center then i am sure you have seen this annoying little box that shows up when you have no refinements. It also shows up when you get no results back from a query like this:

So, what is this? You may ask...Well it is the border of the Refinement Panel DIV which has padding-bottom: 5px and padding-top: 7px and it looks good when there are refinement items but not so much when it is empty...

Well that's great but what can we do?
Well, if you already have a JavaScript file and a jQuery refference, then throw this in there and it will hide it when it is blank...
 function HideEmptyRefiner() {  
      if ( $('.ms-searchref-main').children().length == 0 ) {    
        $('.ms-searchref-main').hide();   
      }  
 }  
_spBodyOnLoadFunctionNames.push('HideEmptyRefiner');  

So, what if you don't want to run jQuery on your site? Well don't worry i won't leave you hanging...you can achieve the same result with plain old JavaScript but as always it is 10 times harder!

I am not going to go into the details (you can find those here on this great blog about the issue) but you have to be careful on how you look to see if there are any childNodes. You can't just do a simple parent.childNodes.length because SharePoint was so kind as to leave a nice little XML comment in this DIV:
 <!-- l version="1.0" encoding="utf-8 -->  

Further more, the childNodes length count is not always consistent cross-browser

So, by using the knowledge gained from the blog above and his example as a starting point this is what i came up with...
 var kids;  
 var realKids;  
 var parent;  
 var i = 0;  
 function hideEmptySearchDiv() {  
   realKids = 0;  
   parent = document.getElementById("SRCHREF");  
   kids = parent.childNodes.length;  
   while (i < kids) {  
     if (parent.childNodes[i].nodeType != 3 && parent.childNodes[i].nodeType != 8) {  
       realKids++;  
     }  
     i++;  
   }  
   if (realKids == 0) {  
     parent.style.display = 'none';  
   }  
 }  
 _spBodyOnLoadFunctionNames.push('hideEmptySearchDiv');  

I found that the nodeType of the comment was 8 so I excluded that, then applied the same "if none found hide the div" logic as I used in my jQuery example above.

Enjoy! I hope this helps some one.

Wednesday, July 4, 2012

SharePoint 2010: Value does not fall within the expected range

Today I was working on a very annoying issue related to some custom code we are using to look-up information from a list.


All of a sudden when logged in as a non-Site Collection Administrator (Site Owner) our code was erroring out on this line:
 SPFieldUserValueCollection siteContacts = new SPFieldUserValueCollection(web, item["Site Contacts"].ToString());  


The error was basically saying that the 'Site Contacts' field did not exist in the list even tough it did.


Come to find out that this issue was not related to the list at all but rather the way that SharePoint gets list items. It does it in a CAML Query type of way thus the list item threshold of 8 columns applies and this column was magic number 9.


So because the list item threshold does not apply to Site Collection Admins the look-up worked fine for them but not for anyone else.


Lesson learned, increase the List View Threshold, perform a specific query on the list using SPQuery and specify less than 8 ViewFields something like this or override the limit like this:
 query.QueryThrottleMode = SPQueryThrottleOption.Override  


Or, in our case, we took a different (3rd) approach.


You can disable the throttling on a list by list basis so we opted for this PowerShell script:
 $web = Get-SPWeb http://your.site.com  
 $list = $web.Lists["My List"]   
 $list.EnableThrottling = $false  
 $list.Update()  



We knew this 'special' list is not going to get out of hand and we didn't want to change the threshold for the whole web application.