In Sharepoint 2013 with cumulative updates of march and april there is a new boolean attribute called ReplaceContent that you can use in the Elements.xml. In my project I use this setting and it seems to work.
The module won't replace files that have already been provisioned.
You could delete them in Feature deactivating if you want to re-provision files in a feature.
I use this code in my project in the feature deactivating
public override void FeatureDeactivating(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);
}
}
}
}
}
}
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 virtualPath = string.Concat(web.Url, "/", module.ProvisioningUrl, "/", file.Name);
SPFile fileDelete = web.GetFile(virtualPath);
if (fileDelete != null)
{
fileDelete.Delete();
}
}
}
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; }
}
}
Have a nice day