Tuesday, December 16, 2014

SharePoint designer 2010: “the business data connectivity metadata store is currently unavailable”

This was driving me crazy the other day… I tried everything, reconfiguring the services, installing updates I didn't need, uninstalling SharePoint Designer and installing it again, 32 bit, 64 bit, what ever you want.

Every time i opened SharePoint designer and tried to add an external content type, I got this error:

image

 

Then I realized I was doing 2 things that might be the issue:

1. I was running 64 bit of SharePoint designer

2. I was running on my SharePoint Server itself, in a dev machine on CloudShare

So, I went ahead and installed SharePoint designer 32 bit on my client machine – and what do you know, it was working.

Now, the question is what was the problem – running on the server, or running the 64 bit version?

So, I uninstalled the 64 bit version and installed the 32 bit version just out of curiosity…

And what do you know? Same error message… It appears that this is not working when running on the server itself.

It might be specific to my configuration – but if you run into this error, try installing the designer on a different client machine.

Good luck!

Friday, November 21, 2014

Cannot start user profile synchronization service

I searched a lot on this issue online… for some reason it was set to the wrong user, I don’t know why or how, and I couldn’t stat this service.

Going to start the service – I could not change the account name, which was grayed out, and didn’t have the password for it – so I couldn’t start the service.

A LOT of internet searches and I didn’t find one post saying why the account id is grayed out, or how to change it.

So, I finally figured it out.

You have to go to central administration, select security on the left navigation and go to “configure service accounts”.

Here, you can select from a drop down any service you want (in my case, the user profile sync) and (finally!) here you can change it to use any other account, and add this account to the managed accounts in the farm.

Simple task, but very hard to find.

Not so intuitive, if you ask me.

Here is how this form looks like:

image

Tuesday, November 11, 2014

Get the zodiac sign for a date in JavaScript

Just like the title says,

I was building a new layout for our data view plus web part that shows upcoming birthdays from a SharePoint list.

I wanted to show the zodiac sign for each person, using HTML codes you can render the signs but the hard part was to figure out the correct sign for each date.

Here is the end result:

image

You can get this layout and the javascript free from our web site (should be posted soon), but here is what I did in a nutshell (stay with me, its not short):

1. I created an object that has all the start dates for each sign, with the HTML sign for it and its name (for tooltip):

var zodiacSigns = {
    120: {html: "&#9809",text: 'Capricorn'},
    218: {html: "&#9810",text: 'Aquarius'},
    320: {html: "&#9811",text: 'Pisces'},
    420: {html: "&#9800",text: 'Aries'},
    521: {html: "&#9801",text: 'Taurus'},
    621: {html: "&#9802",text: 'Gemini'},
    722: {html: "&#9803",text: 'Cancer'},
    823: {html: "&#9804",text: 'Leo'},
    923: {html: "&#9805",text: 'Virgo'},
    1023: {html: "&#9806",text: 'Libra'},
    1122: {html: "&#9807",text: 'Scorpius'},
    1222: {html: "&#9808",text: 'Sagittarius'},
    1231: {html: "&#9809",text: 'Capricorn'}
};

2. Now, for each date I have I build a number from the month+day, next I loop through all elements of zodiacSigns until I get a value greater than the current date – which means the one before was the correct sign. Then I build the html span with that info:



var zodiacValue = parseInt(monthStr + dayStr, 10);
var currentZodiacSign = null;
for (var z in zodiacSigns) {
    try {
        if (currentZodiacSign == null) currentZodiacSign = zodiacSigns[z];
        if (zodiacValue > parseInt(z,10))
            currentZodiacSign = zodiacSigns[z];
        else break;//passed the date - the last one was the right sign. stop looping.
    }
    catch (e) {
    }
}
 
var zodiacPart = "";
if (currentZodiacSign != null)
    zodiacPart = "<span class='ZodiacSign' title='" + currentZodiacSign.text + "'>" + currentZodiacSign.html + "</span>";

A lot of work, but I like the result.

Thursday, October 30, 2014

The power of data view plus web part

Hey guys, thank you for joining me today on my web cast.
Here is the presentation from today’s web cast, if you missed it you can view the recording here.
This presentation talks about KWizCom's data view plus web part, which is an enhanced, more simple and more versatile version of the data view web part. This product does not require SharePoint designer to use, or messing around with XSLT. Simple create, use and reuse templates using simple html, css and javascript, and share with others.
Here are a few samples of what you can do with this amazing web part:

Image slideshow:
image
Blog:
image
Few tasks samples:
image
image
image
Let me know what you think

A link to the product page: http://www.kwizcom.com/sharepoint-add-ons/data-view-plus/overview/

Friday, October 24, 2014

Disk cleanup crashes on SharePoint 2013 server

