SharePoint 2013: Optimize your development Environment

SharePoint 2013 demands more resources – especially more memory. When we need to setup a SharePoint 2013 environment we can optimize resource usage in the development server by provisioning/configuring required services as well as following some other guidelines listed in this post.

Search Service Applications

Search Service is EXTREMELY resource hungry. noderunner process (Search Service process for crawling/indexing) is widely known for it’s resources usage footprint. In case you don’t need search service in your development server, you can delete the service application or at least stop the service. If you need to use the search service from time to time, you can keep the search service application running but stop the search service. However, if you try to stop the search service from windows service, you will find the service will be started again by SharePoint. The correct way to stopping service is from Central admin as shown below:

image

If you need the search service components (crawling/indexing) on development server, you can reduce the performance level by running the following command in SharePoint PowerShell. More information available at http://technet.microsoft.com/en-us/library/ff608126.aspx.

Set-SPEnterpriseSearchService -PerformanceLevel Reduced

You can also control the noderunner memory consumption by changing ‘memoryLimitMegabytes’ in the config file “C:\Program Files\Microsoft Office Servers\15.0\Search\Runtime\1.0\noderunner.exe.config”. Please remember, changing the value to too low might cause the search service to fail.

Provision Required Service Applications only

If you install SharePoint using Installation wizard, different service applications are installed but you many not need all of these service applications. From Central admin you can delete unnecessary Service applications as well as stop services. As you can see below

Stop unnecessary Web Application

Even web application running in your development environment will create w3wp process (if a separate application pool is used) or at least use resources. So if you don’t nee a web application for time being, you can stop the web application as well as related application pool from IIS Manager.

Visual Studio IntelliTrace

If you use Visual Studio debugging in the server and your Visual Studio supports IntelliTrace and the feature is enabled, you can disable the option. That might improve your debugging experience. More information on how to enable/disable the feature can be found at: http://msdn.microsoft.com/en-us/library/dd264948(v=vs.100).aspx

Multiple Disk Drive

If you have configured multi-server farm, you can keep some servers in another disk drive. For example, I’ve a multi-server (4 servers – AD, SQL, WFE and App) farm and I’ve kept two servers in my external USB3 supported external drive. So rather than four server vying for the same disk access, two are vying for internal disk access and other two are vying for external disk.

Even if are running a single server farm, you can use an external SSD drive (or USB3) for better I/O throughput. Especially if you can move your database files in an external drive, you will experience much better performance.

Tracing Service

SharePoint uses a windows Service ‘SharePoint Tracing Service’ for logging. sometimes, like during deployment, you will find the log file is growing few hundreds megabytes in short time. So tracing service might take a bit role in performance. If you don’t need the log file for a period of time, you can disable the windows service. During development I usually disable the service and when I need to see the log file, I enable the service.

Using SharePoint’s Rich Text Box in a page

ASP.Net does not provide a rich text box control in its set of web controls. So, if you need to place a rich text box on your SharePoint page you’ll have to use a commercial, free or open source text box control (and there are plenty out there). However if you don’t want to introduce another dependency, in the form of an external control, you can use SharePoint’s built-in rich text box.
If you’re creating a page layout that binds to a content types field then its straight forward and you can useRichTextField class. However, if you want to display a textbox that does not interact with a content type then you can use the InputFormTextBox and configure its properties so it render as a rich text box.
Here is an example:
Note: change the RichTextMode value to ‘FullHtml’ to render more html icons in text box’s tool bar.

5 Ways to brand Office 365 without Modifying the Master Page

Starting from 1 easiest to 5 hardest (requires dev skills)

1. Office 365 (Personal and Tenant Wide) Themes – You should start here.

