Problem loading states of server controls residing in user control - asp.net

I have user control which contains two text boxes and two dropdown list. I am loading this control first time on page_load event programatically. After that on each button click event of "Add New" button, controls are added dynamically but when this happens, previously loaded controls are showing all server controls(which are inside user control) empty. How can i retain the state of these controls?
My user control code is as shown below.
<%# Control Language="C#" AutoEventWireup="true" CodeFile="qualificationControl.ascx.cs" Inherits="qualificationControl" %>
<style type="text/css">
.RowHeight
{
height: 30px;
}
</style>
<table width="100%">
<tr>
<td class="RowHeight" width="20%">
Course Name</td>
<td width="20%">
<asp:DropDownList ID="courseList" runat="server" Width="100px">
</asp:DropDownList>
</td>
<td width="20%">
Year of Passing</td>
<td width="*">
<asp:DropDownList ID="yearList" runat="server" Width="100px">
<asp:ListItem Value="0">2005</asp:ListItem>
<asp:ListItem Value="1">2006</asp:ListItem>
<asp:ListItem Value="2">2007</asp:ListItem>
<asp:ListItem Value="3">2008</asp:ListItem>
<asp:ListItem Value="4">2009</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td class="RowHeight" width="20%">
Percentage</td>
<td colspan="3">
<asp:TextBox ID="percentageBox" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td class="RowHeight" width="20%">
Instutitute Name</td>
<td colspan="3">
<asp:TextBox ID="InstiNameBox" runat="server" Width="350px"></asp:TextBox>
</td>
</tr>
</table>
and that of aspx.cs page is as below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
public partial class AppplicationForm2 : System.Web.UI.Page
{
Control qualificationControl;
UserControl usrqualificationControl = new UserControl();
int CtrlID = 0;
protected void Page_Load(object sender, EventArgs e)
{
qualificationControl = usrqualificationControl.LoadControl("~/control/qualificationControl.ascx");
if (!IsPostBack)
{
ArrayList CtrlList = new ArrayList();
qualificationControl.ID = CtrlID.ToString();
UserCtrlHolder.Controls.Add(qualificationControl);
CtrlList.Add(qualificationControl);
Session.Add("qualiControl", CtrlList);
}
//else
}
protected void addQualificationBtn_Click(object sender, EventArgs e)
{
ArrayList CtrlList = null;
ArrayList CourseList = new ArrayList();
ArrayList YearList = new ArrayList();
ArrayList percentageList = new ArrayList();
ArrayList InstituteList = new ArrayList();
if (Session["qualiControl"] != null)
{
CtrlList = (ArrayList)Session["qualicontrol"];
}
qualificationControl.ID = CtrlList.Count.ToString();
CtrlList.Add(qualificationControl);
for (int i = 0; i < CtrlList.Count; i++)
{
UserCtrlHolder.Controls.Add((Control)CtrlList[i]);
}
}
private void RestoreUserControl(ArrayList CourseList,ArrayList YearList,ArrayList PercentageList,ArrayList InstiNameList,ArrayList CtrlList)
{
for (int CtrlCnt = 0; CtrlCnt < CtrlList.Count - 1; CtrlCnt++)
{
Control userControl = (Control)UserCtrlHolder.FindControl(CtrlID.ToString());
DropDownList dlCourseList = (DropDownList)userControl.FindControl("courseList");
DropDownList dlYearList = (DropDownList)userControl.FindControl("yearList");
TextBox percentageBox = (TextBox)userControl.FindControl("percentageBox");
TextBox InstiNameBox = (TextBox)userControl.FindControl("InstiNameBox");
dlCourseList.ClearSelection();
dlYearList.ClearSelection();
dlCourseList.Items.FindByText(CourseList[CtrlCnt].ToString()).Selected = true;
dlYearList.Items.FindByText(CourseList[CtrlCnt].ToString()).Selected = true;
percentageBox.Text = PercentageList[CtrlCnt].ToString();
InstiNameBox.Text = PercentageList[CtrlCnt].ToString();
}
}
}

Use Page_Init
Using Page_Load event for dynamic user control loading is too late because view state has already been loaded. Hence your controls are always rendered empty. Try adding your user control in Page_Init event instead. View state gets loaded just after this event which makes sure your dynamic controls should+++ be populated with previous state.
Note +++: If you add dynamic controls deterministically everything will be fine, but if you have non-deterministic processing your controls will have different IDs during page life hence view state will fail to load on each postback. You shouldn't have any problems with code you've provided.

