Convert SharePoint 2010 Solution to 2013 – 15 Hive Folder only

Bumped into this problem where I was trying to convert old codes from SharePoint 2010 to SharePoint 2013.

One issue that you will encounter is that all your Element Files being uploaded to 14 Hive folder (the old 2010 path) rather than the new 15 Hive folder.

If you deploy your solution directly into a SP2013 environment, you will encounter reference link broken or file not found due to codes/files not being deployed to 15 Hive.

One Workaround is to actually deploy your solution with switch -CompatibilityLevel All (for detail please refer here ). However, you can’t always remember to do this steps and in order for you to really upgrade your solution to SP2013, You need to make some changes to the manifest file. And steps below show you how to change it permanently and only stick to 15 hive folder.

Resolution

  1. Open your SharePoint solution via Visual Studio.
  2. Expand the Package folder and Double click “Package.package
  3. Under Properties Panel, change the property “SharePoint Product Version” from 14.0 to 15.0
    upgrade sp2010 to sp2013 solution
  4. Package it and done!

P/S What I additional did to make sure there is no reference link broken is to Find ALL “_layouts/“, “_CONTROLTEMPLATES/” and replace with “_layouts/15/” and “_CONTROLTEMPLATES/15/

Changing Default HomePage for Document Center to a Document Library

As stated in the Title, it is easier said than done to change the default landing page of a Document Center. If you have done publishing sites often, you will usually go to “Welcome Page” in the site setting page to do it.

welcome page publishing

But in Document Center site, this feature is missing and what’s even worse, that there is no Pages or Site Pages library for you to set the homepage

[I’m referring to the set homepage feature below]

make home page

So how to change the default landing page for SharePoint Document Center?

The trick is simple, all you need to do is to go to the Document Library that you want to make default home page.

Hit on the “Edit Page” menu under Site Action gear.

edit page in document library

Once the Document Library page is in Edit Mode, you shall see additional Ribbon Tabs appear and shown below, Go to “Pages” tabs and now you can set the HOME PAGE! (hidden gem)

document library make homepage

There are alternative ways of doing this such as running PowerShell etc. but I personally find this the quickest and easiest way to do it.

Hope it helps!

 

Enable Search feature for SharePoint Lookup Table – Single Value Only

Today I want to talk about how to enable search feature in your SharePoint New/Edit Form for SharePoint Lookup field… I’m gonna use jQuery and jQuery UI’s Autocomplete widget to fulfill this feature.

Let’s assume you have a list called “Lookup” with all your items (to be lookup) and a list “Lookup Test” that lookup to list “Lookup”‘ title. By default, a lookup field does not allow you to do “contains” search (which is kinda very common to have nowadays).

I’m attaching the comparison of the before and after applying the tricks that I’m gonna cover in this post.

search lookup comparison

This is assuming that you already have a SharePoint Designer 2013 and you’ve created two lists as mentioned above.

First of all, Open your SharePoint Designer, navigate to your SharePoint Site and Open the New Form of the “Lookup Test” list.

search lookup designer 2

Once it is opened, make sure you have already click “Advanced Mode” in order to edit the NewForm.aspx

search lookup field 1

Scroll to place holder “PlaceHolderAdditionalPageHead” content placeholder and include the necessary JS/CSS


<script src="https://code.jquery.com/jquery-1.11.3.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css"/>

<style>
.custom-combobox {
position: relative;
display: inline-block;
}
.custom-combobox-toggle {
position: absolute;
top: 0;
bottom: 0;
margin-left: -1px;
padding: 0;
}
.custom-combobox-input {
margin: 0;
padding: 5px 10px;
}
</style>

search lookup field 2

Scroll to right before the closing tag of placeholder “PlaceHolderMain” and insert the following JS Code


