Why would a regular expression not work in an ASP.net application when it is working in online regex?
I tried to implement the same code in ASP.net but it is not working properly. Can anyone figure out these problem?
Unrestricted File Upload as
The application should use a whitelist of allowed file types. This list determines the types of files that can be uploaded and rejects all files that do not match approved types.
The application should use server-side input validation to ensure evasion techniques have not been used to bypass the whitelist filter. These evasion techniques could include appending a second file type to the file name (e.g. image.jpg.php) or using trailing space or dots in the file name.
Only alphanumeric characters and Hyphen should be allowed in the filename.
<asp:RegularExpressionValidator ID="Rg_FrontPage" ValidationExpression="^(\[a-z\]|\[A-Z\]|\[0-9\]|\[-\]|\[(0-9)+\]+)+\.(jpg|JPG|JPEG|jpeg|png|PNG)$"
ControlToValidate="FUp_Front" runat="server" Font-Size="Small" ForeColor="Red"
ErrorMessage="Max size 100KB. Upload only JPEG/JPG/PNG format" ValidationGroup="Submit"
Display="Dynamic" />
An alternative: You could perform the check in the Click event where you could validate the file name (i.e. FUp_Front.FileName) or better the content type (i.e. FUp_Front.PostedFile.ContentType) of the uploaded file. See the FileUpload control tutorial and the Uploading Files (C#) documentation for further information.
To fix the regex:
You don't need to escape the brackets in your regex, e.g. (a little simplified version):
<asp:RegularExpressionValidator ID="Rg_FrontPage" ValidationExpression="^[a-zA-Z0-9.-]+(jpg|JPG|JPEG|jpeg|png|PNG)$" ViewStateIgnoresCase="true"
ControlToValidate="FUp_Front" runat="server" Font-Size="Small" ForeColor="Red"
ErrorMessage="Max size 100KB. Upload only JPEG/JPG/PNG format" ValidationGroup="Submit"
Display="Dynamic" />
See the docs for further information.
i am using javacript method in client side which is solve my problems onclientclick i do not know why regular expression is fails
<asp:ImageButton ID="btnGenerateOtp" runat="server" ImageUrl="images_new/generate_new.jpg" OnClientClick="return complainformvalidate();"ValidationGroup="Submit
" OnClick="btnGenerateOtp_Click" Visible="false" />
function complainformvalidate() {
var flg = true;
if (document.getElementById('<%=FUp_Front.ClientID %>') != null) {
var fu1 = document.getElementById('<%=FUp_Front.ClientID %>').value;
if (fu1 != '') {
if (fu1.split(".").length - 1 > 1) {
document.getElementById('lblFUp_Front').innerHTML = 'Please enter valid file';
document.getElementById('lblFUp_Front').style.color = "red";
document.getElementById('<%=CV_FUp_Front.ClientID %>').style.display = 'none';
flg = false;
}
if (fu1.split(" ").length - 1 > 0) {
//alert('Inavlid file');
document.getElementById('lblFUp_Front').innerHTML = 'Please enter valid file';
document.getElementById('lblFUp_Front').style.color = "red";
document.getElementById('<%=CV_FUp_Front.ClientID %>').style.display = 'none';
flg = false;
}
var filenameWithExtension = fu1.replace(/^.*[\\\/]/, '');
var num = filenameWithExtension;
var pattern = /(^([a-z]|[A-Z]|[0-9]|[-]|[(0-9)+]+)+\.(jpg|JPG|JPEG|jpeg|png|PNG)$)/;
if (num.search(pattern) == -1) {
document.getElementById('lblFUp_Front').innerHTML = 'Please enter valid file';
document.getElementById('lblFUp_Front').style.color = "red";
document.getElementById('<%=CV_FUp_Front.ClientID %>').style.display = 'none';
flg = false;
}
}
}
<asp:ImageButton ID="btnGenerateOtp" runat="server" ImageUrl="images_new/generate_new.jpg" OnClientClick="return complainformvalidate();"
ValidationGroup="Submit" />
}
on server side i have use custom validator which is solve my problmes
<asp:CustomValidator ID="CV_FUp_Front" runat="server" ErrorMessage="Max size 100KB. Upload only JPEG/JPG/PNG format"
ClientValidationFunction="ValidateFile" OnServerValidate="ValidateFile_FUp_Front" Display="Dynamic" ValidationGroup="Submit"
Font-Size="8pt" CssClass="error errorMsg" />
protected void ValidateFile_FUp_Front(object source, ServerValidateEventArgs args)
{
int sizeinbytes_, fileSize_;
string fileName = "";
FileInfo fi;
string ext;
//added by santosh on 25Feb2020 prevent file is accept double extension
var regex = #"(^([a-z]|[A-Z]|[0-9]|[-]|[(0-9)+]+)+\.(jpg|JPG|JPEG|jpeg|png|PNG)$)";
var match = Regex.Match(FUp_Front.FileName, regex, RegexOptions.IgnoreCase);
if (!match.Success)
{
args.IsValid = false;
CV_FUp_Front.ErrorMessage = "Please enter valid file";
Rg_FrontPage.Enabled = false;
Rg_BackPage.Enabled = false;
}
int FUp_Front_count = FUp_Front.FileName.Split('.').Length - 1;
if (FUp_Front_count > 1)
{
args.IsValid = false;
CV_FUp_Front.ErrorMessage = "Please enter valid file";
}
//end by santosh
if (Session["FUp_Front"] == null && !FUp_Front.HasFile)
{
args.IsValid = false;
CV_FUp_Front.ErrorMessage = "Max size 100KB. Upload only JPEG/JPG/PNG format";
Rg_FrontPage.Enabled = false;
Rg_BackPage.Enabled = false;
}
else if (FUp_Front.HasFile)
{
fileName = FUp_Front.PostedFile.FileName;
fi = new FileInfo(FUp_Front.PostedFile.FileName);
ext = fi.Extension.ToLower();
if (ext != ".jpg" && ext != ".jpeg" && ext != ".png")
{
args.IsValid = false;
CV_FUp_Front.ErrorMessage = "Max size 100KB. Upload only JPEG/JPG/PNG format";
Rg_FrontPage.Enabled = false;
Rg_BackPage.Enabled = false;
}
sizeinbytes_ = FUp_Front.PostedFile.ContentLength;
fileSize_ = sizeinbytes_ / 1024;
if (fileSize_ > 100)
{
args.IsValid = false;
CV_FUp_Front.ErrorMessage = "Max size 100KB. Upload only JPEG/JPG/PNG format";
Rg_FrontPage.Enabled = false;
Rg_BackPage.Enabled = false;
}
}
else
{
args.IsValid = true;
}
}
Related
I am using a customValidator to validate whether a date is within a valid range or not within a textbox. It works great if you manually enter in a date and calls my custom ClientValidationFunction. Unfortunately if i use a popup calendar to select a date my customValidator is not triggered.
I was hoping to get a better understanding on how asp:CustomValidators are triggered.
I've tried to force input validation to re-validate when the calendar is closed but have had no luck.
<asp:CustomValidator ID="ValidDateCheck" runat="server" ControlToValidate="txtDate" ErrorMessage="Please enter a valid date." ClientValidationFunction="clientValidate"
EnableClientScript="True" Display="Dynamic" CssClass="dateboxRJS-validator text-danger" ValidateEmptyText="true"></asp:CustomValidator>
Javascript
clientValidate = function (source, args) {
console.log("validating...");
var s = document.getElementById(source.controltovalidate);
var minDate = moment("1900-01-01");
var maxDate = moment().add(200, 'y');
var inputDate;
if (moment(s.value, "MM/DD/YYYY", true).isValid()) {
inputDate = moment(s.value, "MM/DD/YYYY");
console.log(s.value);
console.log("break");
if (!inputDate.isBetween(minDate, maxDate)) {
args.IsValid = false;
s.classList.add("is-invalid");
Page_BlockSubmit = true;
return false;
} else {
s.classList.remove("is-invalid");
args.IsValid = true;
Page_BlockSubmit = false;
return true;
}
}
}
});
I have two resource file Resource.resx and Resource.ar.resx
with the same keys but different english and arabic data
in the following code the text in the is working fine showing english and arabic data with the change in the dropdownlist while the text of the save button always shows English not arabic
</tr>
<tr>
<td><span><%=Resources.Resource.Citations%></span></td>
<td>
<input runat="server" id="taCitations" type="number" style="width: 600px;" /></td>
</tr>
</table>
<asp:Button ID="btnSave" runat="server" Text="<%$Resources:Resource, Save%>" CssClass="btn" OnClick="btnSave_Click" />
I have a dropdownlist in master page
<asp:DropDownList ID="ddlLang" runat="server" AutoPostBack="true">
<asp:ListItem Text="English" Value="en-US">
<asp:ListItem Text="Arabic" Value="ar-sa" />
</asp:DropDownList>
and my work to change language is in preRender of the master page
protected void Page_PreRender(object sender, EventArgs e)
{
if (Request.Form["__EVENTTARGET"] != null && Request.Form["__EVENTTARGET"].Contains("ddlLang"))
{
//Set the Language.
Language = Request.Form[Request.Form["__EVENTTARGET"]];
}
if (Language == "en-US")
{
Body.Attributes["dir"] = "ltr";
tdAppParticulars.Attributes["align"] = "right";
}
else
{
Body.Attributes["dir"] = "rtl";
tdAppParticulars.Attributes["align"] = "left";
}
Thread.CurrentThread.CurrentCulture = new CultureInfo(Language);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(Language);
List<ExtFormInstruction1> lefi = bal.ExtFormInstructionByType("External Reviewers");
formInstructions = new Hashtable();
formIDs = new Hashtable();
string currentItemURL = "";
foreach (ExtFormInstruction1 row in lefi)
{
string itemURL = row.Page;
formInstructions[row.Page] = Language == "ar-sa" ? "" : row.Instruction;
formIDs[row.Page] = row.FormID;
if (Language == "en-US")
{
lblPageTitle.Text = row.Title;
}
else if (Language == "ar-sa")
{
lblPageTitle.Text = bal.GetFormByPage(row.Page.Replace(".aspx", "Ar.aspx"))[0].Title;
}
}
MakeMenu(Language);
if (IsPostBack)
{
return;
}
lblApplicantEmail.Text = bal.GetApplicant(ApplicationID)[0].NameString;
lblEmployee.Text = erBAL.GetExtRevByID(ExtReviewerID)[0].Name;
/* printer friendly */
if (Utils.IsPrintMode())
{
tdLeftMenu.Visible = false;
lnkPrint.Visible = false;
}
lnkPrint.NavigateUrl = currentItemURL + "?print=1";
}
the Language is a property in master page
public string Language
{
set
{
Session["Language"] = value;
}
get
{
if (Session["Language"] != null)
{
return Session["Language"].ToString();
}
else
{
return "en-US";
}
}
}
I would rather do it like this:
<asp:Button ID="btnSave" runat="server" meta:resourceKey="SaveButton" CssClass="btn" OnClick="btnSave_Click" />
And in the Resource.resx file, the entries will be like
Name: SaveButton.Text
Value: Save
Name: SaveButton.Tooltip
Value: Click to Submit
Similarly in Resource.ar.resx file
Name: SaveButton.Text
Value: حفظ
Name: SaveButton.Tooltip
Value: انقر فوق لتقديم
I have read a number of threads here on the subject of posting back data from dynamically added datagrid columns. Everything I've read says that since the columns were added after the Init phase, they are not available in the control collection upon Postback and therefore any data posted back by these dynamically added columns is not available and cannot be restored from ViewState unless they are re-created in Page_Init. I have read that as long as the controls are re-added with identical IDS ( i.e IDS should match match posted back control ids), they will be restored from ViewState.
What if I'm not dynamically adding grid columns but rather dropping some grid columns in the code behind. So the ID's of the columns that remmin should match what was in the control collection to begin with so any data posted back should be resotored right but this is not what I'm seeing. SUppos the following is the list of columns in my ASPX page. If in my code behind I drop the "Test" column but check the checkbox in the first column. Upon postback, the checkbox selection is not maintained. I would have expected it to based on what I've read. Can someone correct my understanding on this?
<Columns>
<asp:TemplateColumn headertext="" headerstyle-width="1%" itemstyle-horizontalalign="center" FooterStyle-CssClass="DataGridFooter" FooterStyle-HorizontalAlign="Center" FooterStyle-VerticalAlign="Top">
<HeaderTemplate>
<input id="checkAll" type="checkbox" onclick="CheckAllDataGridCheckBoxes('checkboxIsSelected',this.checked)"/>
</HeaderTemplate>
<itemtemplate>
<asp:CheckBox runat="server" id="checkboxIsSelected" checked='false' />
</itemtemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Subject" HeaderStyle-Width="10%" Visible="TRUE" ItemStyle-HorizontalAlign="Center" FooterStyle-CssClass="DataGridFooter" FooterStyle-HorizontalAlign="Center" FooterStyle-VerticalAlign="Top" >
<ItemTemplate>
<asp:Label id="labelSubjectID" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "SubjectID") %>' />
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Test" HeaderStyle-Width="5%" Visible="TRUE" ItemStyle-HorizontalAlign="Center" FooterStyle-CssClass="DataGridFooter" FooterStyle-HorizontalAlign="Center" FooterStyle-VerticalAlign="Top" >
<ItemTemplate>
<asp:Label id="labelTestCode" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "TestCode") %>' />
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
Added BindGrid() and the event handler buttonApprove_click. The method SetGridColumns is the one that drops grid columns. Have included that too.
private void BindGrid()
{
try
{
SetMasterDetailControlStates(IsPageInDetailsMode());
if (!ValidateArgs())
{
gridBias.Visible = false;
return;
}
foreach (ListItem displayOption in chkboxDisplay.Items)
{
if (displayOption.Selected)
{
if (displayOption.Value == "Highlight") { _showHighlighting = true; }
}
}
/*
<Snipped>...Make procedure call to get dataset
*/
DataSet ds = sp.GetDataSet();
if (sp.RC != (int)ReturnCode.SUCCESS)
{
if ((sp.RC == (int)ReturnCode.NO_RECORDS_RETURNED))
{
labelMessage.Text = "No data found for the specified filter";
}
else if ((sp.RC == (int)ReturnCode.UNHANDLED_EXCEPTION) || (ds == null))
{
labelMessage.Text = sp.ErrorMessage;
}
ds = null;
gridBias.DataSource = ds;
EnableControls(false);
SetGridColumns();
}
else
{
gridBias.TitleText = BuildGridTitleString();
gridBias.FilterText = BuildGridFilterString();
gridBias.EnableRowsPerPageEdit = true;
SetGridColumns();
//Since grid columns are dynamically added and can change between postbacks
//make sure sort column is valid, if not unset
if (gridBias.SortColumn != null && gridBias.SortColumn.Length > 0)
{
bool foundCol = false;
foreach (DataGridColumn dg in gridBias.Columns)
{
if (gridBias.SortColumn == dg.SortExpression)
{
foundCol = true;
break;
}
}
if (!foundCol)
{
gridBias.SortColumn = "";
gridBias.SortOrder = "";
}
}
if (gridBias.SortColumn.Length == 0) gridBias.SortColumn = "TestCode";
if (gridBias.SortOrder.Length == 0) gridBias.SortOrder = "ASC";
if (gridBias.PageIndex.Length != 0 &&
!gridBias.GridViewMode.Equals(CustomDataGrid.GridViewType.SHOWALL.ToString()))
gridBias.CurrentPageIndex = Convert.ToInt32(gridBias.PageIndex);
ds.Tables[0].DefaultView.Sort = gridBias.SortColumn + " " + gridBias.SortOrder;
gridBias.DataSource = ds.Tables[0].DefaultView;
EnableControls(true);
}
gridBias.HideEmptyColumns = true;
ArrayList cols = new ArrayList();
cols.AddRange(_alRecheckColumns);
gridBias.HideEmptyColumnsList = cols;
gridBias.DataBind();
}
catch (Exception ex)
{
CodeLibrary.ErrorHandling.SetLabel("Error(" + CodeLibrary.ErrorHandling.GetMethodName() + ")", ex.Message, labelMessage, true, "ErrorMsg");
}
}
private void SetGridColumns()
{
ArrayList alCols = new ArrayList();
alCols.Add(""); //Checkbox column
alCols.Add("Subject");
ArrayList alColumnsToBeDeleted = new ArrayList();
Boolean boolColExists = false;
foreach (ListItem chart in chkboxChartType.Items)
{
if (chart.Value == "%Bias")
{
if (rblBiasOptions.SelectedValue == "Subject")
{
foreach (DataGridColumn dg in gridBias.Columns)
{
boolColExists = false;
foreach (string gridColumn in alCols)
{
if (dg.HeaderText == gridColumn)
{
boolColExists = true;
break;
}
}
if (!boolColExists)
{
alColumnsToBeDeleted.Add(gridBias.Columns.IndexOf(dg));
}
}
}
}
// Loop thru the array list and delete columns from the grid.
int count = 0;
foreach (int i in alColumnsToBeDeleted)
{
gridBias.Columns.RemoveAt(i - count); //Subtract index by columns already deleted.
count++;
}
}
protected void buttonApprove_Click(object sender, EventArgs e)
{
try
{
CheckPermission(this.ModuleId, this.GetType().BaseType.ToString(), "buttonApprove_Click");
foreach (DataGridItem i in gridBias.Items)
{
//Loop thru each row and determien values to be saved to DB
if (i.ItemType == ListItemType.Item || i.ItemType == ListItemType.AlternatingItem)
{
bool cbSelected = ((CheckBox)i.FindControl("checkboxIsSelected")).Checked;
if (cbSelected)
{
bool IsApproved = true;
string strSubjectID = ((System.Web.UI.WebControls.Label)i.FindControl("labelSubjectID")).Text;
string strTestCode = ((System.Web.UI.WebControls.Label)i.FindControl("labelTestCode")).Text;
string strSampleType = ((System.Web.UI.WebControls.Label)i.FindControl("labelSampleType")).Text;
string strTestCodeAndType = ((System.Web.UI.WebControls.Label)i.FindControl("labelTestCodeAndType")).Text;
if (((System.Web.UI.WebControls.Label)i.FindControl("labelRecheckNeedsApproval")).Text == "1")
IsApproved = true;
else
IsApproved = false;
SaveToDB(strSubjectID, strTestCode, strSampleType, strTestCodeAndType,IsApproved);
}
}
}
BindGrid();
}
catch (Exception exceptionObject)
{
string strExceptionMessage = exceptionObject.Message + "-" + exceptionObject.InnerException.Message;
CodeLibrary.ErrorHandling.SetLabel("", strExceptionMessage, labelMessage, false, "ErrorMsg"); //--- Set label text
}
}
Hi to all i'm a beginner in asp.net fileUploader and i'm using blow code to upload:
The HTML:
<asp:FileUpload ID="FileUpload1" runat="server" AllowMultiple="true" />
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Upload Selected File(s)" />
JavaScript code:
$("#Button1").click(function (evt) {
var fileUpload = $("#FileUpload1").get(0);
var files = fileUpload.files;
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append(files[i].name, files[i]);
}
var options = {};
options.url = "FileUploadHandler.ashx";
options.type = "POST";
options.data = data;
options.contentType = false;
options.processData = false;
options.success = function (result) { alert(result); };
options.error = function (err) { alert(err.toString()); };
and the handler code:
if (context.Request.Files.Count > 0)
{
HttpFileCollection files = context.Request.Files;
for (int i = 0; i < files.Count; i++)
{
HttpPostedFile file = files[i];
string fname = context.Server.MapPath("~/uploads/" + file.FileName);
file.SaveAs(fname);
}
}
context.Response.ContentType = "text/plain";
context.Response.Write("File(s) Uploaded Successfully!");
I have two problems the first it can't find upload file in the root of the web application and second is the page postback is there somebody that help me about solve my problems thank!
I was a little confused with jQuery-File-Upload myself, but after reviewing the plugin documentation I found what is needed for the plugin to work on Windows environment.
PROBLEM 1: FILE SAVING - regarding this issue, make sure that you are saving to a valid and previously created directory, and also that you have WRITE permissions to that directory.
PROBLEM 2: UPLOAD POSTBACK - You must setup your upload script to write the uploaded file, AND return a valid JSON response to the plugin, as defined on the plugin documentation: https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler
if (context.Request.Files.Count > 0) {
HttpFileCollection files = context.Request.Files;
for (int i = 0; i < files.Count; i++) {
HttpPostedFile file = files[i];
string fname = context.Server.MapPath("~/uploads/" + file.FileName);
file.SaveAs(fname);
}
}
upload_response = '{"files":[{"name": ' + file.FileName + '","size":' file.FileSize + ',"url":"http:\/\/example.org\/files\/ + file.FileName + ",'
upload_response =+ '"thumbnailUrl": "http:\/\/example.org\/files\/thumbnail\/ + file.FileName + ","deleteUrl": "http:\/\/example.org\/files\/ + file.FileName + ",'
upload_response =+ '"deleteType": "DELETE"}]}"'
context.Response.ContentType = "application/json";
context.Response.Write( upload_response );
Please note that I also changed the ContentType to "application/json". The syntax of this code may not be complete, but the most important is to output these JSON fields required by the plugin.
i have a below gridview control with a checkbox on it, so my question is when i hit on save button i able to find the checkbox which have been checked and till here no problem, but the problem started when the user tries to uncheck the checkedbox so how would i track the changes and save it into the db that has been checked. anyhelp?
List<Employee> result = new List<Employee>();
long Id = (long)Session["Id"];
result = Employee.GetEmployeeById(Id);
foreach (GridViewRow row in gv.Rows)
{
CheckBox chkBox = row.FindControl("chkSelected") as CheckBox;
if (c != null)
{
if (result.Count > 0)
{
foreach (Employee item in result)
{
Label Id = row.FindControl("lblId") as Label;
if (Id.Text == item.Id.ToString())
{
chkBox.Checked = true;
}
else
{
chkBox.Checked = false;
}
}
}
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:CheckBox ID="chkSelected" runat="server" Checked="false"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
<script language="javascript" type="text/javascript">
function SelectAll(cb)
{
var gvVar = document.getElementById("<%= gv.ClientID %>");
var cell;
if (gvVar.rows.length > 0)
{
for (i=1; i<gvVar.rows.length; i++)
{
cell = gvVar.rows[i].cells[0];
for (j=0; j<cell.childNodes.length; j++)
{
if (cell.childNodes[j].type =="checkbox")
{
cell.childNodes[j].checked = document.getElementById(cb).checked;
}
}
}
}
}
//--------------------------------------------------------------------------------------------.
function Select(cb)
{
var total = parseInt('<%= this.gv.Rows.Count %>');
var counter=0;
var cbSelectAll=document.getElementById(cb);
var gvVar = document.getElementById("<%= gv.ClientID %>");
var cell;
if (gvVar.rows.length > 0)
{
for (i=1; i<gvVar.rows.length; i++)
{
cell = gvVar.rows[i].cells[0];
for (j=0; j<cell.childNodes.length; j++)
{
if (cell.childNodes[j].type =="checkbox")
{
if(cell.childNodes[j].checked)
counter++;
else
counter--;
}
}
}
}
if(counter==total)
cbSelectAll.checked=true;
else if(counter<total)
cbSelectAll.checked=false;
}
</script>
//----------------------------------------------------------------------------------------
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && (e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate))
{
CheckBox cbSelect = (CheckBox)e.Row.Cells[0].FindControl("cbSelect");
CheckBox cbSelectAll = (CheckBox)this.gv.HeaderRow.FindControl("cbSelectAll");
cbSelect.Attributes.Add("onclick", "javascript:Select('" + cbSelectAll.ClientID + "')");
cbSelectAll.Attributes.Add("onclick", "javascript:SelectAll('" + cbSelectAll.ClientID + "')");
}
}
Yes, store the original value in a hidden field. If always starting with false, you could use JavaScript to set the hidden value to true when the user clicked the checkbox. Using JQuery, you could do:
<asp:TemplateField HeaderText="Select" ItemStyle-CssClass="Checked">
<ItemTemplate>
<asp:CheckBox ID="chkSelected" runat="server" Checked="false"></asp:CheckBox>
<asp:HiddenField iD="dh" runat="server" />
</ItemTemplate>
</asp:TemplateField>
$("#<%= Grid.ClientID %>").find(".Checked > :checkbox").each(function() {
$(this).siblings("input[type='hidden']").attr("value", "True");
});
Something like that. On Server side, parse the value and if true, then you know it changed.
HTH.
It may not be the brightest idea, but you can query the database for the current state, and the compare with what you have got from the web page during a postback button click, or something like that. Or you can go with Brians answer.
It is possible to persist a list of objects into the Viewstate and access it in a consequent postback. The only thing is that the object you are trying to persist must be defined as serializable.
Update:
The ViewState approach
I feel this may be suitable for your need, and it requires a bit of linq. You'd need to create a class as follows:
[Serializable()]
public class OptionState
{
//the id of the item
int ID {get;set;}
//state of the checkbox
bool Checked {get;set;}
}
Note the Serializable attribute. This is required for the instance to persist to the viewstate.
Add the list of options to the viewstate:
var lstOptions = (from x in <your_option_store>
select new OptionState{ID = x.ID, Checked = x.Checked}).ToList();
ViewState.Add("options", lstOptions);
Here is a bit of code that should go into your button click:
foreach(GridViewRow row in gvOptions.Rows)
{
//not writing the bit of code
//which gets the ID and the
//state of checkbox of
//the gridview row being processed
OptionState currentState = GetOptionStateObjectFromRow(row);
List<OptionState> lstStates = (List<OptionState>) ViewState["options"];
OptionState originalState = lstStates.FirstOrDefault(x => x.ID == currentState.ID);
if(currentState.Checked != originalState.Checked)
{
//the appropriate db call needs to be done here.
}
}