About future of the Content Deployment feature for SharePoint 2019

This article is about future of the “Content Deployment” functionality in SharePoint.
SharePoint production team is not improving the feature till SharePoint 2013 and they will not invest “Content Deployment” in newer SharePoint Builds.
So you should be consider to find an alternative on it.

Feature itself It is not depreciated but it will be present in SharePoint “AS IS” for backward compatibility mode and if any new feature implemented in SharePoint 2019 if it is not convenient or breaks content deployment, it will not going to be adjust/fixed.
Another meaning; SharePoint engineering team will not consider the effect for any new features on Content Deployment.
If you want to continue to use “Content Deployment” Either you should disable the newly implemented features in SharePoint 2019 (Where it may not possible some scenarios) or you need to switch an alternative (Mostly 3rd party products or manual operations)

Our official statement on this issue: Content deployment was announced as NOT recommended since SharePoint 2013 and also this statement valid for higher builds, with limitations and alternatives called out here https://blogs.technet.microsoft.com/tothesharepoint/2013/07/15/changes-to-content-deployment-in-sharepoint-server-2013
While it has not been formally deprecated, it has a limited degree of support, including not supporting the deployment of many features.

How to trim Audit Logs in SharePoint 2007&2010

Auditing enables administrators to keep a reliable log of what is happening with important content on a site collection. Administrators are able to retrieve the entire history of actions taken by a particular user and can also retrieve the entire history of actions taken during a particular date range.In SharePoint Content Database we have a table named  AuditData. This table  stores audit logs when “Auditing” enabled in Site or List Libraries. But once you enabled “Auditing” this table size will growth continously and  it will consume your storage space in your SQL Server quickly.At that point you’ll need to delete older audit logs which is stored in your content database

For SharePoint 2007 we have a STSADM command for clearing audit data for maintanence purporse (but it is depreciated in SharePoint 2010)

So clearing old auditlogs you may fallow

1)      Open a Command Prompt as Administrator Privilegdes in your one of SharePoint Server
2)      Change path to
cd c:\program files\common files\microsoft shared\web server extensions\12\Bin
3)  Run fallowing command change it as your content database name
stsadm –o trimauditlog –date 20120822 –databasename MyContentDatabaseName
Important: The audit entries before given date are permanently deleted after this operation has run

This operation is not done automatically by SharePoint 2007 (it is by design) .This responsibility has assigned to System Administrators for maintenance and shoud be done manually by periodically.For more information about trimauditlog you can check: http://technet.microsoft.com/en-us/library/cc706879.aspx

For SharePoint 2010  we have a dedicated TimerJob for doing this operation .Default schedule is set by monthly.

1)      Go to your Central Administration -> Monitoring -> Review Job definitions

2)      You can see in picture every site has own Audit Log Trimming Job. Select correct job for your actual site
3)      Click “Run Now” button.

I would like to inform you about someting when you run this timer job it will use the value of retention (for example 3 )  which you set in Site Settings-> Site Collection Audit Settings .
Even you set the “Automatically trim the audit log for this site” yes and set retention for 3 days (like in example) . the logs will not be deleted from Content Database until “Audit Log Trimming” timer job is run.After timer job runs the logs until retention value ( 3 days in example) will be deleted.

What if you set “Automatically trim the audit log for this site” as No . How could you clear old logs ?

There is another way to do it by using PowerShell . you can able to give here a date as parameter like stsadm command.

1)      Run SharePoint 2010 Powershell Console by administrator priviledges .
2)      Type fallowing commands:
$site = Get-SPSite http://yoursitecollectionURL
$date = Get-Date “22/08/2012”
#(You need to check date format , type $date and press enter)
$date
#Result like:  22 August 2012 00:00:00
#(and check the date is correct because it can be changed by regional settings. if date is in correct format )
$site.Audit.DeleteEntries($date)

You can fallow whats happening in background by tracing ULS logs in real time. And you can learn how many records are deleted.

//See you next article .

Failed to create the Pages library – SharePoint 2010

