Retrieving and updating data from InfoPath repeating tables - c#

I've found this link helpful in getting data out of field in infopath. Unfortunately, after i attempt to set value back every time users made change on field, it appears to be infinite loop and cause error.
Here is my code:
XPathNavigator xNavigation = this.MainDataSource.CreateNavigator();
XPathNodeIterator xNodeIterator = xNavigation.Select(“/my:myFields/my:group1/my:group2”, this.NamespaceManager);
while (xNodeIterator.MoveNext()){
string mystring = xNodeIterator.Current.SelectSingleNode(“my:County”, this.NamespaceManager).Value;
xNodeIterator.Current.SelectSingleNode(“my:County”, this.NamespaceManager).SetValue("mystring"+ mystring);
}
What's the problem here? Please help me.

As I mentioned in the comments, you could use XPathNavigator to go through the list without using While loop:
EDITED, based on more info from comments:
foreach (XPathNavigator nav in xNavigation.Select(“/my:myFields/my:group1/my:group2”, this.NamespaceManager))
{
string mystring = myTextBox.Text + ", " + "GUID"; //replace "GUID" with the actual GUID which you need
nav.SelectSingleNode("my:field3", this.NamespaceManager).SetValue("mystring"+ mystring);
}
Basically, you should not get the value of the element/node, then set the same element/node's value after adding something to it. That will cause an exponential string expansion.

Related

Passing multiple variables between pages and using them

I have three variables I'm trying to pass from one page to another: Two checboxlists (just the checked values) and one DateTime.
I'm getting the checked items like this (this is just for one of these checkboxlists which is called lstUsers):
string cblvalues = "";
foreach (ListItem cbitem in lstUsers.Items)
{
if (cbitem.Selected)
{
cblvalues += cbitem.Value + "-";
}
}
cblvalues = cblvalues.Trim('-');
Response.Redirect("Results.aspx?cblvalues=" + cblvalues);
How would I pass the other checkboxlist and the DateTime to "Results.aspx" as well? I've seen a few different examples such as Server.Transfer, and I'm not sure which one is correct here.
And for using them on the Results.aspx page, would I just do:
string cblvalues = Request.QueryString["cblvalues"];
You can put as many values as you like on the query string. (Though as query strings get very long the web server would eventually impose a limit.) Here you simply append one key/value pair:
Response.Redirect("Results.aspx?cblvalues=" + cblvalues);
Just use a & to separate additional key/value pairs:
Response.Redirect("Results.aspx?cblvalues=" + cblvalues + "&moreValue=" + moreValues);
If you do get to the point where the query string becomes absurdly long and you basically have a lot of data to pass to the next page, then you'd be looking at other ways of doing this. A simple alternative may be to store the values in session state, redirect the user, then pull the values from session state. Something as simple as this:
Session["cblvalues"] = cblvalues;
Session["moreValues"] = moreValues;
Response.Redirect("Results.aspx");
Then in Results.aspx you can get the values:
var cblValues = Session["cblvalues"];
// etc.
You might also clear the session values once you get them, if the session doesn't need to keep carrying them:
Session.Remove("cblvalues");
You can pass multiple values through query string by seperated them with a &
so your snippet will be like the following:
Let cblSecond be the second combobox then;
// Building first value here
foreach (ListItem cbitem in cblSecond.Items)
{
if (cbitem.Selected)
{
cblSecondValues += cbitem.Value + "-";
}
}
Response.Redirect("Results.aspx?cblvalues=" + cblvalues + "&cblSecondValues=" + cblSecondValues);
So that you can access them separately like this:
string cblvalues = Request.QueryString["cblvalues"];// gives you the first value
string cblSecondValues= Request.QueryString["cblSecondValues"];// gives you the second value
Response.Redirect(String.Format("Results.aspx?value1={0}&value2={1}&value3={2}", Value1, Value2, Value3));
If you really want to pass them using querystring then you ahouls include them as well
Response.Redirect("Results.aspx?cblvalues=" + cblvalues + "&cblvalues1=" + cblvalues + "&datetimemy=" + datetimevalue);
Form of a query string like below
http://server_name/path/aspxfile?field1=value1&field2=value2&field3=value3..&fieldn=valuen
As other answer mentioned, there are multiple ways like using Session or cookies or as well you can expose those control values as public properties and use then in next page using Page.PreviousPage property but the restriction is that you will have to use either of Server.Transfer() or Server.Execute() method instead of Response.Redirect.

