Sharepoint: how can i find all the pages that host a particular web part? - sharepoint

As the question says - is there a way to determine which pages are including my web part?

If you're looking for code, I've got something for you. If you'd like to find all Content Query web parts then you would call my code like this:
FindWebPart("http://server.com/", "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart");
Here's the code:
public static void FindWebPart(string siteCollectionUrl, string webPartName)
{
using (SPSite siteCollection = new SPSite(siteCollectionUrl))
{
using (SPWeb rootSite = siteCollection.OpenWeb())
{
FindWebPartHelper(rootSite, webPartName);
}
}
}
public static void FindWebPartHelper(SPWeb site, string webPartName)
{
// Search for web part in Pages document library
SPList pagesList = null;
try
{
pagesList = site.Lists["Pages"];
}
catch (ArgumentException)
{
// List not found
}
if (null != pagesList)
{
SPListItemCollection pages = pagesList.Items;
foreach (SPListItem page in pages)
{
SPFile file = page.File;
using (SPLimitedWebPartManager mgr = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
try
{
SPLimitedWebPartCollection webparts = mgr.WebParts;
foreach (System.Web.UI.WebControls.WebParts.WebPart wp in webparts)
{
// Here perform the webpart check
// For instance you could identify the web part by
// its class name
if (webPartName == wp.GetType().ToString())
{
// Found a match! Now do something...
Console.WriteLine("Found web part!");
}
}
}
finally
{
// Needs to be disposed
mgr.Web.Dispose();
}
}
}
}
// Check sub sites
SPWebCollection subSites = site.Webs;
foreach (SPWeb subSite in subSites)
{
try
{
FindWebPartHelper(subSite, webPartName);
}
finally
{
// Don't forget to dispose!
subSite.Dispose();
}
}
}
Ofcourse you can make little changes to this code. Currently it does a string comparison, but it's easy to do it in a more typed way. Have fun!

By way of an alternative, if you want to test web part pages including the default page on collaboration sites, you can use the following code snippet which uses the Files property of the SPWeb object:
private static void FindWebPart(string siteUrl, string webPartName)
{
using (var site = new SPSite(siteUrl))
{
foreach (SPWeb web in site.AllWebs)
{
foreach (var file in web.Files.Cast<SPFile>().Where(file => file.Name.EndsWith("aspx")))
{
FindWebPartOnPage(webPartName, file);
}
var pagesTemplateType = (SPListTemplateType)Enum.Parse(typeof(SPListTemplateType), "850");
foreach (var documentLibrary in web.Lists.Cast<SPList>().Where(list => list.BaseTemplate == pagesTemplateType || (list.BaseTemplate == SPListTemplateType.DocumentLibrary && list.Title.Contains("Pages"))))
{
foreach (var file in documentLibrary.Items.Cast<SPListItem>().Where(item => item.File.Name.EndsWith("aspx")).Select(item => item.File))
{
FindWebPartOnPage(webPartName, file);
}
}
web.Dispose();
}
}
}
private static void FindWebPartOnPage(string webPartName, SPFile file)
{
using (var webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
if (webPartManager.WebParts.Cast<WebPart>().Any(webPart => webPart.GetType().Name == webPartName))
{
Console.WriteLine(file.ServerRelativeUrl);
}
webPartManager.Web.Dispose();
}
}
Note: the Pages library created by the Publishing feature does not have a BaseTemplate value of SPListTemplateType.DocumentLibrary; instead it is represented by a "hidden" value of 850.
This is called a similar manner to LeonZandman's answer, however only the class name is used to supply a match:
FindWebPart("http://yoursite.com/", "MyWebPart");

Related

Track if the users have read documents Sharepoint 2010 Document Center

