Changing Session in page postpack and using new value in Master Page - c#

I am trying something which is starting to get weird but in principle it sounds normal. Basically I have a MasterPage in my ASP.NET application that takes care of showing the usual Login/Logout box in all pages. When the user is logged in, the usual "Welcome {Name}" appears.
The logged-in user details come from the Session.
Now I have a profile page where the user can change his/her name, which is all normal. As part of the Page Postback after editing, I update the Session with the new User Details.
What I would like to see happening is that the "Welcome" message would show the new Name if the user changed it.
I have digged a bit in the lifecycle and indeed given that the Session is accessed in the Page_Load but then updated in the UpdateButton_Click, the Welcome message is already updated before the Session is changed.
Does anyone have any idea on how to force a refresh for the Master Page or maybe there is something else I need to consider in terms of design?
I have also tried putting the Login/Logout box into a UserControl but things did not change.
Here are more details as requested:
MasterPage on PageLoad (accountMenuTitle is just a Label):
var loggedInUser = (Customer) Session["LoggedInUser"];
accountMenuTitle.InnerHtml = loggedInUser.Name;
ProfilePage Button_Click:
var updatedCustomer = update_Customer_Profile(txtFirstName.Text,
txtLastName.Text, txtAlternateEmail.Text, ... etc. etc.);
Session["LoggedInUser"] = updatedCustomer;
So when I click the button in the profile page, the page reloads, the logged-in User is updated in the Session but the Master Page Load already happened and the label shows the old name.

Dont set a Control in Page_load but directly render the value in the MasterPage.
MasterPage
<div class="title">
<h1>
<% if (Session["UserName"] != null)
{ %>
<%= Session["UserName"] %>
<% } %>
</h1>
</div>
Eventhandler
protected void Button1_Click(object sender, EventArgs e)
{
Session["UserName"] = this.TextBox1.Text;
}

The solution I implemented in the end relies on the Master Page exposing a method for updating itself.
Master Page:
public void UpdateLoginPanel()
{
if (Session["LoggedInUser"] == null) // logged out
{
accountMenuTitle.InnerHtml = "Log in";
}
else // logged in
{
var loggedInUser = (Customer) Session["LoggedInUser"];
accountMenuTitle.InnerHtml = loggedInUser.Name;
}
}
In the Profile page aspx file, you can expose your Master Page like this:
<%# MasterType VirtualPath="~/CustomerPortal.Master" %>
Then in the codebehind button click:
var updatedCustomer = update_Customer_Profile(txtFirstName.Text,
txtLastName.Text, txtAlternateEmail.Text, ... etc. etc.);
Session["LoggedInUser"] = updatedCustomer;
Master.UpdateLoginPanel();
I'm still a bit undecided if this is cleaner than Malcolm's answer to be honest :/

Hi way you have chosen here is correct..
You have defined Master directive so all properties and other access you have now..
One thing I want to share with you why you not set master page property directly from content page instead of calling UPDATEPANEL method(anyway choice is your)
Other thing I can see you have used session...you cam use VIEWSTATE.

Related

Set Master page content from one content page

I have my master page. I need to assign the logged user from the content page.
I am using the following code from the landing page
var currentUser = Membership.GetUser();
Label lblLoggedUser = (Label)Master.FindControl("lblLoggedUser");
lblLoggedUser.Text = currentUser.UserName;
But It goes off while I redirect to another page.
How can I set the master page content from one single page ?
PS- I am using membership providers for teh log in.
I believe what you are saying is that when the user visits the landing page then your listed code executes and sets the user name into the master page. But when they leave the landing page the user name becomes blank. You are trying to set the value once into the master page from the landing page and have it remain for subsequent pagas.
A better approach it to just have the master page set that value. Having the master page be responsible for master page controls frees the individual pages to focus on just their logic.
Move the code into the master page's Page Load or PreRender event.
void Page_PreRender(object sender, EventArgs e)
{
var currentUser = System.Web.Security.Membership.GetUser();
if (currentUser != null && currentUser.IsOnline)
this.lblLoggedUser.Text = currentUser.UserName;
else
this.lblLoggedUser.Text = "not authenticated";
}

