GetListItems() causes a 401 error but Checkout() works - c#

I want to get the contents of a Sharepoint 2007 list via web service. I'm using this code, which I mostly copied from the MSDN page for GetListItems:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace testGetListItems
{
class Program
{
static void Main(string[] args)
{
sharepoint.Lists listService = new sharepoint.Lists();
listService.Credentials = System.Net.CredentialCache.DefaultCredentials;
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
ndQueryOptions.InnerXml =
"<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>" +
"<DateInUtc>TRUE</DateInUtc>";
ndViewFields.InnerXml = "<FieldRef Name='Field1' /> <FieldRef Name='Field2'/>";
ndQuery.InnerXml = "<Where><And><Gt><FieldRef Name='Field1'/>" +
"<Value Type='Number'>5000</Value></Gt><Gt><FieldRef Name='Field2'/>" +
"<Value Type= 'DateTime'>2003-07-03T00:00:00</Value></Gt></And></Where>";
try
{
bool checkoutResult=listService.CheckOutFile("http://sharepoint/sites/mysite/myFile.xlsx", "false", null);
XmlNode ndListItems =
listService.GetListItems("Test List", null, ndQuery,
ndViewFields, null, ndQueryOptions, null);
}
catch (System.Web.Services.Protocols.SoapException ex)
{
Console.WriteLine("Message:\n" + ex.Message + "\nDetail:\n" +
ex.Detail.InnerText +
"\nStackTrace:\n" + ex.StackTrace);
}
}
}
}
The call to CheckOutFile() works correctly. But the GetListItems() call gives me this error:
An unhandled exception of type 'System.Net.WebException' occurred in System.Web.Services.dll
Additional information: The request failed with HTTP status 401: Unauthorized.
I don't understand why CheckOutFile() succeeds but GetListItems() fails, especially because the document that I'm checking out is in the list that's being accessed by GetListItems().

UPDATE: This worked in a test console app, but not in my main application. Leaving this answer up for now, but I'm not going to accept it until I get this fixed.
It turned out the problem was with the URL of the web service. Even though I had added it as:
http://sharepoint/sites/mySite/_vti_bin/Lists.asmx
the app.config file had it listed as:
http://sharepoint/_vti_bin/Lists.asmx
This remained a problem even after I deleted the reference and re-added it; I had to change the app.config contents manually. Once I'd done so, the GetListItems() call succeeded.

You must set a user and password who can get the items in the library/list this way (for me it works, you could try):
public string GetIDFromList(string parameter)
{
string retorno = "";
try
{
string path = "http://www.test.com/web/";
// Reference to the SharePoint Lists web service:
WSSharePointCSCLists.Lists listsWS = new WSSharePointCSCLists.Lists();
listsWS.Url = path + "_vti_bin/lists.asmx";
listsWS.Credentials = GetUserCredential();
string listName = "MyList";
string viewName = "";
//string webID;
string rowLimit = "500";
// Web ID:
webID = "098304-9098asdf-qwelkfj-eoqiula";
XmlDocument xmlDoc = new System.Xml.XmlDocument();
// Query em CAML (SharePoint):
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields =
xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions =
xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
ndQueryOptions.InnerXml =
"<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>" +
"<DateInUtc>TRUE</DateInUtc>" +
"<ViewAttributes Scope=\"RecursiveAll\" />";
ndViewFields.InnerXml = #"<FieldRef Name='Title' />
<FieldRef Name='ID' />";
string caml =
String.Format(
#"<Where>
<Contains>
<FieldRef Name='MyColumn' />
<Value Type='Text'>{0}</Value>
</Contains>
</Where>",
parameter);
ndQuery.InnerXml = caml;
XmlNode retornoWS = listsWS.GetListItems(listName, null, ndQuery,
ndViewFields, rowLimit,
ndQueryOptions, webID);
retorno = retornoWS.InnerXml;
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex.Message);
throw;
}
return retorno;
}
public NetworkCredential GetUserCredential()
{
return new System.Net.NetworkCredential("<username>",
"<password>",
"<domain>");
}

Related

Query to get files URL from sharepoint