I want to track if the users have read sharepoint 2010 document center's documents, currently user infos are not stored in audit logs, is there any way to do it?
It gets stored in audit logs.
Enable auditing for that particular document library and then get the details using the following code:
SPSite oSPsite = new SPSite
SPList doclib= oSPWeb.Lists["doclib"];
SPWeb oSPWeb = oSPsite.OpenWeb()
SPListItemCollection doclibitems= doclib.Items;
foreach (SPListItem odoclibItem in doclibitems)
{
odoclibItem .Audit.AuditFlags = SPAuditMaskType.View;
// odoclibItem .Audit.AuditFlags = SPAuditMaskType
SPAuditQuery oquery = new SPAuditQuery(oSPsite);
oquery.RestrictToListItem(odoclibItem );
odoclibItem .Audit.Update();
SPAuditEntryCollection oAuditEntryCollection =SPsite.Audit.GetEntries(oquery);
foreach (SPAuditEntry entry in oAuditEntryCollection)
{
if (entry.Event == SPAuditEventType.View)
{
id = Convert.ToString(entry.UserId);
// get the user name and other details here
}
}
}
I found the solution. Here is the steps.
1- Create a class library.
2- Right click the library and add new item.
3- Select ASP.NET Module under Web node.
4- Add PreRequestHandlerExecute event handler inside Init.Here is my code.
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += context_PreRequestHandlerExecute;
}
5- Methods
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
var app = sender as HttpApplication;
if (app != null)
{
string requesturl = app.Request.Url.ToString();
string file = string.Empty;
// if document opens in browser
if (app.Request.QueryString["Source"] != null && app.Request.QueryString["id"] != null && app.Request.QueryString["Source"].StartsWith(documentSiteUrl))
{
file = app.Request.QueryString["id"].Remove(0, app.Request.QueryString["id"].LastIndexOf('/'));
Worker(file);
}
// if document opened installed office apps or downloaded the document
if (requesturl.StartsWith(SiteUrl))
{
requesturl = requesturl.Remove(0, requesturl.LastIndexOf('/') + 1);
Worker(requesturl);
}
}
});
}
private void Worker(string requesturl)
{
#region ext control
List<string> extList = new List<string>(Exts.Split(';'));
bool result = false;
foreach (string item in extList)
{
if (requesturl.EndsWith(item))
{
result = true;
break;
}
}
#endregion
if ((!requesturl.Contains(".aspx")) && (!requesturl.EndsWith("/")) && result)
{
SPWeb web = SPContext.Current.Web;
String fileName = requesturl.Substring(requesturl.LastIndexOf("/") + 1);
// Add log
web.AllowUnsafeUpdates = true;
AddReadInfo(web.CurrentUser, fileName, web);
web.AllowUnsafeUpdates = false;
}
}
private void AddReadInfo(SPUser sPUser, string fileName, SPWeb web)
{
#region Logging
SPList logList = web.Lists.TryGetList("LogList");
if (logList != null)
{
SPListItem item = logList.Items.Add();
item["User"] = sPUser.Name;
item["Document"] = fileName;
item["Read"] = "Read";
item.Update();
}
#endregion
}
6- Don't forget signing the project.
7- Build Project.
8- Add dll to GAC and BIN folder under the C:\inetpub\wwwroot\wss\VirtualDirectories\80\ folder.
9- Open IIS Manager.
10- Find your site nod and select.
11- Open Modules.
12- Right click under modules page and select Add Managed Module option.
13- Give a name and select your module under dropdownlist.
14- IIS reset.

EventReceiver to Create folder sharepoint 2010

