Thursday, December 11, 2014

Bamboo World Clock & Weather Web Part stopped working today

We are using a 3rd party webpart for displaying weather and clocks for a few customers on SharePoint 2010. The webpart is also available for 2007 and 2013. This has unexpectedly stoped working today (2nd time in the last 2 months). Usually it works quite alright and for a free solution, there's no better alternative. More info in the Bamboo website.

The webpart looks like that when working (just a basic example, there's lots of configuration you could do on the looks of it, what is displayed, sizing and formatting):



Today, I've proactively noticed that the webpart looks like this as I was doing other work for one of the clients that have this in place:


Some quick analysis shows the feed that it used just doesn't exist anymore. It was located here. Now all it says is:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<weatherdata xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<weather errormessage="Access denied: Please contact weather@microsoft.com if you need access to this API."/>
</weatherdata>

The previous time we've had issues with that webpart, we've just upgraded it as per their recommendations (that includes redeploying the solution and readding the webpart to all pages where you've used it before) and it started working again. I guess a change in the MSN Weather API.
Today, that's not an option as we're running the latest version.

The good news is the webpart has an out of the box option to get the feed from Yahoo instead.
So I've tried that and it worked like a charm. Hopefully that will last longer than the MSN one :)





Wednesday, December 10, 2014

AppFabric Caching Service stopping unexpectedly

Today I had to fix an issue with some slowness of loading pages which was very quickly diagnosed to be related to Distributed Cache being down. The environment is SharePoint 2013 and using the minimum requirements in terms of hardware. No dynamic memory is used, which is known to cause issues with virtualized servers running the AppFabric Caching Service. So... this exists on both dev & prod environments which are running the same version of everything. We'll have a closer look on the dev for the purpose of this post. It's a single server hosting everything, except for SQL which is a separate box.

So, the service is configured with a managed account, it has the correct permissions and everything.
Once started, it takes about 3 minutes until it goes down. The events with source .NET Runtime are the actual crash of the service, just 2 lines above event ID 0 which is the start of it.


A closer look at the errors:



EventID 1000:



Get-SPServiceInstance | ? {($_.service.tostring()) -eq "SPDistributedCacheService Name=AppFabricCachingService"} | select Server, Status command shows the host is online though (Server name and user details are removed due to confidentiality):




If you try to get the cache cluster health when the windows service is running, you can't connect:


Health Analyzer shows nothing related to the Distributed Cache. The Services on Server page shows it as running... but you can't really do more about it. I decided to recreate the instance as the quickest fix:


So, the steps to do that are:

1. Remove-SPDistributedCacheServiceInstance

And then

2. Add-SPDistributedCacheServiceInstance

The service will then warm-up in a few minutes and it’s time to check its health:

3. Get-CacheClusterHealth

Here’s the nice output that we’d expect from a healthy instance (all Healthy = 10.00):
If the result is not 10.00, we would see some unallocated fractions and we need to wait for a couple of more minutes to give the service the time to warm up. Then execute the command again.

Cluster health statistics
=========================

HostName = <localhost>
-------------------------

    NamedCache =
DistributedActivityFeedLMTCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache = DistributedDefaultCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache =
DistributedActivityFeedCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache =
DistributedSecurityTrimmingCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache = DistributedAccessCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache =
DistributedLogonTokenCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache = DistributedViewStateCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache = DistributedServerToAppServerAccessTokenCache_6275b5f8-662d-4d0
6-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
       Throttled             = 0.00

    NamedCache = DistributedBouncerCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00
        Throttled             = 0.00

    NamedCache = DistributedSearchCache_6275b5f8-662d-4d06-bb63-ff3ab18a0e21
        Healthy               = 10.00
        UnderReconfiguration  = 0.00
        NotPrimary            = 0.00
        InadequateSecondaries = 0.00

        Throttled             = 0.00


That's it. The service is running stable now. I guess the root cause is that the memory was not enough in the first place as I saw that as a warning in the event logs prior to the issue, but that's to be confirmed.

Tuesday, December 9, 2014

SharePoint 2013: Search Service not working due to lost permissions

I was delivering a training session in our London office 2 weeks ago, while I was interrupted for an urgent issue for a client that could not wait as this was their live system and the current support provided had no success in resolving it. Briefly - Search not working. SharePoint 2013. I jumped in and there were some actions already tried by the support provider, but mostly restarting the Search Services on all servers. That didn't help. The client production configuration is (the issue did not occur on any of their dev/test environments):


  • 1 WFE running the Query Processing Component 
  • 2 Application servers running all other Search components
  • 1 SQL server (dedicated and only one instance on it)
  • All databases and service applicatoins provisioned through PowerShell (AutoSPInstaller)


The user experience looks like this on any query, executed from anywhere (and that just happened to occur out of the blue):


The Search Service Administration page in Central Admin was showing "All Errors".

The event logs on the APP servers were all flooded with EventID 1357 containing this:

A database error occurred. Source: .Net SqlClient Data Provider Code: 229 occurred 0 time(s) Description:  Error ordinal: 1 Message: The EXECUTE permission was denied on the object 'proc_MSS_GetStatusChangeRequest', database 'Search_Service_Application_DB', schema 'dbo'., Class: 14, Number: 229, State: 5    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command)
   at Microsoft.Office.Server.Search.ManagedSqlSession.ExecuteNonQuery()

.... and a lot more errors related to Search as a consequence of this.

That's SP2013 + SP1 + only 2 security updates released in May this year.  No updates applied after that and everything was working as a charm for 6 months after we've built it. I was given info that there were some network issues experienced just prior to that issue, but I did not have enough data to correlate both.

I've seen the same behavior a couple of months ago when a SQL box was rebooted manually without any actions on the SharePoint farm like stopping services or IIS at all. Then the Search stopped working even when SQL was operational. The reason was lost service account permissions for the Search service account. The same thing happened now for some (unknown yet) reason - the Search service account losts its permission - SPSearchDBAdmin for the Search Service Application database.

I know that's not the best solution, but the only one I could think of in the limited amount of time available to fix this production system - add the permission to the account manually in SQL Server Management Studio. Go to your Search Service Application database (the one referenced above in the application error from the event log, then go to Security -> Users and select the account you use for running your Search Service Application pool, it is also shown in the event log under the error.

In my case that's a dev system on which I've reproduced the issue for the purpose of this post:



On the Membership section, verify the SPSearchDBAdmin role is selected for the account, if it's not (like it was in our case), add it and that should fix your problem. Might need to restart the Search Service again on all the servers running it - we had to do that in our case to get the Admin Component up and running in addition to the Query Processing Component which started working properly immediately after the database permissions were restored.



We still do not know the root cause of that as the environment was handed over long time ago, initially thought that Search in 2013 is very sensitive to connectivity to the SQL Server as I've seen the issue with lost permissoins twice, and the first time was a reboot of SQL definitely causing it. Then I stopped the SQL server on my dev environment for a while to see if that will happen and it didn't, it must  be something else then. And yes, we do use SQL aliases, but we only had one SQL server in that production environment. Hopefully that helps you solve such critical issues quickly.

Monday, December 8, 2014

SQL Server Management Studio not starting

When I logged on to a production SQL 2012, running on a Windows Server 2008 R2 this morning got this wonderful message in an attempt to load the SQL Server Management Studio:


OK. Obviously not going to reinstall the application, not even close. Looking into the event logs I see absolutely nothing related to that. Looking into the installed applications and updates - nothing recently modified.

This thread at the Visual Studio forum suggests that this happens when you install Visual Studio 11, but our environment does not correspond to that scenario. We are running Visual Studio 10. However, since that was a production server and I needed to figure that out quickly, and this solution was posted by Microsoft, I've exported the registry key and deleted it as suggested in there:

1. Start regedit.exe
2. Go to HKEY_CURRENT_USER\Software\Microsoft\SQL Server Management Studio
3. Delete 11.0_Config
4. Restart ssms.exe


That helped. Just make sure you export the key before deleting it.

Saturday, December 6, 2014

Exam 70-346: Managing Office 365 Identities and Requirements passed

I went for this exam yesterday morning and passed it with a result of 866. It's been about 10 months since this exam was published, but I needed some hands-on experience with the technologies involved before being able to pass it. I am saying technologies, as it is totally not just about SharePoint, but instead has a lot of quesions about Active Directory Federation Servers, Directory Synchronization, Exchange and even Lync. Overall, if you've setup a few Office 365 tenants you should be able to cover the general questions like how to setup a new domain, how to plan and perform migrations and what ports would you need to open on the on-prem firewalls, how to troubleshoot Office 365 issues, etc.

I found the questions on Lync and Exchange the most challenging, the good thing is that we've done quite a big hybrid project recently and I was closely involved with the consultants that did those bits of the scope. Not much questions on SharePoint Online. Lots of PowerShell commandlets which are strictly from the MSOnline module. I've used it a couple of times when setting up Hybrid Search.

So... here's what my result looks like, weakest part is Cloud Identities, well... I kind of prefer another 3rd party identity management provider, rather than setting up SSO through ADFS, but I'll blog about that in one of my next posts. Next exam on the list: 70-347: Enabling Office 365 Services


Friday, December 5, 2014

How to redirect a page in SharePoint with JavaScript

There are many ways to redirect a page in SharePoint - embedding code in the page itself, or using some tools that need to be installed on the web front-ends. The code might not be an option for everyone (you need Visual Studio) and the tools have their additional administration overhead.

If you don't have any URL rewrite modules like Helicon or the free one from Microsoft or you simply don't want to use such tools, here's an easy script that will help you redirect users from a SharePoint page to any location.

Just add that in a Content Editor Web part and that should be all working.

<script type="text/javascript">
window.location = "http://<the desired URL here>"
</script>

Hope you find that helpful.

SharePoint 2010 / 2013 and OWA 2010 / 2013 impacted - Security Bulletin coming

Microsoft have just released an advanced notification on that yesterday. It seems we'd need to be applying those updates next week, once they're released on Tuesday, 9th of December. I'll update the article once we apply those to test environments and see if there are any considerations to be taken prior to applying them.

Here's the list of impacted software, concerning all SharePoint people out there:

Microsoft Office Services and Web Apps

Microsoft SharePoint Server 2010
Bulletin Identifier
Bulletin 3
Aggregate Severity Rating
Microsoft SharePoint Server 2010 Service Pack 2
Word Automation Services
(Important)
Microsoft SharePoint Server 2013
Bulletin Identifier
Bulletin 3
Aggregate Severity Rating
Microsoft SharePoint Server 2013
Word Automation Services
(Important)
Microsoft SharePoint Server 2013 Service Pack 1
Word Automation Services
(Important)
Microsoft Office Web Apps 2010
Bulletin Identifier
Bulletin 3
Aggregate Severity Rating
Microsoft Office Web Apps 2010 Service Pack 2
Microsoft Web Applications 2010 Service Pack 2
(Important)
Microsoft Office Web Apps 2013
Bulletin Identifier
Bulletin 3
Aggregate Severity Rating
Microsoft Office Web Apps 2013
Microsoft Office Web Apps Server 2013
(Important)
Microsoft Office Web Apps 2013 Service Pack 1
Microsoft Office Web Apps Server 2013 Service Pack 1
(Important)

Source: https://technet.microsoft.com/library/security/ms14-dec

Wednesday, December 3, 2014

How to change the opening behavior of Calendar items in a Calendar Overlay view

Today I've had another interesting requirement to change the behavior of a SharePoint 2010 calendar, which was built using the Calendar Overlay view to address the need of multiple departments to be able to view all events in the organization. Each department was set with their own calendar, so the quickest choice was to use the Calendar Overlay view. That is quite limited, by the way, but that's a whole different story. You can't have more than 10 calendars and more than 9 different colors assigned to the calendars. You can, however easily customize the colors to your own choice. The final results looks like that:




Now, the user story is they find it annoying that whenever they click on a calendar item, it always loads in a new tab and when they click the "Close" button on it, it leaves the overlay view on the screen and that makes one additional tab open in their  browser.

No out-of-the-box way to change that unfortunately, but everything's possible with a little JavaScipt / jQuery - that will do the exact trick - it'll make the events load in a pop-up window in the same tab:

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"</script><script>
_spBodyOnLoadFunctionNames.push('calendarEventLinkIntercept');

function calendarEventLinkIntercept()
{
if (SP.UI.ApplicationPages.CalendarNotify.$4a)
  {
    var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4a;
    SP.UI.ApplicationPages.CalendarNotify.$4a = function () 
      {
        OldCalendarNotify();
        bindEventClickHandler();
      }
  }
  if (SP.UI.ApplicationPages.CalendarNotify.$4b)
  {
    var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4b;
    SP.UI.ApplicationPages.CalendarNotify.$4b =  function () 
      {
        OldCalendarNotify();
        bindEventClickHandler();

      }  
  }
}

function bindEventClickHandler() {
$('.ms-acal-rootdiv a').click(function(){EditLink2(this,'WPQ2');return false;});
}
</script>

Add that in a Content Editor Web part on your Calendar list overlay page and you're done.
The tricky bit: This only addresses the opening behavior when the user clicks on an item title. If they double click on the calendar field, the event still loads in a new window. I think that's also possible to change, but not worth the effort in researching and developing.

Tuesday, December 2, 2014

JavaScript / jQuery not loading in a site with SSL

This is quite related to the previous post, but decided to split it as some people might just have the generic issue of JavaScript not kicking in on their SharePoint sites... when they use jQuery and SSL :)