When try to create a new site ( Publishing Site ) under your site collection Event log message was: ‘Failed to create the ‘Pages’ library.’.
Exception was: ‘Microsoft.SharePoint.SPException: User cannot be found.
at Microsoft.SharePoint.SPUserCollection.get_Item(String loginName)
at Microsoft.SharePoint.Workflow.SPWorkflowNoCodeSupport.LoadWorkflowBytesElevated(SPFile file, Int32 fileVer, Int32& userid, DateTime& lastModified)

the error caused by the user who created the latest revision of the workflow no longer exists in the site collection.

1) Download and install Sharepoint Designer 2010 if you already do not have it on your system.
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=16573

2)In Sharepoint Designer, please open the root web

3)Go to All files > _Catalogs> wfpub

4)Check out and then Check in all Publishing Workflow configuration files:

5)De-activate and re-activate the publishing Feature from Site Settings

Important: Please proceed with a full farm backup before proceeding with this . It would also be beneficial for your users if you could implement the action plan outside of your regular business hours.

Attach custom master page to personal site using Stapling feature for Sharepoint 2010

Hi Everyone ,

In this article i am explaining how could we attach a custom master page to  Personal sites in MySite Host. I have created two Sharepoint Project named MyMasters and MyMastersStapling using Visual Studio 2010.

you can download the visual studio solution from CodePlex
http://mymasters.codeplex.com/

The solution is anwering fallowing questions  :

* How to deploy custom master page ?
* How to customize a masterpage ?
* How to attach custom master page to personal sites using staping feature ?
* How to set wellcome page programmatically ?
* How to add document library as a web part to a page ?


MyMasters  Project
: is a sharepoint project that deploy a custom master page to a sharepoint site.
MyMasterStapling  Project: is a sharepoint project that attach feature of MyMasters to personal site template and activates the publishing features

First i created a site scope feature named “MyMasters”  and and a feaurereciever .The important part is here the feature guid . You need this guid for feature stapling configuration. you can get the feature guid from Feature manifest file.

<Feature xmlns=”http://schemas.microsoft.com/sharepoint/” Title=”MyMasters” Description=”This feature enables defined master page for your site”
Id=”09c222f7-68ed-4278-a3ce-d64b8dbfb168” ReceiverAssembly=”MyMasters, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2e49c3c1155d0e27″ ReceiverClass=”MyMasters.Features.MyMasters.MyMastersEventReceiver” Scope=”Site”>
… child nodes
</Feature>

And I have create two modules MasterPageModule and CustomAssests Module .

MasterPageModule : contains masterpage file and when the feature is activated it deploy master page the masterpage library under _catalogs folder.
CustomAssests : contains necessary css , js and image files. when the feature is activated it deploy assests to Style Library List of target site by creating specific folder for each asset type.

Here is the code of Feature Reciever.

public class MyMastersEventReceiver : SPFeatureReceiver
{
// Uncomment the method below to handle the event raised after a feature has been activated.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
ApplyTheme(properties);
}
// Uncomment the method below to handle the event raised before a feature is deactivated.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
RevertTheme(properties);
SPSite site = (SPSite)properties.Feature.Parent;
if (site != null)
{
//Remove custom master page
SPFile masterFile = site.RootWeb.GetFile(“_catalogs/masterpage/PersonalSite.master”);
masterFile.Delete();
//Remove assets folders.
site.RootWeb.Folders[“Style Library”].SubFolders.Delete(“CustomCssFiles”);
site.RootWeb.Folders[“Style Library”].SubFolders.Delete(“CustomJSFiles”);
site.RootWeb.Folders[“Style Library”].SubFolders.Delete(“CustomImages”);
}
}   private void ApplyTheme(SPFeatureReceiverProperties properties)
{
SPSite site = (SPSite)properties.Feature.Parent;
if (site != null)
{
// Set the System Master Page to orginal
Uri masterUri = new Uri(site.RootWeb.Url + “/_catalogs/masterpage/v4.master”);
site.RootWeb.MasterUrl = masterUri.AbsolutePath;
// Set the Publishing Master Page our custom PersonalSite.master page.
Uri customMasterUri = new Uri(site.RootWeb.Url + “/_catalogs/masterpage/PersonalSite.master”);
site.RootWeb.CustomMasterUrl = customMasterUri.AbsolutePath;
site.RootWeb.Update();
}
}
private void RevertTheme(SPFeatureReceiverProperties properties)
{
SPSite site = (SPSite)properties.Feature.Parent;
if (site != null)
{
// Set the System Master Page to orginal
Uri masterUri = new Uri(site.RootWeb.Url + “/_catalogs/masterpage/v4.master”);
site.RootWeb.MasterUrl = masterUri.AbsolutePath;
// Set the Publishing Master Page  to orginal
Uri customMasterUri = new Uri(site.RootWeb.Url + “/_catalogs/masterpage/v4.master”);
site.RootWeb.CustomMasterUrl = customMasterUri.AbsolutePath;
site.RootWeb.Update();
}
}
}

