Technical


My friend asked me that he was using web service to fetch data from a list/Document library consisting of 500 items, but the result fetched data only for the first page i.e 100 items.

The list I am querying has pagination, with each page showing 100 items. So, it my list has 500 items, there are 5 pages. But on using the code Lists.GetListItems method, only first 100 records(first page data) is only returned.

The code was as shown below:
Please note: here ibjview is the web reference.

string DocLibName = “Demo Doc Lib”;
XmlNode ndAllView = ibjview.GetViewCollection(DocLibName.Trim());

XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, “Query”, “”);
XmlNode ndViewFields =xmlDoc.CreateNode(XmlNodeType.Element, “ViewFields”, “”);
XmlNode ndQueryOptions = xmlDoc.CreateElement(“QueryOptions”);
ndQueryOptions.InnerXml = “-1”;
ndViewFields.InnerXml = “”;

System.Xml.XmlNode nListView= ibjlists.GetListItems(ndLists.Attributes[“ID”].Value, null, ndQuery, ndViewFields, null, ndQueryOptions, string.Empty);

The xml returned result only for the first page. He was not able to loop the code to get to the next page.
After googling, we found from msdn that,

The XML data returned by this method includes a ListItemCollectionPositionNext attribute inside the rs:Data element that contains the information to support paging.
This string contains data for the fields in the sort and for other items needed for paging.

We debugged, and found the xml was something like:
 
“<rs:Data ListItemCollectionPositionNext=”
Paged=TRUE&p_ID=100&View=
      %7bC68F4A6A%2d9AFD%2d406C%2dB624%2d2CF8D729901E%7d&PageFirstRow=
      101″ Count=1000 >
   <z:row ows_FirstName=”Nancy” ows_LastName=”Name” ….. />”

So, we needed to modify the p_ID to go to the next page.
This is how, we modified our code.