Office 365 themes
After you’ve created your theme
  • Custom logo optionally clickable: Select the image and upload your own JPG, PNG, or GIF with a resolution of 200 x 50 pixels, no larger than 10 KB. This appears in the top navigation bar on every page.
  • Top Nav Background image: Your own JPG, PNG, or GIF, no larger than 15 KB. The background image appears in the top navigation bar on every page.
  • Prevent users from overriding theme: Option to enforce theming at the user level so that everyone in the organization sees the theme you create. The exception to this is a high contrast theme used for accessibility purposes.
  • Accent color: Select a color to use for the app launcher icon, mouse over color, and other accents.
  • Nav bar background color: Select a color to use for the background of the navigation bar. Appears at the top on every page.
  • Text and icons: Color to use for the text and icons in the top navigation bar.
  • App menu icon: Color to use for the app launcher icon
You’ll see your new theme on the Office 365 admin center right away and after a short delay, you’ll see it throughout Office 365 including Outlook and SharePoint pages. You can remove your custom icon or custom colors at any time. Just return to the theme page and choose Remove custom theming or Remove custom colors.
IMPORTANT: In addition to customizing your theme, you can add custom tiles to the My Apps page and then add them to the app launcher or add them to the navigation bar.
Office 365 Branding goes beyond SharePoint
When considering any a custom UI for SharePoint, always consider other services such as One Drive, User Profiles, and Delve. Any CSS, JS, or master-page customization applied to SharePoint as these will not automatically propagate across these other workloads. The only shared tool at this point is the top suite bar. Fortunately, this for the most part is customized by using Office 365 themes. Themes are limited, but this is where you should start. Outlook does have some personal theming, but shouldn’t need much branding anyway. For email you could use Outlook.com add-ins, and recommend company signatures for consistency.
Refrence link : https://support.office.com/en-us/article/Customize-the-Office-365-theme-for-your-organization-8275da91-7a48-4591-94ab-3123a3f79530?ui=en-US&rs=en-US&ad=US
2) Office 365 site options: SharePoint Site Look and Feel branding “Change the Look”
Another good place to start with changing the look of your site while clearly staying way within boundaries is with the Look and Feel section of site settings.
Add a site title, pick a logo, add simple base colors. I would avoid doing too much here or your site will look like it came from FrontPage 98. The out of the box theming engine of composed looks are actually quite ugly in my opinion, but the ability to customize these is in the SharePoint UI and very easy to do. Site themes and composed looks are well covered on the web. The “Change the look option” site theme has skins and additional colors. Changing the navigation is simple and this also is benign and expected. 
3)  Provisioning template in PnP Partner Pack for responsive UI for Office 365 SharePoint Online
Alternative CSS is much more lightweight, but still will require testing and maintenance. Join the Office Dev PnP community where you can share code and best practices. First, use alternative CSS instead of adding references to files on your master pages. You can test in our browser by changing the browser size, but ultimately need to test. A good practice is having a couple of tenants… one in early adopter with a handful of test users and the other in the normal adoption rate.

4) Office UI Fabric
Office UI Fabric is a responsive, mobile-first, front-end framework for developers, designed to make it simple to quickly create web experiences using the Office Design Language. The framework is used internally on products within Office 365—such as our suite branding, OneDrive.com, Outlook.com, Delve and the Video Portal. With Office UI Fabric you can apply simple CSS styles to make your web applications look and feel like the rest of Office. The styling takes into account typography, color, icons, animations, responsive grid layouts and localization.
5)Use JavaScript Injection to embed custom scripts and/or third-party libraries into your sites
“You can use the Office 365 JavaScript UI controls to add an Office 365-style navigation bar to your app and also let users access data about people in Azure Active Directory (AAD). These JavaScript UI controls do not require server-side code, and can be integrated into a single-page application (SPA) with just a few lines of code.”
The Office 365 JavaScript UI controls are supported by the following web browsers:
  • Internet Explorer 10+
  • Chrome 43+
  • Firefox 39+

Renew an expiring client secret in a SharePoint Provider Hosted Apps (Add-in) without deploying the Apps again by changing Client Secret key using Powershell

