Saving to session seems to erase value during Repeater's OnItemDataBound Event - c#

This is weird. I'll try to explain my pain by the following example:
I've got an object in the Session: Session["reportQuestionGroupingTracker"]. It contains a List of strings. When a string is NOT found, a new h3 header is written in the repeater via a string literal.
The problem seems to be the line: Session["reportQuestionGroupingTracker"] = ary; This line seems to somehow (black)magically remove the string value in lit.Text. The value is there when I breakpoint the code and seems to persist until it goes out of scope in the function(so that part works like expected) - but the string value never seems to make it to the Literal control on the ASP.NET page - they are always blank.
Note that if I comment out the problem line or this line: if (!ary.Contains(headingText)), the headers show (but too many of them, since every iteration triggers a header write).
protected void rptQuestionsGroupedByCountry_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
ArrayList ary = new ArrayList();
if (null != Session["reportQuestionGroupingTracker"]) ary = (ArrayList)Session["reportQuestionGroupingTracker"];
if ((item.ItemType == ListItemType.Item) ||
(item.ItemType == ListItemType.AlternatingItem))
{
DataRowView dr = (DataRowView)e.Item.DataItem;
string headingText = dr["Heading"].ToString();
Literal lit = (Literal)e.Item.FindControl("LiteralHeader");
if (!ary.Contains(headingText))
{
lit.Text = String.Format(#"<h3 class=""questionGroupingHeader"">{0}</h3>", headingText);
lit.Visible = true;
ary.Add(headingText);
Session["reportQuestionGroupingTracker"] = ary;
}
}
}
I've been on this for hours, banging my head - I've done similar things hundreds of times before, I just can't work out why it doesn't work this time! I've tried changing the Repeater to a DataList, Tried using the Context.Items object instead of the Session, a List instead of an ArrayList, but I'm stymied. Help!
I've also tried running it in IIS 6, just in case it was some Cassini weirdness, but the output is the same. It's an ASP.NET 4.0 Project.
Here's the code from the aspx page:
<asp:Repeater ID="rptQuestionsGroupedByCountry" runat="server" OnItemDataBound="rptQuestionsGroupedByCountry_OnItemDataBound">
<HeaderTemplate><table></HeaderTemplate>
<ItemTemplate>
<tr><td>
<asp:Literal ID="LiteralHeader" runat="server" Visible="false" />
<h3 class="report-country-tag"><%#DataBinder.Eval(Container, "DataItem.Numbers")%>.<%#DataBinder.Eval(Container, "DataItem.QusetionName")%></h3>
<div class="report-content">
<%#DataBinder.Eval(Container, "DataItem.Answer")%>
<p class="date">Date Updated: <%#DataBinder.Eval(Container, "DataItem.DocumentModifiedWhen")%></p>
</div>
</td></tr>
</ItemTemplate>
<FooterTemplate></table></FooterTemplate>