The issue might be very simple, and usually the first thing to do when your script is not loading is to see how the Developer Tools look like in your browser. When you use SSL and refer to the jQuery library in a JavaScript, make sure you use the https:// prefix, otherwise your script won't load at all and you'll end up with the error below and maybe an error displayed in the browser saying "Only secure content is displayed", depending on which browser you use and its settings.


You can of course workaround this in the browser itself by doing the following (example for IE) but I strongly recommend doing it the right way in your script in the first instance so you don't have to mess with end-user settings at all. Use this workaround for testing purposes only.

Tools -> Internet Options -> Security, Custom level -> Scroll to: Display mixed content -> Enable -> OK -> Restart IE.

Usually the best practice is to store jQuery locally in the SharePoint farm (in a library for example) and then refer to it in your script. That way you ensure the protocol will be consistent between the site and the location of jQuery.

How to change the Web Part Title URL behavior

With my morning cup of coffee I decided to start with something fairly simple (as a requirement) - it's in fact quite fresh as I had to do it for a client yesterday. It sounded like a 5 minute job, at the end it turned out more interesting. I've done this on 2010 and tested on 2013 as well - same behavior.

The requirement is to make just one specific webpart title URL to open in a new window while keeping all others (if any) loading in the same browser window. I am referring to the "Title URL" property, that is set in the Advanced section when you edit the web part.


