ASP.NET updatepanel + invalid postback - asp.net

I have the following very simple form:
<asp:UpdatePanel ID="ClaimRewardsForm" runat="server">
<ContentTemplate>
<span class="largeBold">Select jacket weight:</span><br />
<asp:RadioButtonList runat="server" ID="JacketWeight">
<asp:ListItem Value="Lightweight" Text="Lightweight (fleece)" />
<asp:ListItem value="Heavyweight" Text="Heavyweight (cotton)" />
</asp:RadioButtonList>
<br />
<span class="largeBold">Select size:</span><br />
(Men's sizes only)<br />
<asp:DropDownList ID="JacketSize" runat="server">
<asp:ListItem Value="Small" Text="Small" />
<asp:ListItem Value="Medium" Text="Medium" />
<asp:ListItem Value="Large" Text="Large" />
</asp:DropDownList><br />
<br />
<asp:ImageButton ID="SubmitButton" runat="server" ImageUrl = "~/Content/Images/submitButton.png" onclick="SubmitButton_Click" />
</ContentTemplate>
</asp:UpdatePanel>
In my button's click handler, I have:
protected void SubmitButton_Click(object sender, EventArgs e)
{
if (IsValid)
{
using (var work = UnitOfWorkFactory.Create())
{
var id = new Guid(Session["id"].ToString());
var account = UserAccounts.Get(id);
if (account == null)
throw new Exception("Invalid user account id.");
account.RewardInfo.Clear();
account.RewardInfo.Add(new RewardInfo()
{
UserAccount = account,
JacketWeight = JacketWeight.SelectedValue,
JacketSize = JacketSize.SelectedValue
});
work.Commit();
}
//ClaimRewardsForm.Update();
//ScriptManager.RegisterStartupScript(this, GetType(),
// "confirmation", "ClaimRewards.showConfirmation();", true);
}
}
I'm not modifying the form fields in any way whatsoever, but I'm still getting the following error:
505|error|500|Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.|
Since I'm not modifying teh controls at all during the post back, I cannot for the life of me figure out why it's acting as if I had. Any thoughts?

This guy here is your culprit. You'll have to figure out what you are posting to cause it to block the request or disable EventValidation if you understand the security risks.
I don't see anything in your posted code but <> in option values messes with it for sure.

Stupid me. I'm using a DropDownList adapter to allow for optiongroup elements within my list but that was causing an invalid postback because it modifies the elements in the list behind the scenes without registering the modified values for event validation. I modified the adapter to perform the registration and it works fine now.

Related

Load another web page based on value of drop down list in asp.net

I am trying to redirect to another web page when the user selects the drop down list and the user should be redirected to another web page as soon as the user clicks the submit button.This is my code for drop down list and button.On clicking the "click to proceed" button the user should be taken to next web page depending on list selection.
Iam new to .Net Please help thanks in advance !!
<asp:DropDownList ID="DropDownList1" runat="server"
onselectedindexchanged="DropDownList1_SelectedIndexChanged">
<asp:ListItem Value="-1">Select User</asp:ListItem>
<asp:ListItem Value="staff">Staff</asp:ListItem>
<asp:ListItem Value="student">Student</asp:ListItem>
</asp:DropDownList>
<br />
<br />
<br />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click"
Text="Click to Proceed" />
In your Button1_Click event, use the Response.Redirect method to send people to the appropriate page.
http://msdn.microsoft.com/en-us/library/a8wa7sdt%28v=vs.110%29.aspx
Following can be helpful for you.
protected void Button1_Click(object sender, EventArgs e)
{
string sel_val = DropDownList1.SelectedValue; // use sel_val to apply if, else logic to redirect to
// some possible examples
if (sel_val != "-1") // as SelectedValue is string
{
// assuming there is staff.aspx, and you want to redirect to that page on selecting staff, this is just an example
Response.Redirect(sel_val + ".aspx"); // use this to redirect to required page
}
}
Also change aspx code like this.Note i have changed OnClick from onclick.
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click"
Text="Click to Proceed" />

asp:ListBox SelectedValue not setting (dynamically or when clicked)

I have an asp:ListBox that is populated dynamically from js based on the selected value of another asp:List box. The problem is that the second list box always returns a SelectedValue of "" regardless of whether i set lstBox.selectedIndex = 0 or actually select an item in the list.
.js to add to list then set default selected item
var Option = document.createElement("option");
lstId = document.getElementById(lstId);
Option.text = lstItem;
lstId.add(Option);
lstId.selectedIndex = 0;
.vb to get selected value
Dim selSchedule As String = lstCRMSched.SelectedValue
Now as this list is populated by javascript i had to set my #page EnableEventValidation = "false" otherwise the postback that came later would fail.
Side note: I'm noticing that asp.net doesn't like it when you use hidden divs as overlays that are unhidden based on menu selections as everything it does requires a postback, which wipes out the state of the other divs. Should i just have 10 .aspx files one for each div and just switch locations from the codebehind using sessions to transfer things like selected values and data that is to be shown in another div?
You can access the SelectedValue of the drop down list through the Request object since every element in the form that has a name is submitted in the request.
You simply need to do this:
Dim selSchedule As String = Request[lstCRMSched.UniqueID]
Now, this will work just because you disabled EventValidation on the page. The error you were getting is completely normal. ASP.NET is just making sure that no one sends data that wasn't rendered by the server initially to prevent attacks. If you were to keep the EventValidation enabled on the page, you'd need to register the list for Validation via ClientScriptManager.RegisterForEventValidation
If you add items to the dropdownlist on the client these items are not persisted on the server!
But you may try saving dynamically added items (text-value-pairs) within some hidden input fields and parse them out on the server. See this link for a working example. For your example you will also have to save your selectedIndex within another hidden field to be able to access it on the server.
EDIT
demo.aspx
<script type="text/javascript">
function saveValue() {
var hiddenField1 = document.getElementById("hiddenField1");
hiddenField1.value = "hello world";
}
</script>
<form id="Form1" method="post" runat="server">
<input type="hidden" id="hiddenField1" name="hiddenField1" value="" />
<asp:Button ID="btnPostBack" runat="server" Text="PostBack"
OnClientClick="saveValue()" onclick="btnPostBack_Click" />
</form>
demo.aspx.cs
protected void btnPostBack_Click(object sender, EventArgs e)
{
Debug.WriteLine("Value of hiddenField1: " + Request["hiddenField1"]);
Debugger.Break();
}
This one worked for me. I got "hello world" on the server.
EDIT 2
Icarus pointed out that you can always access any submitted element to the server by referring to the Request object and of course he is absolutelly right! According to your question I thought you'd like to have access to all dynamically created items - and that is - with solution shown below - not possible.
aspxPage
<script type="text/javascript">
function saveToList() {
var ListBox1 = document.getElementById("ListBox1");
var ListBox2 = document.getElementById("ListBox2");
var Option = document.createElement("option");
Option.text = ListBox1.options[ListBox1.selectedIndex].text;
ListBox2.add(Option);
ListBox2.selectedIndex = 0;
}
</script>
<form id="Form1" method="post" runat="server">
<asp:ListBox ID="ListBox1" runat="server">
<asp:ListItem Text="entry1" Value="1" />
<asp:ListItem Text="entry2" Value="2" />
<asp:ListItem Text="entry3" Value="3" />
<asp:ListItem Text="entry4" Value="4" />
</asp:ListBox>
<asp:ListBox ID="ListBox2" runat="server" Width="100"></asp:ListBox>
<input id="Button1" type="button" value="Save to List" onclick="saveToList()" />
<asp:Button ID="btnPostBack" runat="server" Text="PostBack" OnClick="btnPostBack_Click" />
codeBehind
protected void btnPostBack_Click(object sender, EventArgs e)
{
Debug.WriteLine("SelectedValue of ListBox2: " + Request["ListBox2"]);
// no access to all other clientSide created items in ListBox2
Debugger.Break();
}

ASP .net validation techniques

I worked in ASP.net MVC for the past 1.5 years. Where I used enterprise application block for server side validation. I loved the way that viewmodels bind to the view's controls and validation working in that way. But now I am working in a project which is purely webforms without MVC.
Here jQuery is used for client side validation and there is no server side validation at all. I was stressing the importance of server side validation and was planning to use enterprise library for the same.
For some reasons(may be due to the fact I worked in ASP.NET MVC recently) I am getting stuck up at a point.
In my webforms application will my validations necessarily contain the same logic for both client side and server side. Or in general what are the best practices for coding validations in ASP .net web forms?
I wanted to follow the widely accepted practise. Also are there any new concepts in for webforms validation which are better than enterprise library. samples should help me understand.
I think you'd want to validate more rather than less...server-side checks in addition to client-side checks are a good idea (especially for an externally facing application). You want to be especially careful with textboxes. Remember users can shut off scripts (and totally circumvent your client-side scripts).
It's easy enough to implement server-side validation with Custom Validator controls that fire the ServerValidate event.
I haven't worked with the enterprise library, so I can't answer anything about the validation routines it provides.
You can use CustomValidators for anything, they are my favorite!
If you use HTML5 attributes like required="required" you get client side feedback for free.
You can utilize them also to perform server side validation like so:
<asp:ValidationSummary runat="server" id="vSummary" />
<asp:TextBox runat="server" id="txtReq" required="required" />
<asp:DropDownList runat="server" id="ddlReq" required="required">
<asp:ListItem text="..." value="" />
<asp:ListItem text="Yes" value="1" />
<asp:ListItem text="No" value="0" />
</asp:DropDownList>
<asp:Button runat="server" id="cmdSubmit" text="Submit" />
Code Behind Functions:
private void buildRequiredWebControls(List<WebControl> lst, Control c)
{
if (c is WebControl)
if (String.Compare((c as WebControl).Attributes["required"] ?? String.Empty, "required", true) == 0)
lst.Add((c as WebControl));
foreach (Control ch in c.Controls)
buildRequiredWebControls(lst, ch);
}
/* --------------------------------------------- */
private Boolean addAllFieldsRequired(List<WebControl> controls)
{
foreach (WebControl w in controls)
{
if (w as TextBox != null)
if (String.IsNullOrWhiteSpace((w as TextBox).Text)) return false;
if (w as DropDownList != null)
if (String.IsNullOrWhiteSpace((w as DropDownList).SelectedValue)) return false;
}
return true;
}
/* --------------------------------------------- */
private void cmdSubmit_Click(object sender, EventArgs e)
{
vSummary.ValidationGroup = "StackOverflow";
Page.Validate("StackOverflow");
List<WebControl> requiredFields = new List<WebControl>();
this.buildRequiredWebControls(requiredFields, this);
Page.Validators.Add(new CustomValidator()
{
IsValid = this.addAllFieldsRequired(requiredFields),
ErrorMessage = "Please complete all required fields.",
ValidationGroup = "StackOverflow"
});
if (Page.IsValid)
{
//Good to Go on Required Fields
}
}
Beats the very monotonous alternative, which is to manually insert them into the html after every control:
<asp:ValidationSummary runat="server" id="vSummary" ValidationGroup="StackOverflow" />
<asp:TextBox runat="server" id="txtReq" required="required" />
<asp:RequiredFieldValidator runat="server" ControlToValidate="txtReq" ErrorMessage="Please Fill Out Required Field" Text="*" ValidationGroup="StackOverflow" />
<asp:DropDownList runat="server" id="ddlReq" required="required">
<asp:ListItem text="..." value="" />
<asp:ListItem text="Yes" value="1" />
<asp:ListItem text="No" value="0" />
</asp:DropDownList>
<asp:RequiredFieldValidator runat="server" ControlToValidate="ddlReq" ErrorMessage="Please Fill Out Required Field" Text="*" ValidationGroup="StackOverflow" />
<asp:Button runat="server" id="cmdSubmit" text="Submit" />

Getting control that fired postback in page_init

I have a gridview that includes dynamically created dropdownlist. When changing the dropdown values and doing a mass update on the grid (btnUpdate.click), I have to create the controls in the page init so they will be available to the viewstate. However, I have several other buttons that also cause a postback and I don't want to create the controls in the page init, but rather later in the button click events.
How can I tell which control fired the postback while in page_init? __EVENTTARGET = "" and request.params("btnUpdate") is nothing
It is possible to determine which control caused a PostBack by looking at Request.Form["__EVENTTARGET"]. The problem with this is that button ids will not show unless you set their UseSubmitBehavior to false. Here's an example:
.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
switch (Request.Form["__EVENTTARGET"].ToString())
{
case "ddlOne":
break;
case "btnOne":
break;
case "btnTwo":
break;
}
}
}
.aspx
<form id="form1" runat="server">
<asp:DropDownList ID="ddlOne" AutoPostBack="true" runat="server">
<asp:ListItem Text="One" Value="One" />
<asp:ListItem Text="Two" Value="Two" />
</asp:DropDownList>
<asp:Button ID="btnOne" Text="One" UseSubmitBehavior="false" runat="server" />
<asp:Button ID="btnTwo" Text="Two" UseSubmitBehavior="false" runat="server" />
</form>

