Postback of controls which have been modified in javascript

M

mc

I'm writing an app for managing Task Lists, I'm trying to add some
controls to a form that I can use to link tasks, my original intention
was to: -

Add two list boxes, one listing "all Tasks" and the other listing
"Linked Tasks", I have two buttons which in javascript move items from
the first list into the second.

Then when a user clicks a thrid button I would like to save this data.

however, the first problem was that the Event Validator threw a wobly
and rejected my postback.

I turned off EventValidation for the page.

I then noticed that the control state was the same as it was when I
loaded the form. even though I changed the contents of the ListBox?

Hope this makes sense, it's been a long day!

TIA


MC
 
L

LiveCycle

I've done similar things before, and it requires a little bit of process.
First, create a hidden control (<input type="hidden" name="MyHiddenItem" />
(make sure you give it a name attribute)) to store the values that are in
your Linked Tasks listbox. Then, on your form submit event, store the
values from the Linked Tasks listbox as a comma-delimited list in the hidden
control. Finally, server-side, check the Request.Form collection for the
Value of your Linked Tasks listbox. This should give you what you want.

Don't get wobbly, now! :)
Jim
 
S

Steven Cheng[MSFT]

Thanks for Jim's informative input.

Hi MC,

For the two issues you mentioned, they're due to the following things:

1. The ASP.NET Webcontrol's state is stored in ViewState by default and it
is a compressed and encoded format which can not be modified at
client-side. Thus, any change to the webcontrol's state(except those
property that will be postback every time such as TextBox's Text or List's
selectedItem) at client-side will not be automatically post to server-side.

2. For the EventValidation problem, this is due to the new event validation
in ASP.NET 2.0(by default enabled), it will ensure that all the postback on
the page are raised by the built-in postback script generated by the page
or any webcontrol rather than other custom code(directly injected scripts).
For example, if you use Response.Write to output some postback scripts,
it will violate the event validation.

For the two issues, you can consider the following means to work them out:

1) As Jim suggested, you can use an html input hidden field(<input
type="hidden" .../>) in the page and at client-side, whenever the
dropdownlist has been changed(add or remove items), you update the hidden
field so as to persist the changes. After the page postback, you can check
the hidden field's value and synchorize the status into DropDownlist's
server control instance.

2) If disable EventValidation is doable, you can just turn off it on this
page. Else, since EventValidation just ensure the postback is really raised
from the control self, you can use script to invoke a certain control's
postback event. e.g.

We can use script to trigger a button's click event at client-side:

document.getElementById("Button1").click();


How do you think? If you have any other consideration or ideas, please feel
free to post here.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

mc

Ok, I get the first solution with the hidden field, I've implemented it
ok and my code works a treat.

Maybe it's too late in the evening but I'm having a little difficulty
working out the EventValidiation stuff.

I'd rather not have to disable event validation for the whole page.

could you explain a little more about what would i need to to to stop
the eventValidation error occurring (without turning off event validation)?

I've wrapped my module is a web control as it will be used elsewhere, in
my app, will this help or hinder the problem?

TIA

mc
 
S

Steven Cheng[MSFT]

Hello MC,

Thanks for your reply.

As for the EventValidation problem, here is my understanding:

First, the "EventValidation" feature in ASP.NET 2.0 will perform the
following check when a page is postback(if EnableEventValidation is
enabled):

1. It will ensure that any data in the Request.Form collection(the data
post through html input elements....) are originated from existing web
controls on the page. For example, if you dynamically use server-side or
client-side code to output the a following html input element

"<input type='text' name='xxx'...../>",

then, when postback, since this input field is not originally in the page's
control collection, it will report Event Validation error.

2. It will ensure that a postback event (such as Button Click) is really
triggered by the corresponding html element (rendered by the server-side
control). That means, if we use our own script to call "__doPostback"
fundtion to simulate another button's click event, it will raise error at
server-side (if event validation is turn on).


for your scenario, are you calling the "__doPostback" function in your own
script to simulate another control's postback? If you're going to use own
script to trigger a button's postback event, you can consider use script to
reference the button's client element and call its "click()" method. e.g.

