I have a user control loaded by LoadControl, and on the code behind for said user control I try to access a control thats null.
Default.aspx:
protected void Page_Load(object sender, EventArgs e){
// ...
List<String> usersCustomers = custRepo.GetUserCustomers(currentUser.ID).Select(s => s.custName).ToList();
FileTrackingControl fileTrackingControl = (FileTrackingControl)LoadControl(typeof(FileTrackingControl), new object[] { usersCustomers, currentUser });
dashboardWidgetPanel.Controls.Add(fileTrackingControl);
// ...
}
FileTrackingControl.ascx:
public partial class FileTrackingControl : System.Web.UI.UserControl
{
List<string> _custNames;
User _currentUser;
public FileTrackingControl(List<string> custNames, User currentUser)
{
this._custNames = custNames;
this._currentUser = currentUser;
}
protected void Page_OnInit(object sender, EventArgs e)
{
StatToCwData scData = new StatToCwData();
GridView fileTrackingResultsFC = (GridView)FindControl("fileTrackingResults");
// CRASH HERE. NPE: fileTrackingResults is NULL
fileTrackingResults.DataSource = scData.GetControlData(6, _currentUser, _custNames);
fileTrackingResults.DataBind();
}
}
On the basis that you do have a grid view with ID fileTrackingResults (it's always worth double checking!), then I think you're trying to access the controls before they are created (as I recall MS says you shouldn't access the control tree in oninit events). In your case it's probably a case of simply moving the code into the Page_Load event, OR create a Page_PreLoad event and map the event handler manually if you need to reserve the Page_Load for some other sort of functionality. Alternatively, you could create a LoadData type method on your user control and fire it manually (use an interface to declare the method so you can roll it across other code).
Related
The scenario is very simple. I have an aspx page with a user control. I want to set a value and get a response from usercontrol on aspx page's pageload. The SET job is done, but can't GET the response. It's always empty. I tried two methods, but none of them worked.
ASPX PAGE
<uc1:ucContent ID="Content1" runat="server" />
CODE BEHIND
protected void Page_Load(object sender, EventArgs e)
{
// SET job is working without any problem
Content1.ItemName = "X";
//METHOD ONE:
Page.Title = Content1.MetaPageTitle;
//METHOD TWO:
HiddenField hdnPageTitle = (HiddenField)Content1.FindControl("hdnMetaPageTitle");
Page.Title = hdnPageTitle.Value;
}
USER CONTROL
protected void Page_Load(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(itemName))
{
// GET DATA FROM DB
// METHOD ONE:
hdnTitle.Value = DB.DATA;
// METHOD TWO:
metaPageTitle = DB.DATA;
}
}
private string metaPageTitle;
public string MetaPageTitle
{
// METHOD ONE:
get { return metaPageTitle; }
// METHOD TWO:
get { return hdnTitle.value; }
}
EDIT
itemName is a UserControl property to get a value from Parent Page:
private string itemName;
public string ItemName
{
set { itemName = value; }
}
Thanks for your kind help in advance!
I think that the problem is that the page's Page_Load is triggered before the UserControl(Have a look: asp.net: what's the page life cycle order of a control/page compared to a user contorl inside it?).
So you could set the property in Page_init:
In your UserControl:
protected void Page_Init(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(itemName))
{
// GET DATA FROM DB
hdnTitle.Value = DB.DATA;
}
}
Now this should work in your page's Page_Load:
Page.Title = Content1.MetaPageTitle;
Normally i would prefer another kind of communication between a Page and a UserControl. It's called event-driven communication and means that you should trigger a custom event in your UC when the MetaPageTitle changed (so in the appopriate event-handler).
Then the page can handle this specific event and react accordingly.
Mastering Page-UserControl Communication - event driven communication
I am currently attempting to find a way for a page to send information on user choices on a page to an HttpModule. For example, if a user either clicked a checkbox or not, the module could log that information for later error checking. My module can log simple data about the page, such as execution time, but I am hoping for more information.
Is such a thing possible? I have tried using Context.Items but have not found any success.
You are probably using bad event in IHttpModule that runs before you set Context.Items item. Try do it in event EndRequest where page was already processed.
In Page:
protected void Unnamed_Click(object sender, EventArgs e)
{
Context.Items["button_clicked"] = "yes";
}
in HttpModule:
public class DefaultHttpApplicationModule
: System.Web.IHttpModule
{
public virtual void Init(HttpApplication context)
{
context.EndRequest += context_EndRequest;
}
void context_EndRequest(object sender, EventArgs e)
{
var app = ((HttpApplication)sender);
var ctx = app.Context;
string clicked = ctx.Items["button_clicked"] as string;
}
}
You can also access the Page instance directly, becasu System.Web.UI.Page is also IHttpHandler.
There are two events HttpApplication.PreRequestHandlerExecute (Before Page events fired) and HttpApplicatoin.PostRequestHandlerExecute (It runs after Page.Unload).
void context_PostRequestHandlerExecute(object sender, EventArgs e)
{
var app = ((HttpApplication)sender);
var ctx = app.Context;
if (app.Context.Handler != null && app.Context.Handler is Page)
{ // Register PreRender handler only on aspx pages.
Page page = (Page)HttpContext.Current.Handler;
}
}
Having just added a new button in my web application, I get an error when clicking on it, and I'm wondering if this is related to misplaced code. I will describe what/where I did, briefly. Thanks very much.
In ascx file:
<asp:Button ID="btn_rezerv" runat="server" Text="Reserve film" OnClick="btn_rezerv_Click"/>
In the ascx.cs file:
namespace CinProj.UserControls
{
public partial class FilmsList : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
PopulateControls();
}
private void PopulateControls()
{
string categId = Request.QueryString["CategID"];
string filmId = Request.QueryString["FilmID"];
....
if (categId != null)
{
.....
}
if (filmId != null)
{
......
Button btn_rezerv = (Button)item.FindControl("btn_rezerv");
}
}
protected void btn_rezerv_Click(object sender, EventArgs e)
{
string fid = Request.QueryString["FilmID"];
ShoppingCartAccess.AddItem(fid);
}
}
}
"Server Error in '/' Application.
Invalid postback or callback argument. Event validation is enabled using 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. "
Another problem could be because your PopulateControls method should probably only be called when during the Page Load when it's not a PostBack. I can't tell from above, but to me it looks like it only needs done on Load. Try wrapping that call with this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
PopulateControls();
}
}
It's likely the result of making some sort of client change that the server doesn't know about. Many times this is the result of changing values in a dropdown in JavaScript, for example.
To fix, you could:
Do away with using JavaScript for said modification
Use an UpdatePanel and add your control to it. If the client needs to make a change, trigger the UpdatePanel's update in order for the control's viewstate to update.
Suppose there is a user control in a page called Paging.ascx that is embedded in PageWithResults.aspx. This control has the necessary properties to keep track of various details about what page you're on (ie: CurrentPage, TotalRecordsInResults, RecordsPerPage, etc..). It also contains events that fire off when you click on a hyperlink ("next page" or "previous page"). Example below. I need to tell PageWithResults.aspx that one of these LinkButton web controls was clicked. I think I need to assign a delegate in the page, so that when this user control event is called (hyperlink is clicked), it also calls some other method/event in the page class. That way I can quickly check what the new value of CurrentPage is (based on what was called in the event below) and get a new result set for the new page (based on the CurrentPage property). But I'm not sure of the best approach. I'm thinking this will require a delegate, but I'm not sure how to wire it up. If you need more details, please ask.
protected void btnNext_Click(object sender, EventArgs e)
{
this.CurrentPage = this.CurrentPage + 1;
if (OnPageChanged != null) OnPageChanged(this.CurrentPage);
}
I'm thinking I have to put my delegate here somewhere. ??
protected void btnNext_Click(object sender, EventArgs e)
{
this.CurrentPage = this.CurrentPage + 1;
if (OnPageChanged != null) OnPageChanged(this.CurrentPage);
//delegate to call object.method or something
}
Using an event would work fine.
You would create the event within your UserControl like so:
public event EventHandler ButtonClicked;
Then invoke the event when required:
protected void Button1_Click(object sender, EventArgs e)
{
if (ButtonClicked != null)
ButtonClicked(this, new EventArgs());
}
In your page you would need to assign an event handler:
protected void Page_Load(object sender, EventArgs e)
{
UserControl1.ButtonClicked += new EventHandler(UserControl1_ButtonClicked);
}
void UserControl1_ButtonClicked(object sender, EventArgs e)
{
}
As well as using the above approach you can also cast the Page reference in the UserControl and call a public method directly:
MyPage page = (MyPage)Page;
page.AMethod();
Hope this helps.
I have a problem with a webform.
My Goal: Intially when a page is loading, it has to load every textbox empty. After filling the info and click submit, it has to get submitted(UpdatePaymentInfo())
Problem: Here, When the user fills the info and clicks Submit,it calls onload function even before the submit button and makes all text box empty.
Here is the code:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string QueryStringupdatecreditcard1 = Request.QueryString.ToString();
if (String.Equals(QueryStringupdatecreditcard1, "tabID=B"))
{
divTitle.Visible = false;
trmain.Visible = false;
tdOrderSummary.Visible = false;
trCCandBilling.Visible = true;
trtest2.Visible = false;
divUpdatecreditcard.Visible = true;
trusecompaddress.Visible = false;
txtFirstName.Text = "";
txtLastName.Text = "";
txtAddress1.Text = "";
txtAddress2.Text = "";
txtCity.Text = "";
txtZip.Text = "";
txtCardNo.Text = "";
txtVccNumber.Text = "";
trAmountCharged.Visible = false;
}
}
protected void imgbtnSubmit_Click(object sender, ImageClickEventArgs e)
{
try
{
UpdatePaymentInfo();
}
}
Wrap the current contents of your OnLoad method in:
if (!Page.IsPostBack)
{
// Code in here will only be executed when the page is *not* being loaded by a postback
}
This is because, as per the ASP.NET Page Life Cyle, the things that you care about in this instance happen in this order:
Load - During load, if the current request is a postback, control
properties are loaded with information
recovered from view state and control
state.
Postback event handling - If the request is a postback, control event
handlers are called. After that, the
Validate method of all validator
controls is called, which sets the
IsValid property of individual
validator controls and of the page.
So what happens is (somewhat simplified):
You click the image button, triggering the postback.
The data from your form is loaded into your controls.
Your OnLoad method overwrites the values in the controls to clear them.
Your click handler is run, but because of step 3 it sees empty values.
As others have sort-of mentioned, it wouldn't necessarily be a bad thing to refactor your OnLoad method whilst you're doing this. At the moment you seem to have it doing two distinct things:
Clearing the text fields
Setting the visibility of fields
It might be worth separating this into one or two (depending on if the visibility setting and field clearing will be done independently) separate methods and adjusting your OnLoad method so it looks like this:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsInPostBack)
{
SetFieldVisibility();
ClearFields();
}
}
Page_Load always occurs.
See the documentation on the Page Lifecycle
What you need to do is check to see if the Page_Load is being triggered by a Postback.
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
///do stuff in here that you want to occur only on the first lad.
}
else
}
// code that you want to execute only if this IS a postback here.
{
}
// do stuff you want to do on Page_Load regardless of postback here.
}
You can use the IsPostBack property of the Page as follows:
protected override void OnLoad(EventArgs e) {
if (!Page.IsPostBack) {
EmptyTextBoxes();
}
}
Have you tried wrapping the form reset code in a check to see if the page is a postback?
if(!Page.IsPostback) {
// Do form reset here
}
You thought about using the IsPostBack page variable?
protected override void OnLoad(EventArgs e)
{
if(!IsPostBack){
//all your logic here.
}
}
if it's the case, you might use a databound control and set it to insert mode