Devexpress grid - PerformCallback generates Invalid viewstate - asp.net

I have a DevExpress grid that needs to be refreshed every time the value in a combobox is changed. For example, I have a combobox that sets the grid's page size. One of the requirements is that the combobox does not cause a full postback.
The combobox is declared like this:
<asp:DropDownList ID="cboPages" AutoPostBack="false" runat="server"
EnableViewState="false" OnSelectedIndexChanged="cboPages_SelectedIndexChanged" />
On selected index changed, it sets a cookie whose value is the selected value. When the combobox value changes, a javascript function is called:
function PerformCallbackOnGrid(grid) {
try {
grid.PerformCallback("refresh");
}
catch(err){
alert('Could not perform callback on grid.');
}
}
The function is attached in code behind:
this.cboPages.Attributes["onChange"] = "PerformCallbackOnGrid(" + this.GridClientID + ")";
After performing these steps:
The user changes the grid page size using the combobox, so PerformCallback is called at least once.
The user presses F5(refresh).
The user tries to change the page size again.
an 'Invalid viewstate' error message appears.
I have tried setting ViewStateMode to Disabled for the grid, also EnableViewState="false".

Figgured it out by myself! Apparently it was enough to set
EnableViewState="false" EnableRowsCache="false"
to the grid.
Rows cache was the one causing the viewstate error.

Related

Make multiline textbox remember text input (auto complete)

A normal asp.net textbox will remember your old inputs - if you type something into a textbox and leave the page then come back, and type the same thing. The textbox will "auto complete" what you are typing by suggesting what you typed the last time.
I can see that if you set the Textmode property to "multiline" the textbox then loses it's auto complete. Like this:
<asp:TextBox ID="TextBox_Description" TextMode="MultiLine" MaxLength="500" runat="server"></asp:TextBox>
How do I add this funcitonality to my multiline asp Textbox or a TextArea? (multiline textboxes are rendered as textareas).
I am open to both asp.net specific solutions and javascript/jquery solutions.
You can retrieve what was in the multiline textbox and then cache it and on a postback use the cache to output what was used before.
// Get everything in the multiline text box and cache it
Cache["multilineValues"] = TextBox_Description.Text;
// Output what was written again through cache etc when the page loads after a postback.
//You would most likely put this in the Page_Load method.
if(IsPostBack)
{
if(Cache["multilineValues"] != null)
{
//Use what was written before
TextBox_Description.Text = (string)Cache["multilineValues"];
}
}

ASP.NET / UserControl, ViewState and losing Property values