This is a wired one…
I have 2 SP2013 servers, I installed the desktop experience feature to get the disk cleanup utility to clean up some disk space.
It runs perfectly on all my servers except one. On that one it crashed as soon as I tried opening it and gave me this error message:
“Disk Space Cleanup Manager has stopped working”
“a problem caused the program to stop working correctly”
The internet had nothing helpful to say, except one fixit tool that applied only to windows xp.
Opened the windows application logs and got this interesting error:
-------------------
Faulting application name: cleanmgr.exe, version: 6.1.7600.16385, time stamp: 0x4a5bc995
Faulting module name: mso.dll, version: 15.0.4659.1001, time stamp: 0x5423c9a5
Exception code: 0xc0000005
Fault offset: 0x00000000002e45b9
Faulting process id: 0x18a8
Faulting application start time: 0x01cfefb40cac6155
Faulting application path: C:\Windows\system32\cleanmgr.exe
Faulting module path: C:\Program Files\Common Files\Microsoft Shared\Office15\mso.dll
Report Id: 4a772d57-5ba7-11e4-9aa1-00505630df35 -------------
Hm… I looked for this file under Office15 and it wasn’t on any of the other servers. Infact, that folder was almost empty in the other servers, but on this server it had many files.
Now, I don’t have office installed on the server, so I hit start, types “office” and the only thing I found was SharePoint Designer was installed on this machine.
It became my immediate suspect. You know how after you install any office product, you have that first time welcome wizard when you launch it? So, I suspected this application was never launched and the wizard never run.
I launched it, clicked next through the wizard and tried disk cleanup utility again – and this time it run as expected.
I thought this one was worth sharing…

Updates from comments I got suggests many other Microsoft applications needs to be launched at least once after installation or they can cause the disk cleanup to crash. Mainly:
  • Outlook
  • Word, Excel and/or PowerPoint (you only need to launch one)
  • SQL client tools
  • Visual Studio
Leave a comment if you had this issue caused by other application, I'll update this post

Wednesday, September 17, 2014

properties.AfterProperties[“Title”] always null in document libraries

Like the title says,

If you are writing an event handler for document libraries / lists, properties.AfterProperties is usually a good way for you to get the new values that the user modified.

Now, we all know the fact that in lists you have to use internal name and in libraries you have to use display name, right?

So, it appears it is not the only trick up their sleeve…

If you ever tried getting the title or name columns in a document library you will quickly notice AfterProperties and BeforeProperties will always return null.

Now, I came across this technet discussion: http://social.technet.microsoft.com/Forums/sharepoint/en-US/ef6e1b63-c821-4c6c-b05f-0b1e32ebf073/beforeproperties-and-afterproperties-returns-null-value-in-itemupdating-itemupdated-event?forum=sharepointdevelopmentprevious

And at the very bottom, there is an answer by Helm Ifort that I found very interesting.

It appears the title column value is available in AfterProperties, only you have to use the “vti_title” name for it! (STS 2001 anyone?)

In my book, this is a bug, and an undocumented one at the very least… I hope someone fixes it soon, but for now it is one of those things seasoned SharePoint sharks need to remember.

Hope this helps

Tuesday, August 5, 2014

Using minimal.master in SharePoint breaks AJAX

Funny story, I just spent the better part of a day trying to figure out why our products do not work properly on a customer’s custom master page.

He was using SharePoint 2013, and using the new feature that allows you to upload an HTML file template and have SharePoint convert it to a master page automatically.

Then I tried some of the out of the box sample master pages: Oslo.master, Seattle.master and a minimal.master that I created using the design manager under site look & feel:

image
Click “Edit master pages” on the left navigation bar:
image
…and click “Create a minimal master page” above the list.

See, all master pages that I tried worked perfectly, except the minimal.master I created and the master page from my customer.

After a long comparing, trial and error I came up with this simple solution, there are just a few things to change to make AJAX work on these pages:

1. You need to remove the SPWebPartManager from the head. This control must be inside the ASP.Net form tag in order to work properly:

<!--SPM:<SharePoint:AjaxDelta id="DeltaSPWebPartManager" runat="server">-->
<!--SPM:<WebPartPages:SPWebPartManager runat="server"/>-->
<!--SPM:</SharePoint:AjaxDelta>-->
2. Next, you must add the SPWebPart manager along the the missing script manager control as first children of the body:

<!--SPM:<WebPartPages:SPWebPartManager runat="Server"/>-->
<!--SPM:<asp:ScriptManager id="ScriptManager" runat="server" EnablePageMethods="false" EnablePartialRendering="true" EnableScriptGlobalization="false" EnableScriptLocalization="true"/>-->

And that’s it, now my ajax updates were working correctly and there was much rejoicing.


I can’t say there won’t be any other issues with these master pages in the future, that’s why I recommend you don’t start with minimal.master, but instead, use the default, Oslo or Seattle – these look much more stable and work right out of the box without the need to tweak them first.

