I'm using C# to modify a view within a photo library across my sharepoint 2013 farm where there are around 600 sites at the moment.
I'm using the method
olist.Views.Add("AllPictures", strColl, sQuery, 40, true, true,Microsoft.SharePoint.SPViewCollection.SPViewType.Html, false)
and basically I'm trying to recreate the main "All Pictures" view as running a routine to switch this view to a grid has caused this view to no longer display anything. My problem is that once I've deleted the view and run the code above it will create a new All Pictures view that has a baseviewid of 6 so the photos appear as thumbnails rather than a table with the details of the photo. I need to be able to specify the baseviewid as 1 but I've not yet found a way to do this.
Solution:
Use code which I found here http://stefan-stanev-sharepoint-blog.blogspot.co.uk/2010/02/listviewwebpart-spview-two-sides-of.html in the comments section. I hope Stefan doesn't mind me copying some of it here.
Important to note is that the wp.ViewGuid = list.DefaultView.ID.ToString("B").ToUpper(); line is commented out because otherwise it will use the baseviewid of the current default view which is 6
which is exactly what we don't want.
The code gets the Photos and Videos list, then gets all the web parts that the list uses, when it gets the AllPictures web part it then saves it for later deletion, adds a new listviewwebpart (but at this stage we can
only add the baseviewid), then deletes the current web part (it seems to only work well in this order) and then gets the hidden view that is created, see stefan's blog for more details.
The second call to Program.UseList then resets some of the view back to how it should look if there is a baseviewid of 1, for this I look at another site with a baseviewid of 1 and checked in sharepoint designer at the XmlDefinition
to see exactly what the xml should look like.
Hope this helps someone else out.
public void LibraryCode(string url)
{
Guid hiddenViewGuid = Guid.Empty;
SPList library = null;
string listUrl = "Photos1/Forms/AllPictures.aspx";
Program.UseList(url, listUrl, list =>
{
SPFile file = list.ParentWeb.GetFile(listUrl);
Guid listID = file.ParentFolder.ParentListId;
if (!listID.Equals(Guid.Empty))
{
library = list.ParentWeb.Lists[listID];
if (library.ForceCheckout && file.Level != SPFileLevel.Checkout) file.CheckOut();
}
SPLimitedWebPartManager mngr = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
SPLimitedWebPartCollection webparts = mngr.WebParts;
System.Web.UI.WebControls.WebParts.WebPart op = null;
for (int k = 0; k < webparts.Count; k++)
{
//get reference to webpart
op = webparts[k];
//check webpart Title to find webpart whose value is to be changed
if (op.Title.Equals("AllPictures"))
{
break;
}
}
XsltListViewWebPart wp = new XsltListViewWebPart();
wp.ListName = list.ID.ToString("B").ToUpper();
//comment out the line below or the new view gets the same baseviewid as
//wp.ViewGuid = list.DefaultView.ID.ToString("B").ToUpper();
wp.XmlDefinition = "<View BaseViewID='1'/>";
mngr.AddWebPart(wp, "Left", 1);
//remove existing web part otherwise there will be two tables of the data on the same page
mngr.DeleteWebPart(op);
hiddenViewGuid = new Guid(wp.ViewGuid);
});
Program.UseList(url, listUrl, list =>
{
SPView view = list.Views[hiddenViewGuid];
view.Title = "All Pictures";
view.Update();
// load the passed viewSchema in an XmlDocument
XmlDocument doc = new XmlDocument();
doc.LoadXml(view.HtmlSchemaXml);
// set the Name attribute with the ID of the hidden LVP's SPView - we use a simple trick to update the full schema of the hidden view
XmlElement root = doc.DocumentElement;
root.SetAttribute("Name", view.ID.ToString("B").ToUpper());
root.SetAttribute("BaseViewID", "1");
root.SetAttribute("Type", "HTML");
root.SetAttribute("Hidden", "False");
// do some changes to the view schema
XmlElement viewFieldsEl = doc.SelectSingleNode("//ViewFields") as XmlElement;
if (viewFieldsEl != null) { viewFieldsEl.InnerXml = #"<FieldRef Name=""DocIcon""/>
<FieldRef Name=""LinkFilename""/>
<FieldRef Name=""ImageSize""/>
<FieldRef Name=""FileSizeDisplay""/>
<FieldRef Name=""Modified""/>
<FieldRef Name=""RequiredField"" Explicit=""TRUE""/>
<FieldRef Name=""PreviewOnForm"" Explicit=""TRUE""/>
<FieldRef Name=""ImageCreateDate""/>
<FieldRef Name=""Project_x0020_Tags""/>
<FieldRef Name=""_Comments""/>
<FieldRef Name=""Originator""/>"; }
XmlElement javascriptEl = doc.SelectSingleNode("//JSLink") as XmlElement;
if (javascriptEl != null) { javascriptEl.InnerXml = "clienttemplates.js|callout.js"; }
// create a dummy view to hold the new schema
SPView cloneView = new SPView(list, doc);
// a small trick with reflection so that we can update the dummy view
typeof(SPView).GetField("m_bExistsInDatabase", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(cloneView, true);
// this will actually update the hidden SPView associated with the LVP
cloneView.Update();
if (library != null)
{
SPFile file = list.ParentWeb.GetFile(listUrl);
if (library.ForceCheckout) file.CheckIn("");
if (library.EnableMinorVersions) file.Publish("");
if (library.EnableModeration) file.Approve("");
}
});
}
Related
I am trying to write a simple web part for Sharepoint 2013 that searches for all pages of a certain content type and outputs a list of their titles. I am using a CAML query to search for that. But no matter what query, the result I have is just a list of all files and folders in this Sharepoint site.
Finally, I reduced the CAML query to a simple "find everything that starts with the letter T", but still the result is outputting all files and folders in the root level of the site.
What am I doing wrong?
protected override void CreateChildControls()
{
Label label1 = new Label();
try
{
SPQuery query = new SPQuery();
query.Query = #"<Query>
<Where>
<BeginsWith>
<FieldRef Name='Title'></FieldRef>
<Value Type='Text'>T</Value>
</BeginsWith>
</Where>
</Query>";
using (SPSite site = new SPSite("https://xxxxxx/sites/xxxxx/en/xxxx/"))
{
using (SPWeb web = site.OpenWeb())
{
PublishingWeb pubweb = PublishingWeb.GetPublishingWeb(web);
PublishingPageCollection collection = pubweb.GetPublishingPages(query);
//now output the results of the query
label1.Text = "Items: " + collection.Count.ToString();
for (int i = 0; i < collection.Count; i++)
{
label1.Text += collection[i].Title + "<br>";
}
}
}
}
catch (Exception ex)
{
label1.Text = ex.Message;
}
Controls.Add(label1);
}
Weirdly, you need to do two things:
1) Remove the opening and closing tag;
2) Make sure the query does not start or end with a blank line.
Then the results will change the the correct ones.
My SharePoint site having a Large List that contains large data
I have to fetch all items and show them in gridview?
I am using below code and getting the below error
"The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator"
private void GetData()
{
using (SPSite site = new SPSite("URL"))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists.TryGetList("BulkData");
if (list != null)
{
SPQuery query = new SPQuery();
query.Query = "<Where><IsNotNull><FieldRef Name=\"Title\" /></IsNotNull></Where>";
query.QueryThrottleMode = SPQueryThrottleOption.Override;
SPListItemCollection items = list.GetItems(query);
int itemCount = items.Count;
StringBuilder sb = new StringBuilder();
string str1 = string.Empty;
foreach (SPListItem item in items)
{
int i = 1;
sb.Append("\r\n").Append(Convert.ToString(item["Title"])).Append("\r\n");
i++;
}
Log(sb);
}
}
}
}
region Log File
public void Log(StringBuilder ErrorMessage)
{
string LogFileTime = DateTime.Now.ToString("ddMMyyyyHHmmss");
string LogFilePath = Server.MapPath(#"~\\Logs\");
if (!File.Exists(LogFilePath + "BulkData" + LogFileTime + ".txt"))
{
var LogFileName = File.Create(LogFilePath + "BulkData" + LogFileTime + ".txt");
var WriteToLogFile = new StreamWriter(LogFileName);
WriteToLogFile.Write(ErrorMessage);
WriteToLogFile.Close();
LogFileName.Close();
}
}
#endregion
You have to modify the List View threshold in Central Admin, setup by default to 5000 elements.
To minimize database contention, SQL Server often uses row-level locking as a strategy to ensure accurate updates without adversely impacting other users who are accessing other rows.
However, if a read or write database operation, such as a query, causes more than 5,000 rows to be locked at once, then it's more efficient for SQL Server to temporarily escalate the lock to the entire table until the database operation is completed.
See this link on MSDN
See this link for instructions step-by-step
However if you must change this value by code you can
SPQuery q1 = new SPQuery();
q1.QueryThrottleMode = SPQueryThrottleOption.Override;
Caution! Remember to grant privileges to the account that will run the code.
see this link for details.
Try using SPQuery.RowLimit to specify the number of items to be fetched. (The MSDN link also has an example of loading limited number of items in multiple pages)
You may use two different approaches:
ContentIterator object - is not available in SharePoint
Foundation
SPWeb.ProcessBatchData with Display method - is available in SP Foundation but is very complicated as it's very complex.
Is there a way of changing the Fixed Keyword Query in the search results core web part to get the current user (Author:{CurrentUser})?
I have played with scopes and filters and can do this fine with supplying the fixed keyword query but am not able to change it to always get the current user.
Basically I would like to have the FixedQuery field be author:Last First.
Here are a few posts which hint at it but I would like to just change it dynamically in the XSL in the .aspx file and be done with it. Anyone?
http://www.martinhatch.com/2010/07/rcwp-part-1-spretreat-and-related.html
http://www.novolocus.com/2008/05/14/using-a-query-string-parameter-in-the-search-results-web-part/
Ok so I have found a "work around" for this. I will try and lay it out as simple as possible.
Create a new ASPX page which has a "Core Results Web Part" on it and has the "Cross-Web Part query ID" under "Results Query Options" in the properties set to "User query".
We will call this page from inside a "Page View Web Part", the wep part which loads another page in an iframe. We will then add the query to the URL of the page which is being loaded in the "Page View Web Part". (e.g. site.com/ourAspxFromStep1.aspx?k=author:first%20last)
I hope this is clear. I added the web parts with c# server side code dynamically on page load based on values from a list so the queries are dynamically built on page load. Let me know if you have comments or questions.
Here is my client side function which I call which adds the web parts dynamically. core_wp_for_embed.aspx is the file mentioned above in step 1.
protected void refreshFeeds(string tmpUserName, SPUserToken userToken) {
using(SPSite site = new SPSite("http://www.site.com")) {
using(SPWeb web = site.OpenWeb()) {
web.AllowUnsafeUpdates = true;
SPFile file = web.GetFile(web.Url + "/currentPage.aspx");
using(SPLimitedWebPartManager webPartManager =
file.GetLimitedWebPartManager(PersonalizationScope.User)) {
SPLimitedWebPartCollection webparts = webPartManager.WebParts;
int j = webparts.Count;
for (int k = j - 1; k >= 0; k--) {
Microsoft.SharePoint.WebPartPages.WebPart wp =
(Microsoft.SharePoint.WebPartPages.WebPart)webparts[k];
if (wp.GetType().ToString() ==
"Microsoft.SharePoint.WebPartPages.PageViewerWebPart") {
webPartManager.DeleteWebPart(wp);
}
}
// Zone should be cleared. Now loop through list on users site and add web parts for each item
SPSite site2 = new SPSite("http://www.site.com/personal/" + tmpUserName);
SPWeb web2 = site2.OpenWeb();
SPList list = web2.Lists["SomeUserList"];
int i = 0;
foreach(SPListItem currentItem in list.Items) {
if(Convert.ToBoolean(currentItem["BooleanField"]) == true) {
PageViewerWebPart pvwp = new PageViewerWebPart();
pvwp.Title = currentItem["Title"].ToString();
pvwp.ChromeState = System.Web.UI.WebControls.WebParts.PartChromeState.Normal;
pvwp.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.TitleOnly;
pvwp.ContentLink = "http://www.site.com/core_wp_for_embed.aspx?k=scope:"
+ currentItem["Item_Scope"].ToString();
pvwp.AllowEdit = true;
webPartManager.AddWebPart(pvwp, "someZone", i);
webPartManager.SaveChanges(pvwp);
i++;
}
}
}
web.Update();
web.AllowUnsafeUpdates = false;
}
}
Response.Redirect(Request.RawUrl);
}
I want to query a SharePoint list and want to use the data to be displayed in a usercontrol that I have created.
Earlier I had the data coming from a database.
Now I need to modify it to work with a SharePoint list.
Can you please guide me.
Grace.
SPList list = null;
SPListItemCollection LIC = null;
SPListItem listItem = null;
using (SPSite mainSite = new SPSite("http://sitewhereyourlistis"))
{
using (SPWeb mainWeb = mainSite.OpenWeb())
{
list = mainWeb.Lists["ListNameHere"];
//**You will most likely want to limit your return to a single record so I have created the caml to do so with the List Item ID
String caml = String.Format("<Where><Eq><FieldRef Name=\"ID\" /><Value Type=\"Counter\">{0}</Value></Eq></Where>", ListItemID);
SPQuery qry = new SPQuery();
qry.Query = caml;
LIC = list.GetItems(qry);
listItem = LIC[0];
//**Here is where you will fill your textboxes
txtTextBoxName.Text = listItem["ColumnNameHere"].toString();
//**The above statement likes to error out if the value is null so I like to use a custom Application Helper Function to prevent things like this.
//**My actual call to get the data would look like this.
txtTextBoxName.Text = EnsureTextValue(listItem, "ColumnNameHere");
// I added the Function Definition Below
}
}
public String EnsureTextValue(SPListItem item, String param)
{
String tmp = String.Empty;
try
{
tmp = item[param].ToString();
}
catch { "Run Debug Method or Whatever Here" }
return tmp;
}
I am not sure if I missed anything but this should get you close.
Hope it helps!
To get Distinct Values for the column Click Here
To edit the values in the list there is a nice post here
I have used this to Query the SharePoint List
using (SPWeb web = SPContext.Current.Site.RootWeb)
{
SPList mylist = web.Lists["listName"];
SPQuery query = new SPQuery();
query.Query = "<Where><Eq><FieldRef Name='columnName' /><Value Type='Text'>" + strXYZ+ "</Value></Eq></Where>";
SPListItemCollection items = mylist.GetItems(query);
tempDT = items.GetDataTable();
return tempDT;
}
I have a website in Sharepoint 2007. I want to make a query where the field "home" of the webpages is equal to 1 in one specific SPWeb and (this is the important part) its sub-SPwebs.
I can make this work with the site in question and not with the subsites. That is to say: It is not recursive but I indicate it in the "webs scope='recursive'" clause.
I include also the List I want to use, that is to say, the pages (not documents, master pages or whatever) this is whay i look for the "850" basetemplate (the one for pages).
The code I am using is this (i have tried with other methods with the same query and the result is the same):
string campo="home";
SPSiteDataQuery qry = new SPSiteDataQuery();
qry.Query = "<Where><Eq><FieldRef Name='";
qry.Query += campo + "'/><Value
Type='Boolean'>1</Value></Eq>";
qry.Query += "</Where><OrderBy><FieldRef
Name='Modified' Ascending='false'> />";
qry.Webs = "<Webs Scope='Recursive'/>";
qry.ViewFields = "<FieldRef Name='Title'/><FieldRef
Name='Modified'/>";
//this gives me system privileges
using (SPSite site = new SPSite(CurrentSite.ID,
GetSystemToken(CurrentSite)))
{
using (SPWeb web = site.OpenWeb("/News/"))
{
StringBuilder sb = new StringBuilder();
sb.Append("<Lists>");
foreach (SPList list in web.Lists)
{
if (list.BaseTemplate.ToString() ==
"850")
{
sb.Append("<List ID=\"" +
list.ID.ToString() + "\"/>");
}
}
sb.Append("</Lists>");
qry.Lists = sb.ToString();
dt = web.GetSiteData(qry);
..................
So, the only solution I found was to make a loop after the precedent code through the Webs but i don't think this is a very optimized way:
foreach (SPWeb w2 in web.Webs)
{
sb = new StringBuilder();
sb.Append("<Lists>");
foreach (SPList list in w2.Lists)
{
if (list.BaseTemplate.ToString()
== "850")
{
sb.Append("<List ID=\""
+ list.ID.ToString() + "\"/>");
}
}
sb.Append("</Lists>");
qry.Lists = sb.ToString();
DataTable dttmp = w2.GetSiteData(qry);
if (dttmp != null
&& dttmp.Rows.Count > 0)
{
dt.Merge(dttmp);
}
w2.Dispose();
}
Finally I did the following, i don't know what has worked finally, i have changed the way I ask the Lists and i have included RowLimit:
DataTable dt = null;
DataView dv = null;
SPSiteDataQuery qry = new SPSiteDataQuery();
qry.Query = "<Where><Eq><FieldRef Name='";
qry.Query += campo + "'/><Value Type='Boolean'>1</Value></Eq>";
qry.Query += "</Where><OrderBy><FieldRef Name='Modified' Ascending='false' /></OrderBy>";
qry.Webs = "<Webs Scope='Recursive'/>";
qry.Lists = "<Lists ServerTemplate='850' Hidden='FALSE' MaxListsLimit='50'/>";
qry.RowLimit = 3;
qry.ViewFields = "<FieldRef Name='Title'/><FieldRef Name='Modified'/><FieldRef Name='FileRef'/>";
using (SPSite site = new SPSite(CurrentSite.ID, GetSystemToken(CurrentSite)))
{
using (SPWeb web = site.OpenWeb(webUrl))
{
dt = web.GetSiteData(qry);
dv = dt.DefaultView;
}
}
return dv;
You talk about setting the webs scope to recursive, but in your (ill-formatted) example code you leave the webs property blank, meaning the site data query will only search through the specified web.
This specific (omitted) detail of your code is very important, because making even the slightest spelling mistake in the innerXML specification will silently revert the behaviour back to the default, meaning only the current web will be searched. A typical pitfall would be getting the capitalization wrong in either Webs or Scope.
For the record, the correct way of specifying this is
qry.Webs = "<Webs Scope='Recursive' />";
As a quick check, you can try setting the scope to SiteCollection, see if that works.
[Edit] Agreed, now your Webs property shows up it seems fine :-). Have you tried setting the Nullable='TRUE' attribute in the fieldref of the Campo field? If the field isn't present (or corrupted or whatever) in any of the subsites, that might help. [/Edit]