When you create Provider Hosted you have registered a Client ID and Secret ID using SharePoint Register App Page (AppRegNew.aspx) and you have used this Client ID and Secret ID in the Web Config in the web application part of the provider hosted app (App Web), after one year your Apps is stop working, and you will get the following Error:
System.IdentityModel.Tokens.SecurityTokenException: Invalid JWT token. Could not resolve issuer token.
Why?
By default the Secret Key will expire after one year, unfortunately you will not get any alerts before the expiry date, you have to renew the Secret Key at least one day before its expiry, because the new key will take about 12 hours to be generated, following steps will renew the Secret ID
      1.       Use online power shell to create new Client Secret ID
Download the Power shell for Office36:
  •          Microsoft Online Services Sign-In Assistant is installed on the development computer.
  •          Microsoft Online Services PowerShell Module (32-bit; 64-bit) is installed on the development computer.
  •      You are a tenant administrator for the Office 365 tenant (or a farm administrator on the farm) where the app was registered with the AppRegNew.aspx page.
        After downloading the powershell open it and connect to SharePoint online using following     CMDLET:
        Connect-MsolService
        A popup will ask for Username and Password type your Username as:     UserName@DomainName.com
    2.       Find out the expiration dates of the apps for SharePoint installed to the Office 365 tenancy
Get-MsolServicePrincipal  |Where-Object -FilterScript { ($_.DisplayName -notlike “*Microsoft*”) -and ($_.DisplayName -notlike “autohost*”) -and  ($_.ServicePrincipalNames -notlike “*localhost*”) } | foreach-object{
    $principalId = $_.AppPrincipalId
    $principalName = $_.DisplayName

    Get-MsolServicePrincipalCredential -AppPrincipalId $principalId -ReturnKeyValues $true | Where-Object { ($_.Type -ne “Other”) -and ($_.Type -ne “Asymmetric”) } |  foreach-object{
        $date = $_.EndDate.ToShortDateString()
        write-output “$($principalName);$($principalId);$($_.KeyId);$($_.type);$($date);$($_.Usage);$($_.Value)”
    }
} > c:\temp\appsec.txt

    3.       Generate a new secret
$clientId = ‘SPECIFY YOUR CLIENT ID HERE’
$bytes = New-Object Byte[] 32
$rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$rand.GetBytes($bytes)
$newClientSecret = [System.Convert]::ToBase64String($bytes)
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Password -Usage Verify -Value $newClientSecret
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Sign -Value $newClientSecret
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Verify -Value $newClientSecret
$newClientSecret
Copy the new Secret to use it as mentioned in the next Section
    4.       Update the web Config of the Azure Apps Web with the new Secret
The good news is that it’s not required to deploy the Apps again, you just you need to updated the web config file of the web application part of the provider Hosted App (App Web)
    <add key=ClientId value=c86eb4d4-0efd-4269-92ba-97fd48689ec5 />
    <add key=ClientSecret value=“New Secret” />
    <add key=SecondaryClientSecret value=Old Secret />
We will keep the Old key in App setting (SecondaryClientSecret) because the new key will take about 12 hours to be generated in this case the web application will try to use the new Client Secret key but it will fail then it will use the secondary key, once the new key generated the web application will use it
References

Replace an expiring client secret in a SharePoint Add-in

Site Pages and Application Pages (Difference Between SharePoint Application Pages Vs Site Pages)

Application Pages Site Pages
Application pages are stored in the server’s file system Site Pages is a concept where complete or partial page is stored within content database and then actual page is parsed at runtime and delivered to end-users. 
 SharePoint Designer tool cannot be used withapplication pages.  Site pages can be edited by using SharePointDesigner tool. 