By default the following rule applies when you deploy a master page:

  • Site Master Pages: used by all publishing pages – and only by publishing pages
  • System Master Pages: used by everything else including forms and view pages

So in Feature reciever ->  ApplyTheme() function we set two master page first one is V4.master the orginal master for System masterpage and our custom master for Site Master page. As you know you have to enable Publishing Features for  the site if you want to this deplotment work correctly.
For deploying PersonalSite.master via module the element file :

<?xmlversion=1.0encoding=utf-8?>
<Elementsxmlns=http://schemas.microsoft.com/sharepoint/>
<ModuleName=MasterPageModuleList=116Url=_catalogs/masterpage>
   <FilePath=MasterPageModule\PersonalSite.master  Url=PersonalSite.masterType=GhostableInLibrary >
        <PropertyName=UIVersionValue=4 />
        <PropertyName=ContentTypeIdValue=0x010105 />
   </File>
</Module>
</Elements>

You can deploy this solution any site by using visual studio at the end you can able to see this view :

For MyMasterStapling Project . I have created a farm level feature named “MyMastersStapling” and an empty element named “StaplingElement”


Element.xml :

<?xmlversion=1.0encoding=utf-8?>
<Elementsxmlns=http://schemas.microsoft.com/sharepoint/>
<FeatureSiteTemplateAssociationId=f6924d36-2fa8-4f0b-b16d-06b7250180faTemplateName=SPSPERS#0 />
<FeatureSiteTemplateAssociationId=22a9ef51-737b-4ff2-9346-694633fe4416TemplateName=SPSPERS#0 />
<FeatureSiteTemplateAssociationId=09c222f7-68ed-4278-a3ce-d64b8dbfb168TemplateName=SPSPERS#0 />
</Elements>

The FeatureSiteTemplateAssociation element maps feature GUIDs to site defintions – note that the format of the TemplateName attribute value is <SiteDefName>#<ConfigurationID>. This obviously allows a degree of flexibility and allows you to do fairly complex things with different configurations of site definitions. As you now at the beginning of article we highlighted a GUID the feature of MyMasters.

The third item is using this guid 09c222f7-68ed-4278-a3ce-d64b8dbfb168 .What about first two ? these feature ids are blong to Publishing Features. First one is “Publishing Feature Site”  feature’s id at site level and the second one is Publishing feature’s id at web level.

These two ids are built in sharepoint 2010 and it is not change by installation .If you wonder how could i found this ids ,i used the powershell console for sharepoint :
get-spfeature | where-object { $_.DisplayName -like “*Publish*” }


For Template name  SPSPERS is the personal site template name.  for #Zero i am attaching the default configuration.

For More information about site templates.
http://office.microsoft.com/en-us/sharepoint-server-help/a-preview-of-the-sharepoint-server-2010-site-templates-HA101907564.aspx

So far so good. After you deploy our stapling project and activate the feature , the users can able to see our custom master page even if self site creation is enabled for personal sites .

See you next articles.

Sharepoint Deploying resource files to app_globalresources folder using Timer Job.

Hi Everyone ,
in this article i want to explain how to copy your resource files to web application’s app_globalresources folder using by a timer job.

As you know there is four place that the resource files has to be.

\14\Resources\
\14\Template\Features\<Feature Name>\Resources\
\14\Config\Resources\
[Virtual Directory] \App_GlobalResources\

I could not tell about which folder for what,  this is out of concept.But i will explain that

