ASP.Net Nested Master Pages - How Deep Can You Nest? - c#

This is long, so please bear with me. I just want to lay out the situation as completely as possible...
Regarding master pages in ASP.Net - I know that you can nest master pages and that you can have multiple nested master pages at the same level (the top-level master as the "parent" and multiple "children", which are the first-level-nested master pages). Can you go more than one level deep in nesting master pages (to a "grandchild" nested-master) and still be able to reach up the chain to the top-level master page using the "Master.Master.Master" syntax?
The situation:
I'm working on a C# ASP.Net application. I have a three master pages: Site.master (the top-level master page for the site), SiteWizard.master (nested from Site.master), and WizardTransactionDriver.master (a master page nested from SiteWizard.master).
Relevant markup is as follows:
Site.master:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="RegE_BranchV3.SiteMaster" %>
<body>
<form runat="server">
<div class="container body-content">
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="WizardContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
SiteMaster.cs
namespace SomeNameSpace
{
public partial class SiteMaster : MasterPage
{
#region ===== Properties ====
public TLoginSession LoginSession { get; set; }
}
}
SiteWizard.master - nested under Site.Master
<%# Master Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="SiteWizard.master.cs" Inherits="RegE_BranchV3.SiteWizard" %>
<%# MasterType VirtualPath="~/Site.Master" %>
<asp:Content ID="WizardAnswers" ContentPlaceHolderID="MainContent" runat="server">
<asp:ContentPlaceHolder ID="WizardQuestions" runat="server">
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="TransactionEntry" runat="server">
</asp:ContentPlaceHolder>
</asp:Content>
AffidavitWizardText.aspx - content page linked to SiteWizard.master
<%# Page Title="" Language="C#" MasterPageFile="~/SiteWizard.Master" AutoEventWireup="true" CodeBehind="AffidavitWizardText.aspx.cs" Inherits="RegE_BranchV3.WebPages.AffidavitWizardText" %>
<%# MasterType VirtualPath="~/SiteWizard.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="WizardQuestions" runat="server">
</asp:Content>
And code-behind in AffidavitWizardText.aspx.cs:
namespace somenamespace
{
public partial class AffidavitWizardText : System.Web.UI.Page
{
private TBranchSession fBranchSession;
private IBranchCase2 fBranchCase;
private TLoginSession fLoginSession;
protected void Page_Load(object sender, EventArgs e)
{
Master.Master.LoginSession = TApplLib.LoadLoginSession(Session);
}
}
}
The Master.Master.LoginSession reference works just fine.
WizardTransactionDriver.master:
<%# Master Language="C#" MasterPageFile="~/SiteWizard.Master" AutoEventWireup="true" CodeBehind="WizardTransactionDriver.master.cs" Inherits="RegE_BranchV3.WebPages.WizardTransactionDriver" %>
<%# MasterType VirtualPath="~/SiteWizard.Master" %> <%--SiteWizard--%>
<asp:Content ID="Content1" ContentPlaceHolderID="WizardQuestions" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="TransactionEntry" runat="server">
<asp:ContentPlaceHolder ID="TransactionItem" runat="server">
</asp:ContentPlaceHolder>
</asp:Content>
I have a content page WizardTransactionText.aspx - its master page is WizardTransactionDriver.master
<%# Page Title="" Language="C#" MasterPageFile="~/WebPages/WizardTransactionDriver.master" AutoEventWireup="true" CodeBehind="WizardTransactionText.aspx.cs" Inherits="RegE_BranchV3.WebPages.WizardTransactionText" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TransactionItem" runat="server">
</asp:Content>
WizardTransactionText.aspx.cs - the content-page code-behind:
namespace somenamespace
{
public partial class WizardTransactionText : System.Web.UI.Page
{
private TBranchSession fBranchSession;
private IBranchCase2 fBranchCase;
private TLoginSession fLoginSession;
protected void Page_Load(object sender, EventArgs e)
{
Master.Master.Master.LoginSession = TApplLib.LoadLoginSession(Session);
}
}
}
Visual Studio does not recognize the Master.Master.Master.LoginSession reference above and gives me an error. It recognizes the Master.Master.LoginSession reference in the higher level content page AffidavitWizardText that is bound to SiteWizard.master at the first level of master-page-nesting. Why doesn't it recognize a nested-nested reference? Is there a limit to how many levels (how deep) you can nest master pages?
In this thread, bkaid says "you can nest as many master pages as you like". That can be taken a couple of ways. The example in the article he links to only shows one level of nesting of master pages. Every article and example I've seen only shows one level of master page nesting. Is there something behind the scenes that limits the number of levels that the code recognizes, even though I can create multiple levels of nested master pages when adding items in the Solution Explorer? We don't have a great deal of ASP.net experience here - is there another issue we're missing, or another path to doing this?
Thanks for any help and insight!

