Category Archives: SharePoint 2013

PowerShell script to Open or Close SharePoint Web Parts

If you ever need to make changes to your SharePoint Web Parts such as hiding/showing, this post will help you to cut down unnecessary time.

Run the PowerShell script below via SharePoint Management Shell.

Change the Parameter accordingly base on your environment.


$web = Get-SPWeb [URL]
$f = $web.GetFile("Pages/Default.aspx");

if( $f.CheckOutStatus -eq "None" )
{
  $f.CheckOut();
}
$wpm = $f.GetLimitedWebPartManager("Shared")
$webParts = $wpm.WebParts | ? {$_.GetType().Name -eq "ContentEditorWebPart"} //Change for your own web part type
if($webParts.GetType().Name -eq "Object[]")
{
  $webParts | % {
    #$wpm.CloseWebPart($_);
    $wpm.OpenWebPart($_);
    $wpm.SaveChanges($_);
  }
}
else
{
  #$wpm.CloseWebPart($webParts)
  $wpm.OpenWebPart($webParts)
  $wpm.SaveChanges($webParts)
}

$f.CheckIn("");
$f.Publish("");

The example above will check if the page is check out before making any changes to the web parts. Subsequently, it closes/opens all content editor web parts within it and check in and publish the page. You can additional perform more tasks such as DeleteWebPart or AddWebPart, MoveWebPart or only make changes to only certain type of web part by changing PowerShell rules

 

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.

 

 

 

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.

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

 

SharePoint Custom Solution Branding and Tips – Part 1

Today, I want to talk about some of the good practices when it comes to SharePoint custom code development. More often than not, you would learn that SharePoint custom solution requires you to create Feature (and usually it’s automatically created when you pick any of the default SharePoint Project template e.g. Visual Web Part) to deploy your web part, style sheet, JavaScript files, or master pages.

I can understand that the Microsoft VS team is trying to help SharePoint Developers setting up a working solution as easy and as best as they could. What we need to really take note or at least be aware of is those default values assigned to the template. Below are some of the items in which I personally think that it should not be left unchanged or not thought thoroughly in order to develop a quality solution.

Namespace

Before even creating a new SharePoint 2010/2013 project, please think through the namespace that you want to use. Changing of namespace after you have tons of web parts, feature or pages will kill you. And I kid you not, using VS rename feature does not 100% guarantee you that the code will not break. I have experienced it, and it really takes you a lot of time to just renaming a namespace. (if you are new to SharePoint Development of course)

What I always like to use for namespace naming convention is as per below format

[Company Name].[Type/Name of the solution].[Sub type]

e.g. Microsoft.Branding, Microsoft.Branding.UserControls, Microsoft.Branding.DelegateControls

I would say it is not advisable to have more than 3 levels as it would introduce a very lengthy code referencing.

And I would also suggest using sub type like “UserControls”, “WebParts” or “WebPages” to organize your codes accordingly. It makes the next developer who is taking over your code easier to understand.

Feature Name

Sorry to say that this is one of the item that I dislike most when you found out that your developers did not use it correctly or not even care about changing the name of the feature!

You may not see the impact for now but once you have your code deployed to your customer’s SharePoint environment, it would really look bad and unprofessional to have this appearing in their Site Collection Feature or Manage Site Feature page.

sharepoint feature name bad practice

If you care enough, you will notice that only your custom feature’s name is ending with the numeric “1”. As if there is feature 2 and so on? LOL hell no!

Well, as a new beginner, you will likely to use the SharePoint – Visual Web Part template for a quick start.

sharepoint visual web part

What this template provides by default in the solution is the feature, package and a visual web part. Refer pic below

shareopint default feature name

Please please, remove the “1” and use a proper name.

Note that if you have already deployed your solution to production. After changing the name, you have to retract existing solution by running “Uninstall-SPSolution”, “Remove-SPSolution” and subsequently “Add-SPSolution” and “Install-SPSolution”. You should not use “Update-SPSolution” or else you will hit error deploying it.

Please also use a meaningful description. =)

Feature Image

The next thing I want to talk about is the icon of SharePoint feature. SharePoint by default assign an icon GenericFeature for your feature. As the image name suggested, it is a Generic Feature gif and in order to out stand or brand your feature, I would always like to use a custom image for my feature.

One simple reason is that it makes life easier when there is a lot of features within your SharePoint Site and you need to scroll through the entire list in order to activate or deactivate your feature.

sharepoint long list of feature

How to not miss the “EASY” icon if the color is outstanding enough. You know what I’m trying to say. Outstanding!

The following paragraph describes how you can actually add feature icon into your SharePoint Feature.

First of all, create a good icon for your feature, and put it into your SharePoint Solution.

sharepoint add images mapped folderSimply right click the project, hover to Add and click “SharePoint Images Mapped Folder” (if you already mapped, this option will be grey out)

Once you have it mapped, you can just dump your  images into the mapped image folder and it will automatically be included into your package. The relative URL of your images folder is always starting from “/_layouts/15/IMAGES/”

