Seems a simple enough task, where one needs to retreive page-url, fetch SPLimitedWebPart manager based on page-url. Use SPLimitedWebPart Manager to iterate through collection of webparts which exist of specified page URL and update properties based on configuration input.
Like any other developer, I started of by creating a console application and dumping code in it like a no mad. Half-way down the line when I began to query webparts collection using SPLimitedWebPart Manger, I see all webparts returned are of type "ErrorWebParts".
[/code]
This code loops through all webparts on all pages, checks to see if the webpart
is a ContentByQueryWebpart and updates some properties.
As soon as you use webpartmanager to fetch webpart, it will return your queried
webpart as Microsoft.SharePoint.WebPartPages.ErrorWebPart.
Why? Because of the following code is called by the specific properties of the ContentByQueryWebpart
(actually its parent, the CmsDataFormWebpart):
internal static string MakeServerRelativeUrl(string url)
{
return concatenateUrls(SPContext.GetContext(HttpContext.Current).Site.ServerRelativeUrl, url);
}
The webpart will always call the SPContext, but from a console
application there is no web-context. Therefore when initiating the
ContentByQueryWebpart, it will always thow an exception like:
"An error occured while setting the value of this property:
Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart:MainXslLink -
Exception has been thrown by the target of an invocation."
A workaround for this would be to provide it with a context. Take a look at the
modifications done to rectify the problem -
[code]
using (SPSite mysite = new SPSite("http://server:27158/"))
{
using (SPWeb myweb = mysite.RootWeb)
{
myweb.AllowUnsafeUpdates = true;
bool isContextNull = false;
if (HttpContext.Current == null)
{
isContextNull = true;
HttpRequest request = new HttpRequest("", myweb.Url, "");
HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
HttpContext.Current.Items["HttpHandlerSPWeb"] = myweb;
}
using (SPLimitedWebPartManager manager = myweb.GetLimitedWebPartManager(
"/Pages/Home.aspx", System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared))
{
IEnumerator myWebPArtsEnum = manager.WebParts.GetEnumerator();
String xmlstring = "";
while (myWebPArtsEnum.MoveNext())
{
xmlstring += "
if (myWebPArtsEnum.Current.ToString() =="IST.MOSS.Webparts.ISTContentByQueryWebPart")
{
xmlstring += " Title='" + ((System.Web.UI.WebControls.WebParts.WebPart)myWebPArtsEnum.Current).Title + "'";
xmlstring += " ID='" + ((System.Web.UI.WebControls.WebParts.WebPart)myWebPArtsEnum.Current).ID + "'";
xmlstring += " DisplayTitle='" + ((System.Web.UI.WebControls.WebParts.WebPart)myWebPArtsEnum.Current).DisplayTitle + "'";
((Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart)myWebPArtsEnum.Current).ItemLimit = 20;
//((Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart)myWebPArtsEnum.Current).CommonViewFields = "Title,Text;URL,URL;Forward_x0020_to_x0020_URL,Link;Show_x0020_for_x0020_Locations,Text;";
//PublishingWeb pw = PublishingWeb.GetPublishingWeb(myweb);
//((Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart)myWebPArtsEnum.Current).Update(pw);
manager.SaveChanges((Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart)myWebPArtsEnum.Current);
myweb.Update();
}
xmlstring += " />";
}
xmlstring += "";
}
if(isContextNull)
HttpContext.Current = null;
myweb.AllowUnsafeUpdates = false;
}
}
[/code]
Hope this helped.
-cheers
7 comments:
Great Article!!! But I'm still facing the issue with my console app, I'm missing something here.
For a console app, make your your web part assembly is in the GAC.
You're amazing. Creating the HttpContext did the trick. Don't have to worry about timeout on my 4000+ files that need updated. How did you ever figured this out?
Thanks,
Xopher
Great post!
I was battling with this error for a while now. Creating httpContext fixed it all, I can update my webpart smoothly now.
Thanks a lot!
Cedric
Good investigation!
http://pioneeringsharepoint.blogspot.com/2009/09/i-need-my-spcontext-now.html
Great post, thanks for sharing !
Thanks for that... definitely a great post since it solved my problem.
Setting the SPContext did the trick...
Post a Comment