this is about ASP.NET, ViewState, UserControls and losing the values of my properties. It is an classic question by know, I know, and even though I have searched here and on Google for a resolution to this problem, I havent succeeded. On the contrary, the more I test different things, the less I understand it seems.
On top of this I am using ext.net and their so called DirectMethod's but I dont think that has much to do with this problem. There are numerous questions I have and I hope that this text will be fairly readable and understandable =)
The UserControl
I have a UserControl, Customers.ascx, that contains some Properties. The "most" important is *_CustomerId*. The _CustomerId is set in code-behind, in ext.net's "DirectMethod" like this (code below from the Page Customers.aspx):
[DirectMethod]
public void SetCustomer()
{
RowSelectionModel sm = GridPanel2.SelectionModel.Primary as RowSelectionModel;
if (sm.SelectedRow != null)
{
uint customerId = uint.Parse(sm.SelectedRow.RecordID);
customer_modify._CustomerId = customerId;
}
}
The "customer_modify" is the instance of the UserControl as defined in Customers.aspx (a Page, not a UserControl):
<asp:Content ID="Content2" ContentPlaceHolderID="CPH_center" runat="server">
<CP:Customer ID="customer_modify" runat="server" _IsCreateMode="false" ViewStateMode="Enabled" />
</asp:Content>
In that Page, Customers.aspx, I have ext.net GridPanel that lists the Customers and when I click the rows in the GridPanel the (Direct)method SetCustomer is executed.
As you can see in the SetCustomer-method, the property "_CustomerId" is updated with an uint, so lets take a look at the Property in the UserControl:
public uint _CustomerId
{
get
{
object o = ViewState["_CustomerId"];
if (o == null)
return 0;
return (uint)o;
}
set
{
object o = ViewState["_CustomerId"];
ViewState["_CustomerId"] = value;
SetCustomer();
}
}
As you can see, I am using the ViewState-thingie and it was my hope that the state, ie the value of the properties would be remembered. They are not.
When I click a Row in the GridPanel the first time I can see (by breaking) that the ViewState["_CustomerId"] == null which is alright. I see thereafter that the setter for _CustomerId is executed and that the ViewState["_CustomerId"] is assigned the RecordID (uint).
I now click another Row in the GridPanel and the SetCustomer-method is executed again. I break in the setter for _CustomerId and take a look at what the ViewState["_CustomerId"] is BEFORE assigning it. It is 0, but I expect it to be the value from the previous Row clicked.
Why is it 0? What am I missing?
Also:
I actually have two of there UserControls on the Page, the other one named "customer_create":
<ext:Window
ID="Window_CreateNewCustomer"
runat="server"
Icon="New"
Title="Skapa ny kund"
Hidden="true"
Width="480"
Height="370"
Modal="true">
<Content>
<CP:Customer ID="customer_create" runat="server" Title="Skapa ny kund" _IsCreateMode="true" />
</Content>
</ext:Window>
What disturbs me a lot is that each and every time I click on a Row in the GridPanel the Page_Load in the UserControl is executed twice, even though I am only updating one of them in the SetCustomer()-method.
Why is that?
Any tips, ideas and help would be greatly appreciated.
ViewState is serialized, enciphered and sent to the client as a hidden form field so that it may be reconstituted when something triggers a form submission. A [DirectMethod] does not go through form submission (it's processed as an AJAX call), so it can neither read nor write ViewState data, unless round-tripping of this data is specifically requested with ViewStateMode.Enabled.
On any given request directed to a form, the Load event will be fired from the Page, and thus received by every user control on the page that subscribes to the event at the expected phase of the page processing lifecycle -- whether it's two instances of one UserControlor two different UserControls, it's two subscribers and therefore two calls (one to each instance).

ASP.NET CheckBox does not fire CheckedChanged event when unchecking

I have a CheckBox on an ASP.NET Content Form like so:
<asp:CheckBox runat="server" ID="chkTest" AutoPostBack="true" OnCheckedChanged="chkTest_CheckedChanged" />
In my code behind I have the following method:
protected void chkTest_CheckedChanged(object sender, EventArgs e)
{
}
When I load the page in the browser and click the CheckBox it becomes checked, the page posts back, and I can see chkTest_CheckedChanged being called.
When I then click the CheckBox again it becomes unchecked, the page posts back, however chkTest_CheckedChanged is not called.
The process is repeatable, so once the CheckBox is unchecked, checking it will fire the event.
I have View State disabled in the Web.Config, enabling View State causes this issue to disappear. What can I do to have reliable event firing while the View State remains disabled?
Update:
If I set Checked="true" on the server tag the situation becomes reversed with the event firing when un-checking the CheckBox, but not the other way around.
Update 2:
I've overridden OnLoadComplete in my page and from within there I can confirm that Request.Form["__EVENTTARGET"] is set correctly to the ID of my CheckBox.
To fire CheckedChanged event set the following properties for CheckBox, AutoPostBack property should be true and should have a default value either checked false or true.
AutoPostBack="true" Checked="false"
Implementing a custom CheckBox that stores the Checked property in ControlState rather than ViewState will probably solve that problem, even if the check box has AutoPostBack=false
Unlike ViewState, ControlState cannot be disabled and can be used to store data that is essential to the control's behavior.
I don't have a visual studio environnement right now to test, but that should looks like this:
public class MyCheckBox : CheckBox
{
private bool _checked;
public override bool Checked { get { return _checked; } set { _checked = value; } }
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//You must tell the page that you use ControlState.
Page.RegisterRequiresControlState(this);
}
protected override object SaveControlState()
{
//You save the base's control state, and add your property.
object obj = base.SaveControlState();
return new Pair (obj, _checked);
}
protected override void LoadControlState(object state)
{
if (state != null)
{
//Take the property back.
Pair p = state as Pair;
if (p != null)
{
base.LoadControlState(p.First);
_checked = (bool)p.Second;
}
else
{
base.LoadControlState(state);
}
}
}
}
more info here.
It doesn't fire because with viewstate disabled the server code does not know that the checkbox was previously checked, therefore it doesn't know the state changed. As far as asp.net knows the checkbox control was unchecked before the postback and is still unchecked. This also explains the reverse behavior you see when setting Checked="true".
I'm not sure but I guess that my solution is working only for .NET Framework 4.0:
Use ViewStateMode = "Disabled" to disable view state insted of EnableViewState="false". This will caution the same behavior except that you can save a local view state.
So, on your checkbox, set the attribute ViewStateMode = "Enabled" and the problem is solved, without implementing a custom checkbox.
It's an old post but I had to share my simple solution in order to help others who searched for this problem.
The solution is simple: Turn on AutoPostBack.
<asp:CheckBox id="checkbox1" runat="server"
AutoPostBack="True" //<<<<------
Text="checkbox"
OnCheckedChanged="knowJobCBOX_CheckedChanged"/>
I wanted to tidy things up a bit so I've just spent a bit of time testing a solution for this.
joshb is correct with his explanation for why the CheckBox behaves the way it does.
As I don't know how I got round this last year or even if I did (I can't remember what I was working on at the time to check), I've put together a simple solution/workaround.
public class CheckBox2 : CheckBox
{
protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
bool isEventTarget = postCollection["__EVENTTARGET"] == UniqueID;
bool hasChanged = base.LoadPostData(postDataKey, postCollection);
hasChanged = hasChanged || isEventTarget;
return hasChanged;
}
}
If you now register CheckBox2 in your page and use it in place of your standard CheckBoxes, you will get the CheckedChanged event fired as you expect with ViewState disabled and AutoPostBack enabled.
The way this works is allowing the normal CheckBox to do its thing with validation and change checking, but then performs an additional check to see if it was the target of the event that caused the postback. If it was the target, it returns true to tell the framework to raise the CheckedChanged event.
Edit:
Please note that this only solves the problem for AutoPostBack on the CheckBox. If the PostBack is invoked from anything else (a button, for example), the CheckedChanged event still exhibits the observed problem.
I had the same problem. I have spent a lot of time on it and finally have solved it.
In my case the Checkbox was disabled by default:
<asp:CheckBox ID="chkActive" runat="server" Enabled="false"/>
It turns ViewState isn't loaded for disabled or invisible controls.
So remove Enabled="false" or Visible="false" and it will work as expeceted. And of course ViewState shouldn't be disabled.
Additionally: Check for any errors in the JavaScript console.
I experienced the same exact issue described by OP except that it only happened in Safari (checkbox worked fine in Chrome and Firefox). Upon inspecting the JavaScript console, I found an error that was being thrown by a malformed jQuery selector.
In my case, I had $('a[id*=lbView') which was missing a closing ]. This threw an error in Safari but, surprisingly, not in Chrome nor in Firefox.
The super easy answer is to set the ViewState on for that one control.
Just add the EnableViewState="true" to the AutoPostBack="true" property in the checkbox tag.
The default value of "Checked" Property of CheckBox is false (which means Uncheck). So, when you Check/Uncheck the CheckBox it compares with Checked Property.
If it does not match with Checked Property, ASP fires OnCheckedChanged Event.
If it matches with the Checked Property it will not fire the OnCheckedChanged Event.
So, in order to make ASP to fire OnCheckedChanged event when unchecking, it has to know Original value, so that it compares with the value from user and fires the event.
By adding data-originalValue='<%# Eval("ValueFromCodeBehind") %>' property in asp:CheckBox will be able to fire the OnCheckChanged Event as ASP can now able to know its previous value. So that when we change it, ASP fires OnCheckChanged Event even if we do Uncheck.