Related

content placeholders pages not showing inside master page

I'a currently working on C# aspx.net project, and all of a sudden the pages that should load inside master page are not shown, it's like "hidden", only master page is showing, i didn't do nothing revelant to it, i think.
It's getting me insane because i already loaded a backup that i got, and the same problem occurs. So maybe i did something wrong to my Visual Studio 2019?
Does that ever happened to anyone?
I've tryed to change the Netframework from 4.5 to 4.6 but the problem persists.
if i inspect the page on google devtools, the page's are there, but not showing on the content placehonder.
Example of my master page:
<%# Master Language="C#" AutoEventWireup="false" CodeBehind="Masterpage.Master.cs" Inherits="WORKFLOW_FACTURE.Site1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
....
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<div id="wrapper">
</div>
<div id="page-wrapper">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
<!-- /#page-wrapper -->
</body>
</html>
example of one page that should be loaded whenthe user enter the masterpage:
<%# Page Title="" EnableEventValidation="false" Language="C#" AutoEventWireup="false" MasterPageFile="~/Masterpage.Master" CodeBehind="Indicateurs.aspx.cs" Inherits="WORKFLOW_FACTURE.Indicateurs" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<form runat="server">
....
</form>
<script type="text/javascript">
...
</script>
</asp:Content>
I alredy had that same problem on my asp.net application, where bootstrap classes weren't recognized.
It can happen for two main reasons:
1 - *the links *.css / script .js are being called from the master page at bad order, and because of that, dind't load properly.
2 - Calling bootstrap.css instead of bootstrap.min.css, that happened to me, i think that's because of the load time that can be relevant to the content page.

PreviousPage is null when attempting a cross-page postback using a button and the PostBackURL attribute

I followed the tutorial: Getting Public Property Values from the Source Page on MSDN and I started a fresh Web Forms site and created the below two pages. They work just fine. Now, if I copy paste these into my other Web Forms project then PreviousPage == null. I have no idea what the issue could be. There is no errors whatsoever. I just get
messageSTr.Text = "Not a cross-page post.";
UPDATE: I deleted the MasterPage reference in the page declaration and im still getting the error. I copied this projects web.config to the other working one and it still works. Its not my web config, I am at a complete loss here. This is a vital tool that I need for my application.
This page submits to page 1
<%# Page
Title=""
Language="C#"
MasterPageFile="~/Site.Master"
AutoEventWireup="true"
CodeBehind="WebForm2.aspx.cs"
Inherits="WebApplication5.WebForm2" %>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<asp:Button id="button1" Text="Submit to PostBackUrl" PostBackUrl="~/WebForm1.aspx" runat="server"/>
This page receives the submit
<%# Page
Title=""
Language="C#"
MasterPageFile="~/Site.Master"
AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs"
Inherits="WebApplication5.WebForm1" %>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<asp:Label ID="messageSTr" runat="server"></asp:Label>
WebForm1.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (PreviousPage != null)
{
if (PreviousPage.IsCrossPagePostBack == true)
{
messageSTr.Text = PreviousPage.imaliveStr;
}
}
else
{
messageSTr.Text = "Not a cross-page post.";
}
}
The problem was the FriendlyUrls nuget package was removing the .aspx after my page names so my target page was not WebForm2.aspx but just WebForm2. This made the previous page null.