I have this event receiver c# class that I am trying to implement on a Sharepoint site. It did not work. I have deployed it from visual studio 2010 after it was build ok. Does anyone see what is the problem? Is the code ok? or is the problem on the SP? Thank you.
- here is the new code
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace EventReceiverCFolder.EventReceiver1
{
/// <summary>
/// List Item Events
/// </summary>
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item is being added.
/// </summary>
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
if (properties.ListTitle == "CF") // list where the item was added
{ // if item was added to this list then create a folder on - Dlib - list
UpdateFolder(properties);
}
}
catch (Exception ex)
{
properties.Status = SPEventReceiverStatus.CancelWithError;
properties.ErrorMessage = ex.Message;
properties.Cancel = true;
}
}
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("DLib"); // this is doc Library where the new folder will be created
//note that we are creating a list item, not a folder - a folder IS a list item
SPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (createdFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
finally { }
}
}
}
Don't do this: SPUser privilegedAccount = properties.Web.AllUsers[#"SHAREPOINT\SYSTEM"];
Read up on using SPSecurity.RunWithElevatedPrivileges. See the MSDN documentation here.
Also don't do a using (SPSite... and inside the using block you try to get the web via SPContext.Current - that web won't be elevated anymore.
The correct way is something along these lines (I didn't try this, so it' just to give you an idea where you are headed):
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("ListTitle"); //is that really the list title?
//note that we are creating a list item, not a folder - a folder IS a list item
SSPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (newFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
Also try to debug your code, set breakpoints etc.
I had to get folder name like this:
string foldername = Convert.ToString(properties.AfterProperties["Title"]);
Did you try to debug it? try to debug and tell us what error you are getting.
BUT before you debug first use sharepoint manager to see if your event receiver is attached properly.
If you dont know how to debug sharepoint event receiver then please see this

webpart is working on local server but not working on production when "SPSite" class is uesd in the webpart

webpart is working on local server but not working on production server when "SPSite" class is uesd in the web part. On the production server it throws error. If I do not use that class in the webpart the web part also works on live machine.
Any idea what might be causing the error?
the code in the webpart is this:
namespace CompanyNews
{
[Guid("40de3c60-9e30-4050-b9f3-01e71868f522")]
public class CompanyNews : System.Web.UI.WebControls.WebParts.WebPart
{
private HtmlTextWriter writer;
public CompanyNews()
{
}
protected override void RenderContents(HtmlTextWriter writer)
{
base.RenderContents(writer);
using (SPSite site = SPContext.Current.Site)
{
using (SPWeb web = site.OpenWeb())
{
string listName = "News Display";
writer.Write(listName);
SPList list = null;
foreach (SPList currentList in web.Lists)
{
if (currentList.Title.Equals(listName,
StringComparison.InvariantCultureIgnoreCase))
{
list = currentList;
break;
}
}
writer.WriteBeginTag("ul");
foreach (SPListItem item in list.Items)
{
writer.Write("<li style=\"font-size:12px;padding:1px\">");
writer.Write(item["Title"].ToString() + "... ");
writer.Write("<a class=\"smallerred\" href=\"#\">Read More</a>");
writer.Write("</li>");
}
writer.WriteEndTag("ul");
}
}
}
}
}
The dll of the webpart is in the bin folder and in the web.config file there is an entry for the web par as a safe control.
Other webpart which displays a "hellow world" message is also uploaded to production the same way.
I i guess its the code that is causing the problem.
The error message is: "An error occurred while previewing the web part"
just something I noticed, you shouldn't wrap objects from the Current Context in a using statement. Good article here Clicky
Better practice would be to use the following
using (SPSite mySite = new SPSite(SPContext.Current.Site.Url))
{
...
}
Also you should look at packaging up your solution in a WSP, allowing stsadm to deploy it. Dragging into the GAC isn't very good practice.
Shane
The SPSite object isn't getting reference anywhere that I can see. Why don't you remove it anyway as it's superflous to your needs?
SPWeb web = SPContext.Current.Web;
string listName = "News Display";
writer.Write(listName);
SPList list = null;
foreach (SPList currentList in web.Lists)
{
if (currentList.Title.Equals(listName,
StringComparison.InvariantCultureIgnoreCase))
{
list = currentList;
break;
}
}
writer.WriteBeginTag("ul");
foreach (SPListItem item in list.Items)
{
writer.Write("<li style=\"font-size:12px;padding:1px\">");
writer.Write(item["Title"].ToString() + "... ");
writer.Write("<a class=\"smallerred\" href=\"#\">Read More</a>");
writer.Write("</li>");
}
writer.WriteEndTag("ul");

SPListItem.Update Fails

Using the following block of code, the listItem.Update fails with a NullReferenceException:
SPWeb web = null;
SPList list = null;
SPListItem listItem = null;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(this.SiteUrl))
{
web = site.OpenWeb();
list = web.Lists[this.ListName];
listItem = list.Items.Add();
listItem["Background"] = "foo";
}
}
);
listItem.Update();
}
catch
{
}
finally
{
web.Dispose();
}
If I move the listItem.Update() method inside of the anonymous delegate, I get "Operation is not valid due to the current state of the object."
Yes, I've combed through SO and have tried many permutations without success.
Any ideas?
Update:
After the first comment, I tried to remove the anonymous delegate from the code to see if it fared any better:
// store the selected item to pass between methods
public T SelectedItem { get; set; }
// set the selected item and call the delegate method
public virtual void Save(T item)
{
SelectedItem = item;
try
{
SPSecurity.RunWithElevatedPrivileges(SaveSelectedItem);
}
catch
{
}
}
public virtual void SaveSelectedItem()
{
if (SelectedItem != null)
{
using (SPSite site = new SPSite(this.SiteUrl))
{
using(SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[this.ListName];
SPListItem listItem = list.Items.Add();
//UpdateListItem(listItem, SelectedItem);
listItem["Background"] = "foo";
listItem.Update();
}
}
}
}
And this still fails "Operation is not valid due to the current state of the object." In both code samples, it looks like site.Impersonating is false. I am using Windows Auth, and Impersonation in the web.config. This is running from the ASP.Net Development server.
I found an example from this site (blackninjasoftware). I create a reference to the site, grab its SystemAccount token and then create another reference to the site, using the admin token. It seemed a little hackish to me at first - but hey - I have a deadline.
Final working method body now looks like:
SPListItem new_item = null;
SPSite initialSite = new SPSite(this.SiteUrl);
using (var site = new SPSite(this.SiteUrl, initialSite.SystemAccount.UserToken))
{
// This code runs under the security context of the SHAREPOINT\system
// for all objects accessed through the "site" reference. Note that it's a
// different reference than SPContext.Current.Site.
using (var elevatedWeb = site.OpenWeb())
{
elevatedWeb.AllowUnsafeUpdates = true;
SPList list = elevatedWeb.Lists[this.ListName];
new_item = list.Items.Add();
UpdateListItem(new_item, item);
if (new_item != null)
{
new_item.Update();
}
}
}
initialSite.Dispose();