Is it possible to get a perticular file from sharepoint instead of getting all files at onlce?
In below query when I queryNode is empty I am getting all the files but when queryNode is commented query I am not getting any file.
What is missing here?
XmlDocument xmlDoc = new XmlDocument();
XmlNode queryNode = xmlDoc.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "Query", ""));
//queryNode.InnerXml = "<Where>" +
// " <Eq>" +
// " <FieldRef Name='FileLeafRef'></FieldRef>" +
// " <Value Type='File'>" + SomeFileName + "</Value>" +
// " </Eq>" +
// "</Where>";
queryNode.InnerText = "";
XmlDocument xmlDoc1 = new XmlDocument();
XmlNode viewNode = xmlDoc.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", ""));
viewNode.InnerXml = "";
XmlDocument xmlDoc2 = new XmlDocument();
XmlNode optionsNode = xmlDoc.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", ""));
optionsNode.InnerText = "";
XmlNode nodeListItems = wsList.GetListItems("Documents",
"",
queryNode,
viewNode,
"1",
optionsNode,
null);
This will retrieve all items in a list with a filename of "filename" only.
var list = web.Lists["ListTitle"];
var fileQuery = new SPQuery();
fileQuery .ViewAttributes = "Scope=\"Recursive\"";
string strQuery = "<Where>" +
"<Eq>" +
"<FieldRef Name=\"FileLeafRef\"/>" +
"<Value Type=\"Text\">" + fileName + "</Value>" +
"</Eq>" +
"</Where>";
fileQuery .Query = strQuery ;
SPListItemCollection collListItems = list.GetItems(fileQuery );

c# asmx web service. How to read in post data from aspx page

I am writing a web service for my company using c#. So I have a test page default.aspx.
From the aspx page I have an input name="zip" which i need to pass to the webservice.
I can't figure out how to get the posted data. Webservice will run an sql statement based on the zip code passed as xml. then returns the zipcode xml as a response.
code from aspx page below.
string sendXml = String.Format(#"<?xml version=""1.0"" encoding=""utf-8""?>,
<zip>{0}</zip>",
Request["zip"]);
string postXml = "xmlRequest=" + HttpUtility.UrlEncode(sendXml);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:51857/zipfinder.asmx/showRecords");
req.Method = "POST";
req.ContentLength = postXml.Length;
req.ContentType = "application/x-www-form-urlencoded";
using (StreamWriter writer = new StreamWriter(req.GetRequestStream()))
{
writer.Write(postXml);
writer.Close();
}
var result = "";
try
{
using (StreamReader reader = new StreamReader(req.GetResponse().GetResponseStream()))
{
string getResult = reader.ReadToEnd();
Response.Write(getResult);
}
}
catch (Exception ex)
{
Response.Write("error: " + ex.ToString());
}
then on the .asmx page
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public DataSet getZip() {
DataSet dataSet = db.QueryDataRows("*", "zip_codes_simple", "zip = '00501' or zip = '00544'", "", "zip_codes_simple");
return dataSet;
}
[WebMethod]
public XmlDocument showRecords(){
DataSet dataSet = getZip();
string recs = "";
XmlDocument doc = new XmlDocument();
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
doc.AppendChild(dec);
XmlNode root = doc.CreateElement("zipcodes");
doc.AppendChild(root);
XmlElement zip = doc.CreateElement("zip");
XmlElement type = doc.CreateElement("type");
XmlElement primaryCity = doc.CreateElement("primaryCity");
XmlElement state = doc.CreateElement("state");
XmlElement latitude = doc.CreateElement("latitude");
XmlElement longitude = doc.CreateElement("longitude");
foreach (DataTable dt in dataSet.Tables)
{
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
zip.InnerText = dr["zip"].ToString();
root.AppendChild(zip);
type.InnerText = dr["type"].ToString();
root.AppendChild(type);
primaryCity.InnerText = dr["primary_city"].ToString();
root.AppendChild(primaryCity);
state.InnerText = dr["state"].ToString();
root.AppendChild(state);
latitude.InnerText = dr["latitude"].ToString();
root.AppendChild(latitude);
longitude.InnerText = dr["longitude"].ToString();
root.AppendChild(longitude);
//recs = "<p>" + dr["zip"] + ", " + dr["primary_city"] + "</p>";
//Response.Write("<p>" + dr["zip"] + " in " + dr["state"]);
}
}
else
{
//recs = "<p style='color: red;'>Invalid user name or password</p>";
}
}
return doc;
}
How can i get the zip code from the aspx page to pass to the query where zip = ''
I am looking for something to read in the formatted string and extract the zip code from the incoming xml document.
any help appreciated.
thanks
If I understood it right, you want to get the value from the <input type='text' name='zip' /> in your page. Since it is not an asp:TextBox, you should get it using Request.Form, so your code would look like this:
string sendXml = String.Format(#"<?xml version=""1.0"" encoding=""utf-8""?>,
<zip>{0}</zip>",
Request.Form["zip"]);
But there is another solution: Instead of doing this:
<input type='text' name='zip' />
You could use an ASP.NET Webform control:
<asp:TextBox runat='server' ID='zip' />
And then you could get the value with zip.Text.
Is there any reason why you're not doing this?

Can't get inner text from FQL using Xpath C#