Application pages cannot be used within sandboxed solutions. Site pages are used within Sandboxed solutions. 
An Application page cannot be customized and modified by end user, instead a developer is required. These are the normal .aspx pages deployed within SharePoint. A site page can be customized and modified by end user.
SharePoint specific features like Information Management Policies, Workflows, auditing, security roles can only be defined against site pages not against application pages. SharePoint specific features like Information Management Policies, Workflows, auditing, security roles can only be defined against site pages not against application pages.
These are typical ASP.Net aspx pages and can utilize all of the functionalities available within ASP.Net including code-behind, code-beside, inline coding etc.

These are compiled by .Net runtime like normal pages. If you deploy your custom ASPX pages within _layouts folder or within SharePointapplication using a virtual directory, you will not be able to use SharePoint master pages and have to deploy your master page within the virtual directory or _layouts folder. 

Since they are rendered not compiled hence it is not easy to add any inline code, code behind or code beside. Best way of adding code to these pages is through web-parts, server controls in master pages, user controls stored in “Control Templates” folder or through smart parts. If you want to add any inline code to master page, first you need to add  configuration within web.config: To add code behind to SharePoint master pages or page layouts.

Application page : Application pages are used to support application implementations inSharePoint Foundation. An application page is an ASP.NET Web page that is designed for use in a SharePoint Web site. Application pages are a specialized type of ASP.NET page.
Application pages are stored on the file system of the front-end Web server in the %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS directory and exist for every site in a Web application. This folder is mapped to an Internet Information Services (IIS) virtual directory called _layouts. Every site and subsite will have access to the application pages by using the _layouts virtual directory. For example, http://myserver/_layouts/settings.aspx and http://myserver/subsite/_layouts/settings.aspx access the same application page on the front-end Web server unlike site pages, which are an instance for the specified site.
Application pages are not subject to the same restrictions as site pages. They allow in-line code without restriction. They cannot, however, use dynamic Web Parts or Web Part zones or be modified using SharePoint Designer. Modifying the default application pages is not supported inSharePoint Foundation. Custom application pages can be added to a subdirectory inside the _layouts folder.
Site Page : Site pages are pages that are created, edited, and customized by end users. They are primarily used for the content in a site. Site pages come in two types—a standard page and a Web Parts page. A standard page contains text, images, Web Parts, and other elements. A Web Parts page contains Web Parts in Web Part zones. They have a predefined layout that uses Web Part zones. Both types of site pages are edited using a Web browser or Microsoft SharePointDesigner.
Site pages are provisioned from a template page that is stored on the file system of the front-end Web server. When a site is provisioned, SharePoint Foundation creates a pointer to the instance of the page template on the file system. This allows SharePoint Foundation to avoid repeatedly creating copies of the pages, which are provisioned each time a site is created.
When a user customizes a site page, the template for the page is then stored in the contentdatabase. The page is retrieved from the content database every time it is requested by a user. A customized page can, however, be reset to the original template page through the Web browser or a tool such as SharePoint Designer.
Pages stored in Pages libraries or document libraries or at root level within SharePoint (Wiki pages) .
They are at user-level not at web-application or farm level and can be customized per site level. 

Renew an expiring client secret in a SharePoint Provider Hosted Apps (Add-in) without deploying the Apps again by changing Client Secret key using Powershell

When you create Provider Hosted you have registered a Client ID and Secret ID using SharePoint Register App Page (AppRegNew.aspx) and you have used this Client ID and Secret ID in the Web Config in the web application part of the provider hosted app (App Web), after one year your Apps is stop working, and you will get the following Error:
System.IdentityModel.Tokens.SecurityTokenException: Invalid JWT token. Could not resolve issuer token.
Why?
By default the Secret Key will expire after one year, unfortunately you will not get any alerts before the expiry date, you have to renew the Secret Key at least one day before its expiry, because the new key will take about 12 hours to be generated, following steps will renew the Secret ID
      1.       Use online power shell to create new Client Secret ID
