Behavior of Session Getters - c#

I have the following property for getting and setting a Session variable...
protected List<Item> SearchResults
{
get
{
if (Session["SearchResults"] == null)
Session["SearchResults"] = new List<string>();
return ((List<string>) Session["SearchResults"]).Select(s => new Item(s)).ToList();
}
set { Session["SearchResults"] = value.Select(p => p.Serialize()).ToList(); }
}
As you can see, I am storing the items as serialized strings.
When the user checks a few checkboxes in a GridView and then clicks submit, I would like to modify the value of the Selected property of the Items that he has selected. Here is my code for doing that and it is working great...
private void RecordSelections()
{
var searchResults = SearchResults; //localize session list
foreach (var checkBox in AssignGrid.Rows.Cast<GridViewRow>().Select(r => (CheckBox)r.FindControl("chkSelect")))
{
var result = searchResults.FirstOrDefault(r => r.Key == long.Parse(checkBox.Attributes["ItemKey"].ToString()));
if (result != null) result.Selected = checkBox.Checked;
SearchResults = searchResults; //store session list
}
}
My question then is this. I have found it necessary to localize the session list (see commented line) and then to store that session list (also commented), but what is it precisely that is happening when I access this Session variable through the getter? I would like to do something like the following to get an Item out of the list and modify it's value. I am not able to answer exactly why it is that this doesn't work. Would it work if I were not serializing the object (the reason for serializing the item is another post altogether)?
private void RecordSelections()
{
foreach (var checkBox in AssignGrid.Rows.Cast<GridViewRow>().Select(r => (CheckBox)r.FindControl("chkSelect")))
{
var result = SearchResults.FirstOrDefault(r => r.Key == long.Parse(checkBox.Attributes["ItemKey"].ToString()));
if (result != null) result.Selected = checkBox.Checked;
}
}
Thanks in advance for your help.

Related

Setting the Data within a nested datagrid programatically

SubVwr.Tables[0].tbl is a table of several items, some of which require specific Trace. Those items which require trace have serial numbers assiciated with them. To handle this, I created a new window for each, where I'd like the user to input serial numbers. Some of the Data inside of the new table (dialog) should be pulled from the previous table (Subvwr). What would be the syntax here if I wanted to complete an assignment for a specific value within each row of dialog?
private void requestSerials()
{
// needs to check for a difference. If QtyRcvd has changed, then we need to request "QtyRcvd" number of serials
//for each row in our received order..
foreach (DataRow row in SubVwr.Tables[0].Tbl.Rows)
{
// check to see if it neesd to be traced..
if (row["TraceReq"].ToString() == "Y")
{
//if yes, create a serialInputDialogWindow
SerialInputDialogWindow dialog = new SerialInputDialogWindow()
{
Topmost = true
};
//Iterate through the dialogWindow before we display it to fill it with some necessary data.
var itemsSource = dialog.serialtable.ItemsSource as IEnumerable;
if (itemsSource != null)
{
foreach (var item in itemsSource)
{
var serialrow = item as System.Data.DataRowView;
serialrow["PN"] = "test"; //doesn't work
serialrow.Row["PN"] = "test"; //doesn't work
}
}
dialog.ShowDialog();
}
}
}
An example of similar code that works. It populates that specific column for each row as specified. I'd like to take Data from Subvwr and populate Dialog in a similar way
foreach(DataRow row in SubVwr.Tables[0].Tbl.Rows)
{
row["DateRcvd"] = DateTime.Today;
row["QtyRcvd"] = row["QtyPer"];
}
The items in the ItemsSource are of some type. If for example dialog.serialtable.ItemsSource returns a DataView, you can cast the items to DataRowViews and then access any columns using the indexer:
foreach (var item in itemsSource)
{
var serialrow = item as System.Data.DataRowView;
if (serialrow != null)
{
var name = serialrow["ColumnName"].ToString();
}
}
If it is an IEnumerable<T> and T is a YourClass, you cast it to this type:
foreach (var item in itemsSource)
{
var serialrow = item as YourType;
if (serialrow != null)
{
var name = serialRow.Property1;
}
}

