Why is Page.PreviousPage always null? - asp.net

I am experimenting with cross-page posting by following this MSDN article. I have this code:
CrossPagePosting1.aspx
<form id="form1" runat="server">
<h1>Page 1</h1>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />
<asp:Button ID="Button1" runat="server" Text="Button" PostBackUrl="CrossPagePosting2.aspx"/>
</form>
CrossPagePosting2.aspx
<form id="form1" runat="server">
<h1>Page 2</h1>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</form>
CrossPagePosting2.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
TextBox TextBox1 = (TextBox)Page.PreviousPage.FindControl("TextBox1");
Label1.Text = TextBox1.Text;
}
This code above produces a NullReferenceException at Page.PreviousPage. Why?
This is an ASP.Net 4.0 application.
It uses FriendlyUrls, which is the default.
NOTE: I do NOT want the previous page to be strongly-typed, e.g. using the PreviousPageType directive. According to the referenced article, this shouldn't be necessary.

I found that Friendly URLS might get you this problem. By default, the Web Forms template includes ASP.NET Friendly URLs.
When you use the default WebForm from visual Studio, the AutoRedirectMode is set to Permanent. This makes you request into a "GET" and since you are using Friendly URLS, you can’t evaluate the PreviousPage.
Workarounds:
If you want a "POST" action then set the AutoRedirectMode =
RedirectMode.Off (this will give you PreviousPage info but only from
non-Friendly-Url pages [ex: www.you.com/mypage.aspx], however this
will get you an error if you try to access the Friendly-Url page [ex:
www.you.com/mypage] << no .aspx).
If you want the PreviousPage information you will have to set the
previous post directive in you webpage <%# PreviousPageType
VirtualPath="~/Page1.aspx" %> OR maybe use the Server.Transfer in a
OnClick Method.

The problem here was being caused by FriendlyUrls, which were installed by default on the test site I was working in. I disabled FriendlyUrls, and it worked.

I think following article will helps you.
http://csharpdotnetfreak.blogspot.com/2009/08/cross-page-posting-in-aspnet.html
there are two method how to use Cross Page Posting PostBack

The reason this is happening is simply because you did not set the postbackurl property correctly.
If CrossPagePosting2.aspx is at root of your program change postbackurl to ~/CrossPagePosting1.aspx
You do not need to add the <%# PreviousPageType %> directive when using postbackurl property. using PreviousPage.FindControl(id) will search the form elements that are posted using postbackurl property

Try this
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack && PreviousPage != null)
{
Page page = PreviousPage;
Label1.Text = ((TextBox)page.FindControl("TextBox1")).Text;
}
}

Related

Using Code Nuggets as property values

I have the following code
<asp:Content ID="Content1" runat="server">
<asp:Label runat="server" ID="Label1" Text="<%= MyHelperClass.Value%>"></asp:Label>
<%= MyHelperClass.Value%>
</asp:Content>
The Label doesn't work, it has the Text <%= MyHelperClass.Value%> the next row returns the expected value.
Question: can i use those code nuggets to set values of the property of an control?
Why it's working outside and not with Control?
Well <%= %> is called Content Code Nuggets because they inject content in the html which is sent by server to browser. It does the work of Reponse.Write. We use this mainly to call any code written in code behind file for example, you have a simple method in your code behind:-
public string UserCity()
{
return "London";
}
Then you can call it from aspx page like this:-
You live in <%= UserCity() %>.
Content code nuggets used to inject the html to response at the last in PreRender event and thus it's called late binding. This is the main reason why it is NOT working with your control.
How to fix this?
You can use the data binding code nuggets (<%# %>). These are used with DataBound controls but you can force the Page's DataBound or control's DataBound method to bind your control like this:-
<asp:Label runat="server" ID="Label1" Text="<%# MyHelperClass.Value%>"></asp:Label>
Call DataBind method in code behind:-
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Page.DataBind();
}
}

Using same form on multiple pages?

I am writing an application, and I have a user form, which will be the same for the users and the administrators on different pages.
I want to only create the form once, and then be able to put it on two different aspx files.
I tried it with the "control", but it then gets really complicated trying to access fields on the control from the aspx page to do the calculation, etc.
is there another way to do this? creating a form in one place, be able to add it to any aspx page, and have easy access to it's controls?
It's not very difficult at all. You can provide an accessor method or make the control inside public.
Example: A page which displays the contents of a TextBox inside a control, when a button is pressed.
Control
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
Page
<form runat="server">
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<Test:Control ID="ctlTest" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</form>
Code (If TextBox1 is public)
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = ctlTest.TextBox1.Text;
}
Or you could have, in the code of the control
public string GetText()
{
return TextBox1.Text;
}
And in the aspx code page
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = ctlTest.GetText();
}
What is so difficult about that?!
you have to create MasterPage:
http://msdn.microsoft.com/en-us/library/wtxbf3hh.aspx
so that you can share common controls between pages. Master pages can be nested, too. You can access controls on master page from child page via Master.FindControl("abc")
EDIT: it seems that you want to reuse common piece of functionality, then you might want to use user control, like in this example:
http://msdn.microsoft.com/en-us/library/3457w616.aspx
you created the control, and do not use findControl() method to access the control that inside you UserControl, that is not feasible or proper solution.
Better to use Properies. Define Properties, so your control can be generalised and you can use that on multiple pages.

