Not sure where to begin. I have code setup to create a new site and then copy the look, lists, and webparts from a template site.
IT WORKS FINE WHEN LOGGED IN AS SYSTEM ADMIN!
foreach (Microsoft.SharePoint.WebPartPages.WebPart webPartTemplate in webPartCollectionTemplate)
{
try
{
MemoryStream memoryStream = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
webPartManagerTemplate.ExportWebPart(webPartTemplate, xmlWriter);
xmlWriter.Flush();
memoryStream.Flush();
memoryStream.Position = 0;
XmlTextReader xmlReader = new XmlTextReader(memoryStream);
Microsoft.SharePoint.WebPartPages.ListViewWebPart listViewWebPartTemplate = null;
Microsoft.SharePoint.WebPartPages.ListViewWebPart listViewWebPartTarget = null;
Microsoft.SharePoint.WebPartPages.WebPart webPartTarget = null;
bool webPartIsListViewWebPart = false;
// If it throws an exception, the web part is not a ListViewWebPart
try
{
listViewWebPartTemplate = (ListViewWebPart)webPartTemplate;
webPartIsListViewWebPart = true;
}
catch { }
if (webPartIsListViewWebPart)
{
string errorMessage = "";
listViewWebPartTarget = (Microsoft.SharePoint.WebPartPages.ListViewWebPart)webPartManagerTarget.ImportWebPart(xmlReader, out errorMessage);
if (errorMessage != null)
// log it
// Drop the brackets from the Guid and create a Guid object from the string. Then use it to find the list so we can get the title.
SPList listTemplate = webTemplate.Lists[new Guid(listViewWebPartTemplate.ListName.ToString().TrimStart('{').TrimEnd('}'))];
SPList listTarget = webTarget.Lists[listTemplate.Title];
listViewWebPartTarget.ListName = listTarget.ID.ToString("B").ToUpper();
listViewWebPartTarget.WebId = webTarget.ID;
listViewWebPartTarget.TitleUrl = webPartTemplate.TitleUrl.ToString().Replace(siteTemplate.ServerRelativeUrl, siteTarget.ServerRelativeUrl);
listViewWebPartTarget.Title = webPartTemplate.Title;
listViewWebPartTarget.ZoneID = webPartTemplate.ZoneID;
webPartDictTarget.Add(listViewWebPartTarget.ZoneID + webPartTemplate.ZoneIndex.ToString(), listViewWebPartTarget);
}
else
{
string errorMessage = "";
webPartTarget = (Microsoft.SharePoint.WebPartPages.WebPart)webPartManagerTarget.ImportWebPart(xmlReader, out errorMessage);
if (errorMessage != null)
// log it
webPartTarget.ChromeType = webPartTemplate.ChromeType;
webPartTarget.TitleUrl = webPartTemplate.TitleUrl.ToString().Replace(siteTemplate.ServerRelativeUrl, siteTarget.ServerRelativeUrl);
webPartTarget.Title = webPartTemplate.Title;
webPartTarget.ZoneID = webPartTemplate.ZoneID;
webPartDictTarget.Add(webPartTarget.ZoneID + webPartTemplate.ZoneIndex.ToString(), webPartTarget);
}
}
catch (Exception ex)
{
}
}
// Acquire keys and sort them.
List<string> list = new List<string>(webPartDictTarget.Keys);
list.Sort();
// Loop through keys.
int i = 0;
foreach (var key in list)
{
try
{
Microsoft.SharePoint.WebPartPages.WebPart wpTmp = (Microsoft.SharePoint.WebPartPages.WebPart)webPartDictTarget[key];
webPartManagerTarget.AddWebPart(wpTmp, wpTmp.ZoneID, i);
}
catch (Exception ex)
{
}
i++;
}
The error is thrown on the following line:
webPartManagerTarget.AddWebPart(wpTmp, wpTmp.ZoneID, i);
The stack trace follows {“There was an error generating the XML document.”}:
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter
xmlWriter, Object o, XmlSerializerNamespaces namespaces, String
encodingStyle, String id) at
System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter,
Object o) at
Microsoft.SharePoint.WebPartPages.WebPart.SerializeXml(XmlWriter
writer, XmlSerializer xmls, Boolean shouldSerializeAll) at
Microsoft.SharePoint.WebPartPages.WebPart.WriteXmlAsBytes(XmlSerializer
xmls) at
Microsoft.SharePoint.WebPartPages.WebPart.WriteXmlGlobal(Boolean
disableSafeControlsCheck) at
Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.Serialize(PersonalizationScope
scope) at
Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.get_Links()
at
Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartToStore(WebPart
webPart, Int32 viewId, String viewGuid) at
Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartInternal(SPSupersetWebPart
superset, Boolean throwIfLocked) at
Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager.AddWebPartInternal(WebPart
webPart, String zoneId, Int32 zoneIndex, Boolean throwIfLocked) at
Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager.AddWebPart(WebPart
webPart, String zoneId, Int32 zoneIndex) at
admSitePanelSolution.admSiteCreateCollection.<>c_DisplayClasse.b_c()
And the InnerException {“Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))”}:
at
Microsoft.SharePoint.SPGlobal.HandleUnauthorizedAccessException(UnauthorizedAccessException
ex) at
Microsoft.SharePoint.Library.SPRequest.GetViewsSchemaXml(String
bstrUrl, String bstrListName, Boolean bFullBlown, ISP2DSafeArrayWriter
p2DWriter, Int32& plDefaultViewIndex) at
Microsoft.SharePoint.SPViewCollection.EnsureViewSchema(Boolean
fullBlownSchema) at
Microsoft.SharePoint.SPViewCollection..ctor(SPList list) at
Microsoft.SharePoint.SPList.get_Views() at
Microsoft.SharePoint.SPList.get_DefaultView() at
Microsoft.SharePoint.SPList.get_DefaultViewUrl() at
Microsoft.SharePoint.WebPartPages.ListViewWebPart.ShouldSerializeDetailLink()
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterListViewWebPart.Write9_ListViewWebPart(String
n, String ns, ListViewWebPart o, Boolean isNullable, Boolean needType)
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterListViewWebPart.Write10_WebPart(Object
o)
Can anyone provide some help of why this happens when not logged in as system admin. This whole block also runs inside elevated privileges and the SPSite and SPWeb were also instantiated inside the elevated block. This code is an excerpt.
UPDATE
If I make the user a site collection owner of the base site collection, then the code above runs fine. So what in the code above resets context or needs to reference the base site collection. Thank you.
And my colleague swoops in to save the day! In SP dev, there is a well known ‘hack’ which is used a lot when permissions get weird and stupid. It is to nullify the HttpContext. I tried this around the line and loop which was giving me an issue but it appears that you have to place it much higher in the code during the import.
Here is the new fix.
This code now works for copying webparts from one apsx page to another. Hope it helps someone.