How can I output a list of field names and values that were changed?

I'm still learning C# whilst building an MVC web app. Trying to find a way to create a list of values that were changed by a user during an edit operation.
Here's one way I have that would work:
public List<string> SaveVehicleTechnicalInformation(VehicleAssetTechnicalInformationViewModel editmodel)
{
// Create a list of fields that have changed
List<string> changes = new List<string>();
var record = db.VehicleAssetTechnicalInformations.Find((int)editmodel.RecordID);
if (editmodel.Make != null && editmodel.Make != record.Make)
{
changes.Add(" [Make changed from " + record.Make + " to " + editmodel.Make + "] ");
record.Make = editmodel.Make;
}
if (editmodel.Model != null && editmodel.Model != record.Model)
{
changes.Add(" [Model changed from " + record.Model + " to " + editmodel.Model + "] ");
record.Model = editmodel.Model;
}
return changes;
}
But... As you can tell, I am going to need to write an IF/ELSE statement for every single field in my database. There are about 200 fields in there. I'm also worried that it's going to take a long time to work through the list.
Is there some way to go through the list of properties for my object iteratively, comparing them to the database record, changing them if necessary and then outputting a list of what changed.
In pseudo code this is what I guess I am after:
foreach (var field in editmodel)
{
if (field != database.field)
{
// Update the value
// Write a string about what changed
// Add the string to the list of what changed
}
}
Because I'm still learning I would appreciate guidance/tips on what subject matter to read about or where I can independently research the answer. The gaps in my skill are currently stopping me from being able to even research a solution approach.
Thanks in advance.
You can try to use Reflection for your purposes. Something like this
var fields = editmodel.GetType().GetFields();
foreach (var item in fields)
{
if (item.GetValue(editmodel) == database.field)
{
// Update the value
// Write a string about what changed
// Add the string to the list of what changed
}
}
I think I have found the hint I was looking for...
System.Reflection
More specifically, the FieldInfo.GetValue() method.
I was previously unaware of what System.Reflection was all about, so I'll research this area further to find my solution.

SelectSingleNode and SelectNodes XPath syntax

My question is very similar to this one XmlNode.SelectSingleNode syntax to search within a node in C#
I'm trying to use HTML Agility Pack to pull price/condition/ship price... Here's the URL I am scraping: http://www.amazon.com/gp/offer-listing/0470108541/ref=dp_olp_used?ie=UTF8&condition=all
Here's a snippet of my code:
string results = "";
var w = new HtmlWeb();
var doc = w.Load(url);
var nodes = doc.DocumentNode.SelectNodes("//div[#class='a-row a-spacing-medium olpOffer']");
if (nodes != null)
{
foreach (HtmlNode item in nodes)
{
var price = item.SelectSingleNode(".//span[#class='a-size-large a-color-price olpOfferPrice a-text-bold']").InnerText;
var condition = item.SelectSingleNode(".//h3[#class='a-spacing-small olpCondition']").InnerText;
var price_shipping = item.SelectSingleNode("//span[#class='olpShippingPrice']").InnerText;
results += "price " + price + " condition " + condition + " ship " + price_shipping + "\r\n";
}
}
return results;
No matter what combination I try of .// and . and ./ and / etc... I cannot get what I want (just now trying to learn xpaths), also currently it is returning just the 1st item over and over and over, just like the original question I referenced earlier. I think I'm missing a fundamental understanding of how selecting nodes work and/or what is considered a node.
UPDATE
Ok, I've changed the URL to point to a different book and the first two items are working as expected... When I try to change the third item (price_shipping) to a ".//" Absolutely no information is being pulled from anything. This must be due to sometime there is not even a shipping price and that span is omitted. How do I handle this? I tried if price_shipping !=null.
UPDATE
Solved. I removed the ".InnerText" from the price_shipping that causing issues when it was null... then I did the null check and Then it was safe to use .InnerText.
Solved. I removed the ".InnerText" from the price_shipping that causing issues when it was null... then I did the null check and Then it was safe to use .InnerText.