your problem with line
if (!ary.Contains(headingText))
You must populate literal text every time page loaded
if (!ary.Contains(headingText))
{
ary.Add(headingText);
Session["reportQuestionGroupingTracker"] = ary;
}
lit.Text = String.Format(#"<h3 class=""questionGroupingHeader"">{0}</h3>", headingText);
lit.Visible = true;

As Micheal suspected, the databind routine was being hit twice for every page load. The first time through the Session gets set properly, but the second time through, the Headers get skipped because the if (!ary.Contains(headingText)) correctly told it to. My bad for not noticing the two databinding hits. I feel very foolish. Coding while tired is no excuse for such an obvious issue. Sorry for wasting your time!
Also I was working with too large a dataset - I'd walk through the first 5 loops and see that the value was being set and then just F5. It wasn't until I was clearheaded this morning and just put breakpoints in every function so that I could see the execution order and understand what the heck was going on. Then it was a headslap moment... quickly followed by a single line change to fix the issue... and then a feeling of elation. Ain't programming fun?
Cheers and thanks for the help!
PS - Shout out to Kochobay for the line: '...every time page loaded...' which induced the headslapping epiphany!

Related

Trying to extract elements from a List<model> and display in Blazor razor component

I am brand new to Blazor Server, coming from a background in ASP.NET Webforms. I have a database that stores questions and answers for an employee safety test, and Im trying to display the test questions programatically in the HTML section of my page. When debugging, I get an Index Out of Range error.
Related Code:
#code {
private List<IForkLiftPerfTestContentModel> testquestion = new List<IForkLiftPerfTestContentModel>();
protected override async Task OnInitializedAsync()
{
testquestion = await testService.GetTestQuestions();
}
When I debug testquestion, it displays data properly as shown:
When I try to display an element by zero-based index, I get Index out of Range, although Intellisense doesnt complain about my code:
<td>
#testquestion[0].Topic
</td>
Clearly Im missing something, but again I am learning Blazor. Any help is appreciated!
When your blazor page will render first time, it will not yet have awaited your async operation, it will re-render once that operation is done.
Meaning on first render your testquestion will be empty - that's why you have Index Out Of Range, so you need to handle it, say for example "if testquestion is empty - display loading"
Thanks #Nikita! That was perfect!
I wrapped the Edit Form in an if/else like this:
#if (testquestion.Count == 0)
{
<h4>Test Loading...</h4>
}
else
{ <Editform>.....</EditForm>

c# fail to get element in content page with getelementbyid, getelementsbytagname

I have posted the same question but I post it again since I haven't got any answers to that post yet.
I am trying to get some information (such as tagName, id using GetElementsByTagName method or GetElementById method) from a content page in a website using winforms.
as you see the pictures attached, no matter which selection you make (select1, select2, select3 etc) web address stays same. however, contents under those selections are different in content page.
I am trying to access to a tagName(or id) from one of them(not selections but contents under a specific selection).
I have debugged and figured out(or seems like) I can not access to tagName(or id) from any of those contents under a specific selection.
It seems like I can only access tagName(or id) from main page. picture 3 will help better explanation of some terms such as main page, content page.
I tried to explain in detail, if my question seems still not clear, let me know plz.
My code looks like this.
var countGetFile = webBrowser1.Document.GetElementsByTagName("IFRAME");
foreach (HtmlElement l in countGetFile)
{
if (l.GetAttribute("width").Equals("100%"))
{
MessageBox.Show(l.GetAttribute("height").ToString());
MessageBox.Show(l.GetAttribute("outerText").ToString());
}
}
I was not able to grab information under 2 down level of #document from html.
html looks something like
...
<src="..." id="A" ... >
#document
...
<src="..." id="B" ... >
#document
...
<span="C" ...>
...
I could grab span information (third curly brackets) with codes looking like
HtmlWindow frame1 = webBrowser1.Document.GetElementById("A").Document.Window.Frames["A"];
HtmlWindow frame2 = frame1.Document.GetElementById("B").Document.Window.Frames["B"];
foreach (HtmlElement elm in frame2.Document.All)
{
if (elm.GetAttribute("tagName").Equals("C"))
{
// your command
}
}
to use Document.Window.Frames you need a header using "System.Collections";
btw, there is a problem. When I try to access to the information in third curly bracket, I need to do some kinds of work between frame1 and frame2 such as delaying for frame2 to have enough time to be able to access to next level after frame1.
I figured a kind of hack to get it through. Place a messagebox to pop up for short time delay, or place a delay function( not freeze ) with async code looking like,
async Task PutTaskDelay()
{
await Task.Delay(5000);//5 secs
}
I just found a temporary solution for accessing to second level. I will appreciate anyone who knows some ways to solve this problem.

Why might my SELECT control change selectedIndex not change sometimes?

Background: I am running a process nightly that reads a database and then writes the results into another system. The target system does not have an interface other than HTML Web Service with a UI. I originally set up this system a few years ago and it was really reliable when running in IE 9. However, the host that I have to run this process on has changed from Windows 2008 R2 to 2012 R2 and the version of IE has changed to IE 11 and it mostly works, but in infuriatingly SOME cases, it does NOT work.
I am manipulating a web page with a dropdown SELECT with either "Off" (value=0) or "On" (value=1) and the name of the dropdown is variable, as there are multiple identical dropdowns, which I find and then set individually.
I have written some code to find the SELECT and to set the value, but in SOME cases, it works like a charm and in others, it just does NOT set the value, even though I have stepped through the code and watched IE with the page, which does not set the value. The code is here:
bool bDone = false;
mshtml.IHTMLElementCollection objEventCollection = (mshtml.IHTMLElementCollection)objDocument.getElementsByTagName("select");
for (int i = 0; i < objEventCollection.length; i++)
{
mshtml.IHTMLElement objElement = (mshtml.IHTMLElement)objEventCollection.item(i, 0);
if (objElement.getAttribute("name").EndsWith("NewEvent"))
{
objElement.click();
mshtml.HTMLSelectElement objEvent = (mshtml.HTMLSelectElement)objElement;
switch (sEventType)
{
case "Off":
objEvent.selectedIndex = 0; // This SOMETIMES works and SOMETIMES will error out!
bDone = true;
break;
case "On":
objEvent.selectedIndex = 1; // This SOMETIMES works and SOMETIMES will error out!
bDone = true;
break;
}
}
if (bDone)
{
break;
}
}
bOK = bDone;
The relevant page code looks like this:
<td valign="middle" align="center"><input class="data" type="hidden" name="No1EventString" value="0"><input class="data" type="hidden" name="No1OriginalEvent" value="0"><select class="data" name="No1NewEvent">
<option value="0" selected="">Off</option>
<option value="1">On</option>
</select></td>
I don't know why SOMETIMES, the value of the NewEvent dropdown is changing, but not every time.
When I run this in debug, it runs through quite happily, but then, sometimes, I get the following error:
Does anyone know of a more reliable method for setting this, if I can't fix it?
Alternatively, are there any workarounds, such as setting the focus to the SELECT and then pressing the down button (but I don't know how to do this)?
Well, I got to learn something during my lunch:
It seems that IE 11 SOMETIMES rejects the IHTMLElement.selectedIndex = x lines, but when I changed the lines to IHTMLElement.value = x instead, it was reliable!
When did that change?

error while updating a database in ASP.NET

I am having trouble updating an SQL database, the problem is not that it doesn't update at all, but that particular parameters are being updated while the others are not.
here is the code for updating the parameters:
string EditRequest = "UPDATE Requests SET Description = #Desc, BJustif = #Justif, Priority = #Priority, Requested_System = #Requested, Request_Status = #Stat WHERE";
EditRequest += " Req_ID=#ID";
SqlConnection Submit_conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["DBConn"].ConnectionString);
SqlCommand Submit_comm = new SqlCommand(EditRequest, Submit_conn);
Submit_comm.Parameters.AddWithValue("#ID", Request.QueryString["reqid"]);
Submit_comm.Parameters.AddWithValue("#Desc", DescBox.Text);
Submit_comm.Parameters.AddWithValue("#Justif", JustifBox.Text);
Submit_comm.Parameters.AddWithValue("#Priority", PriorityList.SelectedValue);
Submit_comm.Parameters.AddWithValue("#Requested", RelatedBox.Text);
Submit_comm.Parameters.AddWithValue("#Stat", 1);
Submit_conn.Open();
Submit_comm.ExecuteNonQuery();
Submit_comm.Dispose();
Submit_comm = null;
Submit_conn.Close();
get_Description();
Page.ClientScript.RegisterStartupScript(this.GetType(), "Refresh", "ReloadPage();", true);
this function is called by a button on a pop-up form which shows the parameters content that is being changed in a text box which is also used to submit the changes back to the database, but when I press submit, the parameters which are displayed on the form don't change, I can't find any problem wit the code, even though I've compared it to similar code which is working fine.
In case you need to, here is one of the text boxes I'm using to display and edit the content:
<asp:TextBox ID="JustifBox" TextMode="MultiLine" runat="server" Width="250" Height="50"></asp:TextBox>
What exactly is wrong with the code?
EDIT: I forgot to mention that when I traced the function, it appeared that the controls' content did not change when I submitted them, but were resubmitted as if they were unchanged in their original form.
You mentioned two problems here:
1) Fields in the database are not updated when the UPDATE is performed
2) The UI is not updated with the latest data
First tackle the SQL UPDATE query. What fields are not being updated? Copy paste the T-SQL query in the query analyzer and then check which field is being updated and which is NOT. Also, your code is OPEN to SQL injections so read about that and then adjust the code.
For the UI not being updated you need to see whether you are even populating the UI fields with the correct object.