<script type="text/javascript">
(function( $ ) {
$.widget( "custom.combobox", {
_create: function() {
this.wrapper = $( "<span>" )
.addClass( "custom-combobox" )
.insertAfter( this.element );

this.element.hide();
this._createAutocomplete();
this._createShowAllButton();
},

_createAutocomplete: function() {
var selected = this.element.children( ":selected" ),
value = selected.val() ? selected.text() : "";

this.input = $( "<input>" )
.appendTo( this.wrapper )
.val( value )
.attr( "title", "" )
.addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
.autocomplete({
delay: 0,
minLength: 0,
source: $.proxy( this, "_source" )
})
.tooltip({
tooltipClass: "ui-state-highlight"
});

this._on( this.input, {
autocompleteselect: function( event, ui ) {
ui.item.option.selected = true;
this._trigger( "select", event, {
item: ui.item.option
});
},

autocompletechange: "_removeIfInvalid"
});
},

_createShowAllButton: function() {
var input = this.input,
wasOpen = false;

$( "<a>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.tooltip()
.appendTo( this.wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "custom-combobox-toggle ui-corner-right" )
.mousedown(function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.click(function() {
input.focus();

// Close if already visible
if ( wasOpen ) {
return;
}

// Pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
});
},

_source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( this.element.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text,
value: text,
option: this
};
}) );
},

_removeIfInvalid: function( event, ui ) {

// Selected an item, nothing to do
if ( ui.item ) {
return;
}

// Search for a match (case-insensitive)
var value = this.input.val(),
valueLowerCase = value.toLowerCase(),
valid = false;
this.element.children( "option" ).each(function() {
if ( $( this ).text().toLowerCase() === valueLowerCase ) {
this.selected = valid = true;
return false;
}
});

// Found a match, nothing to do
if ( valid ) {
return;
}

// Remove invalid value
this.input
.val( "" )
.attr( "title", value + " didn't match any item" )
.tooltip( "open" );
this.element.val( "" );
this._delay(function() {
this.input.tooltip( "close" ).attr( "title", "" );
}, 2500 );
this.input.autocomplete( "instance" ).term = "";
},

_destroy: function() {
this.wrapper.remove();
this.element.show();
}
});
})( jQuery );

</script>

The similar javascript can be found in jQuery UI Autocomplete Combobox example

Within the same location, insert the following script to convert the lookup field into combo box with search feature.


//Change the lookupField base on the internal field name that you want to enable search feature.

var lookupField = "Lookup";

ExecuteOrDelayUntilBodyLoaded(function(){

$('select[id^="' + lookupField + '"][id$="LookupField"]').combobox();

});

search lookup field 3

Save your NewForm.aspx  and you will be prompted warning message saying that the page will no longer base on the site definition, which is okay. Click Yes to see the miracle!

Once you are happy, make sure you do the same steps for your EditForm.aspx.

 

 

 

Do you know? CTRL + SHIFT powerful keys

Do you know that if you hold CTRL + SHIFT and Left click on any program such as “cmd.exe”. You are actually running the program as Administrator?

And instead of hitting “Enter” to open a program, you can do CTRL + SHIFT + Enter to run it as Administrator.

 

Do you know that if you hold CTRL + SHIFT and Right click on any program, you can then run the program as another user such as impersonating someone’s login to open IE browser etc etc.

 

Do you know that if you hit CTRL + SHIFT + ESC, you can easily fire up Task Manager

Be Pro!

SharePoint Search Content Source Crawl Log Access Denied

I have the following issue when setting up SharePoint 2013 Search Service Application.

Whenever I started full crawling my content sources, after certain time (usually the next day). Content Sources page and Crawl Log will give Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
search service application content source access denied

Checking Search Instance Server’s Application Log and you can see the following error

The Execute method of job definition Microsoft.Office.Server.Search.Administration.IndexingScheduleJobDefinition (ID e611e95c-dc0a-40ee-a3a3-c58f2099c2d1) threw an exception. More information is included below.

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

Event ID 6398

Subsequently go to Central Administration page > Timer Jobs to look for the respective Timer

Found “Indexing Schedule Manager on xxxServerNamexxx” failed miserably, for every 5 minutes.

It was then found that some user has this issue previously which has got something to do with TASKS folder in your C:\WINDOWS

sharepoint search windows task access denied issue

In case if you do not have the history of your Domain GPO, this particular folder was previously a target for Conficker Worm virus. Refer here. MS recommended to actually change the permission of this folder which then conflict the requirement for SharePoint Search Service.

If you are interest in checking your own GPO setting, you can simply run “rsop.msc” in your server’s RUN command. And you should be able to see the settings made as per below

sharepoint search windows task access denied issue conflicker

 

Workaround

In order to solve the issue, you have to get your AD GPO team to remove this setting from your sharepoint servers. Explicitly for this requirement or else your search cannot crawl.

For temp solution, you have to change the Owner of this TASKS folder and grant