Invalid data has been used to update the list item. The field you are trying to update may be read only

I am getting this error while updating discussion item's any property on SharePoint online. Error doesn't occur in case of document library and custom lists. Error Code is -2147024809 my code goes like this.
public static SBUpdatePropsResponse UpdateProps(string siteCollectionUrl,string webUrl ,SBUpdatePropsRequest updateRequest)
{
var updateResponse = new SBUpdatePropsResponse();
var clientContext = Admin.GetAuthenticatedClientContext(webUrl);
var web = clientContext.Web;
var oList = clientContext.Web.Lists.GetById(updateRequest.ListID);
var itemProps = updateRequest.ItemProperties;
var itemUserProps = updateRequest.UserTypeProperties;
var itemDateTimeProps = updateRequest.DateTimeItemProperties;
ListItem listItem = oList.GetItemById(updateRequest.DocID);
clientContext.Load(web);
clientContext.Load(listItem);
clientContext.ExecuteQuery();
try
{
//Need to create a extra dictionary to save server time against property
var itemDateTimePropsLocal = new Dictionary<string, string>();
foreach (var prop in itemDateTimeProps)
{
var dateTimeLocal = new DateTime(prop.Value, DateTimeKind.Utc);
var temp = web.RegionalSettings.TimeZone.UTCToLocalTime(dateTimeLocal);
clientContext.ExecuteQuery();
itemDateTimePropsLocal.Add(prop.Key, temp.Value.ToString());
}
foreach (var userProp in itemUserProps)
{
if (userProp.Value != null && !string.IsNullOrEmpty(userProp.Value.ToString()))
{
var uservalues = userProp.Value as int[];
//Handle for multi user property
if (uservalues.Length > 1)
{
var propValues = new List<FieldUserValue>();
foreach (var values in uservalues)
{
if (values > 0)
propValues.Add(new FieldUserValue { LookupId = values });
}
listItem[userProp.Key] = propValues.ToArray();
}
else
listItem[userProp.Key] = (new FieldUserValue { LookupId = uservalues[0] });
}
}
foreach (var prop in itemProps)
{
if (prop.Key.Equals("ContentType"))
continue;
if (prop.Value != null && !string.IsNullOrEmpty(prop.Value.ToString()) && prop.Value.GetType() != typeof(FieldUrlValue))
listItem.ParseAndSetFieldValue(prop.Key, prop.Value.ToString());
}
foreach (var prop in itemDateTimePropsLocal)
{
listItem[prop.Key] = prop.Value;
}
listItem.Update();
clientContext.ExecuteQuery();
updateResponse.IsSuccess = true;
}
catch(Exception ex)
{
Logging.LogWriteLine("Failed to update list item properties", ex);
updateResponse.IsSuccess = false;
}
}
I am putting my answer here in case people find this question by googling the error message that in the title of this SO question. This answer might help others who come across this strange error message.
I had the same error when I was updating a calendar event with server side code.
My code first added a new empty list item. This new list item had default values for the start date and end date. A few lines later, the list item fields are updated one by one (similar to the op code) and then a list item update is called. In my case, the start date was not being updated by my code and remained the default value. The end date got updated by my code and made the end date earlier in time than the start date. When the list item update was called, this error would be displayed in my exception logs.
Once I corrected this and adjusted the start date to always fall before the end date and then call update, the error went away.

Can't check whether a list contains a select item in C#