the files which in  \14\Config\Resources can copied to [Virtual Directory] \App_GlobalResources\ folder when a new web.application created. But what about the existing ones.
Friendly stsadm command give us some help.
STSADM -o CopyAppBinContent
But still you can run this command all your sharepoint servers.And this is not an aswer for if you aim to deploy some specific web applications.
You can use
SPWebApplication.ApplyApplicationContentToLocalServer()  fuction for do it with programmatically by creating and using a feature reciever class.

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
            if (webApp != null)
            {
                 ...Somecodes.
                 webApp.Farm.Services.GetValue().ApplyApplicationContentToLocalServer();
            }
        }

I could say that cause a latency when you click to activate button for this feature.and stsadm -o copyappbincontent and ApplyApplicationContentToLocalServer() only copy the resource files on the local server.So
we have  options with Visual Studio 2010 and Sharepoint 2010

First  i will start with the easy way if you are using Sharepoint 2010 and Visual Studio 2010 .
1) Create an Empty Element from vs ide and rename it OurResources.
2) Add a resource file to this element named TestResource.resx
3) Select TestResource.resx and Change property value of  “Build Action”  key to “Resource” from Visual Studio IDE Properties window
4) Change property value of Deployment Type key to “AppGlobalResource”
5) Expand the “Deployment Location” and set the Path is empty .for doing that we can able to copy our resource file root folder of App_GlobalResources.

Second you can use ApplicationResourceFiles element on your Solution xml
<ApplicationResourceFiles> 
    <ApplicationResourceFile Location=”blog.resx”/> 
    <ApplicationResourceFile Location=”blog.en-US.resx”/> 
  </ApplicationResourceFiles>

But what if you are developing a farm scope feature or webapplication scope features that should add extra resource file to selected web applications or you have multiple server farm and you want to deploy resource files accross the farm .This time you may need a TimerJob for deploying your resource files.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.IO;

namespace ResourceDeployment
{

    public class DeployResourcesJob : SPJobDefinition {
        public readonly static string DefinitionName = "job-deploy-resources";

        #region Constructors
        public DeployResourcesJob() : base() { }
        public DeployResourcesJob(SPWebApplication webApp) : base(DeployResourcesJob.JobDefinitionName, webApp, null, SPJobLockType.None) {
            this.Title = "Deploy Resource Files";
        }
        #endregion

        public static void ActivateJob(SPWebApplication webApp) {
            // Delete if any existing jobs
            DeployResourcesJob.Delete(webApp.JobDefinitions, JobDefinitionName);

            DeployResourcesJob job = new DeployResourcesJob(webApp);
            job.Schedule = new SPOneTimeSchedule(DateTime.Now.AddHours(-2));
            job.Update();
        }

       public static void RemoveJob(SPJobDefinitionCollection jobDefinitions, string name) {
           DeployResourcesJob existingJob = jobDefinitions.GetValue(DeployResourcesJob.JobDefinitionName);
            while (existingJob != null)
            {
                existingJob.Delete();
                existingJob.Unprovision();
                existingJob = jobDefinitions.GetValue(DeployResourcesJob.JobDefinitionName);
            }
        }

       public override void Execute(Guid targetInstanceId) {

             string source = SPUtility.GetGenericSetupPath("Resources");
            // Copy or remove the resource file for all zones
            if (Directory.Exists(source)) {
                foreach (SPUrlZone zone in this.WebApplication.IisSettings.Keys) {

                    // Get the location of the App_GlobalResources folder under the target Web Application
                    string destination = this.WebApplication.GetIisSettingsWithFallback(zone).Path + "\\App_GlobalResources";

                    if (Directory.Exists(destination)) {
                        string[] resourceFiles = Directory.GetFiles(source, "MyResource*.resx");
                        foreach (string filename in resourceFiles)
                        {
                            string destinationFilename = destination + "\\" + Path.GetFileName(filename);
                            File.Copy(filename, destinationFilename, true);

                        }
                    }

                }
            }
        }

}
}

Here Some Resources:
http://blogs.msdn.com/b/johnwpowell/archive/2009/11/29/sharepoint-2010-localization-with-visual-studio-2010.aspx
http://blogs.msdn.com/b/maximeb/archive/2008/04/26/deploying-resource-files-across-a-farm.aspx
http://cicoria.com/cs1/blogs/cedarlogic/archive/2010/01/31/deployment-of-resource-files-resx-to-app-globalresources-under-sharepoint.aspx

End of Article 🙂