var btn = document.getElementbyId("btnSubmit");
btn.click();

Please feel free to post here if you have any further questions.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

mc

I think that my scenario is somewhat simpler than the one you explain.

Unfortunately I can't post the code as I do not have access to it from
this terminal.

I've written a web User control which contains two list boxes, two image
buttons and a TaskId property.

The image buttons have no event handler on the server side and are
purely used (client side) to move items between the lists. No postback
occurs when either of these buttons are clicked.

Upon loading the control I initialize it by loading all the tasks into
the first list box. I have two methods Load_Data and Save_Data.

The load data method shuffles the contents of the lists around
server-side so they match the list (for the specified TaskId) stored in
the db

The save data method uses the values stored in the hidden control to
update the list (for the specified TaskId) stored in the db.

A page that uses the control, sets the controls TaskId property and then
calls the controls Load_Data method (during the page_load event).

then upon completing the page the user clicks a button which fires an
event handler, this calls the controls Save_Data method.

The problem seems to stem from the fact that when the control is added
to the page the list boxes contain one "State" and then as a result of
the user adjusting the contents of the lists (via Java script) when the
server gets the post back the Lists boxes "State" has changed and as a
consequence I get the error "A potentially dangerous Request.Query......"


Regards


MC
 
S

Steven Cheng[MSFT]

Hello MC,

Thanks for your reply.

So you think the problem is due to the dynamically changed list
items(through client script) on the page. I've created a simple page which
contains two Listbox(<select runat="server" .../>) and use script to add
items into one of it and postback. However, it doesn't report any
validation error. Therefore, I'm wondering the problem should be specific
to how to modify the listbox and store the data to persist from client to
server. If the complete source is not available, is it convenient that you
create a simplified page which could reproduce the issue and send me this
test page?



Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Steven Cheng[MSFT]

Hello MC,

Have you got any further progress on this issue? Or if the problem remains,
is it convenient that you send me a simplified page that can repro the
problem? Also, If you feel this an urgent issue and will need a thorough
resolution, I would suggest you contact CSS for further assistance.

http://support.microsoft.com/

Please feel free to followup if there is anything we can help.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

mc

Sorry, a "higher" priority issue has kept me away from looking at this
one for the last week, I'll post some code here in the next couple of days.
 
M

mc

I was finding the bug very difficult to reproduce in something small
enough to post until I added an extra bit of Javascript. The function in
question sets the item (which has just been moved) as the selected value
in the destination list. The function is as follows: -

function selectListBoxItem(ListBox,ItemValue) {
for (var i = 0; i < ListBox.options.length; i++) {
if (ListBox.options.value == ItemValue) {
ListBox.options.selected = true;
}
else{
ListBox.options.selected = false;
}
}
}

If I run the code below, but comment out the call to the
"selectListBoxItem" function all is fine!

Full Code:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
btnJS.OnClientClick = "moveCurrentSelectedItemFromTo('" +
ListBox1.ClientID + "','" + ListBox2.ClientID + "'); return false;";
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>

<script language="javascript">
function moveCurrentSelectedItemFromTo(FromListBoxName,ToListBoxName){
FromListBox = document.getElementById(FromListBoxName);
ToListBox = document.getElementById(ToListBoxName);
if(FromListBox.selectedIndex != -1){
var selectedValue = FromListBox.options[FromListBox.selectedIndex].value;
var selectedText = FromListBox.options[FromListBox.selectedIndex].text;
addOption(ToListBox,selectedText,selectedValue);
deleteOption(FromListBox,selectedValue);
selectListBoxItem(ToListBox,selectedValue);
}
return false;
}

function addOption(selectObject,optionText,optionValue) {
var optionObject = new Option(optionText,optionValue);
var optionRank = selectObject.options.length;
selectObject.options[optionRank]=optionObject;
}

function deleteOption(selectObject,optionValue) {
var rowToDelete = -1;
for (var i = 0; i < selectObject.options.length; i++) {
if (selectObject.options.value == optionValue) {
rowToDelete = i;
}
}
selectObject.options[rowToDelete] = null;
}