ASP.NET - How to get to Div control in ContentPlaceHolder?

I've created very simple web site for the test purposes. Only one master page and one content page.
My content page looks like this:
<%# Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<div id="TestDiv1">bla bla</div>
<div id="TestDiv2">ble ble</div>
</asp:Content>
Now, based on some condition I would like to show/hide a given div. So I am trying to reach one of those divs by Controls collection, like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ContentPlaceHolder myContent = (ContentPlaceHolder)this.Master.FindControl("ContentPlaceHolder1");
myContent.FindControl("TestDiv1").Visible = false; //this is not working
}
}
}
}
But the above example is not working. None of the two div control exists in the myContent.Controls collection. If I place for example a TextBox on my content page, I can reach it through Controls.
So what should I do to be able to access the div control?
your divs are HTMLcontrols, try to add them the tag runat="server"
<div id="TestDiv1" runat="server">bla bla</div>
That should solve your issue.
You need to set runat="server" on the divs.

ASP.NET content incode id

I recently started using Masterpages, the thing is I would like to add text in code to an asp:Content tag.
So my content page markup code is:
<%# Page Language="C#" MasterPageFile="~/Template.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ASP_Test_WebApp.Default" %>
<asp:Content id="TEST" ContentPlaceHolderID="Main" Runat="Server" />
So now I would like to add Contents to the "TEST" id incode.
But my in code doesn't recognize TEST. If I don't use a masterpage and I give an id to a tag my in code reconigzes it, but now that I started using masterpages it doesn't.
What am I doing wrong?
Content tags don't have any UI on their own, you need to add controls inside them that you can then address in your code e.g.
<%# Page Language="C#" MasterPageFile="~/Template.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ASP_Test_WebApp.Default" %>
<asp:Content id="TEST" ContentPlaceHolderID="Main" Runat="Server" >
<asp:label runat="server" id="MyLabel"/>
</asp:content>
public partial class Default: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyLabel.Text = "StackOverflow rocks!"
}
}
You don't need that ID. Try to add your content like: this.Controls.Add(mycontentcontrol)

Using nested Master Pages

