I have resolved the same issue using the my post.
In Feature.xml add a reference to the Feature receiver class.
<?xml version="1.0" encoding="utf-8"?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
Id="{35867BDA-82DC-418c-9005-79CCC363E3CD}"
Title="blah"
Description="blah"
Scope="Site"
Hidden="FALSE"
Version="1.0.0.0"
ReceiverAssembly="TestSPSolution, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f5afeac9a8e5e1b0"
ReceiverClass="TestSPSolution.UpdateFiles">
<ElementManifests>
<ElementManifest Location="ProvisionedFiles.xml" />
</ElementManifests>
</Feature>
Feature Receiver class will contain the following code and your master pages and page layouts will be updated like a charm :)
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Globalization;
using System.Xml;
using System.Collections;
using System.Linq;
namespace TestSPSolution
{
public class UpdateFiles : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
if (properties != null)
{
using (SPSite currentSite = (SPSite)properties.Feature.Parent)
{
using (var web = currentSite.OpenWeb())
{
var ElementDefinitions = properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture);
foreach (SPElementDefinition ElementDefinition in ElementDefinitions)
{
if (ElementDefinition.ElementType == "Module")
{
Helper.UpdateFilesInModule(ElementDefinition, web);
}
}
}
}
}
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
//// throw new NotImplementedException();
}
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
////throw new NotImplementedException();
}
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{
//// throw new NotImplementedException();
}
}
internal static class Helper
{
internal static void UpdateFilesInModule(SPElementDefinition elementDefinition, SPWeb web)
{
XElement xml = elementDefinition.XmlDefinition.ToXElement();
XNamespace xmlns = "http://schemas.microsoft.com/sharepoint/";
string featureDir = elementDefinition.FeatureDefinition.RootDirectory;
Module module = (from m in xml.DescendantsAndSelf()
select new Module
{
ProvisioningUrl = m.Attribute("Url").Value,
PhysicalPath = featureDir,
Files = (from f in m.Elements(xmlns.GetName("File"))
select new Module.File
{
FilePath = (m.Attribute("Path") == null) ? string.Empty : Path.Combine(featureDir, m.Attribute("Path").Value),
Name = f.Attribute("Url").Value,
Properties = (from p in f.Elements(xmlns.GetName("Property"))
select p).ToDictionary(
n => n.Attribute("Name").Value,
v => v.Attribute("Value").Value)
}).ToArray()
}).First();
if (module == null)
{
return;
}
foreach (Module.File file in module.Files)
{
string physicalPath = string.IsNullOrEmpty(file.FilePath) ? Path.Combine(module.PhysicalPath, file.Name) : Path.Combine(file.FilePath, file.Name);
string virtualPath = string.Concat(web.Url, "/", module.ProvisioningUrl, "/", file.Name);
if (File.Exists(physicalPath))
{
using (StreamReader sreader = new StreamReader(physicalPath))
{
if (!CheckOutStatus(web.GetFile(virtualPath)))
{
web.GetFile(virtualPath).CheckOut();
}
SPFile spFile = web.Files.Add(virtualPath, sreader.BaseStream, new Hashtable(file.Properties), true);
spFile.CheckIn("Updated", SPCheckinType.MajorCheckIn);
if (CheckContentApproval(spFile.Item))
{
spFile.Approve("Updated");
}
spFile.Update();
}
}
}
}
private static bool CheckOutStatus(SPFile file)
{
if (file.CheckOutStatus != SPFile.SPCheckOutStatus.None)
{
return true;
}
else
{
return false;
}
}
private static bool CheckContentApproval(SPListItem listitem)
{
bool isContentApprovalEnabled = listitem.ParentList.EnableModeration;
return isContentApprovalEnabled;
}
public static XElement ToXElement(this XmlNode node)
{
XDocument xDoc = new XDocument();
using (XmlWriter xmlWriter = xDoc.CreateWriter())
node.WriteTo(xmlWriter);
return xDoc.Root;
}
}
public class Module
{
public string ProvisioningUrl { get; set; }
public string PhysicalPath { get; set; }
public Module.File[] Files { get; set; }
public class File
{
public string FilePath { get; set; }
public string Name { get; set; }
public Dictionary<string, string> Properties { get; set; }
}
}
}
Update: 2013-11-23
I have created a sample project with feature receiver code, sample page layouts and a master page. The solution (sample project) is tested with SharePoint 2013 also.
For SharePoint 2013, The complete Visual Studio 2013 solution (source code) can be downloaded from Technet
For SharePoint 2010, you may need to use SharePoint 2010 project template, add modules (for master pages and page layouts) and feature event receiver (copy paste the code in the feature event receiver)