Add lookup field to list from a RootWeb - c#

I have the site collection rootweb called Main Site.
I have many subsites called according to the year, 2012, 2011, etc.
In the rootweb, there is a list called Products.
In the subsites there is a list called Sales, and I need to add a lookup field to the list Products in the root site.
I found this code, but its not working, it created the lookup field, but the dropdown is empty even if there are products.
//Request North lookup
currentList = currentWeb.GetSafeListByName(SponsoringCommon.Constants.LISTNAMES_SALESNORTH);
string sFldReqNr = SponsoringCommon.Constants.FIELDS_REQUESTNUMBERLOOKUPNORTH_NAME + currentWeb.Title;
Functions.CreateRequestNumberLookup(currentList, sFldReqNr, false, Functions.NorthSouth.North);
ArrayList colPreviousContentTypes = new ArrayList();
currentList.AddFieldToContentType(sFldReqNr, SponsoringCommon.Constants.CONTENTTYPES_SALESNUMBER_NAME, 2, colPreviousContentTypes, 1033);
public static void CreateProductNameLookup(SPList currentList, string strInternalFieldName, bool allowMultipleValues)
{
Logger.LogDebug("Functions",
"CreateProductNameLookup(SPList currentList, string strInternalFieldName, bool allowMultipleValues)", "BEGIN");
SPWeb currentWeb = currentList.ParentWeb;
SPList targetList = currentWeb.Site.RootWeb.GetSafeListByName(SponsoringCommon.Constants.LISTNAMES_PRODUCT_NAME);
SPFieldCollection colFields = currentList.Fields;
Guid targetListID = targetList.ID;
int L1 = strInternalFieldName.Length;
int L2 = currentWeb.Title.Length;
string sFieldNameWithoutYear = (strInternalFieldName.EndsWith(currentWeb.Title) ?
strInternalFieldName.Substring(0, L1 - L2) :
strInternalFieldName);
if (colFields.ContainsField(strInternalFieldName))
{
Logger.LogDebug("Functions",
"CreateProductNameLookup(SPList currentList, string strInternalFieldName, bool allowMultipleValues)",
"Field '" + strInternalFieldName + "' already exists. (>> Skipped)");
}
else
{
strInternalFieldName = colFields.AddLookup(strInternalFieldName, targetListID, false);
SPField fld = colFields.GetFieldByInternalName(strInternalFieldName);
fld.ShowInNewForm = true;
fld.ShowInEditForm = true;
fld.ShowInDisplayForm = true;
SPFieldLookup fldLU = fld as SPFieldLookup;
fldLU.AllowMultipleValues = allowMultipleValues;
string strSchemaXml = fldLU.SchemaXmlWithResourceTokens;
strSchemaXml = strSchemaXml.Replace("DisplayName=\"" + strInternalFieldName + "\"", "DisplayName=\"$Resources:SPNLSponsoring,Field_" + sFieldNameWithoutYear + "_Name;\"");
strSchemaXml = strSchemaXml.Replace("/>", " ShowField=\"" + targetList.Fields[SponsoringCommon.Constants.FIELDS_PRODUCT_NAMENEW].InternalName + "\" " +
"Description=\"$Resources:SPNLSponsoring,Field_" + sFieldNameWithoutYear + "_Description;\" " +
"Group=\"$Resources:SPNLSponsoring,Field_NationaleLoterijSponsoringColumns_Group;\" />");
fldLU.SchemaXml = strSchemaXml;
fldLU.Update(true);
currentList.Update();
}
Logger.LogDebug("Functions",
"CreateProductNameLookup(SPList currentList, string strInternalFieldName, bool allowMultipleValues)", "END");
}

its possible, I already solved it, I had to use another overload of the method addlookup that receives the parentweb.id
strInternalFieldName = colFields.AddLookup(strInternalFieldName, targetListID, currentWeb.Site.RootWeb.ID, true);
then it works fine

Related

How can I find a phrase anywhere in a String Array?