DropDownList's SelectedIndexChanged event not firing

I have a DropDownList object in my web page. When I click on it and select a different value, nothing happens, even though I have a function wired up to the SelectedIndexChanged event.
First, the actual object's HTML code:
<asp:DropDownList ID="logList" runat="server"
onselectedindexchanged="itemSelected">
</asp:DropDownList>
And this is that function, itemSelected:
protected void itemSelected(object sender, EventArgs e)
{
Response.Write("Getting clicked; " + sender.GetType().ToString());
FileInfo selectedfile;
Response.Write("<script>alert('Hello')</script>");
foreach (FileInfo file in logs)
{
if (file.Name == logList.Items[logList.SelectedIndex].Text)
{
Response.Write("<script>alert('Hello')</script>");
}
}
}
None of the Responses appear, and that portion of JavaScript is never run. I've tried this on the latest 3.6 version of Firefox, as well as Internet Explorer 8. This is being served from a Windows Server 2003 R2 machine, running ASP.NET with the .NET Framework version 4.
Set DropDownList AutoPostBack property to true.
Eg:
<asp:DropDownList ID="logList" runat="server" AutoPostBack="True"
onselectedindexchanged="itemSelected">
</asp:DropDownList>
try setting AutoPostBack="True" on the DropDownList.
I know its bit older post, but still i would like to add up something to the answers above.
There might be some situation where in, the "value" of more than one items in the dropdown list is duplicated/same. So, make sure that you have no repeated values in the list items to trigger this "onselectedindexchanged" event
Add property ViewStateMode="Enabled" and EnableViewState="true"
And AutoPostBack="true" in drop DropDownList
Also make sure the page is valid.
You can check this in the browsers developer tools (F12)
In the Console tab select the correct Target/Frame and check for the [Page_IsValid] property
If the page is not valid the form will not submit and therefore not fire the event.
For me answer was aspx page attribute, i added Async="true" to page attributes and this solved my problem.
<%# Page Language="C#" MasterPageFile="~/MasterPage/Reports.Master".....
AutoEventWireup="true" Async="true" %>
This is the structure of my update panel
<div>
<asp:UpdatePanel ID="updt" runat="server">
<ContentTemplate>
<asp:DropDownList ID="id" runat="server" AutoPostBack="true" onselectedindexchanged="your server side function" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
Instead of what you have written, you can write it directly in the SelectedIndexChanged event of the dropdownlist control, e.g.
protected void ddlleavetype_SelectedIndexChanged(object sender, EventArgs e)
{
//code goes here
}

TemplateField button causing GridView Invalid Postback