How to know if it is really going into that URL? You can check by looking into the Property of the Images mapped folder – Deployment Location where it stated “{SharePointRoot}\Template\Images”. This actually goes to your SharePoint 15 hives (SP2013) of your deployed server and if you look into IIS Manager for your SharePoint Web application. This folder is actually mapped as a Virtual Directory with path

sharepoint virtual directory image

Once you have your image prepared in the solution, next step is to tell your Feature to use the image. Easy. Go to your feature element files as shown below.

Simply place your cursor right before the end of the “>” tag and you should see the intellisence starting to show up. At this stage, the attribute that you would need to pick is quite self-explanatory.

sharepoint feature auto suggestion

Insert the ImageUrl. Just remember to make sure the url is correctly populated. Sample as shown below.

sharepoint feature image url example

Once you have it specified correctly, deploy it and you should see that your feature is now with your custom icon. Sample below shows not really a good example, but please use a size that you find fits.

sharepoint feature image output

 

Custom Action Group and Action

Another item that worth mentioning when doing SharePoint development is the Custom Action and Group. Since SharePoint 2010 (not sure about SharePoint 2007). It introduces a new feature where you can inject Stuff (could be links, could be Ribbon action or event Site Action) into certain area of your SharePoint pages.

Basically, the idea is that there is list of area (which it is called Location) in SharePoint where you can add/remove Stuff and within each area, there is another sub-area (which is called Group ID) if you need to further scoping down into a more specific area.

You can refer to MSDN https://msdn.microsoft.com/en-us/library/office/bb802730.aspx for Location and GroupID that you can make use of.

Things can be made easier if you need to display some custom site action or site settings link for your user to access certain page (be it your custom application page or SharePoint OOTB pages where it may not be displayed by default e.g. /_layouts/groups.aspx (Groups Page)).

I’m going to share how to go about doing it.

First of all, go to MSDN link above and identify the Location that you want to use. For the simplicity, let use Microsoft.SharePoint.SiteSettings as a example.

So let assume you want to insert a hyperlink into Site Setting page.

Go to your VS Project, Right click and add new item. Select Empty Element as shown

sharepoint empty element

Pick a nice name and hit Add. Note that once it is added, you can find a file called “Elements.xml” being added. Open it and,

Insert the following code.

sharepoint feature site setting example

 

Things that you need to note here is the GroupId and Location used. I added a Custom Action Group with a custom id, but using a valid Location. Subsequently, create another CustomAction and use the custom GroupId and the same valid Location (You still need to specify the same value as the CustomActionGroup or else it won’t work).

The Sequence in the Custom Action Group tells how earlier you want your group to be rendered in the Location. In the example above, 1 is being the first to render.

sharepoint site setting link

 

Hence it will be at the top of all existing group.

Things get a little bit complicated here if, let say other feature have used the same Sequence number as you did. In this case, the later registered ones will be displayed first.

Like example below. Group A being registered later and hence it is displayed first before the Group B.

sharepoint feature sequence does matters

 

Note that you need not to order the Custom Action xml to below Custom Action Group. SharePoint can still recognize them.

 

I have much more to share but that’s it for today! I hope above info and tips can help giving you some ideas and to be able to build a good SharePoint solution!

 

Read part 2 here

How to clear SharePoint People Picker suggestion cache

If you have been SharePoint Site owner long enough, you would have definitely bumped into task like assigning document permission using SharePoint People Picker.
One of the out of the box SharePoint People Picker features is that it auto caches all previous user entry entered/selected by you.

 

This cached people picker entity is meant to help you to quickly find the user and assign the permission.people picker cache issue
It would introduce invalid entry if there is cease of identity provider (for whatsoever reason that the decision made from the IT management needs us to swing the SharePoint identity provider to other platform).

Things could get messier for those who frequently accessing people picker, to be seeing the old cached user.

Another situation that introduce inconsistency is when there is change of user name/job title etc for which is cached and not reflecting the correct info to the end user.

 

SharePoint People Picker uses LocalStorage to cache the people picker entity. In order to flush the cache, you would need to run a JavaScript to clear the cache. What’s worst is that there is no expiration set.
If you fire up your browser development tool and type in “localStorage” (case sensitive) in the console. You would see the cache key/value for ClientPeoplePickerMRU.

hit F12: For Chrome, IE and Firefox (Note:You must be firing up the developer tool at the SharePoint Page)ie people picker localstorage

 

Chrome – Resource tab

chrome people picker localstorage

 

So what can we do?

If you are developer and techie, you can easily fire up the developer console of your browser and run the below JavaScript


localStorage.clear();

If you are helping your end user to flush the cache, one possible way is to provide them a quick custom web part using javascript above to flush their cache. Alternatively, creating a custom JS with leveraging Cookie as expiration check, put it into your home page. Whenever user accessing to your home page, this JS will check from Cookies to see if it is time to Refresh (or clear) the local storage.
The other possible way is to get them clear the Local Storage from their Browser. I couldn’t find where the IE local storage is. If you know, I will be more than happy if you can tell me.

For IE Users who wish to clear the people picker. Here are the steps you may follow
1. Go to page with people picker
2. F12 Developer Tools
a. Console
b. localStorage.clear();
3. Close F12
4. Then refresh the web page to test it.

[Credit goes to Chris for the steps above]