OnClick vs OnClientClick for an asp:CheckBox?

Does anyone know why a client-side javascript handler for asp:CheckBox needs to be an OnClick="" attribute rather than an OnClientClick="" attribute, as for asp:Button?
For example, this works:
<asp:CheckBox runat="server" OnClick="alert(this.checked);" />
and this doesn't (no error):
<asp:CheckBox runat="server" OnClientClick="alert(this.checked);" />
but this works:
<asp:Button runat="server" OnClientClick="alert('Hi');" />
and this doesn't (compile time error):
<asp:Button runat="server" OnClick="alert('hi');" />
(I know what Button.OnClick is for; I'm wondering why CheckBox doesn't work the same way...)
That is very weird. I checked the CheckBox documentation page which reads
<asp:CheckBox id="CheckBox1"
AutoPostBack="True|False"
Text="Label"
TextAlign="Right|Left"
Checked="True|False"
OnCheckedChanged="OnCheckedChangedMethod"
runat="server"/>
As you can see, there is no OnClick or OnClientClick attributes defined.
Keeping this in mind, I think this is what is happening.
When you do this,
<asp:CheckBox runat="server" OnClick="alert(this.checked);" />
ASP.NET doesn't modify the OnClick attribute and renders it as is on the browser. It would be rendered as:
<input type="checkbox" OnClick="alert(this.checked);" />
Obviously, a browser can understand 'OnClick' and puts an alert.
And in this scenario
<asp:CheckBox runat="server" OnClientClick="alert(this.checked);" />
Again, ASP.NET won't change the OnClientClick attribute and will render it as
<input type="checkbox" OnClientClick="alert(this.checked);" />
As browser won't understand OnClientClick nothing will happen. It also won't raise any error as it is just another attribute.
You can confirm above by looking at the rendered HTML.
And yes, this is not intuitive at all.
Because they are two different kinds of controls...
You see, your web browser doesn't know about server side programming. it only knows about it's own DOM and the event models that it uses... And for click events of objects rendered to it. You should examine the final markup that is actually sent to the browser from ASP.Net to see the differences your self.
<asp:CheckBox runat="server" OnClick="alert(this.checked);" />
renders to
<input type="check" OnClick="alert(this.checked);" />
and
<asp:CheckBox runat="server" OnClientClick="alert(this.checked);" />
renders to
<input type="check" OnClientClick="alert(this.checked);" />
Now, as near as i can recall, there are no browsers anywhere that support the "OnClientClick" event in their DOM...
When in doubt, always view the source of the output as it is sent to the browser... there's a whole world of debug information that you can see.
You are right this is inconsistent. What is happening is that CheckBox doesn't HAVE an server-side OnClick event, so your markup gets rendered to the browser. http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.checkbox_events.aspx
Whereas Button does have a OnClick - so ASP.NET expects a reference to an event in your OnClick markup.
For those of you who got here looking for the server-side OnClick handler it is OnCheckedChanged
I was cleaning up warnings and messages and see that VS does warn about it:
Validation (ASP.Net): Attribute 'OnClick' is not a valid attribute of element 'CheckBox'. Use the html input control to specify a client side handler and then you won't get the extra span tag and the two elements.
Asp.net CheckBox is not support method OnClientClick.
If you want to add some javascript event to asp:CheckBox you have to add related attributes on "Pre_Render" or on "Page_Load" events in server code:
C#:
private void Page_Load(object sender, EventArgs e)
{
SomeCheckBoxId.Attributes["onclick"] = "MyJavaScriptMethod(this);";
}
Note: Ensure you don't set AutoEventWireup="false" in page header.
VB:
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
SomeCheckBoxId.Attributes("onclick") = "MyJavaScriptMethod(this);"
End Sub
You can do the tag like this:
<asp:CheckBox runat="server" ID="ckRouteNow" Text="Send Now" OnClick="checkchanged(this)" />
The .checked property in the called JavaScript will be correct...the current state of the checkbox:
function checkchanged(obj) {
alert(obj.checked)
}
You can assign function to all checkboxes then ask for confirmation inside of it. If they choose yes, checkbox is allowed to be changed if no it remains unchanged.
In my case I am also using ASP .Net checkbox inside a repeater (or grid) with Autopostback="True" attribute, so on server side I need to compare the value submitted vs what's currently in db in order to know what confirmation value they chose and update db only if it was "yes".
$(document).ready(function () {
$('input[type=checkbox]').click(function(){
var areYouSure = confirm('Are you sure you want make this change?');
if (areYouSure) {
$(this).prop('checked', this.checked);
} else {
$(this).prop('checked', !this.checked);
}
});
});
<asp:CheckBox ID="chk" AutoPostBack="true" onCheckedChanged="chk_SelectedIndexChanged" runat="server" Checked='<%#Eval("FinancialAid") %>' />
protected void chk_SelectedIndexChanged(Object sender, EventArgs e)
{
using (myDataContext db = new myDataDataContext())
{
CheckBox chk = (CheckBox)sender;
RepeaterItem row = (RepeaterItem) chk.NamingContainer;
var studentID = ((Label) row.FindControl("lblID")).Text;
var z = (from b in db.StudentApplicants
where b.StudentID == studentID
select b).FirstOrDefault();
if(chk != null && chk.Checked != z.FinancialAid){
z.FinancialAid = chk.Checked;
z.ModifiedDate = DateTime.Now;
db.SubmitChanges();
BindGrid();
}
gvData.DataBind();
}
}
One solution is with JQuery:
$(document).ready(
function () {
$('#mycheckboxId').click(function () {
// here the action or function to call
});
}
);

Resources