There's no out of the box option to configure that, you could remove the URL, or point it to the page itself by changing it to #, but no way to make it open in a new window by adding "_blank" or something.

We can, however use a tiny piece of JavaScript to achieve that (tell SharePoint to do a specific thing when someone clicks on a specific URL) and we have a couple of options doing that thanks to jQuery.

Depending on whether that webpart is reused in many sites or web apps, you need to decide which method is the right one for you, You can do it globally with a full trust solution. That would have a wide impact on all web apps that have the solution deployed.
Let's assume you already have some branding solution in place which has a ccustomizations file in a .js format, you can add that piece of code in there. We are using the onload function here to ensure the site has fully loaded. If you have other JavaScript / jQuery customizations in the site that's the preferred method of calling jQuery to avoid any conflicts. The downside is that it will load only after all images are fully loaded, including some banner ads, etc.

In those example scripts I'm using the Microsoft CDN hosted version of the jQuery library, you can, however download a copy and store it locally on your site. Please make sure you use the https:// prefix in the reference if your site is accessed through SSL.

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"</script><script>
window.onload = function() {
    if (window.jQuery) {
        jQuery(document).ready(function () {
                                jQuery('a[href^="http://www.contoso.com (replace with your URL)"]').click(function () {
                                jQuery(this).attr("target", "_blank");
                                });

                });
 </script>

The second way (more granular) is to store the script as a .js file in SharePoint and apply that on the page level by using the Content Editor webpart to call it. Here we're using the statement known as the ready event. This ensures that the code will run as soon as the document is ready for manipulation. Preferred method if we don't experience any conflicts with other customizations when trying to load it that way. Executes straight away without loading all the images first.

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"</script><script>
$(document).ready(function(){
  $('a[href^="http://www.contoso.com (replace with your URL)"]').click(function() {
    $(this).attr("target","_blank");
  });
});
 </script>

You can also do that for all web part title URLs, the script will look like this:

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"</script><script>
$(document).ready(function(){
$("h3.ms-WPTitle a").attr("target","_blank");
 });
 </script>

That's it. You can then export/import your CEWP and reuse it on any other page quickly. Don't forget to set its Chrome type to None so you don't actually display it on the web page.

Monday, December 1, 2014

Boom... that's the sound of my blog's launch :)




So...after some exciting 4 years and 3 versions in the SharePoint world I'm setting some time aside to run my own blog. It's been a busy and rewarding adventure in terms of knowledge, experience and personal development. The only reason why SharePoint is so successful is the great community behind it. I've gained a lot of my expertise from all the enthusiasts and authorities in the community out there and now it's time to give some of that back, so stay tuned for my first "real" post...