Download the Power shell for Office36:
  •          Microsoft Online Services Sign-In Assistant is installed on the development computer.
  •          Microsoft Online Services PowerShell Module (32-bit; 64-bit) is installed on the development computer.
  •      You are a tenant administrator for the Office 365 tenant (or a farm administrator on the farm) where the app was registered with the AppRegNew.aspx page.
        After downloading the powershell open it and connect to SharePoint online using following     CMDLET:
        Connect-MsolService
        A popup will ask for Username and Password type your Username as:     UserName@DomainName.com
    2.       Find out the expiration dates of the apps for SharePoint installed to the Office 365 tenancy
Get-MsolServicePrincipal  |Where-Object -FilterScript { ($_.DisplayName -notlike “*Microsoft*”) -and ($_.DisplayName -notlike “autohost*”) -and  ($_.ServicePrincipalNames -notlike “*localhost*”) } | foreach-object{
    $principalId = $_.AppPrincipalId
    $principalName = $_.DisplayName

    Get-MsolServicePrincipalCredential -AppPrincipalId $principalId -ReturnKeyValues $true | Where-Object { ($_.Type -ne “Other”) -and ($_.Type -ne “Asymmetric”) } |  foreach-object{
        $date = $_.EndDate.ToShortDateString()
        write-output “$($principalName);$($principalId);$($_.KeyId);$($_.type);$($date);$($_.Usage);$($_.Value)”
    }
} > c:\temp\appsec.txt

    3.       Generate a new secret
$clientId = ‘SPECIFY YOUR CLIENT ID HERE’
$bytes = New-Object Byte[] 32
$rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$rand.GetBytes($bytes)
$newClientSecret = [System.Convert]::ToBase64String($bytes)
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Password -Usage Verify -Value $newClientSecret
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Sign -Value $newClientSecret
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Verify -Value $newClientSecret
$newClientSecret
Copy the new Secret to use it as mentioned in the next Section
    4.       Update the web Config of the Azure Apps Web with the new Secret
The good news is that it’s not required to deploy the Apps again, you just you need to updated the web config file of the web application part of the provider Hosted App (App Web)
    <add key=ClientId value=c86eb4d4-0efd-4269-92ba-97fd48689ec5 />
    <add key=ClientSecret value=“New Secret” />
    <add key=SecondaryClientSecret value=Old Secret />
We will keep the Old key in App setting (SecondaryClientSecret) because the new key will take about 12 hours to be generated in this case the web application will try to use the new Client Secret key but it will fail then it will use the secondary key, once the new key generated the web application will use it
References

Replace an expiring client secret in a SharePoint Add-in

Use Site Url in SharePoint

There are several ways to reference site collection or site url in masterpage, layout page, application page and web parts.


1. Token: ~sitecollection ~site

These tokens only works with SharePoint server side controls. They do not work with ASP.NET control or HTML control.

2. SharePoint Server Token 

This token is only available for SharePoint Office Server not the SharePoint Foundation Server and it only works with a few SharePoint server controls.

If it doesn’t work, you can use asp.net letral control to work around as

<script type="text/javascript" src='<asp:Literal runat="server" Text="<% $SPUrl:~Site/appBin/js/jquery.min.js %>” />’>
3. Emedded Code: 

You can use the embedded code any where in application page and web parts but don’t use it in master page and page layout even though they seem work, because master page and page layout can be customized. The embedded code is only allowed in the uncustomized pages.

4. SharePoint Control: 

You can use the value returned by this control as control attribute but this is more like an hack, but it works.

If you don’t want to use it directly in attribute, you can use asp.net leteral control like this


 
 

 

Here is when to use which option with different controls

1.
The only way works for ScripLink is the token ~sitecollection

<SharePoint:ScriptLink ID="ScriptLink2" language="javascript" name="~sitecollection/_layouts/TestScript1.js" OnDemand="true" runat="server"/>


2.

Use ScriptLink to include JavaScript in SharePoint. If you have to use , then this usage will work