Why CAML doesn't return all Fields/values from sharepoint List?

I have a Sharepoint list which have columns like : CopmanyName, Add1, Add2 Country, State/Province. State/Province have a condition to enter only when country is as selected as America or Canada, So few records in SharePoint have this field(ows_State) as empty.
Now I am trying to get the records from SharePoint using webservices, CAML query, the problem that I am facing is that if the field (State/Provice) is empty then the CAML doesn't get its information, in-fact the field name itself is not added in the z:row element of XML.
I have this field bound to a gridView on front-end (as Eval) and if element ows_State is not found in XML then it throws error.
Any suggestion would be much appreciated,
If nothing works then probably I'll have to check and dynamically add this field.
var StateElement = doc.Element(rs + "data").Element(z + "row").Attribute("ows_State_x002f_Province");
if (StateElement == null)
{
doc.Element(rs + "data").Element(z + "row").Add(new XAttribute("ows_State_x002f_Province", " "));
}
I have had similar problem. The thing is, If your field is empty, CAML won't return you that field in your XML.
The solution I made was to check XML for attribute's existence, If it's not there, add it manually.
Check this out :
http://naimishpandya.wordpress.com/2011/11/15/how-to-add-xml-attribute-to-an-existing-xml-node-in-c-c-sharp/
You can also achieve it through LINQ To XML.
http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/thread/be75108d-2265-41f0-8a22-f2ecc025cf53
foreach(XElement zrow in doc.Root.Elements(z + "row").Where(u => u.Attribute("ows_State_x002f_Province")==null).ToList())
{
zrow.Add(new XAttribute("ows_State_x002f_Province", " "));
}

Batch Element in Sharepoint to Delete a List item when you do not know the ID