I'm trying to get the inner text from a XML tag called sharecount, I need to get it by the normalized_url tag like so:
string ShareCount;
string Url = "'" + "http://www.example.com/Article.aspx?id=" + GuideID + "'";
XmlNode Node;
try
{
//return Share count (using Xpath).
XmlDoc.SelectSingleNode("fql_query_response/link_stat[normalized_url=" + Url + "]/share_count");
ShareCount = XmlDoc.InnerText;
int.TryParse(ShareCount, out Value); //Turn string to int.
return Value;
}
catch
{
return 0;
}
and this is the XML:
<fql_query_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" list="true">
<link_stat>
<url>http://www.example.com/Article.aspx?id=1909</url>
<normalized_url>http://www.example.com/Article.aspx?id=1909</normalized_url>
<share_count>11</share_count>
<like_count>3</like_count>
<comment_count>0</comment_count>
<total_count>14</total_count>
<commentsbox_count>8</commentsbox_count>
<comments_fbid>10150846665210566</comments_fbid>
<click_count>0</click_count>
</link_stat>
</fql_query_response>
<link_stat>
<url>http://www.example.com/Article.aspx?id=1989</url>
<normalized_url>http://www.example.com/Article.aspx?id=1989</normalized_url>
<share_count>11</share_count>
<like_count>3</like_count>
<comment_count>0</comment_count>
<total_count>14</total_count>
<commentsbox_count>8</commentsbox_count>
<comments_fbid>10150846665210566</comments_fbid>
<click_count>0</click_count>
</link_stat>
</fql_query_response>
The thing is i got in the return value: "www.example.com/Article.aspx?id=1132http://www.example.com/Article.aspx?id=190900000101502138970422760" what am i doing wrong? thanks!
The problem is you are Selecting a single node but obtaining the content from the root element. On top of that, you have a root namespace, therefore use of NameSpaceManger for searches is required. Try this sample:
string GuideID = "1989";
string Url = "'" + "http://www.example.com/Article.aspx?id=" + GuideID + "'";
var XmlDoc = new XmlDocument();
XmlDoc.Load(new FileStream("XMLFile1.xml",FileMode.Open,FileAccess.Read));
var nsm = new XmlNamespaceManager(XmlDoc.NameTable);
nsm.AddNamespace("s", "http://api.facebook.com/1.0/");
var node = XmlDoc.SelectSingleNode("s:fql_query_response/s:link_stat[s:normalized_url=" + Url + "]/s:share_count", nsm);
var ShareCount = node.InnerText;
And here is the LINQ way with same namespace manager and an XPathSelector.
XDocument xdoc = XDocument.Load(new FileStream("XMLFile1.xml", FileMode.Open, FileAccess.Read));
var lnode = xdoc.XPathSelectElements("s:fql_query_response/s:link_stat[s:normalized_url=" + Url + "]/s:share_count",nsm).First();
var ret = lnode.Value;

Exception thrown when doing a SOAP call to SharePoint

I am getting this exception when I try to run my application:
Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown
I am making a soap call to SharePoint and it is choking when the soap call is being executed.
below is the code I am running any ideas why this is happening?
public string getListData()
{
Lists myservice = new Lists();
myservice.Credentials = System.Net.CredentialCache.DefaultCredentials;
try
{
/* Assign values to pass the GetListItems method*/
string listName = "*list name*";
string viewName = "*view name*";
string rowLimit = "100";
//string successtest;
//string failtest;
// Instantiate an XmlDocument object
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
System.Xml.XmlElement query = xmlDoc.CreateElement("Query");
System.Xml.XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
System.Xml.XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");
/*Use CAML query*/
query.InnerXml = "<Where><Gt><FieldRef Name=\"ID\" />" + "<Value Type=\"Counter\">0</Value></Gt></Where>";
viewFields.InnerXml = "<FieldRef Name=\"Title\" />";
queryOptions.InnerXml = "";
viewFields.InnerXml = "<FieldRef Name=\"Name\" />";
queryOptions.InnerXml = "";
System.Xml.XmlNode nodes = myservice.GetListItems(listName, viewName, query, viewFields, rowLimit, null, null);
foreach (System.Xml.XmlNode node in nodes)
{
if (node.Name == "rs:data")
{
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (node.ChildNodes[i].Name == "z:row")
{
//List<String> testList;
test = node.ChildNodes[i].Attributes["ows_Title"].Value;
//Console.WriteLine(node.ChildNodes[i].Attributes["ows_Title"].Value + "</br>");
}
}
}
}
}
catch (Microsoft.SharePoint.SoapServer.SoapServerException ex)
{
test = ex.Detail.InnerText;
//Console.WriteLine(ex.Message);
}
return test;
}

is there any easy wasy to convert the XML output from sharepoint GetListItems() to a DataTable