I am storing a list of select items in my view model. When adding the correct select items i get them from a list stored in a spreadsheet, some of which are duplicates. I want to eliminate these duplicates and have the following code to do so.
//Fill with all the install locations
foreach (App y in applications)
{
//Check if the app has a server listed
if (y.Server != "")
{
SelectListItem ItemToAdd = new SelectListItem { Text = y.Server, Value = y.Server };
//Check if the the item has already been added to the list
if (!vm_modal.serverLocations.Contains(ItemToAdd))
{
vm_modal.serverLocations.Add(ItemToAdd);
}
}
}
However this is not working as it is just adding everything so there are a lot of duplicates. I don't know if contains works differently because I'm not just dealing with regular strings or something like that.
In this instance, as you are using the same string for Text and Value, you can iterate through your source, and add non-duplicate values to a simple List<string> before adding all of the checked values to your select list.
List<string> result = new List<string>();
foreach (App y in applications)
{
//Check if the app has a server listed and for duplicates
if (y.Server != "" && !result.Contains(y.Server))
{
result.Add(y.Server);
}
}
result.ForEach(x => vm_modal.serverLocations.Add(
new SelectListItem(){Text = x, Value = x}));
for a "one liner" of what ste-fu presented you can write
vm_modal.serverLocations
.AddRange(applications
.Where(app => app.Server != "")
.Select(app => app.Server)
.Distinct()
.Select(server => new SelectListItem{ Text = server, Value = server }));

remove item in dictionary using value

i have a dictionary that you can add cards to by searching on a listbox but now i want to be able to remove that item from the dictionary if the user presses a button here is the code i use to add a value to the dictionary
if (!m_banlists[BanList.Items[BanList.SelectedIndex].ToString()].Exists(banListCard => banListCard.ID == Program.CardData[cardid].Id))
{ m_banlists[BanList.Items[BanList.SelectedIndex].ToString()].Add(
new BanListCard { ID = Program.CardData[cardid].Id, Banvalue = 0, Name = Program.CardData[cardid].Name });
}
i wont post all the code as its too long
heres the code i use to remove an item
var list = (ListBox) sender;
if (list.SelectedIndex != -1)
{
int cardid = Int32.Parse((string)list.SelectedItem.ToString());
if (m_banlists[BanList.Items[BanList.SelectedIndex].ToString()].Exists(banListCard => banListCard.ID == Program.CardData[cardid].Id))
{
m_banlists[BanList.Items[BanList.SelectedIndex].ToString()].Remove();
list.Items.RemoveAt(list.SelectedIndex);
}
}
but i cant figure out what to put in the brackets of remove to find the value oh and it needs to look for the ID value
I think you can try this
m_banlists[BanList.Items[BanList.SelectedIndex].ToString()].ToList().RemoveAll(x=>x.ID==someId);

Using database query results instead of displaying in datagrid

I am using C# to create a Silverlight 4 application.
I am trying to do the following:
MapNode endNode = null;
if (keyword != null && keyword != "")
{
EntityQuery<NodeIDProj> res = CampusQueries.getNodeIDByNameQuery(keyword);
var queryres = CampusQueries.Load<NodeIDProj>(res, (items) =>
{
foreach (var item in items.Entities)
{
MapNode n = mapHelp.getNodeByID(item.NodeID);
if (n != null)
{
endNode = n;
TrackAnimation();
}
}
}, true);
}
However, after this point, my variable endNode is still null. TrackAnimation() works as though endNode has a valid value, but outside of the Load statement, endNode is back to null.
I know that I am lacking in understanding of how this works, and I would really appreciate an help given.
What I am trying to do, is query my database and I want to use those results in other methods rather than displaying them in a datagrid.
I want endNode to have value which I can use in other methods.
Please help me to figure out a way to do this, thank you!
EDIT:
Thank you, SLaks
Can I do something like:
MapNode endNode = null;
if (keyword != null && keyword != "")
{
EntityQuery<NodeIDProj> res = CampusQueries.getNodeIDByNameQuery(keyword);
var queryres = CampusQueries.Load<NodeIDProj>(res, (items) =>
{
foreach (var item in items.Entities)
{
MapNode n = mapHelp.getNodeByID(item.NodeID);
if (n != null)
{
endNode = n;
TrackAnimation();
}
}
}, true);
}
queryres.Completed += new EventHandler(queryres_Completed);
void queryres_Completed(object sender, EventArgs e)
{
//stuff
}
If so, how can I get access to the endNode variable, as it is declared within another method?
Your Load method is probably asynchronous, meaning that the callback happens some time after the rest of your code runs.
You can only use the result after you actually receive it.

Categories