<script src='/_layouts/TestScript4.js'></script>


3.

The only way works for ScripLink is the SharePoint Office Server token

<SharePoint:CssRegistration ID="CssRegistration3" Name="<% $SPUrl:~sitecollection/_layouts/TestStyle2.css %>" After="corev4.css" runat="server"/>

 
4.

For link, try this first
 

<link rel="stylesheet" type="text/css" href="<% $SPUrl:~sitecollection/_layouts/TestStyle3.css %>">


If it doesn’t work, try

<link rel="stylesheet" type="text/css" href="<SharePoint:ProjectProperty ID="ProjectProperty22" Property="SiteUrl" runat="server"/>Style%20Library/test.css"/>


5.

<img src='/_layouts/SiteUrlTest/blog3.png' />


Conclusion:

When you need to reference site collection url such as /sites/hr/…, try the token “~sitecollection” first. If it doesn’t work, try the SharePoint Office Server token “”.

As last resort, try the control as control attribute value or combine it usage with literal control.

Resource throttles and limits

The following table summarizes information about resource throttles and limits that you need to be aware of. These throttles and limits are set on the Resource Throttling page in Central Administration. Contact your administrator for specific limits and requests for your site.
NOTE   To assist with management, the administrator is not subject to the following resource throttles and limits.
Threshold 
or Limit
Default
value
Description
List View Threshold
5,000
Specifies the maximum number of list or library items that a database operation, such as a query, can process at one time. Operations that exceed this limit are blocked.
To give you time to make alternative plans, You are warned on the List Settings page when your list has exceeded 3,000 items. The warning contains a help link to this topic.
Unique permissions limit
50,000
Specifies the maximum number of unique permissions allowed for a list or library.
Every time you break the inheritance of permissions for an item or folder, it is counted as 1 unique permission toward this limit. If you try to add an item that would lead to exceeding this limit, you are prevented from doing so.
Row size limit
6
Specifies the maximum number of table rows internal to the database used for a list or library item. To accommodate wide lists with many columns, each item is wrapped over several internal table rows, up to 6 rows and up to a total of 8,000 bytes (excluding attachments).
For example, if you have a list with many small columns, one that contains hundreds of Yes/No columns, then you could exceed this limit, in which case you would not be able to add more Yes/No columns to the list, but you still may be allowed to add columns of a different type.
NOTE   Administrators can only set this limit by using the object model, not through the user interface.
List View Lookup Threshold
8
Specifies the maximum number of join operations, such as those based on lookup, Person/Group, or workflow status columns.
If the query uses more than eight columns, the operation is blocked. However, it is possible to programmatically select which columns to use by using maximal view, which can be set through the object model.
List View Threshold size for auditors and administrators
20,000
Specifies the maximum number of list or library items that a database operation, such as a query, can process at one time when performed by an auditor or administrator with appropriate permissions. This setting works in conjunction with Allow Object Model Override.
Allow Object Model Override
Y
Specifies whether or not developers can perform database operations, such as queries, that request an override of the List View Threshold to the higher limit specified by the List View Threshold for auditors and administrators. An administrator must enable an object model override, and then developers with appropriate permission may then programmatically request that their query use the higher List View Threshold to take advantage of it.
Daily time window
None
Specifies a time period during which resource thresholds and limits are ignored. An administrator can configure a time window during “off-peak” hours in 15 minute increments and up to 24 hours, such as, 6:00 PM to 10:00 PM or 1:30 AM to 5:15 AM.
NOTE   A database operation or query started within the daily time window continues until completion (or failure) even if it doesn’t finish within the specified time window.

Enabling ScriptManager PageMethods doesn’t work in some scenarios in SharePoint 2013

I worked on a case where the problem was that PageMethods won’t execute from within a SharePoint 2013 application page (page deployed to the _layouts folder).  To replicate the problem, I had a custom master page deployed through a VS 2012 solution with the following definition within the element.