i am able to retrieve data from sharepoint
com.sharepoint2.Lists lists = new Lists();
lists.Credentials = new System.Net.NetworkCredential("user", "pwd", "domain");
lists.Url = "http://sharepoint2.company.com/sites/mysite/_vti_bin/Lists.asmx";
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
XmlNode listitems = lists.GetListItems("MyList", null, ndQuery, ndViewFields, null,ndQueryOptions, null);
i now have this huge XML blog with all of my data. Is there any easy way to convert this to a datatable so i treat this like a matrix to loop through each row ??
i tried something like this but it doesn't seem to work:
System.IO.StringReader sr = new System.IO.StringReader(listitems.OuterXml);
XmlTextReader tr = new XmlTextReader(sr);
DataSet ds = new DataSet("resultDataSet");
ds.ReadXml(tr);
Ahh, xml returned from GetListItems is almos the same as SPListItemCollection.Xml. I have an extension method that converts this XML into datatable.
You can just try to use ConvertZRowToRegularXml method on your returned XML - and you would get back an XML that DataTable understands.
Credits for the solution goes to Vincent Rothwell.
public static class SPListItemCollectionExtensions
{
public static readonly string xsltFromZRowToXml =
"<xsl:stylesheet version=\"1.0\" " +
"xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" " +
"xmlns:s=\"uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882\" " +
"xmlns:z=\"#RowsetSchema\">" +
"<s:Schema id=\"RowsetSchema\"/>" +
"<xsl:output method=\"xml\" omit-xml-declaration=\"yes\" />" +
"<xsl:template match=\"/\">" +
"<xsl:text disable-output-escaping=\"yes\"><rows></xsl:text>" +
"<xsl:apply-templates select=\"//z:row\"/>" +
"<xsl:text disable-output-escaping=\"yes\"></rows></xsl:text>" +
"</xsl:template>" +
"<xsl:template match=\"z:row\">" +
"<xsl:text disable-output-escaping=\"yes\"><row></xsl:text>" +
"<xsl:apply-templates select=\"#*\"/>" +
"<xsl:text disable-output-escaping=\"yes\"></row></xsl:text>" +
"</xsl:template>" +
"<xsl:template match=\"#*\">" +
"<xsl:text disable-output-escaping=\"yes\"><</xsl:text>" +
"<xsl:value-of select=\"substring-after(name(), 'ows_')\"/>" +
"<xsl:text disable-output-escaping=\"yes\">></xsl:text>" +
"<xsl:value-of select=\".\"/>" +
"<xsl:text disable-output-escaping=\"yes\"></</xsl:text>" +
"<xsl:value-of select=\"substring-after(name(), 'ows_')\"/>" +
"<xsl:text disable-output-escaping=\"yes\">></xsl:text>" +
"</xsl:template>" +
"</xsl:stylesheet>";
public static DataTable GetFullDataTable(this SPListItemCollection itemCollection)
{
DataSet ds = new DataSet();
string xmlData = ConvertZRowToRegularXml(itemCollection.Xml);
if (string.IsNullOrEmpty(xmlData))
return null;
using (System.IO.StringReader sr = new System.IO.StringReader(xmlData))
{
ds.ReadXml(sr, XmlReadMode.Auto);
if (ds.Tables.Count == 0)
return null;
return ds.Tables[0];
}
}
static string ConvertZRowToRegularXml(string zRowData)
{
XslCompiledTransform transform = new XslCompiledTransform();
XmlDocument tidyXsl = new XmlDocument();
try
{
//Transformer
tidyXsl.LoadXml(Balticovo.SharePoint.Extensions. SPListItemCollectionExtensions.xsltFromZRowToXml);
transform.Load(tidyXsl);
//output (result) writers
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
using (XmlTextWriter tw = new XmlTextWriter(sw))
{
//Source (input) readers
using (System.IO.StringReader srZRow = new System.IO.StringReader(zRowData))
{
using (XmlTextReader xtrZRow = new XmlTextReader(srZRow))
{
//Transform
transform.Transform(xtrZRow, null, tw);
return sw.ToString();
}
}
}
}
}
catch
{
return null;
}
}
}
You should pass the XmlNodeType to the XmlTextReader like this:
DataSet ds=new DataSet();
using(var reader=new XmlTextReader(listItems.OuterXml,XmlNodeType.Element,null))
{
ds.ReadXml(reader);
}
Concering the object model vs the web services: The usual way to create web parts, event receivers etc. is to use Sharepoint's server object model. The web services are not used that much, because they are a bit cumbersome. In Sharepoint 2010 a new client object model and the WCF Data Services makes things a LOT easier and the old ASMX web services are considered deprecated.
BUT Sharepoint Online is actually a 2007 version that doesn't allow server-side code, so AJAX and the ASMX web services are the only way to customize and communicate with a Sharepoint Online site. This has brought the ASMX services to the front just as they became deprecated. Go figure.

Categories

Resources