Session in master page asp.net

I have master page containing login and logout button.
I want it visible and invisible when session["Userid"] is null.
How can I do that?
I know how to make visible and invisible
code is:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//string s = Session["UserId"].ToString();
if (Session["UserId"] != null)
{
divLogin.Visible = true;
divLogout.Visible = false;
}
else
{
divLogin.Visible = false;
divLogout.Visible = true;
}
}
Please help.
You can also achieve this with this code in HTML. Try,
<div id="divLogin" style="display: <%= Session["UserId"]!=null ? "none" : "block" %>">Your Login content</div>
<div id="divLogout" style="display: <%= Session["UserId"]==null ? "none" : "block" %>">Your Logout content</div>
You must set runat="server" for the div.
<div id="divLogin" runat="server"></div>
Code Behind
divLogin.visible=false;
Use the logic in OnPreRender function as user login & logout always occurs after OnInit is called for the master page. So, during refresh you will get proper values but not the first time.
From MSDN you can find the below information
Master pages behave like child controls on a page: the master page Init event occurs before the page Init and Load events, and the master page Load event occurs after the page Init and Load events.
What I think is (most probably) you are setting the user's login information in the Login page's buttonClick event handler, which gets called after the OnInit of the master page. So when the master page's OnInit gets executed, Session already contains previous state (null during login and user information during logout)
Even if the login controls and login button are provided on the Master page, it is better to provide this logic in PreRender event.
Glad to help! Please remember to accept the answer if you found it helpful.

Change label in masterpage in just one content page

How do I define a label in a masterpage from inside one control page, withouth losing it when I navigate to another control page? I know that I can use this code and it works:
(Master.FindControl("myControl") as Label).Text = "someNewContent";
But I have to define this on every page to keep the same content in the label. Is there a easier/shorter way to define this piece of code only one time in the whole program? Thanks in advance.
I think I get the gist of what you're asking:
Firstly, I would strongly type the master page, in your content page just below the #Page directive, by using the #MasterType directive:
<%# MasterType TypeName="*fully qualified type of your master page*" %>
Next, place a public property on your master page, like so:
public string MyText
{
set { this.ViewState["TheText"]; }
}
In your content page (during the Page_Init, for instance) you can add:
this.Master.MyText = "Whatever you want to say!";
Then load your master pages control text property in the Page_Load event:
protected void Page_Load(object sender, EventArgs e)
{
this.myControl.Text = Convert.ToString(this.ViewState["TheText"]);
}
This won't persist from content page to content page because each content page instantiates a new instance of the master page. In that case, put whatever text you want to persist in Session, then read it in the mater pages Page_Load event.
Hope this answers your question.

Hide Master page controls