http://www.google.com.tw/search?hl=en&safe=off&q=asp.net+add+control+dynamically&aq=1&aqi=g10&aql=&oq=asp.net+add+control
there are a ton of articles about adding controls dynamically, find one that suits you

Related

CSRF fix in aspx page

I need the fix for CSRF flaw for aspx page. The code is like this -
ASPX -
<asp:Content runat='server'>
<asp:Panel runat='server'>
<table>
<tr>
<td>Username</td>
<td><asp:TextBox runat="server" ID="Username" autocomplete="off"></asp:TextBox></td>
</tr>
<tr>
<td>Password</td>
<td><asp:TextBox runat="server" ID="Password" TextMode="Password" autocomplete="off"></asp:TextBox></td>
</tr>
<tr>
<asp:Button ID="Submit" runat="server" Text="Submit"
OnClick="SubmitButton_Click" CssClass="Resizable" />
</tr>
</table>
</asp:Panel>
</asp:Content>
ASPX.cs -
protected void SubmitButton_Click(object sender, EventArgs e)
{
//Code here
}
Now while inserting <%# Html.AntiForgeryToken() %> at the top throws error "The server block is not well formed". So how should I proceed with the fix.
You're using webforms here. They already have anti-xsrf set up in the template of the master page (I think it's tucked in with all of the viewstate data).
So as long as you are using a master page then you needn't worry.
If you're not using a master page just build your own using session state, a hidden field and a guid. I've taken the below from http://willseitz-code.blogspot.com/2013/06/cross-site-request-forgery-for-web-forms.html
Your hiddenfield...
<asp:HiddenField ID="antiforgery" runat="server"/>
The code that does the work server side...
public static class AntiforgeryChecker
{
public static void Check(Page page, HiddenField antiforgery)
{
if (!page.IsPostBack)
{
Guid antiforgeryToken = Guid.NewGuid();
page.Session["AntiforgeryToken"] = antiforgeryToken;
antiforgery.Value = antiforgeryToken.ToString();
}
else
{
Guid stored = (Guid) page.Session["AntiforgeryToken"];
Guid sent = new Guid(antiforgery.Value);
if (sent != stored)
{
throw new SecurityException("XSRF Attack Detected!");
}
}
}
}
And finally the following in your Page_Load method in code behind...
AntiforgeryChecker.Check(this, antiforgery);

Unable to pass data from one content page to another using master page

I'm trying to make an asp webform that posts data to another webform.
I've made two separate projects, one that uses master page and one the doesn't.
Senario:
WebForm1.aspx has two text boxes and a submit button
<table>
<tr>
<td >Name:</td>
<td >
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</td>
<td class="auto-style1"></td>
</tr>
<tr>
<td>Id:</td>
<td>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</td>
<td> </td>
</tr>
</table>
WebForm2.aspx.cs has two labels which should display the data received from WebForm1.aspx
Page prevPage = this.PreviousPage;
if (prevPage != null)
{
Label1.Text = ((TextBox)prevPage.FindControl("TextBox1")).Text;
Label2.Text = ((TextBox)prevPage.FindControl("TextBox2")).Text;
}
Case 1: [Posting without master page]
The data is posted normally.
Case 2: [Posting with master page]
I get NullReferenceException.
So I broke down the code.
Page prevPage = this.PreviousPage;
if (prevPage != null)
{
ControlCollection collec = prevPage.Controls;
Control ctrl= prevPage.FindControl("TextBox1");
TextBox txtbx = (TextBox)ctrl;
Label1.Text = txtbx.Text; //Exception raised here
Label2.Text = ((TextBox)prevPage.FindControl("TextBox2")).Text;
}
While debugging:
I executed "collec.Count" in the Immediate Window.
Case 1: [Posting without master page]
collec.Count returned 5
Case 2: [Posting with master page]
collec.Count returned 1 [ WHY? ]
Later,
I tried to pass data using public properties
WebForm1.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Server.Transfer("WebForm2.aspx");
}
public string Name { get { return TextBox1.Text; } }
public string ID { get { return TextBox2.Text; } }
WebForm2.aspx.cs
WebForm1 prevPage = (WebForm1)this.PreviousPage;
if (prevPage != null)
{
ControlCollection c = prevPage.Controls;
Label1.Text = prevPage.Name;
Label2.Text = prevPage.ID;
}
and now it works correctly, even with master page.
So could anybody explain me whats going on and why posting from one content page to another content page with master giving me NullReferenceException ?
First you must look in the Content Placeholder of the submitting page
Therefore, the code would look more like this:
ContentPlaceHolder placeHolder = (ContentPlaceHolder)PreviousPage.Master.FindControl("ContentPlaceHolder1");
TextBox txt1 = (TextBox)placeHolder.FindControl("TextBox1");
When you are using master page a TextBox with an id of TextBox1 inside a Content control tied to ContentPlaceHolder1 will have its id attribute extended like this:
<input name="ctl00$ContentPlaceHolder1$TextBox1" type="text" id="ContentPlaceHolder1_TextBox1" />
But when you are not using Master page there is no 'ContentPlaceHolder' so TextBox1 will rendered like this:
<input name="TextBox1" type="text" id="TextBox1" />