Find out the URL for the document library of a SharePoint document

If i know the URL for a document, can I find the URL for sharepoint document library in which the document is present. The following are two sample URLs for a SharePoint site. The first document is present under the root of a document library. The second document is present under a folder "folder1" within the document library. Appreciate if there is anyway to know the URL for a document library (http:///sites/site1/DocLib/Forms/AllItems.aspx).
http:///sites/site1/DocLib/a.doc
http:///sites/site1/DocLib/folder1/a.doc
Thanks for your replies. I am looking for a solution with MOSS OOTB web service or based on the URL pattern. Can we use any of these to acheive this please?
Thanks.
The SPWeb object has a GetFile method, which takes the full file url.
SPFile file = web.GetFile(yoururl);
Now it's easy to get to the SPList's url, by using the following:
string listUrl = file.Item.ParentList.DefaultViewUrl;
So, in a method together:
public string GetListUrlFromFileUrl(string fullFileUrl)
{
using (SPSite site = new SPSite(fullFileUrl))
{
using(SPWeb myWeb = site.OpenWeb())
{
SPFile file = myWeb.GetFile(fullFileUrl);
return file.Item.ParentList.DefaultViewUrl;
}
}
}
Make sure to reference Microsoft.Sharepoint.dll in your project as well.
There are two different ways I do this, depending on the situation. Neither performs extremely well (important to note), though the second solution typically performs fairly well for our use cases.
The first is extremely simple:
private SPList GetListForFile(string fileUrl)
{
using (SPSite site = new SPSite(fileUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPFile file = web.GetFile(fileUrl);
if (file.Exists)
{
return file.Item.ParentList;
}
}
}
return null;
}
The second is a little more complex. It does require you first chopping off the file part of the URL, then passing it in to the method to get the correct SPWeb, then finding the right list in the web.
private SPList GetListForFile(string fileUrl)
{
using(SPWeb web = OpenWeb(GetFolderUrl(fileUrl)))
{
string listName = fileUrl.Replace(web.ServerRelativeUrl, "");
listName = listName.Substring(0, listName.IndexOf('/'));
return web.Lists[listName];
}
}
private string GetFolderUrl(string fileUrl)
{
return Regex.Replace(fileUrl, #"/[^/]+?\.[A-Z0-9_]{1,6}$", "",
RegexOptions.IgnoreCase | RegexOptions.Singleline);
}
private SPWeb OpenWeb(string folderUrl)
{
SPWeb web = null;
while(web == null)
{
web = Site.OpenWeb(folderUrl);
if (!web.Exists)
{
web.Dispose();
web = null;
}
folderUrl = folderUrl.Substring(0, folderUrl.LastIndexOf("/"));
if (folderUrl.Length == 0)
{
folderUrl = "/";
}
}
return web;
}

Resources