I'm very new to ASP.NET, help me please understand MasterPages conception more.
I have Site.master with common header data (css, meta, etc), center form (blank) and footer (copyright info, contact us link, etc).
<%# Master Language="C#" AutoEventWireup="true" CodeFile="Site.master.cs" Inherits="_SiteMaster" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="tagHead" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="styles.css" type="text/css" />
</head>
<body>
<form id="frmMaster" runat="server">
<div>
<asp:ContentPlaceHolder ID="holderForm" runat="server"></asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="holderFooter" runat="server">Some footer here</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
and I want to use second master page for a project into sub directory, which would contains SQL query on Page_Load for logging (it isn't necessary for whole site).
<%# Master Language="C#" AutoEventWireup="true" CodeFile="Project.master.cs" Inherits="_ProjectMaster" MasterPageFile="~/Site.master" %>
<asp:Content ContentPlaceHolderID="holderForm" runat="server">
<asp:ContentPlaceHolder ID="holderForm" runat="server" EnableViewState="true"></asp:ContentPlaceHolder>
</asp:Content>
<asp:Content ContentPlaceHolderID="holderFooter" runat="server">
<asp:ContentPlaceHolder ID="holderFooter" runat="server" EnableViewState="true"></asp:ContentPlaceHolder>
</asp:Content>
But I have a problem: footer isn't displayed.
Where is my mistake? Am I right to use second master page as super class for logging?
Project page looks like this:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" MasterPageFile="~/Project.master" %>
<asp:Content ContentPlaceHolderID="holderForm" runat="server">
<p>Hello World!</p>
</asp:Content>
<asp:Content ContentPlaceHolderID="holderFooter" runat="Server">
Some footer content
</asp:Content>
I've been working with nested master pages and have run in to something similar. From what I see where you have "Some footer here" in the Site.Master is where the problem lies and I've had similar problems with having content with-in a contentplaceholder tag. if you try this instead
<asp:ContentPlaceHolder ID="holderFooter" runat="server"/>Some footer here
Then you should be able to see the footer content.
I'm not sure I'd use master pages for this. If it's really just going to do logging, I'd implement IHttpModule, register it in web.config, and then check whether or not to log based on the path of the request. I think of master pages as being about content rather than other processing such as logging.
See the IHttpModule walkthrough on MSDN for an example - in your BeginRequest handler, you'd probably check the request path and log appropriately if it matched.
Apologies if I misunderstood what you're trying to do though.
You should leave your ContentPlaceHolder empty, for it gets substituted by the content of the Content in your actual Page...
When you move the "Some footer here" text to your Content, you will see your lines of text :)
HTH
This link gives a simple explanation on Master pages,
http://waxtadpole.wordpress.com/2009/01/16/master-page-content-not-visible-visual-studio-2008/
The question are you right to use child Master pages in this instance - I would say master pages should be helping you solve issues around building a consistent layout, not for whether or not logging should occur.
The problem is, when the text elements placed inside Default.aspx are put in their relative Content Placeholders, they are written on the placeholders of your Site.master page and not those of Project.master (which have the same names).
You should resolve the naming conflict, by assigning different ContentPlaceHolderIDs to the the placeholders in Project.master (this means you'll also have to change the references in Default.aspx).
This would be your Project.master file:
<%# Master Language="C#" AutoEventWireup="true" CodeFile="Project.master.cs" Inherits="_ProjectMaster" MasterPageFile="~/Site.master" %>
<asp:Content ContentPlaceHolderID="holderForm" runat="server">
<!-- whatever... -->
<asp:ContentPlaceHolder ID="holderFormInternal" runat="server" EnableViewState="true"></asp:ContentPlaceHolder>
<!-- ... -->
</asp:Content>
<asp:Content ContentPlaceHolderID="holderFooter" runat="server">
<asp:ContentPlaceHolder ID="holderFooterInternal" runat="server" EnableViewState="true"></asp:ContentPlaceHolder>
</asp:Content>
And thus, your .aspx pages that use the Project master page instead of the global Page.master must be changed to:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" MasterPageFile="~/Project.master" %>
<asp:Content ContentPlaceHolderID="holderFormInternal" runat="server">
<p>Hello World!</p>
</asp:Content>
<asp:Content ContentPlaceHolderID="holderFooterInternal" runat="Server">
</asp:Content>
If the only reason is to implement loggin why would you mess around with masterpages?
If the logging isent supposed to display any text!?
You either do as Skeet proposed with an IHTTP handler.. Or lazier one would be do have a class that derives from webpage and implement logging in that class and make your pages that need logging dervice from that..
ex:
public class LoggingPage : : System.Web.UI.Page
{
public override void OnLoad()
{
// Do logging
}
}
partial class OneOfTheWebPages : LoggingPage
{
public void onLoad()
{
base.onLoad();
}
}
I may be misunderstanding your problem - but from the code you've posted, there isn't anything in the footer.
In your Project page, the <asp:Content> tag for the holderFooter content place holder doesn't have anything in it.
I have next inheritance tree:
Site.master <-- Page1.aspx
<-- Project.master <-- Page2.aspx
And I don't know why Page2 display only content of itself and it's master page - Project. But doesn't display a content of Site (as Page1 does) Why? What have I to write for doing that?

Categories

Resources