function selectListBoxItem(ListBox,ItemValue) {
for (var i = 0; i < ListBox.options.length; i++) {
if (ListBox.options.value == ItemValue) {
ListBox.options.selected = true;
}
else{
ListBox.options.selected = false;
}
}
}
</script>

<body>
<form id="form1" runat="server">
<div>
<asp:ListBox ID="ListBox1" runat="server">
<asp:ListItem Value="A" Text="A" />
<asp:ListItem Value="B" Text="B" />
<asp:ListItem Value="C" Text="C" />
</asp:ListBox>
<asp:Button ID="btnJS" runat="server" Text="->" />
<asp:ListBox ID="ListBox2" runat="server"></asp:ListBox>

<asp:Button ID="btnPost" runat="server" Text="Post" />
</div>
</form>
</body>
</html>
 
S

Steven Cheng[MSFT]

Thanks for your followup MC,

Well, after the further information you posted, I can confirmed that this
is a typical "eventvaliation" violation issue. the script function you
provided violate the following rule I mentioned in the previous message:

==========================
1. It will ensure that any data in the Request.Form collection(the data
post through html input elements....) are originated from existing web
controls on the page. For example, if you dynamically use server-side or
client-side code to output the a following html input element

"<input type='text' name='xxx'...../>",

then, when postback, since this input field is not originally in the page's
control collection, it will report Event Validation error.
==========================


here, you have two listbox, list1 and list2, suppose list1 originally
contains A1,B1,C1 items, list2 originaly contains X1. At cilent-side, if
you use script function to move B1, C1 to list2 and make B1(MOVED from
list1) as selected in list2, then when the page postback, since the "B1" is
in list2's postback data(in Request.Form collection), the ASP.NET page
detect that "B1" is not expected to be in list2's postback data, and throw
out exception.

Therefore, for your scenario, if the moved item will be selected in the new
target list, you have to turn off "EventValidation" so as to ensure the
postback work.


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

mc

Ah yes!!!

It has all become very clear, it isn't the fact that the list boxes
contain different list items it is that the current Selected Value was
not in the list sent to the browser.

I have added some extra JS to the submission button to set the
selectedIndex of each of the list boxes to -1 and now the problem
doesn't exist!

This all works fine when I've full control of the entire form, however I
have developed a control which may be used from any form, Is there any
way I can register Javascript code to run when the form is submitted?
 
M

mc

I have found a solution!

For each of the Dynamic list boxes in my control I now have a statement: -

Page.ClientScript.RegisterOnSubmitStatment(this.GetType(),"ClearListBox1","selectListBoxItem(document.getElementById('"+ListBox1.ClientId+"'),-1);\r\n");

In the tests I have run this works, does anyone have any comments?

Is there a better way?

does ClientScriptManager.RegisterForEventValidation do anything for me?


MC
 
S

Steven Cheng[MSFT]

Hello MC,

Thanks for your followup.

Yes, if you do not set the listbox selected index(if single selected) to a
item which is moved from other list, you can avoid turning off
EventValidation. For registering onsubmit script, the
Page.ClientScript.RegisterOnSubmitStatment should be the preferred one. The
ClientScriptManager.RegisterForEventValidation will not help for your
scenario, it is used for manually register event vaildation for some
certain postback event.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

mc

Sorry to reopen this topic, however now I've come to test my code in
Internet Explorer I've stumbled into a significant issue.

To date all my testing has been done in Firefox, and the code with the
"ClientScript" fix works fine, however when the page is loaded in
Internet explorer, The form submits and then just hangs.

The Page reaches a breakpoint added in Page_Init, but doesn't get as far
as Page_Load. What is happening here?

I'm Very confused!

For the time being I have turned event validation off which resloves the
issue, however I would like to understand why when I view the test page
in Firefox everything is fine and when viewed in Internet explorer (6.0
if that is significant) it just hangs.

Regards


MC
 
S

Steven Cheng[MSFT]

Hello MC,

Merry Christmas!

Regarding on the new issue you met, would you provide some detailed code
logic and implementation info about your current custom control? If it
behaves different on IE and firefox, mostly it should be caused by script
function's behavior from different browsers. Also, have you tried this from
different machines to see whether this is an machine specific issue?

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top