XmlNode xmlPosition = nListView.SelectSingleNode(“//@ListItemCollectionPositionNext“);

XmlTextReader reader = new XmlTextReader(nListView.OuterXml, XmlNodeType.Element, null);

 

reader = new XmlTextReader(nodes.OuterXml, XmlNodeType.Element, null);
XmlDocument xmldoc = new XmlDocument();
 xmldoc.LoadXml(nodes.InnerXml.Replace(“z:”, “”).Replace(“rs:”, “”));
 nodelist1 = xmldoc.SelectNodes(“/data/row”);                                                                                                                                                                                                                                                                                                                          

  for (int i = 0; i < nodelist1.Count; i++)
 { foreach (XmlAttribute attr in nodelist1[i].Attributes) {/*write your code*/}}

  if (xmlPosition != null)
  {
  ndQueryOptions.InnerXml = “<Paging ListItemCollectionPositionNext='” + xmlPosition.InnerXml + “‘ /><MeetingInstanceID>-1</MeetingInstanceID><ViewAttributes Scope=’RecursiveAll’  IncludeRootFolder=’True’ />”;            

}                     

The above code will run until xmlposition is null, which will only occur at the last page.

Advertisements

To find the content databases for the web application selected by WebApplicationSelector control, the code below works:

SPWebApplication webApplication = Selector.CurrentItem;
SPContentDatabaseCollection contentDBs = webApplication.ContentDatabases;
foreach (SPContentDatabase contentDB in contentDBs)
{
Console.WriteLine(contentDB.Name);
}

To find all content databases in the Farm, the code is given below:

SPServiceCollection services = SPFarm.Local.Services;
//foreach (SPService service in services)
{
if (service is SPWebService)
{
SPWebService webService = (SPWebService)service;
SPWebApplicationCollection webApplications = webService.WebApplications;
foreach (SPWebApplication webApplication in webApplications)
{
SPContentDatabaseCollection contentDBs = webApplication.ContentDatabases;
foreach (SPContentDatabase contentDB in contentDBs)
{
Console.WriteLine(contentDB.Name);
}
}
}
}

I needed to use GetListItems of web service Lists.asmx, to get all aspx pages in Pages library.
However, I saw, that I needed to pass the WebId as parameter to GetListItems. So I added another reference to SiteData.asmx.

Below, is the code to get The WebId, need to add reference to Lists.asmx here, webPath is the url of the sarepoint site.

private Guid GetWebID(string webPath)
{

SiteDataWebService.SiteData siteDataWS = new SiteDataWebService.SiteData();

siteDataWS.UseDefaultCredentials = true;

SiteDataWebService._sWebMetadata webMetaData;

SiteDataWebService._sWebWithTime[] arrWebWithTime;

SiteDataWebService._sListWithTime[] arrListWithTime;

SiteDataWebService._sFPUrl[] arrUrls;

string roles; string[] roleUsers; string[] roleGroups;

siteDataWS.Url = webPath + “/_vti_bin/sitedata.asmx”;

siteDataWS.Credentials = new NetworkCredential(username, password, domain);

uint i = siteDataWS.GetWeb(out webMetaData, out arrWebWithTime, out arrListWithTime, out arrUrls, out roles, out roleUsers, out roleGroups);

Guid gid = new Guid(webMetaData.WebID);

return gid;
}

The code to access GetListItems is shown below:

private System.Xml.XmlNode GetItems(string webPath)

{

ListsOnLocalhost.Lists listsWS = new Sharepoint_Unit_Tests.ListsOnLocalhost.Lists();

listsWS.Url = webPath + “/_vti_bin/lists.asmx”;

listsWS.UseDefaultCredentials = true;

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();

doc.LoadXml(“”);

System.Xml.XmlNode listQuery = doc.SelectSingleNode(“//Query”);

System.Xml.XmlNode listViewFields = doc.SelectSingleNode(“//ViewFields”);

System.Xml.XmlNode listQueryOptions = doc.SelectSingleNode(“//QueryOptions”);

Guid gid = GetWebID(webPath);

System.Xml.XmlNode items = listsWS.GetListItems(listName.Text, string.Empty, listQuery, listViewFields, string.Empty, listQueryOptions, gid.ToString());

return items;

}

This example shows how to add custom links under site administrator from site settings page. Below is Elements.xml modification

  <CustomActionGroup Id=”DF784448-CD3F-4221-9B8A-69769FA961EE” Title=”Cargolink Adminsitration” Location=”Microsoft.SharePoint.SiteSettings” Sequence=”110” />
<CustomAction Id=”EDBEB420-A817-4896-BE42-F5B9048C0CF5” Title=”Manage Company Profile” Location=”Microsoft.SharePoint.SiteSettings” GroupId=”DF784448-CD3F-4221-9B8A-69769FA961EE” Sequence=”120” RequireSiteAdministrator=”True“>
  <UrlAction Url=”_layouts/CargoLink/CompanyProfile.aspx” />
  </CustomAction>
<CustomAction Id=”29020219-0C09-4ef0-BF0A-8921F99AD1B0” Title=”Import from CSV” Location=”Microsoft.SharePoint.SiteSettings” GroupId=”DF784448-CD3F-4221-9B8A-69769FA961EE” Sequence=”130” RequireSiteAdministrator=”True“>
  <UrlAction Url=”_layouts/CargoLink/CompanyImport.aspx” />
  </CustomAction>

   </Elements>

This will create a new custom group called “Cargolink Administration” under the site settings page and have the 2 links placed under it.

There is a property which says RequireSiteAdminsitrator and its made as true. So in that case if non-adminsitrators will not be able to load the page. You can test the permissions too.

If you want to place the links under Site Administration group in Site settings page,this is what you write.

<CustomAction Id=”EDBEB420-A817-4896-BE42-F5B9048C0CF5” Title=”Manage Company Profile” Location=”Microsoft.SharePoint.SiteSettings” GroupId=”SiteAdministration” Sequence=”120” RequireSiteAdministrator=”True“>
  <UrlAction Url=”_layouts/CargoLink/CompanyProfile.aspx” />
  </CustomAction>
<CustomAction Id=”29020219-0C09-4ef0-BF0A-8921F99AD1B0” Title=”Import from CSV” Location=”Microsoft.SharePoint.SiteSettings” GroupId=”SiteAdministration” Sequence=”130” RequireSiteAdministrator=”True“>
  <UrlAction Url=”_layouts/CargoLink/CompanyImport.aspx” />
  </CustomAction>
  </Elements>
 
From feature.xml in call this element.xml as
<?xml version=”1.0″ encoding=”utf-8″ ?>
<Feature Id=”8f20690b-efb1-46bf-99dd-688aab89ac2e” Title=”Cargolink Administration” Description=”Cargolink Administration Pages” Version=”12.0.0.0” Hidden=”FALSE” Scope=”Web” DefaultResourceFile=”core” xmlns=”http://schemas.microsoft.com/sharepoint/“>
<ElementManifests>
  <ElementManifest Location=”elements.xml” />
  </ElementManifests>
  </Feature>
 
Run the stsadm to install the feature.

Stsadm to install feature

 C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN>stsadm -o installfeature -name “CargolinkAdministration”  -force

The go to site site actions -> site settings Site Features and Activate the Feature “Cargolink Adminisrtation” .

It is a known issue that on exporting list items,look up column values are lost.

If the list is very big,it might not be possible to fix that manually.This problem occues since list template does look up on a table using GUID,on creating a list template and exporting to a different site,this GUID changes,hence it is no longer able to retain the values.

Suppose I have a list “Category” which has a look up column “sub category” which refers to list “Sub Categories“. I assume you have already created a look up list “Sub Categories” in the destination web.

  1. Browse to the source Web’s lookup list “Sub Category” and choose Modify settings and columns.
  2. Copy the source lookup list GUID from the URL.It should be a sequence of numbers and letters similar to:  %7BFFA47BF8%2D849C%2D4F20%2D9C50%2D173D2F5B6725%7D
  3. Browse to the destination Web’s lookup list and choose Modify settings and columns.
  4. Copy the destination lookup list GUID from the URL.Similar as point 2.
  5. Delete %2D from the string and replace with a dash sign (-). There should be no dash sign (-) at the start and the end. GUID should be in the following format: FA47BF8-849C-4F20-9C50-173D2F5B6725
  6. Save the source Web’s list that contains a lookup column “Category” to the lookup list as a list template called category.stp.
  7. Export the list template STP from the source list template gallery to the file system.
  8. Rename the category.stp file to category.cab so Windows can open it.
  9. Open the file, right click on the manifest.xml file and export it to the file system.
  10. Edit the manifest.xml file; find the source Web’s lookup list GUID and replace it with the destination Web’s lookup list GUID.
  11. Save the manifest.xml file.
  12. Open a VS.NET command prompt.
  13. Run the makecab command as: makecab manifest.xml category.stp
  14. Import the new STP into the destination Web’s list template gallery. You will need to delete it if it has previously been imported.
  15. Create a new list “Category” based upon the new STP file.

I was writing code using SPWeb under the impression that “using” statement takes care of disposing objects.
My Function was something like the one shown below:

public void LoadFunction()
{
using (SPWeb ospWeb = SPContext.Current.Web)
{
….Logic
}
}

However,I kept getting the error “Trying to use an SPWeb object that has been closed or disposed and is no longer valid.”
I realized, we should dispose off the SPSite object and not the SPWeb object directly.

So,I modified the code as shown below:

public void LoadFunction()
{
using(SPSite spSite=new SPSite(SPContext.Current.Web.Url))
{
using (SPWeb spWeb = spSite.OpenWeb())
{
….Logic
}
}
}

This solved the problem of “Trying to use an SPWeb object that has been closed or disposed and is no longer valid.”

We sometimes need to add lists,document/image libraries to a site automatically, or in other words when a feature is activated.To do that,we need a Feature Receiver class and on Feature Activated,we need to write the code for asdding list/doc library/picture library

using (SPSite siteCollection = new SPSite(“Absolute_url”))
{
using (SPWeb mySite = siteCollection.OpenWeb())
{
SPListCollection _Lists = mySite.Lists;
try
{
if (_Lists[strListName] != null)
Message += ” List Already Exists”;

}
catch(Exception ex)
{
Guid listGuid = _Lists.Add(“MapPicLibrary”, “Map Picture Library”, SPListTemplateType.PictureLibrary);
}
}
}

Next Page »