ListView find dropdownlist in table

I have a list view with table inside and i need to get all dropdown lists and file upload controls, but find returns nothing. This is my code:
<asp:ListView runat="server" ID="MyListView" OnItemDataBound="FillDropDownList">
<LayoutTemplate>
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<th>Wholesaler</th>
<th>Import</th>
<th>Period</th>
<th>Upload Date</th>
<th>Upload</th>
</tr>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr class="row1">
<td><%# DataBinder.Eval(Container.DataItem, "Wholesaler") %></td>
<td><%# DataBinder.Eval(Container.DataItem, "Import")%></td>
<td><%# DataBinder.Eval(Container.DataItem, "Period")%></td>
<td><asp:DropDownList runat="server" ID="DaysDropDownList"></asp:DropDownList></td>
<td><asp:FileUpload ID="FileUpload" runat="server" /></td>
</tr>
</ItemTemplate>
</asp:ListView>
DropDownList dr = (DropDownList)MyListView.Controls[0].FindControl("DaysDropDownList");
FileUpload fl = (FileUpload)MyListView.Controls[0].FindControl("FileUpload");
figured...and you got that error, because the listview was not binded yet, so i think the best way would be to do all this on the ItemDataBound event. You would find the dropdownlist like:
protected void FillDropdownlist(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
DropDownList dr = (DropDownList)e.Item.FindControl("DaysDropDownList");
FileUpload fl = (FileUpload)e.Item.FindControl("FileUpload");
if (dr!= null)
{
//code here
}
}
}
You need to iterate over the Items collection of the listview, and then use FindControl on each item. Something like this should put you on the right track:
foreach (var lvItem in MyListView.Items)
{
if (lvItem.ItemType == ListViewItemType.DataItem)
{
DropDownList dr = (DropDownList)lvItem.FindControl("DaysDropDownList");
FileUpload fl = (FileUpload)lvItem.FindControl("FileUpload");
}
}
That's because MyListView.Controls[0] points to an inner control that does not contain those two.
Try debugging and finding precisely which is your container control, and then accessing it directly without a hard coded index. It's accessible via the event parameter of your row binding calls.
Also might I suggest you use the as operator as it doesn't raise an exception:
The as operator is like a cast except that it yields null on conversion failure instead of raising an exception
i.e.
DropDownList dr = e.Item.FindControl("DaysDropDownList") as DropDownList;
FileUpload fl = e.Item.FindControl("FileUpload") as FileUpload;
or after it's bound
//Loop i for the items of your listview
DropDownList dr = MyListView.Items[i].FindControl("DaysDropDownList") as DropDownList;
FileUpload fl = MyListView.Items[i].FindControl("FileUpload") as FileUpload;

ListView DataPager is not paging