<asp:ScriptManager id="ScriptManager" runat="server" EnablePageMethods="true" EnablePartialRendering="true" EnableScriptGlobalization="false" EnableScriptLocalization="true" />
 
      <script type="text/javascript">
 
          function CallMe() {
              alert("called from master page");
              // call server side method
              PageMethods.TestMethod(OnRequestComplete, OnRequestError);
          }
 
          
          function OnRequestComplete(res, userContext, methodName) {
 
              alert(res);
 
          }
 
          function OnRequestError(error, userContext, methodName) {
 
              if (error != null) {
 
                  alert(error.get_message());
 
              }
 
          }
 
    

And I had my TestMethod defined in my application page as shown below.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.Services;
 
namespace SPProj.Layouts.SPProj
{
    public partial class ApplicationPage1 : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Button1.Attributes.Add("onclick", "javascript:CallMe()");
        }
 
        [WebMethod]
        public static string TestMethod()
        {
            return "Hello";
        }
    }
}

Notice the ‘onclick’ attribute added to the server-side button control in the Page_Load event.  The idea is, when this page is loaded and the button is clicked, we call the “CallMe()” function defined in the master page.  And this client-side function will call the server-side TestMethod method by virtue of having PageMethods enabled.  But this is what happens in SharePoint 2013.

The page loads.

image

Click the button.

image

Click OK on this alert and the second message box won’t come up.  You might have already noticed the JavaScript error in IE status bar.  Double-click on it and you’ll see this error.

image

Apparently, this is because of anonymous JavaScript functions being pushed to the page by the new web-scoped feature called “Following Content”.  Here’s a snippet from IE Developer Tools.  For brevity, only relevant snippet is shown.

PageMethods.set_path("applicationpage1.aspx");
PageMethods.TestMethod= function(onSuccess,onFailed,userContext) {
/// 
/// 
/// 
PageMethods._staticInstance.TestMethod(onSuccess,onFailed,userContext); }
 
// from custom action with id = "FollowingCalloutScriptBlock"
(function(){
 
        if (typeof(_spBodyOnLoadFunctions) === 'undefined' || _spBodyOnLoadFunctions === null) {
            return;
        }
        _spBodyOnLoadFunctions.push(function() {

The problem is that when PageMethods are pushed to the page, a semi-colon isn’t added to properly terminate the JavaScript block.  This is actually not a SharePoint but ASP.NET issue that PageMethods are not properly block terminated.  Since the following JavaScript code is anonymous function at runtime it’s considered to be in the same block and executed, which causes the object expected error.

There are multiple ways to fix it.

1. Deactivate “Following Content” feature.  Not a good one, but if this feature is not being used (which is highly unlikely), then simply deactivating it resolves this error.

2. Modify the “Following Content” feature.  Change the 2 functions defined in the ScriptBlock of element to be named functions instead of anonymous.  Deactivate/Uninstall “Following Content” feature.  Install/Activate “Following Content” feature.  THIS OF COURSE, IS UNSUPPORTED.

3. Override the Render method in the application page and inject a semi-colon character.  Below is the modified application page code.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.Services;
 
namespace SPProj.Layouts.SPProj
{
    public partial class ApplicationPage1 : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Button1.Attributes.Add("onclick", "javascript:CallMe()");
        }
 
        [WebMethod]
        public static string TestMethod()
        {
            return "Hello";
        }
 
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, typeof(ApplicationPage1), "semicolon", ";", true);
            base.Render(writer);
        }
    }
}

Once you deploy this solution, browse to the application page and watch the scripts pushed using IE Developer Tools, you’ll see this.