Good luck!

Friday, June 20, 2014

Why I say Data View Plus web part is the best we ever made #1

** UPDATE: try this updated version ** 

KWizCom Data View Plus web part is a simple web part that was built with the designer in mind.

It connects to various data sources, lists, list views, enterprise aggregation feature (more source coming), and does something rather simple.

Unlike the SharePoint data view web part that forces you to work with XSL to transform you data into HTML, the Data View Plus takes a different approach, one that I personally think is much more natural for developers and designers alike.

It works with a list of templates, each template has a simple header, footer and body HTML.

You can simply write the HTML you wish to have at the header and footer of the web part, and the body part will be rendered once for each item in the source.

So, how do you get the values from your data into the HTML? Using simple tokens.

{Item:Title:Value} will render the title field value of the item, you can use this token for any field on the current item.

The list of tokens is long, yet very simple to understand. You can find it in the admin guide of the web part on page 23: Download KWizCom Data View Plus administration guide

So, why do I say it is the best we ever made? Since using it, it took me an hour to make an upcoming birthday’s web part.

I build a new data view plus template called: “Upcoming birthdays”, connected it to my birthdays list and here is the result:

image

Have you ever asked yourself “how do I show upcoming birthdays in SharePoint?” – now you got the answer! Here is a step by step guide on how I did it:

Step 1: Create birthdays list

Create a custom list, use the title to type the person’s name.

Add a choice field called “Month” with options 01, 02…12

Add a choice field called “Day” with options 01, 02… 31

Fill in some birthdays in the list.

Step 2: Install Data View Plus web part

If you haven’t done so already, download and install KWizCom data view plus web part:

http://www.kwizcom.com/sharepoint-add-ons/data-view-plus/download/

Enable the site collection feature and it will create the default template list for you

Step 3: Build the birthdays list template

Visit the “KWizCom Data View Plus Display Layouts” list at your site collection (Not there? Go back to step 2.)

Create a new item in the list with the following data:

(for easy copy, I’ve put this here: http://pastebin.com/ErgixJWv)

1. Title:

Upcoming Birthdays

2. Description:

This shows a simple grouped list with the next 10 weeks of birthdays coming up.
It splits them into groups: Today, tomorrow, this week, or upcoming.

3. EmptyView: (this is the html that will be rendered if no items were found in the source)

<div>There are no upcoming birthdays.</div>

4. Header: (We will use script to transform our data into a birthday list, so the script will go in the header)

   1: <script>
   1:  
   2: KWizCom.DVPWP.Instances['_WPQ_'].Load = function() 
   3: { 
   4:             var numOfWeeksToShow = 10; 
   5:             var monthNames = { 
   6:                 "01": "Jan", 
   7:                 "02": "Feb", 
   8:                 "03": "Mar", 
   9:                 "04": "Apr", 
  10:                 "05": "May", 
  11:                 "06": "Jun", 
  12:                 "07": "Jul", 
  13:                 "08": "Aug", 
  14:                 "09": "Sep", 
  15:                 "010": "Oct", 
  16:                 "011": "Nov", 
  17:                 "012": "Dec", 
  18:             } 
  19:             var groupNames = { 
  20:                 "today": "Today", 
  21:                 "tomorrow": "Tomorrow", 
  22:                 "thisweek": "This week", 
  23:                 "upcoming": "Upcoming" 
  24:             } 
  25:  
  26:             var make2DigitString = function (n) { 
  27:                 return n < 10 ? "0" + n : "" + n; 
  28:             } 
  29:              
  30:             var now = new Date(); 
  31:             var tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000); 
  32:             var nextWeek = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); 
  33:             var endDate = new Date(now.getTime() + numOfWeeksToShow * 7 * 24 * 60 * 60 * 1000); 
  34:             var $list = $kw("#_WPQ_Birthdays"); 
  35:             var $placeholder = $kw("#_WPQ_BirthdaysPlaceHolder"); 
  36:             var currentYear = now.getFullYear(); 
  37:             var nextYear = currentYear + 1; 
  38:             var currentMonth = now.getMonth() + 1;//it is zero based 
  39:             var currentDay = now.getDate(); 
  40:             var tomorrowMonth = tomorrow.getMonth() + 1; 
  41:             var tomorrowDay = tomorrow.getDate(); 
  42:             var tomorrowYear = tomorrow.getFullYear(); 
  43:             var nextWeekMonth = nextWeek.getMonth() + 1; 
  44:             var nextWeekDay = nextWeek.getDate(); 
  45:             var nextWeekYear = nextWeek.getFullYear(); 
  46:             var endMonth = endDate.getMonth() + 1; 
  47:             var endDay = endDate.getDate(); 
  48:             var endYear = endDate.getFullYear(); 
  49:  
  50:             var todayString = currentYear + "-" + make2DigitString(currentMonth) + "-" + make2DigitString(currentDay); 
  51:             var tomorrowString = tomorrowYear + "-" + make2DigitString(tomorrowMonth) + "-" + make2DigitString(tomorrowDay); 
  52:             var nextWeekString = nextWeekYear + "-" + make2DigitString(nextWeekMonth) + "-" + make2DigitString(nextWeekDay); 
  53:             var endDateString = endYear + "-" + make2DigitString(endMonth) + "-" + make2DigitString(endDay); 
  54:             var birthdaysList = new Array(); 
  55:  
  56:             $list.find("li").each(function () { 
  57:                 try{ 
  58:                     var title = $kw(this).attr("data-title"); 
  59:                     var month = parseInt($kw(this).attr("data-month"),10); 
  60:                     var day = parseInt($kw(this).attr("data-day"),10); 
  61:                     var sortableString = currentYear + "-" + make2DigitString(month) + "-" + make2DigitString(day); 
  62:                     if (sortableString < todayString)//this one passed. move it to next year 
  63:                         sortableString = nextYear + "-" + make2DigitString(month) + "-" + make2DigitString(day); 
  64:                     if( sortableString <= endDateString ) 
  65:                         birthdaysList[birthdaysList.length] = sortableString + ":" + title; 
  66:                 } catch (e) { 
  67:                 } 
  68:             }); 
  69:  
  70:             birthdaysList.sort();//now we got sorted birthdays 
  71:             var titleMode = null; 
  72:             var html = ""; 
  73:             for (var i = 0; i < birthdaysList.length; i++) { 
  74:                 var datePart = birthdaysList[i].split(":")[0]; 
  75:                 var titlePart = birthdaysList[i].split(":")[1]; 
  76:                 var dateArr = datePart.split("-"); 
  77:                 var dateString = monthNames[dateArr[1]] + " " + dateArr[2]; 
  78:  
  79:                 var newGroup = false; 
  80:                 if (todayString == datePart) { 
  81:                     if (titleMode != "today")//add title 
  82:                     { 
  83:                         newGroup = true; 
  84:                         titleMode = "today"; 
  85:                     } 
  86:                 } 
  87:                 else if (tomorrowString == datePart) { 
  88:                     if (titleMode != "tomorrow")//add title 
  89:                     { 
  90:                         newGroup = true; 
  91:                         titleMode = "tomorrow"; 
  92:                     } 
  93:                 } 
  94:                 else if (nextWeekString >= datePart) { 
  95:                     if (titleMode != "thisweek")//add title 
  96:                     { 
  97:                         newGroup = true; 
  98:                         titleMode = "thisweek"; 
  99:                     } 
 100:                 } 
 101:                 else { 
 102:                     if (titleMode != "upcoming")//add title 
 103:                     { 
 104:                         newGroup = true; 
 105:                         titleMode = "upcoming"; 
 106:                     } 
 107:                 } 
 108:  
 109:                 if (newGroup) 
 110:                 { 
 111:                     if (html != "") html += "</div>"; 
 112:                     html += "<h3>"+groupNames[titleMode]+"</h3><div>"; 
 113:                 } 
 114:  
 115:                 html += "<p>" + titlePart + "<span style='float:right'>" + dateString + "</span></p>"; 
 116:             } 
 117:             if (html != "") { 
 118:                 html += "</div>"; 
 119:                 $placeholder.append(html); 
 120:                 //$placeholder.accordion({ 
 121:                 //    heightStyle: "content" 
 122:                 //}); 
 123:             } 
 124:             else { 
 125:                 $kw("#_WPQ_NoBirthdaysPlaceHolder").show(); 
 126:             } 
 127: } 
128: </script>
 129: <div id="_WPQ_BirthdaysPlaceHolder"></div> 
 130: <div id="_WPQ_NoBirthdaysPlaceHolder" style="display:none">No upcoming birthdays.</div> 
 131: <ul id="_WPQ_Birthdays" style="display:none">

5. Body: (This will be rendered for each item)

   1: <li data-title="{item:Title:value}" data-month="{item:Month:value}" data-day="{item:Day:value}"> 
   2: {item:Title:value} - {item:Month:value} - {item:Day:value} 
   3: </li>

6. Footer: (This will be rendered at the end)

   1: </ul>

Notes:

In the header script, you can find at the beginning options to configure the template, like translating the text and how many weeks of birthdays to show.

Step 4: Add the web part to your page

Now, all you got to do is add the data view plus web part to your page, connect to the birthdays list and select the new template you just created, and you are done!

Now, you see how easy it is to modify my template and brand it to what ever your customers are asking for? You got complete control over the HTML, and no need to mess with XSL.

I would love to hear your comments or thoughts, I will try to build a few more templates and share them here. If you got ideas or requests let me know!