The ListView is displaying properly and the DataPager is displaying the buttons at the bottom, but when I click the NEXT button, the DataPager is not going to the next page of data.
ASPX page:
<div id="EventListing">
<asp:ListView ID="ListEvents" runat="server">
<LayoutTemplate>
<div ID="itemPlaceholder" runat="server">
</div>
<div id="pagerFormat">
<asp:DataPager ID="ListingDataPager" runat="server" PageSize="5" PagedControlID="ListEvents" QueryStringField="page" >
<Fields>
<asp:NextPreviousPagerField
FirstPageText="First"
LastPageText="Last"
NextPageText="Next"
PreviousPageText="Back" />
</Fields>
</asp:DataPager>
</div>
</LayoutTemplate>
<ItemTemplate>
<table id="tblEvents">
<tr>
<td rowspan="4" id="Col1Events"></td>
<td rowspan="4" id="Col2Events"></td>
<td rowspan="4" id="Col3Events"></td>
<td class="tdEvents"><span style="font-weight:bold; font-size: 1em;"><%#Eval("EVENT_DATERANGE") %>: <%#Eval("EVENT_NAME") %></span></td>
</tr>
<tr>
<td class="tdEvents"> <span style="font-size: .9em;"><%#Eval("EVENT_DESC") %></span></td>
</tr>
<tr>
<td class="tdEvents"><span style="font-size: .9em;"><%#Eval("EVENT_STREET") %>, <%#Eval("CITY.CITY_NAME") %></span></td>
</tr>
<tr>
<td class="tdEvents"><span style="font-size: .9em;"><%#Eval("EVENT_PHONE") %></span></td>
</tr>
<tr>
<td colspan="4" id="tdEmpty"></td>
</tr>
</table>
</ItemTemplate>
</asp:ListView>
</div>
Code Behind Page:
protected void btnFindEvents_Click(object sender, EventArgs e)
{
DateTime StartDt;
string EventType = ddlEventType.SelectedValue;
string dt = Request.Form["DatePickername"];
if (ddlEventType.SelectedIndex == 0)
{
EventType = "";
}
if (dt != "")
{
StartDt = Convert.ToDateTime(Request.Form["DatePickerName"]);
}
else
{
StartDt = DateTime.Now;
}
string CityName= ddlEventCity.SelectedValue;
if (ddlEventCity.SelectedIndex == 0)
{
CityName = "";
}
if ((ddlEventType.SelectedIndex == 0) && (ddlEventCity.SelectedIndex == 0))
{
//(1) ALL EVENTS
BLgetEvents obj = new BLgetEvents();
var EventList = obj.getAllEvents(StartDt);
ListEvents.DataSource = EventList;
ListEvents.DataBind();
}
}
you have to bind data again on the ListView when you page by DataPager. So, you need to implement this bind on PagePropertiesChanging event of your ListView control. Something like:
// 1 - add a method to bind ListView, add some parameters if you need
protected void BindListView()
{
var data = // get data from database
ListEvents.DataSource = data;
ListEvents.DataBind();
}
// 2 - call this method on the button
protected void btnFindEvents_Click(object sender, EventArgs e)
{
BindListView();
}
// 3 - call this method on the PagePropertiesChanging event of the ListView
protected void ListEvents_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)
{
//set current page startindex, max rows and rebind to false
YourDataPagerControlId.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
//rebind List View
BindListView();
}
And on your asp.net webform, you need to set the event on the listview tag:
<asp:ListView ID="ListEvents" runat="server" OnPagePropertiesChanging="ListEvents_PagePropertiesChanging">
...
</asp:ListView>
When you set the datasource from code behine, the same principle is valid for other databound controls like GridView, DataList, Repeater etc (you need to bind again on some paging event). An alternative way to solve this, you could add a datasource control (like objectdatasource, linqdatasource, etc...) and set it on the ListView's DataSourceID property and the DataPager will work automatically.
For more details, look at this link: http://weblogs.asp.net/hajan/archive/2011/09/08/paging-listview-using-datapager-without-using-datasource-control.aspx

How to retrieve server control's values place inside user control after post back