Why doesn't this JavaScript display a confirm box?

I am trying to fix some bugs in a product I inherited, and I have this snippet of javascript that is supposed to hilight a couple of boxes and pop up a confirm box. What currently happens is I see the boxes change color and there is a 5 or so second delay, then it's as if the missing confirm just accepts itself. Does anyone smarter than I see anything amiss in this code?
function lastCheckInv() {
document.getElementById("ctl00$ContentPlaceHolderMain$INDet$txtInvNumber").style.background = "yellow";
document.getElementById("ctl00$ContentPlaceHolderMain$INDet$txtInvNumber").focus();
document.getElementById("ctl00_ContentPlaceHolderMain_INDet_AddCharges").style.background = "yellow";
document.getElementById("ctl00_ContentPlaceHolderMain_INDet_lblFreight").style.background = "yellow";
bRetVal = confirm("Are you sure the information associated with this invoice is correct?");
return bRetVal;
}
The only thing I can think of is if one of the lines before the confirm is throwing an exception and you're never actually getting to the confirm.
If you're using IE, make sure script debugging is enabled. If you're using Firefox, install the Firebug add-on and enable it for your website.
Or, for very primitive debugging, just put alerts after each statement and figure out where it's bombing.
You should use the following method to reference your controls from JavaScript:
document.getElementById(<%= txtInvNumber.ClientID %>).style.background = "yellow"
If that doesn't help, try setting a breakpoint in your JavaScript and stepping through it to see where it's failing.
This test script ran fine for me in IE, Firefox, and Opera. So there doesn't seem to be anything wrong with your basic syntax. The problem is either in the ID's (which doesn't fit with the fact that it acts as if confirmed after 5 seconds) or in some other conflicting JavaScript on the page. It will be difficult to help you without seeing more of the page.
<script language="javascript">
function lastCheckInv() {
document.getElementById("test1").style.background = "yellow";
document.getElementById("test1").focus();
document.getElementById("test2").style.background = "yellow";
document.getElementById("test3").style.background = "yellow";
bRetVal = confirm("Are you sure?");
return bRetVal;
}
</script>
<form method="get" onsubmit="return lastCheckInv();">
<input id="test1" name="test1" value="Hello">
<input id="test2" name="test2" value="Hi">
<input id="test3" name="test3" value="Bye">
<input type="submit" name="Save" value="Save">
</form>
A few thoughts: Could be the .focus() call is hiding your confirm behind the page? Or could it be that one of your control id's is not correct causing, the .style.background references to fail?
You should set the focus after showing the confirm box, otherwise the confirm box will grab focus away, making that line meaningless.
Don't hard-code ASP.Net id's like that. While they typically are consistent, a future version of ASP.net won't guarantee the same scheme, meaning your setting yourself up for pain when it comes time to update this code at some point in the future. Use the server-side .ClientID property for the controls to write those values into the javascript somewhere as variables that you can reference.
Update:
Based on your comment to another response, this code will result in a postback if the function returns true. In that case, there's not point in running the .focus() line at all unless you are going to return false.
I do not like accesing objects directly by
document.getElementById("ctl00_ContentPlaceHolderMain_INDet_lblFreight").style.background = "yellow";
If the object is not returned JavaScript will error out. I prefer the method of
var obj = document.getElementById("ctl00_ContentPlaceHolderMain_INDet_lblFreight");
if(obj)
{
obj.style.background = "yellow";
}
My guess is you are trying to access an object that is not on the DOM, so it never gets to the confirm call.
It might be worth checking that the elements actually exist. Also,try delaying the focus until after the confirm():
function lastCheckInv() {
var myObjs,bRetVal;
myObjs=[
"ctl00_ContentPlaceHolderMain_INDet_AddCharges",
"ctl00_ContentPlaceHolderMain_INDet_lblFreight",
"ctl00$ContentPlaceHolderMain$INDet$txtInvNumber"
];
bRetVal = confirm("Are you sure the information associated with this invoice is correct?");
for (var i=0, j=myObjs.length, myElement; i<j; i++){
myElement=document.getElementById(myObjs[i]);
if (!myElement){
// this element is missing
continue;
}
else {
// apply colour
myElement.style.background = "yellow";
// focus the last object in the array
if (i == (j-1) ){
myObj.focus();
}
}
}
return bRetVal;
}
function lastCheckInv()
{
document.getElementById("ctl00_ContentPlaceHolderMain_INDet_txtInvNumber").style.background = "yellow";
document.getElementById("ctl00_ContentPlaceHolderMain_INDet_txtInvNumber").focus();
document.getElementById("ctl00_ContentPlaceHolderMain_INDet_AddCharges").style.background = "yellow";
document.getElementById("ctl00_ContentPlaceHolderMain_INDet_lblFreight").style.background = "yellow";
return confirm("Are you sure the information associated with this invoice is correct?");
}
The first two lines in your function are wrong, $ are in the UniqueID of an ASP.Net Control.
On Clientside you have to use the ClientID, replace $ with _ .
If you are sure that the Controls exists, the
code above might work.
Is bRetVal actually declared anywhere?
If not, "var bRetVal = confirm...." is a friendly way of telling jscript that it is a variable.

Categories