ASP.NET DropDownList / HTML select list default selection

For my ASP.NET page, in the code behind I load various items/options into a DropDownList but I do not set a default by assigning SelectedIndex. I notice for the postback SelectedIndex is set to 0, even if I never set focus to or changed the value in the DropDownList.
If not otherwise specified in the code behind or markup, will a default value of 0 be used for the SelectedIndex in a postback with a DropDownList? If yes, is this part of the HTML standard for selection lists, or is this just the way it is implemented for ASP.NET?
This is normal behavior for the HTML SELECT control.
Unless the selected property is used, it will always start at the first item (index of 0).
In many cases, I don't want this in ASP.NET because I specifically want the user to select an option.
So what I do is add a blank item which I can then validate.
i.e.
<asp:DropDownList runat="server" DataSourceID="SomeDS" AppendDataBoundItems="true"> // Notice the last property
<asp:ListItem Text="Please select an option" Value="" />
</asp:DropDownList>
This way, I can set a validator which checks if the value is blank, forcing the user to make a selection.
For anybody looking for a way to do this from the code behind, you can add the extra list item there by using the Insert function and specifying an Index of 0, as mentioned in this SO Question. Just make sure to do so after you've called DataBind()
myDropDownList.DataSource = DataAccess.GetDropDownItems(); // Psuedo Code
myDropDownList.DataTextField = "Value";
myDropDownList.DataValueField = "Id";
myDropDownList.DataBind();
myDropDownList.Items.Insert(0, new ListItem("Please select", ""));