I need to see if any phrase, such as "duckbilled platypus" appears in a string array.
In the case I'm testing, the phrase does exist in the string list, as shown here:
Yet, when I look for that phrase, as shown here:
...it fails to find it. I never get past the "if (found)" gauntlet in the code below.
Here is the code that I'm using to try to traverse through the contents of one doc to see if any phrase (two words or more) are found in both documents:
private void FindAndStorePhrasesFoundInBothDocs()
{
string[] doc1StrArray;
string[] doc2StrArray;
slPhrasesFoundInBothDocs = new List<string>();
slAllDoc1Words = new List<string>();
int iCountOfWordsInDoc1 = 0;
int iSearchStartIndex = 0;
int iSearchEndIndex = 1;
string sDoc1PhraseToSearchForInDoc2;
string sFoundPhrase;
bool found;
int iLastWordIndexReached = iSearchEndIndex;
try
{
doc1StrArray = File.ReadAllLines(sDoc1Path, Encoding.UTF8);
doc2StrArray = File.ReadAllLines(sDoc2Path, Encoding.UTF8);
foreach (string line in doc1StrArray)
{
string[] subLines = line.Split();
foreach (string whirred in subLines)
{
if (String.IsNullOrEmpty(whirred)) continue;
slAllDoc1Words.Add(whirred);
}
}
iCountOfWordsInDoc1 = slAllDoc1Words.Count();
sDoc1PhraseToSearchForInDoc2 = slAllDoc1Words[iSearchStartIndex] + ' ' + slAllDoc1Words[iSearchEndIndex];
while (iLastWordIndexReached < iCountOfWordsInDoc1 - 1)
{
sFoundPhrase = string.Empty;
// Search for the phrase from doc1 in doc2;
found = doc2StrArray.Contains(sDoc1PhraseToSearchForInDoc2);
if (found)
{
sFoundPhrase = sDoc1PhraseToSearchForInDoc2;
iSearchEndIndex++;
sDoc1PhraseToSearchForInDoc2 = sDoc1PhraseToSearchForInDoc2 + ' ' + slAllDoc1Words[iSearchEndIndex];
}
else //if not found, inc vals of BOTH int args and, if sFoundPhrase not null, assign to sDoc1PhraseToSearchForInDoc2 again.
{
iSearchStartIndex = iSearchEndIndex;
iSearchEndIndex = iSearchStartIndex + 1;
if (!string.IsNullOrWhiteSpace(sFoundPhrase)) // add the previous found phrase if there was one
{
slPhrasesFoundInBothDocs.Add(sFoundPhrase);
}
sDoc1PhraseToSearchForInDoc2 = slAllDoc1Words[iSearchStartIndex] + ' ' + slAllDoc1Words[iSearchEndIndex];
} // if/else
iLastWordIndexReached = iSearchEndIndex;
} // while
} // try
catch (Exception ex)
{
MessageBox.Show("FindAndStorePhrasesFoundInBothDocs(); iSearchStartIndex = " + iSearchStartIndex.ToString() + "iSearchEndIndex = " + iSearchEndIndex.ToString() + " iLastWordIndexReached = " + iLastWordIndexReached.ToString() + " " + ex.Message);
}
}
doc2StrArray does contain the phrase sought, so why does doc2StrArray.Contains(sDoc1PhraseToSearchForInDoc2) fail?
This should do what you want:
found = Array.FindAll(doc2StrArray, s => s.Contains(sDoc1PhraseToSearchForInDoc2));
In List<T>, Contains() looking for an T, Here in your code to found be true must have all the text in particular index (NOT part of it).
Try this
var _list = doc2StrArray.ToList();
var found = _list.FirstOrDefault( w => w.Contains( sDoc1PhraseToSearchForInDoc2 ) ) != null;

Retrieving members of a group that contains a subgroup