WSS_WPG with minimum “Read” and “Write” access.

Finger Crossed

Office Web App for SharePoint Cannot Preview Word Document

This is rather a Weird problem I encountered when deploying Office Web App for SharePoint 2013. (Not sure about SP2010).

After following MSDN technet of deploying/configuring OWA for SharePoint, Ran a Full Crawl and trying to preview Office Document.

One funny thing that happen to me was that I can preview Excel Document but not Word and PowerPoint document!

Like below

office web app issue c drive

never ending load

Toggling Developer Tool to check the package and found

ResReader.ashx giving Status 404 error

The sample request is like below


https://[office web app url]/wv/ResReader.ashx?n=p1.img
&WOPIsrc=xxxxxx%2F%5Fvti%5Fbin%2Fwopi%2Eashx%2Ffiles%2F5fc24fed52ee41d58d06c3a19355da66
&access_token=[RANDOM CHAR]g&access_token_ttl=xxxx
&v=00000000-0000-0000-0000-000000000602
&usid=xxxx&splashscreen=1

Reslution

The reason being is that i’ve selected F drive for the OWA Installation path (which is not C by default).

Due to some best practices, I always prevent from using C as the installation path. BUT SOMEHOW for Some reason, Office Web Apps needs to be installed in C DRIVE

It may or may not happen as the other environment that i setup was on F drive and it worked Fine. It took me 2 days to dig and the last resolution was to reinstall the OWA.

After installing to C drive. The OWA works as per normal

 

Office Web Apps Sorry, there was a problem and we can’t open this document. If this happens again, try opening the document in Microsoft Word.

Got this error after configuring Office Web Apps for SharePoint.

officewebapp sorry there was a problem

Digging into the ULS for Office Web App [C:\ProgramData\Microsoft\OfficeWebApps\Data\Logs\ULS\***] and found the following error messages when browsing a document via OWA

HttpRequestAsync, (WOPICheckFile,WACSERVER) no response [WebExceptionStatus:ConnectFailure, url: xxxxxxx
...syncResult asyncResult, Exception& exception)