I have user control placed in my .aspx page. User controls are added dynamically on button click event. My problem is, after post back, I can retrieve server controls placed inside user control but cant retrieve their values.
Here is the code of my user control's .ascx page
<%# Control Language="C#" AutoEventWireup="true" odeFile="qualificationControl.ascx.cs" Inherits="qualificationControl" %>
<table width="100%">
<tr>
<td class="RowHeight" width="20%">
Course Name</td>
<td width="20%">
<asp:DropDownList ID="courseList" runat="server" Width="100px">
</asp:DropDownList>
</td>
<td width="20%">
Year of Passing</td>
<td width="*">
<asp:DropDownList ID="yearList" runat="server" Width="100px">
<asp:ListItem Value="0">2005</asp:ListItem>
<asp:ListItem Value="1">2006</asp:ListItem>
<asp:ListItem Value="2">2007</asp:ListItem>
<asp:ListItem Value="3">2008</asp:ListItem>
<asp:ListItem Value="4">2009</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td class="RowHeight" width="20%">
Percentage</td>
<td colspan="3">
<asp:TextBox ID="percentageBox" runat="server"> </asp:TextBox>
</td>
</tr>
<tr>
<td class="RowHeight" width="20%">
Instutitute Name</td>
<td colspan="3">
<asp:TextBox ID="InstiNameBox" runat="server" Width="350px"></asp:TextBox>
</td>
</tr>
</table>
Here is the code of my .axcs.cs page
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
public partial class qualificationControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
using (DataOperation oDo = new DataOperation())
{
DataTable dt = oDo.DropDownList("select * from tblqualificationMaster");
foreach (DataRow row in dt.Rows)
{
courseList.Items.Add(new ListItem(row[1].ToString(), row[0].ToString()));
}
}
}
catch (Exception ex)
{
throw;
}
}
}
Code of my .aspx page
<%# Page Title="Application Form Level2" Language="C#" MasterPageFile="~/AppMaster.master" AutoEventWireup="true" CodeFile="AppplicationForm2.aspx.cs" Inherits="AppplicationForm2" %>
<%# Register src="Control/qualificationControl.ascx" tagname="qualificationControl" tagprefix="uc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<table width="100%">
<tr>
<td>
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td class="SubTitle">
Education details:</td>
</tr>
<tr>
<td runat="server" id="tdQualificationn">
<%--<uc1:qualificationControl ID="qualificationControl1" runat="server" />--%>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="UserCtrlHolder" runat="server"></asp:PlaceHolder>
</ContentTemplate>
<%-- <Triggers> <asp:AsyncPostBackTrigger ControlID="addQualificationBtn" /></Triggers>--%></asp:UpdatePanel>
</td>
</tr>
<tr>
<td align="center">
<asp:Button ID="addQualificationBtn" runat="server"
Text="Add More Qualifications" Height="40px"
onclick="addQualificationBtn_Click" />
</td>
</tr>
</table>
</asp:Content>
Code of my .aspx.cs page
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
public partial class AppplicationForm2 : System.Web.UI.Page
{
Control qualificationControl;
UserControl usrqualificationControl = new UserControl();
int CtrlID = 0;
ArrayList CtrlList = new ArrayList();
protected void Page_Load(object sender, EventArgs e)
{
qualificationControl = usrqualificationControl.LoadControl("~/control/qualificationControl.ascx");
if (!IsPostBack)
{
ArrayList CtrlList = new ArrayList();
qualificationControl.ID = CtrlID.ToString();
UserCtrlHolder.Controls.Add(qualificationControl);
CtrlList.Add(qualificationControl);
Session.Add("qualiControl", CtrlList);
Session.Add("ControlHolder", UserCtrlHolder);
}
}
protected void addQualificationBtn_Click(object sender, EventArgs e)
{
RememeberOldValues();
if (Session["QualiControl"] != null)
{
CtrlList = (ArrayList)Session["qualicontrol"];
}
qualificationControl.ID = CtrlList.Count.ToString();
CtrlList.Add(qualificationControl);
for (int i = 0; i < CtrlList.Count; i++)
{
UserCtrlHolder.Controls.Add((Control)CtrlList[i]);
}
}
public void RememeberOldValues()
{
try
{
if (Session["ControlHolder"] != null)
{
ArrayList CourseList = new ArrayList();
ArrayList YearList = new ArrayList();
ArrayList percentageList = new ArrayList();
ArrayList InstituteList = new ArrayList();
ArrayList CtrlList = (ArrayList)Session["qualicontrol"];
PlaceHolder PlaceHolder = (PlaceHolder)Session["ControlHolder"];
for (int intListCnt = 0; intListCnt < CtrlList.Count; intListCnt++)
{
Control userControl = (Control)PlaceHolder.FindControl(CtrlID.ToString());
DropDownList dlCourseList = (DropDownList)userControl.FindControl("courseList");
DropDownList dlYearList = (DropDownList)userControl.FindControl("yearList");
TextBox percentageBox = (TextBox)userControl.FindControl("percentageBox");
TextBox InstiNameBox = (TextBox)userControl.FindControl("InstiNameBox");
CourseList.Add(dlCourseList.SelectedValue);
YearList.Add(dlYearList.SelectedValue);
percentageList.Add(percentageBox.Text);
InstituteList.Add(InstiNameBox.Text);
}
}
}
catch (Exception ex)
{
throw;
}
}
}
Please guide me how can I retrieve those values.
You have to find particular control from user control
((DropDownList)qualificationControl1.FindControl("yearList")).SelectedValue

Resources