I want to delete an item in a list when it matches some critera using UpdateListItems web service. I dont know the ID of the list item that I want to delete but do know the criteria.
For example in SQL I could do:
DELETE FROM listName WHERE LastName='Bauer' AND FirstName='Jack'
How would you write a Batch Element to do this?
Update
Would it be something like this?
<Batch PreCalc='TRUE' OnError='Continue'>
<Method ID='1' Cmd='Delete'>
<Field Name='LastName'>Bauer</Field>
<Field Name='FirstName'>Jack</Field>
</Method>
</Batch>
Is the ID for the Method or the ID of the thing you wish to delete?
Update
I have tried the following code and the error that is returned is
Invalid URL Parameter
The URL provided contains an invalid Command or Value. Please check the URL again.
My guessing is that it is not possible to do without the ID...
As an addition to ChrisB's answer (formatting a CAML query in a comment didn't seem to work out), you'd make the query something like this:
SPQuery query = new SPQuery();
query.Query = "<Where><And>"+
"<Eq><FieldRef Name='LastName'/><Value Type='Text'>Bauer</Value></Eq>"
"<Eq><FieldRef Name='FirstName'/><Value Type='Text'>Jack</Value></Eq>"
"</And></Where>";
SPListItemCollection items = list.GetItems(query);
(this is the object model specification, but it extends naturally into the webservices call)
Then you'd loop through the listitems and build up your batch.
This does not look possible.
My way round this was to query the list and get the id's. Loop for the response pull out the id's then create a method for each ID to delete it.
Similarly, to get list item returned from the the Sharepoint 2010 object model that can be used in C# corresponding value of a key node in xml we have to get rid of that additional character attached at position 1 in the xml. This can be done as follows:
// Code to decipher XML string returned from SharePoint Server 2010 object model list item. - Courtesy - Rajiv Kapoor - ideals.co.in. View http://www.ideals.co.in/estore/code.php for complete solution.
string sRetVal = "";
string myXMLStr = "​<robot><Key>ConstSigned</Key><Value>Rad Is Signed</Value><Key>CodeAddChangeReqSub</Key><Value>ACRS</Value><Key>CodeAddChangeReqInit</Key><Value>ACRI</Value><Key>CodeSupTaskComp</Key><Value>STC</Value><Key>CodeSupApprComp</Key><Value>SAC</Value><Key>CodeSupRejComp</Key><Value>SAR</Value><Key>CodeOperAppr</Key><Value>OPA</Value><Key>CodeOperRej</Key><Value>OPR</Value><Key>Oper1TaskCreated</Key><Value>OTC</Value><Key>Oper2TaskCreated</Key><Value>QCTC</Value><Key>Oper2TaskAppr</Key><Value>QCRA</Value><Key>Oper2TaskRej</Key><Value>QCRR</Value><Key>ApprPending</Key><Value>Approval Pending</Value><Key>PendingProcessing</Key><Value>Pending Processing</Value><Key>PendingReview</Key><Value>Pending Review</Value><Key>Approved</Key><Value>Approved</Value><Key>GroupOperation</Key><Value>Operation</Value><Key>WorkFlowHistoryList</Key><Value>/Lists/Workflow History</Value><Key>ColInitDateTime</Key><Value>Initiated Date Time</Value><Key>ColWorkFlowHistoryParentInst</Key><Value>Workflow History Parent Instance</Value><Key>ColWorkflowAssId</Key><Value>Workflow Association ID</Value><Key>ColListId</Key><Value>List ID</Value><Key>ColPrimaryItemId</Key><Value>Primary Item ID</Value><Key>ColDate</Key><Value>Date Occurred</Value><Key>ColOutcome</Key><Value>Outcome</Value><Key>ColDesc</Key><Value>Description</Value><Key>ColCreated</Key><Value>Created</Value><Key>ColTaskStatus</Key><Value>TaskStatus</Value><Key>ServiceReqList</Key><Value>Service Request</Value><Key>CAUEventList</Key><Value>Events</Value><Key>ReqStatus1</Key><Value>Request Status</Value><Key>ReqStatCode</Key><Value>Request Status Code</Value><Key>ColumnCode</Key><Value>Code</Value><Key>SuperUser</Key><Value>SuperUser</Value><Key>AssignedTo</Key><Value>AssignedTo</Value><Key>TaskListId</Key><Value>ID</Value><Key>DocLibId</Key><Value>List</Value><Key>WorkflowInstanceId</Key><Value>WorkflowInstanceID</Value><Key>TaskTitle</Key><Value>Title</Value><Key>Priority</Key><Value>Priority</Value><Key>ReqStatusCode</Key><Value>Request Status Code</Value><Key>ServiceRequestList</Key><Value>Service Request</Value><Key>CAUEventList</Key><Value>Events</Value><Key>ColumnDesc</Key><Value>Description</Value><Key>ColumnStatus</Key><Value>Status</Value><Key>Completed</Key><Value>Completed</Value><Key>ReqStatus</Key><Value>Request Status</Value><Key>ColumnTaskStatus</Key><Value>TaskStatus</Value><Key>ColumnPerComp</Key><Value>PercentComplete</Value><Key>Rejected</Key><Value>Rejected</Value><Key>CodeSupTaskCreated</Key><Value>STC</Value><Key>CodeSupTaskInit</Key><Value>SAI</Value><Key>Oper1TaskInit</Key><Value>OPI</Value><Key>Oper2TaskInit</Key><Value>QCRI</Value><Key>ColActedBy</Key><Value>Acted By</Value><Key>WorkFlowCode</Key><Value>Workflow Code</Value><Key>ProcCode</Key><Value>Process Code</Value></robot>";
string myXMLStr1 = myXMLStr;
int ln = myXMLStr.Length;
int lnMinus1 = ln - 1;
char[] myst = { ' ', ' ', ' '};// create a long array enough to fit the xml
string mys = "";
object m1 ;
string m2 = "";
myXMLStr.CopyTo(0, myst, 0, ln); m1 = myst.Clone();
m2 = new string(myst);// m1;// ToString();
m2.TrimStart();
m2.TrimEnd();
m2 = m2.Substring(1);
sRetVal = GetConfigVal(m2, "ProcCode");
Console.WriteLine("****#*" + sRetVal + "*#******");
I am not that familiar with using the web services, but I assume there is one for searching. Using the API you would create an SPQuery and use CAML to get the list items you wanted to remove.

Categories