I created a dot.net form that uses c# code to retrieve members of an Active Directory group that a user selects from a drop-down, then displays the list of members (users is all I want) on the web page.
This works fine for groups that DO NOT contain sub-groups. When an Active Directory group contains users and sub-groups I receive an error.
I only want users of the group that the users selects from the drop-down. I don't want users from any sub-groups.
I have done lots of searching on the internet and testing various code suggestions.
public List<string> GetAllUsersFromGroup(string domain,
string group)
{
List<string> retVal = new List<string>();
DirectoryEntry entry = new DirectoryEntry(domain);
DirectorySearcher searcher = new DirectorySearcher("
(&(objectCategory=Group)(cn=" + group + "))");
searcher.SearchRoot = entry;
searcher.SearchScope = SearchScope.Subtree;
SearchResult result = searcher.FindOne();
var x = 0;
var txtCN = "";
var txtDispName = "";
var firstItem = 0; // Display Name
var secondItem = 1; // CN
var arraryResultsSize = result.Properties["member"].Count;
string[] deResultsArray = new string[arraryResultsSize];
foreach (string member in result.Properties["member"])
{
DirectoryEntry de = new DirectoryEntry(String.Concat(domain,
"/", member.ToString()));
if (de.Properties["objectClass"].Contains("user") &&
de.Properties["cn"].Count > 0)
{
deResultsArray[x] = de.Properties["displayName"]
[0].ToString() + "~" + de.Properties["cn"]
[0].ToString();
}
x = x + 1;
}
if (deResultsArray[0] != null) {
string[] sortSeperatedItems = sortLDAPUsers(deResultsArray);
for (var i = 0; i < sortSeperatedItems.Length/2; i++) {
txtDispName = "<tr><td>" + sortSeperatedItems[firstItem]
+ "</td>";
txtCN = "<td>" + sortSeperatedItems[secondItem] + "</td>
</tr>";
retVal.Add(txtDispName);
retVal.Add(txtCN);
firstItem = firstItem + 2;
secondItem = secondItem + 2;
}
} else {
txtDispName = "<tr><td>Group has no members</td>";
txtCN = "<td> </td></tr>";
retVal.Add(txtDispName);
retVal.Add(txtCN);
}
// retVal.Add("Array Size is: " + propCount);
return retVal;
}
public string[] sortLDAPUsers(string[] strArray) {
Array.Sort(strArray);
var newArraySize = (strArray.Length * 2);
string[] itemSeperated = new string[2];
string[] allSepItems = new string[newArraySize];
var arrayItemsString = "";
var xDName = 0;
var xCName = 1;
for (var i = 0; i < strArray.Length; i++) {
itemSeperated = strArray[i].Split('~');
allSepItems[xDName] = itemSeperated[0];
allSepItems[xCName] = itemSeperated[1];
arrayItemsString = arrayItemsString + "Length of allSepItems
is: " + allSepItems.Length + " Text is: " +
allSepItems[xDName] + " NetId is: " + allSepItems[xCName] +
"<br><br>";
xDName = xDName + 2;
xCName = xCName + 2;
}
return allSepItems;
}
When user selects an Active Directory group that contains users and sub-group(s), I receive the following error:
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 205: for (var i = 0; i < strArray.Length; i++) {
Line 206:
Line 207: itemSeperated = strArray[i].Split('~');
Line 208: allSepItems[xDName] = itemSeperated[0];
Line 209: allSepItems[xCName] = itemSeperated[1];
I think the error has to do with how I'm filtering or getting results in GetAllUsersFromGroup(). I don't know how to just get users from a group and not include any sub-group(s) in the results.
The problem with this filter (&(objectCategory=Group)(cn=<group>)) is that you are querying a specific group to iterate and grab all its members regardless of the type/objectClass, so you are left with users, groups and whatever.
Instead, you can request users that are members of this group directly using the proper filter :
new DirectorySearcher("(&(objectCategory=person)(memberOf=" + groupDN + "))");
Note that the memberOf attribute must match a DN, so given the passed in variable group (if the caller can't pass the actual group dn) you may have to grab it in the first place using the 1st filter.
The error you get then is another issue due to sorting, maybe comment this part until you get the proper results.
You do not need to work that hard when you could let Microsoft Active Directory do the work.
An LDAP search request with an LDAP filter to Resolve all members (including nested) Security Groups (requires at least Windows 2003 SP2)
(&(objectClass=user)(memberof:1.2.840.113556.1.4.1941:=CN=GroupOne,OU=Security Groups,OU=Groups,DC=YOURDOMAIN,DC=NET)
This will return all (objectClass=user) that are members of the "GroupOne".

c# Retrieve multiple XML child nodes

I've managed to link up a single XElement successfully into my program though I'm not having any luck with the other two I have in place, I've tried using;
IEnumerable query = from booking in doc.Descendants("Booking")
Though I've haven't had much luck placing the values into list box.
Here's the code for function:
private void btnimport_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.CheckFileExists = true;
open.InitialDirectory = "#C:\\";
open.Filter = "XML Files (*.xml)|*.xml|All Files(*.*)|*.*";
open.Multiselect = false;
if (open.ShowDialog() == DialogResult.OK)
{
try
{
XDocument doc = XDocument.Load(open.FileName);
//Grabs the customer elements
var query = from booking in doc.Descendants("Booking")
select new
{
//Customer Elements
CustomerId = booking.Element("CustomerId").Value,
Title = booking.Element("Title").Value,
Firstname = booking.Element("FirstName").Value,
Lastname = booking.Element("LastName").Value,
DateofBirth = booking.Element("DateofBirth").Value,
Email = booking.Element("Email").Value,
HouseNo = booking.Element("HouseNo").Value,
Street = booking.Element("Street").Value,
Postcode = booking.Element("Postcode").Value,
Town = booking.Element("Town").Value,
County = booking.Element("County").Value,
ContactNo = booking.Element("ContactNo").Value,
//Holiday Elements
HolidayId = booking.Element("HolidayId").Value,
HotelName = booking.Element("HotelName").Value,
Location = booking.Element("Location").Value,
BookFrom = booking.Element("BookFrom").Value,
BookTo = booking.Element("BookTo").Value,
CheckInTime = booking.Element("CheckInTime").Value,
CheckOutTime = booking.Element("CheckOutTime").Value,
NoOfRoomsBooked = booking.Element("NoOfRoomsBooked").Value,
RoomType = booking.Element("RoomType").Value,
RoomServices = booking.Element("RoomServices").Value,
Parking = booking.Element("Parking").Value,
Pet = booking.Element("Pet").Value,
//TravelInfo Elements
TravelInfoId = booking.Element("TravelInfoId").Value,
TravellingFrom = booking.Element("TravellingFrom").Value,
Destination = booking.Element("Destination").Value,
Fare = booking.Element("Fare").Value,
TravelInsurance = booking.Element("TravelInsurance").Value,
InFlightMeals = booking.Element("In-FlightMeals").Value,
LuggageAllowance = booking.Element("LuggageAllowance").Value,
ExtraLuggage = booking.Element("ExtraLuggage").Value,
CarHire = booking.Element("CarHire").Value,
ReturnTransfer = booking.Element("ReturnTransfer").Value,
};
//Inputs all of the values in bookings
foreach (var booking in query)
{
//Customer values
txtCustomerId.Text = txtCustomerId.Text + booking.CustomerId;
txttitle.Text = txttitle.Text + booking.Title;
txtfname.Text = txtfname.Text + booking.Firstname;
txtlname.Text = txtlname.Text + booking.Lastname;
txtdob.Text = txtdob.Text + booking.DateofBirth;
txtemail.Text = txtemail.Text + booking.Email;
txthouseno.Text = txthouseno.Text + booking.HouseNo;
txtstreet.Text = txtstreet.Text + booking.Street;
txtpostcode.Text = txtpostcode.Text + booking.Postcode;
txttown.Text = txttown.Text + booking.Town;
txtcounty.Text = txtcounty.Text + booking.County;
txtcontactno.Text = txtcontactno.Text + booking.ContactNo;
//Holiday Values
txtHolidayId.Text = txtHolidayId.Text + booking.HolidayId;
txthname.Text = txthname.Text + booking.HotelName;
txtl.Text = txtl.Text + booking.Location;
txtbf.Text = txtbf.Text + booking.BookFrom;
txtbt.Text = txtbt.Text + booking.BookTo;
txtcit.Text = txtcit.Text + booking.CheckInTime;
txtcot.Text = txtcot.Text + booking.CheckOutTime;
txtnorb.Text = txtnorb.Text + booking.NoOfRoomsBooked;
txtrt.Text = txtrt.Text + booking.RoomType;
txtrs.Text = txtrs.Text + booking.RoomServices;
txtpark.Text = txtpark.Text + booking.Parking;
txtpet.Text = txtpet.Text + booking.Pet;
//TravelInfo Values
txtTravelInfoId.Text = txtTravelInfoId.Text + booking.TravelInfoId;
txttf.Text = txttf.Text + booking.TravellingFrom;
txtd.Text = txtd.Text + booking.Destination;
txtf.Text = txtf.Text + booking.Fare;
txtti.Text = txtti.Text + booking.TravelInsurance;
txtifi.Text = txtifi.Text + booking.InFlightMeals;
txtla.Text = txtla.Text + booking.LuggageAllowance;
txtel.Text = txtel.Text + booking.ExtraLuggage;
txtch.Text = txtch.Text + booking.CarHire;
txtrtrans.Text = txtrtrans.Text + booking.ReturnTransfer;
}
MessageBox.Show("XML has been imported");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
If anyone knows where I've gone wrong or what I need to add / change please let me know :)
Many thanks,
10gez10
You have several problems:
Firstly, your data elements are not immediate children of the booking element, there are intermediate elements <Customer>, <Holiday> and <TravelInfo>. Thus you need to do something like
var query = from booking in doc.Descendants("Booking")
let customer = booking.Element("Customer")
let holiday = booking.Element("Holiday")
let travelInfo = booking.Element("TravelInfo")
select new
{
//Customer Elements
CustomerId = customer.Element("CustomerId").Value,
Title = customer.Element("Title").Value,
HolidayId = holiday.Element("HolidayId").Value,
TravelInfoId = travelInfo.Element("TravelInfoId").Value,
}
Secondly, several elements are misspelled:
CheckOutTime should be CheckoutTime
In-FlightMeals should be InFlightMeals.
CarHire should be CareHire (yes "CareHire" is what's in the XML.)
Thus, when you do (e.g.) Element("In-FlightMeals").Value, Element() is returning null so you get a null reference exception and your code is aborted.
Thirdly, the element BookTo is completely missing, so BookTo = holiday.Element("BookTo").Value generates a null reference exception.
More generally, I do not recommend this coding approach. If any of your XML elements are missing, your query will throw an exception because element.Element("name") will be null. What's worse, Visual Studio doesn't seem to report an accurate line number on which the null reference occurs, instead giving the line number of the select new statement. And (on my version at least), it's not possible to step into the constructor for an anonymous type either. This makes debugging well-nigh impossible.
Instead, skip the intermediate anonymous type and do things in a more direct, traditional manner:
foreach (var booking in doc.Descendants("Booking"))
{
var customer = booking.Element("Customer");
var holiday = booking.Element("Holiday");
var travelInfo = booking.Element("TravelInfo");
XElement element;
if (customer != null)
{
if ((element = customer.Element("CustomerId")) != null)
txtCustomerId.Text = txtCustomerId.Text + element.Value;
}
// And so on.
}

put data from simpleDB into data gridview

I was trying to retrieve data from Amazon SimpleDB and currently it only displays data in text like domainName: {attribute1, value2} {attribute1, value2}.
How can I show the data in data grid view? My code is as follows:
public static List<String> GetItemByQuery(IAmazonSimpleDB simpleDBClient, string domainName)
{
List<String> Results = new List<String>(); ;
SelectResponse response = simpleDBClient.Select(new SelectRequest()
{
SelectExpression = "Select * from " + domainName
});
String res = domainName + " has: ";
foreach (Item item in response.Items)
{
res = item.Name + ": ";
foreach (Amazon.SimpleDB.Model.Attribute attribute in item.Attributes)
{
res += "{" + attribute.Name + ", " + attribute.Value + "}, ";
}
res = res.Remove(res.Length - 2);
Results.Add(res);
}
return Results;
}
How you an read here:
http://docs.aws.amazon.com/sdkfornet1/latest/apidocs/html/P_Amazon_SimpleDB_Model_SelectResult_Item.htm
your response.Items is
public List<Item> Item { get; set; }
so you should directly use to DataSource of your Grid, set autogenerate column to your grid to start to view the result

How do I access a tasks collection on user stories using Rally .NET toolkit?

I get:
Unhandled Exception: System.Collections.Generic.KeyNotFoundException: The given
key was not present in the dictionary.
when iterating over user story query results and try to access story["Tasks"]
foreach (var story in queryStoryResults.Results)
{
Console.WriteLine("FormattedID: " + story["FormattedID"]);
Console.WriteLine("Name: " + story["Name"]);
Console.Write("Tasks: " + story["Tasks"]);
}
First, make sure that Tasks are being fetched, along with task specific fields that you want to extract, e.g. State.
Next, a nested loop is needed inside the loop that iterates over user story results.
Here is the code example. It queries on user stories from the current iteration and prints out FormattedID and State of tasks associated with the query results:
namespace RESTexample_storiesFromIteration
{
class Program
{
static void Main(string[] args)
{
//Initialize the REST API
RallyRestApi restApi;
restApi = new RallyRestApi("user#domain.com", "1984", "https://rally1.rallydev.com", "1.43");
//Set our Workspace and Project scopings
String workspaceRef = "/workspace/1111";
String projectRef = "/project/2222";
bool projectScopingUp = false;
bool projectScopingDown = true;
DateTime now = DateTime.Today;
String nowString = now.ToString("yyyy-MM-dd");
Request iterationRequest = new Request("Iteration");
iterationRequest.Workspace = workspaceRef;
iterationRequest.Project = projectRef;
iterationRequest.Fetch = new List<string>()
{
"Name",
"StartDate",
"EndDate",
"Project",
"State"
};
String iterationQueryString = "((StartDate <= \"" + nowString + "\") AND (EndDate >= \"" + nowString + "\"))";
iterationRequest.Query = new Query(iterationQueryString);
QueryResult queryIterationResults = restApi.Query(iterationRequest);
var myIteration = queryIterationResults.Results.First();
var myIterationName = myIteration["Name"];
var myIterationProject = myIteration["Project"];
var myIterationProjectName = myIterationProject["Name"];
Console.WriteLine("Name: " + myIterationName);
Console.WriteLine("Project Ref: " + myIterationProjectName);
Console.WriteLine("State: " + myIteration["State"]);
// Query for Stories
Request storyRequest = new Request("hierarchicalrequirement");
storyRequest.Workspace = workspaceRef;
storyRequest.Project = projectRef;
storyRequest.ProjectScopeUp = projectScopingUp;
storyRequest.ProjectScopeDown = projectScopingDown;
storyRequest.Fetch = new List<string>()
{
"Name",
"ObjectID",
"ScheduleState",
"State",
"FormattedID",
"PlanEstimate",
"Iteration",
"Tasks"
};
storyRequest.Query = new Query("Iteration.Name", Query.Operator.Equals, myIterationName);
QueryResult queryStoryResults = restApi.Query(storyRequest);
foreach (var s in queryStoryResults.Results)
{
Console.WriteLine("----------");
Console.WriteLine("FormattedID: " + s["FormattedID"]);
Console.WriteLine("Name: " + s["Name"]);
Console.WriteLine("PlanEstimate: " + s["PlanEstimate"]);
var tasks = s["Tasks"];
foreach (var t in tasks)
{
Console.WriteLine("Task: " + t["FormattedID"] + " " + t["State"]);
}
}
}
}
}

Categories