Ok, so I've got a template field in a gridview that contains just a simple button...
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Administration.aspx.cs"
Inherits="Administration" %>
<%# Register TagPrefix="ajaxToolkit" Namespace="AjaxControlToolkit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Keywords Administration</title>
</head>
<body class="popupbody">
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" EnablePartialRendering="true" CombineScripts="false"></ajaxToolkit:ToolkitScriptManager>
<asp:Label ID="AddLabel" runat="server">Add a Keyword</asp:Label>
<br />
<asp:TextBox ID="AddTextBox" runat="server" />
<asp:Button ID="AddButton" Text="Add" runat="server" OnClick="AddKeyword_Click" />
<asp:GridView ID="KeywordsGridView" AllowPaging="false" AutoGenerateColumns="false" BackColor="white"
GridLines="None" HeaderStyle-CssClass="Table_Header" RowStyle-CssClass="Table_Style"
OnRowDataBound="RowBound" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="References" SortExpression="References" HeaderText="Total References" />
<asp:BoundField DataField="Keyword" SortExpression="Keyword" HeaderText="Keyword" />
</Columns>
</asp:GridView>
</form>
</body>
</html>
Whenever I click the button I get the error...
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.
I've found a decent amount of articles referencing this issue, including a couple on SO, for example...
Invalid postback or callback argument. Event validation is enabled using '<pages enableEventValidation="true"/>'
and...
Invalid postback or callback argument
I might just be misunderstanding, but as far as I can tell they don't really help me. How do I get this to go away without setting enableEventValidation="false"?
EDIT Posted all the code for my page.
I know this post is old, but I also had this problem recently.
After checking the how the code was generated for the asp:ButtonField and also for the asp:Button that I have added in an ItemTemplate I discovered quite a big difference:
asp:ButtonField:
input type="button" onclick="javascript:__doPostBack('ctl00$ctl00$cphMain$cphContent$gvEmails','SendFromBatch$0')" value="Continue">
asp:Button:
input id="ctl00_ctl00_cphMain_cphContent_gvEmails_ctl02_btnCont" type="submit" onclick="FreezeScreen('Emails are being sent...');" value="Continue" name="ctl00$ctl00$cphMain$cphContent$gvEmails$ctl02$btnCont">
The Type was the problem! So, after i changed the UseSubmitBehavior from "Submit" to "False" I did not get the error anymore.
EDIT:
I recently wanted to change from the normal btns to imgBtns so that I can save some space and also make the gridview nicer :D. Of course I had the same problem popping up and the imagebtn does not have UseSubmitBehavior property, so I started looking after a solution.
Found the following (The code below is in a UserControl).
1) Bind in !IsPostBack
2) Register the usercontrol itself in the Render
and everything works just as planned - no validation errors.
protected void Page_Load(object sender, EventArgs e)
{
OnLoadingEvent(new EventArgs());
if (!Page.IsPostBack)
{
gvEmails.DataSource = odsEmails;
try
{
gvEmails.DataBind();
}
catch (Exception)
{
}
}
if (!writeText) divWriteEmail.Visible = false;
}
protected override void Render(HtmlTextWriter writer)
{
Page.ClientScript.RegisterForEventValidation(this.UniqueID);
base.Render(writer);
}
EDIT:
I was playing around with the code above and asked myself, what if you actually need to rebing your objectdatasource - what happens then? Well the code above will not work if you rebind in the page load, because the gridview will be rebound again when you click a btn in the gridview's row and it will not be recognized as being generated on the server. Fair and square, but how to avoid this behaviour? Well... i figured out a way, maybe not the best but it does the trick.
Actually, you do not want to rebind the gridview when you click a btn on the gv's row... but how do we know that since the page load method is first called? Well, actually i do not want to rebind the gridview if the select param of the object data source do not change. So, I keep the select param of the objectDataSource in the session view and I rebind my gridview only when one of them changes - this behaviour is only during the PageLoad event. In order to see latest rows i click refresh and get the latest rows with no problem and at the moment i click a gvRow btn, the error dissapears.
To make all of this happen you have to
Directly call the .Select() of the object data source
Catch the OnSelecting event from the datasource, save the select param set the e.Cancel = true
Check if the select param are different and then bind the gridview and this time when catching the OnSelecting you have to set e.Cancel = false in order to retrieve the data from the DB - only one time.
Hope this helps!
This fellow found a solution to a similar problem (scroll down to about the 4th comment), which was to set unique id's for the GridView buttons.
I had the similar error today but with a different solution. I've worked with gridviews for years now and never had the issue so I figured it must be something stupid. Turns out I had forgotten to put my code that loads the gridview into a if(!Page.IsPostBack) block which caused the button to be recreated after I clicked it, thus causing the error. Placing the loading code in said block eliminated the issue.
You need to give your button an ID. Just a runat="server" does not meet the minimum information that needs to be provided for a server control to be created.

ASP.NET linkbutton visible property issue

I'm using a public variable called IsAdmin in the code behind of an aspx page.
public partial class _news : System.Web.UI.Page
{
public bool IsAdmin = false;
protected void Page_Load(object sender, EventArgs e)
{
if (User.Identity.Name.Contains("admin"))
{
IsAdmin = true;
}
else
{
IsAdmin = false;
}
}
And i use the property Visible='<%#IsAdmin%>' to assign to panels which i want to show if the user is an admin in the aspx design of the page. Strangely it works for the linkbuttons i've put on the repeater.
<asp:Panel ID="Panel1" runat="server" Visible='<%#IsAdmin%>'>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl='<%# "news_edit.aspx? Action=edit&id=" + Convert.ToString( Eval("news_id")) %>Edit</asp:LinkButton>
<asp:LinkButton ID="LinkButton3" runat="server" PostBackUrl='<%# "news.aspx?Action=delete&id=" + Convert.ToString( Eval("news_id")) %>'>Delete</asp:LinkButton>
</asp:Panel>
and it works fine, however outside the repeater i've put another linkbutton without a panel
<asp:LinkButton ID="LinkButton4" runat="server" PostBackUrl="~/news_edit.aspx?action=new" Visible='<%#IsAdmin%>'>Add New Item</asp:LinkButton>
but the visible property doesn't work on it! I tried putting it inside a panel too and setting it's visible property but that too didn't work.
So i have following doubts
1)what is the issue?
2)what is the technical name when we use references like '<%#IsAdmin%>' in the design page
3)Does page load happen before page is rendered of after page is rendered?
Thanks
<%# %> is the syntax used for accessing databound fields. Since you are likely databinding the Repeater control at some point, these expressions will be evaluated.
Since you are likely not calling databind on the Panel and the Linkbuttons outside of the Repeater, these expressions will not be processed. You can probably change them to something like
<%= IsAdmin.ToString() %>
and get the result you want.
Check this great blog entry for more information on the differences.
Also, Page Load happens before the page is rendered. Rendering the page is the last thing that happens in the ASP.Net page lifecycle.

Resources