WOPI CheckFile: Catch-All Failure [exception:Microsoft.Office.Web.Common.EnvironmentAdapters.UnexpectedErrorException:
HttpRequest failed ---> Microsoft.Office.Web.Apps.Common.HttpRequestAsyncException:
No Response in WebException ---> System.Net.WebException:
Unable to connect to the remote server ....
FileUnknownException while loading the app....

 

Checking Application Event Logs and got the following error

Exception type: ExcelWebRendererException Exception message:
We couldn't find the file you wanted.
at Microsoft.Office.Excel.WebUI.EwaState.OpenWorkbook()
...

Turned out that this is due to certain URL not being resolvable by Office Web App Servers.

Here is the catch, the SharePoint Web Application of mine is using multiple Zonez for authentication. The default zone was used for internal servers (not registered in DNS) while Intranet Zone was used for all users.

After the SPWOPI binding is done, the OWA takes in the Default Zone URL whenever user accessing office document via Intranet Zone. The Default Zone’s URL is never set in DNS and hence error thrown.

Resolution

The workaround is to change the HOSTS file in OWA server (C:\Windows\System32\drivers\etc\hosts) to add in the IP of SharePoint Web Server with Default Zone’s URL.

Alternatively, if the Default URL is okay to be exposed to public. Please feel free to add in a DNS record.

Content Plugin can not be initialized – list of CSS addresses is not set.

Having this error in my SharePoint Servers running Search Service Application.

This error was due to Search Index folder not granted FULL CONTROl permission to the following SharePoint Local Group

WSS_ADMIN_WPG

WSS_WPG

Content Plugin cannot be initialized

Go to your search index folder and grant them!

 

If you do not know how to find your Search Index folder. Run the PowerShell below in SharePoint Management Console


##Change the name in case you are using a different name for the search service application

$ssa = Get-SPEnterpriseSearchServiceApplication "Search Service Application"

$ssa.ActiveTopology.GetComponents() | ? {$_.Name -like "IndexComponent*"}

## you should see able to see RootDirectory properties. and that is your search index location.

Changing Domain and Changing SharePoint Distributed Cache Host Name

Today, I’m asked to change my SharePoint Servers to another domain. (jaw dropped). And I’m gonna share the important steps that help you to rename your existing distributed cache host name to a new host name.

I will be using the following naming for better illustration

SharePointWeb01.olddomain.com  -> SharePointWeb01.newdomain.com

As usual, you would domain disjoint, restart server, join to the new domain (using enterprise admin of the new domain). Once the server is joint to the new domain. You can instantly see many error log generated in your event viewer. This post I’m gonna cover only how to swing Distributed Cache and make it goes Live again and with assumption that you have changed the SharePoint Farm Account to a new account. (cause this is domain change activity! big task)

 

First thing first

Make sure the OLD distrbuted host name is pingable and it is still connecting back to the same server. How to do that?

Fire NOTEPAD and edit C:\windows\system32\drivers\etc\hosts

Add in your server IP with the old host name. You will then remove the old host name AFTER successfully getting the distributed cache cluster up.

 

Secondly, change the distributed cache service from the old orphan service account to a new one in the new domain.

Run the following to change the service account


$farm = Get-SPFarm
$cacheService = $farm.Services | where {$_.Name -eq "AppFabricCachingService"}
$accnt = Get-SPManagedAccount -Identity "NEWDOMAIN\NewFarmAdmin"
$cacheService.ProcessIdentity.CurrentIdentityType = "SpecificUser"
$cacheService.ProcessIdentity.ManagedAccount = $accnt
$cacheService.ProcessIdentity.Update()
$cacheService.ProcessIdentity.Deploy()

Restart-CacheCluster

## At this step you will see error but please ignore.

Get-CacheHost

## And you should see your old cache host is UP.

## Register your new Host Name

## Note the DataSource=XXX it may be different from your environment. Change it accordingly to yours.

Register-CacheHost -Provider "SPDistributedCacheClusterProvider"
-ConnectionString "Data Source=SQL;Initial Catalog=SharePoint_Config;Integrated Security=True;Enlist=False"
-Account "<NEW DOMAIN>\<NEW FARM ACCOUNT>"
-CachePort 22233 -ClusterPort 22234 -ArbitrationPort 22235 -ReplicationPort 22236
-HostName <HOST NAME of the server, SharePointWeb01>

After executing the Register-CacheHost

Kindly perform a Export-CacheClusterConfig -Path c:\cache.xml to double check cache.xml if the new FQDN of your server is showing under datacache > hosts

Should look something like that


<hosts>
 <host replicationPort="22236" arbitrationPort="22235" clusterPort="22234"
 hostId="54695588" size="781"
 leadHost="true" account="<new service account>"
 cacheHostName="AppFabricCachingService"
 name="<new and Correct FQDN e.g. SharePointWeb01.newdolmain.com>"
 cachePort="22233" />

 <!-- Together with another host that stating your OLD FQDN e.g. SharePointWeb01.olddomain.com -->
</hosts>

new host’s name should be a FQDN that you can ping and resolve right away without the need of editing HOSTS file.

Once this is done, run the final command in SharePoint Powershell console

Unregister-CacheHost -Provider "SPDistributedCacheClusterProvider" 
-ConnectionString "Data Source=SQL;Initial Catalog=SharePoint_Config;Integrated Security=True;Enlist=False" 
-HostName <the old host name e.g. SharePointWeb01.olddomain.com>

Go back to your HOSTS file and remove the old ip mapping to SharePointWeb01.olddomain.com.

 

Target Audience in Web Part Property is missing.

Or rather how to prevent Target Audience feature in Web Part from missing.

I bumped into this problem where I wanted to set a web part to show only to a certain group of users.

Checking the Web Part properties does not show the Target Audience column. The behavior of this Target Audience web part property is that it will be shown (which we thought it was supposed to be shown by default), only when there is User Profile Service Application associated to your web application. (which usually will be provisioned automatically if you configure the farm via wizard).

user profile service application association

One reason for not associating this is for to prevent user from accessing My Site when they hit “About Me” site action menu.

about me

For some reason, this will also turn off the Target Audience in the Web Part. So. In order to turn on back the target audience feature. Here are the steps.

Resolution:

  1. Go to SharePoint Central Admin
  2. Go to Application Management and hit “Configure service application associations”
  3. In your web application row, hit the application proxy group to show the associations.
  4. Tick “User Profile Service Application” and hit OK.
  5. Your web part should immediately show Target Audience property

web part property target audience sharepoint