ASP:Checkbox how to autopostback only on checked?

I've got a checkbox that's set up as below:
<asp:CheckBox ID="myCheckbox" runat="Server" OnClick="showLoadingScreen(this.checked);" AutoPostBack="true" Text="Check me for more data!" />
The function showLoadingScreen is as below:
function showLoadingScreen(isChecked) {
if (isChecked)
{
document.getElementById('form1').style.display='none';
document.getElementById('img_loading').style.display='block';
}
else { return false; }
}
I've added the else clause in hopes that I can get it to only post back when the checkbox is checked, but it's posting back in either case.
I've got a grid on the page (inside form1) that has a set of data loaded into it on page load, but in order to add some extra data to it I've added this checkbox (its a longer running process, so I only want to load it on demand, not upfront). When it's checked I want to show the loading gif, postback, grab the data, and return. If the box gets unchecked I don't want to do anything, since leaving more than enough data on the page is perfectly fine (that is to say, the data displayed upfront is a subset of the data displayed when the checkbox is checked).
Is there any way to make it so the checkbox auto posts back on checked, but not on unchecked?
Edit: Using Dark Falcon's suggestion, I've modified the checkbox to look like:
<asp:CheckBox ID="myCheckbox" runat="Server" OnClick="return showLoadingScreen(this.checked);" AutoPostBack="true" Text="Include HQ Values" />
And the javascript to be:
function showLoadingScreen(checked) {
alert(checked);
if (checked)
{
document.getElementById('form1').style.display='none';
document.getElementById('img_loading').style.display='block';
document.form1.submit(); //my own addition, to get it to post back
}
else { return false; }
}
Now, it posts back on checked, but the box is not able to be unchecked anymore. As you can see I've added an alert to show the value being passed in. It's passing in the correct value when you uncheck the box (false), but then it somehow gets checked again.
It's not a huge issue, since there's really no reason to ever uncheck the box (since as I stated before, the dataset when checked is a superset of the unchecked dataset), but I'd still like to know why it's doing that. Any ideas?
Do not set AutoPostBack in this case. "AutoPostBack" means post back to the server any time the value of this control changes... which is NOT what you want.
Instead, use GetPostBackEventReference(myCheckbox,"") to get the appropriate postback script and call this from your showLoadingScreen method if the checkbox is checked.
For your onclick handler, you need to do:
return showLoadingScreen(this.checked);
Try to avoid using _doPostback as it is a hack which you will have to know what control ID is posting back and other parameters for that Javascript function from Microsoft ASP.NET. To understand what's happening behind the scene, you have to know why there is a postback and how to prevent the postback from happening.
Here's what's happening with an ASP.NET checkbox (ASP:Checkbox) when auto-postback is set:
<ASP:Checkbox runat="server" id="chkCheckbox" AutoPostback="true" onclick="return isDoPostback(this.checked);" ClientIdMode="static" ... />
generated HTML code is:
<input type="checkbox" ... id="..." onclick="return isDoPostback(this.checked);_doPostback(...);" .../>
The custom onclick event is appended to the beginning of the onclick event of the checkbox. No matter what you do, that prepended function call will execute. Worst off, if you have a return value, the _doPostback will never get executed.
This is what you really want to do (I use a mix of jQuery and native Javascript here):
var checkbox = $("#chkCheckbox");
...
checkbox .on("change", function(e)
{ if(this.checked)
{
var isConfirmedToContinue = confirm("Continue with Postback?");
if(!isConfirmedToContinue)
{ this.checked = false; //Uncheck the checkbox since the user canceled out
var onClickDelegate = this.onclick;
if(onClickDelegate)
{ var me = this;
this.removeEventListener("click", onClickDelegate); //Remove the onclick event so that auto-postback no longer happens
setTimeout(function()
{ //Add back the onclick delegate after 250ms
me.addEventListener("click", onClickDelegate);
}, 250);
this.onclick = null; //Remove the current onclick event by nulling it out
}
}
}
});
Try using a JS routine for checking whether it is checked, and if it is set to true, try doing:
_doPostBack(checkElementReference.name, "");
_doPostBack is responsible for performing posts to the server for controls that don't normally postback. You have to pass the name of the element, which on the server happens to be the UniqueID property for the server-side checkbox control.

Resources