I want to hide master page table from the content page.
I have tried to hide the table control in different ways but I get following error message on line:
tbl = (HtmlTable)Page.Master.FindControl("tbl_login");
ERROR:
Object reference not set to an instance of an object.
Here is the table control on the master page and the code for hidding master page control from the login page.
There is a page called POView and it has got one link button to Approve PO and it shows POP up window which has got few controls defined one master page(text box and two button in html table) when you hit the button it sends the request to another page called Login which authenticate user password and do some updates in DB and then show the message to this POP up window (response.write).
All i want is to hide the controls (textbox and button defined on master page) from this login page.
NOTE: That Login page doesn't have any reference tag for the master page.
# Page Language="C#" AutoEventWireup="true" CodeFile="login.aspx.cs" Inherits="login" %>
ADDED: Here is the function which is called onClick of Master page button. It is sending request to login page.
function showHint(str, str2, str3, reason)
{
gDiv = 'appFeedback';
xmlHttp=GetXmlHttpObject();
if (xmlHttp==null)
{
alert ("Your browser does not support AJAX!");
return;
}
//replace "tricky" chars in QS
var pwd= str.replace('£','!!pound!!');
pwd= pwd.replace('£','!!pound!!');
pwd= pwd.replace('£','!!pound!!');
pwd= pwd.replace('£','!!pound!!');
pwd= pwd.replace('&','!!and!!');
pwd= pwd.replace('&','!!and!!');
pwd= pwd.replace('&','!!and!!');
pwd= pwd.replace('&','!!and!!');
var url="login.aspx";
url=url+"?q="+pwd;
url=url+"&q2="+str2;
url=url+"&q3="+str3;
url=url+"&reason="+reason;
url=url+"&entity=<%= Request["entity"] %>";
url=url+"&sid="+Math.random();
xmlHttp.onreadystatechange=stateChanged;
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}
Try To call this javascript After doing the login window.opener.document.getElementById("tbl_login").style.visibility="hidden";
In you code it is given as
xmlHttp.onreadystatechange=stateChanged;
Here the "stateChanged" must be a javascript function which will be fired after doing the login.
Inside that function you can write the code to hide.
for more information about the readystatechangedevent please look into this :http://www.w3schools.com/ajax/ajax_xmlhttprequest_onreadystatechange.asp
Return success from Loginpage
//After doing the Logic return the status (foreg:- i return here as "success")
Response.Clear();
Response.ContentType = "text/plain";
Response.Write("success");
Response.End();
When content page have directive
<%# MasterType VirtualPath="~/Main.Master" %>
you have access to content of master page. Now, if you make method on master page that just hidding your table - something like this
public void SetTableUnvisible()
{
tbl_login.Visible = false;
}
you can call this method on Page_Load event of content page
Master.SetTableUnvisible();
and your table is no more visible.
It sounds like you're trying to always remove the table, even though one or more pages don't even contain the table since they don't reference the master page anyway. Is that correct?
If so, your code will be falling over because you're dereferencing Page.Master anyway, even though it won't always exist. Try this, which checks to see whether there is a master page before trying to use it:
MasterPage master = Page.Master;
if (master != null)
{
tbl = master.FindControl("tbl_login") as HtmlTable;
if (tbl != null)
{
tbl.IsVisible = false;
}
}
If your login page doesn't use the master page then you can't do it on server but with client side code only. Make a script method that hides the table. You can insert it in the master page:
<script type="text/javascript">
function hideTable()
{
$('#<%=tbl_login.ClientID%>').hide();
}
</script>
In the login page:
ClientScript.RegisterStartupScript(this.GetType(), "hide", "hideTable();", true);
BTW, if you want to do anything in the master page, don't try to find controls on it from your page. Write a method in the master page that do it and call it from your page. You'll need to cast Master to the master type, or put a master type in the master directive that do it for you.

Session variable and Masterpages

I want to log a users session on my site. I was hoping to just set a session variable. But the initialisation of it is giving me problems.
protected void Page_Load(object sender, EventArgs e)
{
if (Session["SESSION_GUID"] == null)
{
Session["SESSION_GUID"] = Guid.NewGuid().ToString();
Response.Redirect(Request.Url.ToString(), true);
return;
}
lnkUpload.Visible = (Session["LOGGED_IN"] != null);
btnLogout.Visible = (lnkUpload.Visible);
}
It seems that the masterpage is creating the variable OK, but the rest of the pages load (ones using that master page). So in my log, I am seeing TWO hits. One with no session ID set, and the second hit has a session id.
Any idea why the child page of this masterpage is loading twice? This only happens on the first request to the site. After that, the session is working fine and we only get one hit.
The Page_Load event of the content page will be called before the Page_Load of the master page as seen in steps 6-7 in the ASP.NET Page Lifecycle
The master page Page_Init event is called before the content page Page_Init event though, so if all you're doing is checking for Session, probably best to handle it in the Page_Init of the master page and redirect there. This could cause problems based on how other code in your project looks but conceptually, one of the first things you are wanting to do is check Session and handle properly so, you don't need page/controls to load before handling the redirect.
Try doing a Response.End() in the master page. This will halt the remaining markup from being rendered.

Categories