PageMethods.set_path("applicationpage1.aspx");
PageMethods.TestMethod= function(onSuccess,onFailed,userContext) {
/// 
/// 
/// 
PageMethods._staticInstance.TestMethod(onSuccess,onFailed,userContext); }
;
// from custom action with id = "FollowingCalloutScriptBlock"
(function(){
 
        if (typeof(_spBodyOnLoadFunctions) === 'undefined' || _spBodyOnLoadFunctions === null) {
            return;
        }
        _spBodyOnLoadFunctions.push(function() {

Notice that “;” character after the PageMethods declaration just before the anonymous functions from “Following Content” feature starts.  Now, when the application page is browsed.

image

And the button is clicked.

image

The first alert is displayed and when you click OK, you’ll see the second alert as well.

image

That resolves this issue.  Hope this post was helpful.

Cross post from http://blogs.msdn.com/sridhara

SharePoint Feature Deactivation – Removing Module Assets

If your feature is going to install assets to your site, i.e. web parts (.webpart or .dwp files), master pages, page layouts, images, javascript files, custom stylesheet, even possibly custom content type, list definitions and list instances, it is normally considered best practices to remove what you added when the feature is deactivated. I say normally because sometime you may not be able to remove custom Content Types or List Instances if they are being used. Or possibly your assets may have been modified, so removing them even if the feature is deactived could be a problem. Features in of themselves do not offer a pre-built way to remove what was added, nor would uninstalling and deleting the solution remove assets a feature installed, but features do offer the function:

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

By overriding this function we can add our own code that can use a similar method as we used when checking in files during the feature activation, that being we can take the Element Definition Collection from the feature itself, loop through it and look for what we know we added, possibly modules (don’t forget that .webpart files are added to _catalogs/wp via a module), or a List Instance, etc. Once we grab a list of assets, lists etc that were added we can remove them.
Let us look at feature deactivation code that could be used in a farm based solution’s feature event receiver.
 public override void FeatureDeactivating(SPFeatureReceiverProperties properties)  
{
using (SPSite spSite = properties.Feature.Parent as SPSite)
{
using (SPWeb web = spSite.RootWeb)
{
List lModuleFiles = new List();
List lListInstances = new List();
SPElementDefinitionCollection spFeatureElements = properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture);
foreach (SPElementDefinition spElementDefinition in spFeatureElements)
{
if (spElementDefinition.ElementType == "Module")
{
XmlElement xmlElementNode = (XmlElement)spElementDefinition.XmlDefinition;
String sModName = xmlElementNode.GetAttribute("Name");
String sModUrl = SPUtility.ConcatUrls(spSite.Url, xmlElementNode.GetAttribute("Url"));
foreach (XmlElement xmlChildElementNode in xmlElementNode.ChildNodes)
{
if (xmlChildElementNode.Name == "File")
{
String sFile = SPUtility.ConcatUrls(sModUrl, xmlChildElementNode.GetAttribute("Url"));
lModuleFiles.Add(sFile);
}
}
}
else if (spElementDefinition.ElementType == "ListInstance")
{
XmlElement xmlElementNode = (XmlElement)spElementDefinition.XmlDefinition;
String sModTitle = xmlElementNode.GetAttribute("Title");
String sModUrl = xmlElementNode.GetAttribute("Url");
lListInstances.Add(sModTitle);
}
}
#region Delete list instances added by this feature
try
{
if (lListInstances.Count > 0)
{
foreach (String listName in lListInstances)
{
try
{
SPList workList = spSite.RootWeb.Lists.TryGetList(listName);
if (workList != null)
{
Guid gd = workList.ID;
spSite.RootWeb.Lists.Delete(gd);
}
}
catch { }
}
}
}
catch { }
try
{
if (lModuleFiles.Count > 0)
{
foreach (String fileUrl in lModuleFiles)
{
try
{
SPFile file = web.GetFile(fileUrl);
if (file != null) {
SPFolder folder = file.ParentFolder;
file.Delete();
web.Update();
//attempt to delete the folder if it is now empty
if (folder.Files.Count < 1)
folder.Delete();
}
}
catch { }
}
}
}
catch { }
}
}
}