PDA

View Full Version : .net: How to include the contents of one aspx page in another?


david7777
05-05-2003, 04:12 PM
I am trying to create the best navigation system fo my site.

First of all - any suggestions on the best way?

I have the idea of using a main.aspx page as a template, and passing the page i want displayed like this: main.aspx?p=default

Then in the code of main.aspx i will have the menu set up and ready, and want to include the contents of "default.aspx" in the page.
So for instance - main.aspx?p=default is called.
main.aspx has a table with a menu on the side, and and a footer. The main part of the page is blank for the body.
I will get the name of the page requested - ie: default.
I will only use .aspx files, so therefore, default.aspx.

Now include default.aspx in the allocated section of the table in main.aspx. eg: <!--#include file="default.aspx" -->(I know that way wont work - just an example)
How do i do that?

Keep in mind that .aspx files are being used, so the server side code must be run before displayed...

angiras
05-05-2003, 07:04 PM
for the moment you have two good way to do a kinds of page Template

1)

class basePage : inherits Page

the your pages will not inherits Page but basePage

2)
you do a template.ascx inherits userControl

with all your page in it and you load it

this second way (which is not mine)is developped by microsfot as masterPages

----------------------

an exemple of inheritance :


Namespace heritage

Public MustInherit Class pageTemplate : Inherits Page



Protected form As HtmlForm



Sub New()

MyBase.new()

form = New HtmlForm()

form.ID = "frm"

End Sub



Protected Overrides Sub OnInit(ByVal e As System.EventArgs)



End Sub



Protected Overrides Sub AddParsedSubObject(ByVal obj As Object)

form.Controls.Add(CType(obj, Control))

End Sub



Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)

EnsureChildControls()

Me.Controls.Add(form)

End Sub



Protected Overrides Sub Render(ByVal w As System.Web.UI.HtmlTextWriter)



w.WriteLine("<?xml version=""1.0"" encoding=""iso-8859-1""?>")

w.WriteLine("<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">")

w.WriteLine("<html xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""fr"">")

w.WriteLine("<head>")

w.WriteLine("<meta http-equiv=""Content-Type"" content=""text/html; charset=iso-8859-1"" />")

w.WriteLine(metasTags.metas)

w.WriteLine("</head>")

w.WriteLine("<body>")

MyBase.Render(w)

w.WriteLine("</body>")

w.WriteLine("</html>")



End Sub



End Class



Public Module metasTags



Private _title As String

Private _keywords As String

Private _description As String



Private _metas As String = "<title>{0}</title><meta name=""keywords"" content=""{1}"" /><meta name=""description"" content=""{2}"" />"



Public ReadOnly Property metas() As String

Get

sb = New StringBuilder()

sb.AppendFormat(_metas, title, keywords, description)

Return sb.ToString

End Get

End Property



Public Property title() As String

Get

Return _title

End Get

Set(ByVal Value As String)

_title = Value

End Set

End Property



Public Property keywords() As String

Get

Return _keywords

End Get

Set(ByVal Value As String)

_keywords = Value

End Set

End Property



Public Property description() As String

Get

Return _description

End Get

Set(ByVal Value As String)

_description = Value

End Set

End Property



End Module

End Namespace



default.aspx


<%@ Page Codebehind="default.aspx.vb" Inherits="test.masterPage.heritage.mainPage" %>



default.aspx.vb


Namespace heritage

Public Class mainPage : Inherits pageTemplate



<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

End Sub



Private Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Init

InitializeComponent()

End Sub



Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load



If Not Page.IsPostBack Then

title = "new title"

keywords = "1, 2, 3"

Description = "description try"

End If

form.Controls.Add((New LiteralControl("page content")))



End Sub



End Class

End Namespace

david7777
05-06-2003, 08:01 AM
Thanx a lot angiras :thumbsup:

So is using a page template the best way? I just dont want to go through the trouble of what seems to be quite a big job, and then realise there is a better way...

Forgive me, but I am still learning ASP.net, so i havent worked with classes yet... - Im not too sure on how this all works, but ill give it a try and get back to you if i have any problems... Thanx again!

david7777
05-06-2003, 08:21 AM
<%@ Page Codebehind="default.aspx.vb" Inherits="test.masterPage.heritage.mainPage" %>


Where does the text in bold red come from? why test.masterPage.heritage.mainPage?

I used the code you gave me, with the first part of code in template_page.vb. The second part in default.aspx and the 3rd in default.aspx.vb

I get the error - Could not load type 'test.masterPage.heritage.mainPage'.


Did i do something wrong?

angiras
05-06-2003, 08:29 AM
test.masterPage.heritage.mainPage

test.masterPage is my nameSpace Root

then I have a class with

Namespace heritage


and the class itself has name mainPage



for exemple you build an application =

then your root namespace will be david and your dll = david.dll

then you can create a group of pages under another (sub)namespace


namespace Admin

it will be then david.Admin

and any class under this namespace will be


class AnyClass


david.Admin.AnyClass

I hope it is clear enough :-((

it's a way to organize your application

angiras
05-06-2003, 08:31 AM
if you want to avoid inheritance you can try ascx file with all the content in it

david7777
05-06-2003, 08:36 AM
Oh ok! :D

That makes sense!

Do you know of any good sites i can check to learn how to use all that? Like dll's (how to create and compile) and namespaces and so forth...

It would be easier just to ask you how to create my namespace root, but thats not going to help me, is it? :confused:

Thanx alot for you help! :thumbsup:

david7777
05-06-2003, 08:39 AM
Posts crossed...
if you want to avoid inheritance you can try ascx file with all the content in it
no - i want to do this the propper way... I need to learn the hard stuff - it is there for a reason, and needs to be used :)

angiras
05-06-2003, 09:25 AM
you said : no - i want to do this the propper way
but microsoft itself use ascx as masterPage

I use it if I work with a designer, for myself I use inheritance

I have join here a Zip from microsft masterPages you can have a look

-------------------------

for dLL (how to create and compile) if you have visual studio it does it alone, otherwise you have a bat file into the zip which will compile it

david7777
05-06-2003, 10:50 AM
I appreciate that - thanx a lot! :thumbsup:

david7777
05-06-2003, 12:13 PM
I have tried to use the files you gave me in the zip, but it doesnt work... I have never run c# on my IIS, but im sure that shouldn't be a problem?

I get the error:

Parser Error Message: File or assembly name MasterPages, or one of its dependencies, was not found.

Source Error:


Line 1: <%@ language="c#" debug="true"%>
Line 2: <%@ Register TagPrefix="mp" namespace="Microsoft.Web.Samples.MasterPages" assembly="MasterPages" %>
Line 3:
Line 4: <script runat="server">

Source File: c:\inetpub\wwwroot\pagemaster\TestPage.aspx Line: 2

:confused: :confused: :confused:
Any suggestions?

PS - I did compile the dll with the bat file.

angiras
05-06-2003, 02:05 PM
ok let's say you have an application named test.masterPage (c:\inetpub\wwwroot\test.masterPage\)
you will get a dll as test.masterPage.dll

then into your web.config just put this 2 lignes into appSettings section

web.config

<appSettings>
<add key="masterPage.defaultFolder" value="modeles" />
<add key="masterPage.templateFile" value="template.ascx" />
</appSettings>

----------------------------------

into a folder named modeles

template.ascx

<?xml version="1.0" encoding="iso-8859-1"?>
<%@ Control CodeBehind="template.ascx.vb" Inherits="test.masterPage.masterPageMS.template" %>
<%@ Register TagPrefix="ms" namespace="test.masterPage.masterPageMS" assembly="test.masterPage" %>
<!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' xml:lang='fr'>
<head>
<title><ms:region runat="server" id="region0">Default titre ici</ms:region></title>
</head>
<body>
<form id="frm" method="post" runat="server">
<table border width="100%">
<tr align="middle">
<td colspan="2"><div id="header">This is the Header</div>
</td>
</tr>
<tr>
<td><h3>First arbitrary content area</h3>
<p>
<ms:region runat="server" id="region1">Default region1 content</ms:region></p>
</td>
<td><h3>Second arbitrary content area
</h3>
<p>
<ms:region runat="server" id="region2" /></p>
</td>
</tr>
<tr>
<td colspan="2"><h3>Third arbitrary content area
</h3>
<p>
<ms:region runat="server" id="region3">Default region3 content. It is displayed if the page does not define content for the region.</ms:region></p>
</td>
</tr>
<tr align="middle">
<td colspan="2"><div id="footer">This is the Footer</div>
</td>
</tr>
</table>
</form>
</body>
</html>

template.ascx.vb

Namespace masterPageMS

Public MustInherit Class template : Inherits UserControl

Protected WithEvents region0 As Region
Protected WithEvents region1 As Region
Protected WithEvents region2 As Region
Protected WithEvents region3 As Region

#Region " Web Form Designer Generated Code "

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

End Sub

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
InitializeComponent()
End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

End Class

End Namespace

---------------------------------------

at the root of your application :


default.aspx
<%@ Page Codebehind="default.aspx.vb" Inherits="test.masterPage.masterPageMS.mainPage" %>
<%@ Register TagPrefix="ms" namespace="test.masterPage.masterPageMS" assembly="test.masterPage" %>
<ms:contentContainer id="cc" runat="server" masterPageFile="">
<ms:content id="region0" runat="server" />
<ms:content id="region1" runat="server">
<a href="MasterPages.htm" runat="server">Relative link test</a><br />
<asp:textbox id="tb1" runat="server" />
<asp:button text="Capitalize" onclick="ClickedCapitalize" runat="server" />
<asp:literal id="capitalized" runat="server" />
</ms:content>
<ms:content id="region2" runat="server">
<asp:textbox id="tb2" runat="server" /><asp:button text="Say hello" onclick="SayHello" runat="server" />
Hello <asp:literal id="name" text="[name goes here]" runat="server" />!
</ms:content>
</ms:contentContainer>

default.aspx.vb


Namespace masterPageMS

Public Class mainPage : Inherits Page

#Region " Controles "

Protected WithEvents cc As contentContainer
Protected WithEvents region0 As Content
Protected WithEvents region1 As Content
Protected WithEvents region2 As Content

Protected WithEvents tb1 As System.Web.UI.WebControls.TextBox
Protected WithEvents Button1 As System.Web.UI.WebControls.Button
Protected WithEvents capitalized As System.Web.UI.WebControls.Literal
Protected WithEvents tb2 As System.Web.UI.WebControls.TextBox
Protected WithEvents Button2 As System.Web.UI.WebControls.Button
Protected WithEvents name As System.Web.UI.WebControls.Literal

#End Region

#Region " Web Form Designer "


<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
End Sub

Private Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Init
InitializeComponent()

End Sub

#End Region

Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load

region0.Controls.Add(New LiteralControl("mon nouveau titre"))
region1.Controls.Clear()
region1.Controls.Add(New LiteralControl("titre ici"))

End Sub


#Region " Methodes "

Sub ClickedCapitalize(ByVal o As Object, ByVal e As EventArgs)
capitalized.Text = Server.HtmlEncode(tb1.Text.ToUpper())
End Sub

Sub SayHello(ByVal o As Object, ByVal e As EventArgs)
name.Text = Server.HtmlEncode(tb2.Text)
End Sub

#End Region


End Class
End Namespace


------------------------

then your masterPage.vb


Namespace masterPageMS

Public Class contentContainer : Inherits PlaceHolder
Implements INamingContainer

#Region " variables "

Private _contents As New ArrayList()

#End Region

#Region " proprietes "

Public Property masterPageFile() As String
Get
Return CStr(ViewState("masterPageFile"))
End Get
Set(ByVal Value As String)
Dim f, s As String
f = "~/" + ConfigurationSettings.AppSettings("masterPage.defaultFolder") + "/"
If f = "" Then
f = "~/modeles/"
End If
If Value <> "" Then
s = Value
Else
s = ConfigurationSettings.AppSettings("masterPage.templateFile")
End If
ViewState("masterPageFile") = f + s
ChildControlsCreated = False
End Set
End Property

#End Region

#Region " constructeurs "

Sub New()
MyBase.new()
End Sub

Protected Overrides Sub AddParsedSubObject(ByVal obj As Object)
If TypeOf obj Is Content Then
_contents.Add(obj)
Else
Throw New Exception("le controle conteneur ne peut contenir que des controles")
End If
End Sub 'AddParsedSubObject


Protected Overrides Sub OnInit(ByVal e As EventArgs)

If masterPageFile Is Nothing Or masterPageFile = "" Then
Throw New Exception("Il faut definir les proprietes du masterPageFile")
End If

Dim masterPage As Control = Page.LoadControl(masterPageFile)
Dim content As content

For Each content In _contents
' Look for a region with the same ID as the content control
Dim [region] As Control = masterPage.FindControl(content.ID)
If [region] Is Nothing Then
Throw New Exception("region non trouvee pour l' ID '" + content.ID + "'")
End If

' Set the Content control's TemplateSourceDirectory to be the one from the
' page. Otherwise, it would end up using the one from the Master Pages user control, which would be incorrect.

content._templateSourceDirectory = TemplateSourceDirectory

' Clear out any default content that the region might have
[region].Controls.Clear()

' Move the content control into its designated region
[region].Controls.Add(content)
Next content

' Add the master page to the content container control
Controls.Add(masterPage)

MyBase.OnInit(e)
End Sub


#End Region

End Class 'contentContainer

'/ The control marks a place holder for content in a master page.
Public Class [Region] : Inherits PlaceHolder
Implements INamingContainer
End Class '[Region]

Public Class Content : Inherits PlaceHolder

friend _templateSourceDirectory As String

Public Overrides ReadOnly Property templateSourceDirectory() As String
Get
Return _templateSourceDirectory
End Get
End Property

End Class 'Content

End Namespace

-------------------------

you must just compile the dll including the 3 files

masterpage.vb
modeles/template.ascx.vb
default.aspx.vb

angiras
05-06-2003, 02:16 PM
vbc /t:library /r:System.Web.dll /r:System.dll /out:bin\test.masterPage.dll *.vb modeles\*.vb >> test.masterPage.txt

you copy paste this into a mp.bat file and run the compile

if you have an error you will get it written into the test.masterPage.txt

david7777
05-07-2003, 11:42 AM
Where would i import other namespaces like System.web.UI etc?

When i compile, i get some errors stating that

C:\Inetpub\wwwroot\test.masterPage\default.aspx.vb(3) : error BC30002: Type 'Page' is not defined.

Public Class mainPage : Inherits Page


I can fix that by adding in the namespace to every object used, but it would be a lot easier knowing where to just import each one once.

Something like:
import System.web.UI
import System.text
etc...

david7777
05-07-2003, 12:34 PM
Ok - After a few changes, I got it all working - Thanx a million!! :D :thumbsup:

angiras
05-07-2003, 01:15 PM
:-))

david7777
05-07-2003, 01:57 PM
Oh dear - i found a problem... :confused:

Ok - I have worked out how to use everything fine, except for one problem.

I have the code,

region0.Controls.Add(New System.Web.UI.LiteralControl(" : Site Name"))

in the default.aspx.vb file in the Page_Load sub.

So basically - if my title(region0) is set to "Home" in default.aspx, then it should display "Home : Site Name" when viewed with the browser. The problem is - it is displaying "Home : Site Name : Site Name".

If I use this code in default.aspx.vb instead:

region0.Controls.Clear()
region0.Controls.Add(New System.Web.UI.LiteralControl(" : Site Name"))

Then the title comes out as " : Site Name"

So - if i clear the region, then ": Site Name" is displayed once, but if i dont clear it, then it is displayed twice after my set title. How do i find the problem?

Even if i try:

region0.Controls.Add(New System.Web.UI.LiteralControl(" : Site"))
region0.Controls.Add(New System.Web.UI.LiteralControl(" Name"))

I still get "Home : Site Name : Site Name"

It seems that the Page_Load event is called twice or something??

This problem is not only with the title, but all regions. As long as there are controls in the region, and in Page_Load i try add without clearing first, the added controlls double up. Im sure it will do the same on your computer. Just try the code you gave me and change the default.aspx.vb Page_Load code to this:

region1.Controls.Add(New System.Web.UI.LiteralControl("this is more text in"))
region1.Controls.Add(New System.Web.UI.LiteralControl(" region one and will double up"))

That's all - just those two lines. After recompiling, you will see that the text will appear twice... Any ideas?

angiras
05-07-2003, 02:44 PM
in your default.aspx

<ms:content id="region0" runat="server" />

in your default.aspx.vb

Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load

region0.Controls.Add(New LiteralControl("new title"))

End Sub

in your template.ascx



<ms:region runat="server" id="region0">Default title</ms:region>

david7777
05-07-2003, 03:15 PM
I dont think you understand what i want to do:

In default.aspx I have this code:

<ms:content id="region0" runat="server" >Home</ms:content>

That sets the title of the page to Home
Now in default.aspx.vb I have this:

title_region.Controls.Add(New System.Web.UI.LiteralControl(" : MySite Online"))

That should add onto the given title. So it should now be "Home : MySite Online"

In template.ascx i have:

<title><ms:region runat="server" id="title_region" />MySite Online</title>


So basically, i want ": MySite Online" added to the end of the title of the page - Just for uniformity of the site...

So a page titled "Contact Us" should in fact show the title "Contact Us : MySite Online" and the same with any others...

angiras
05-07-2003, 03:48 PM
the default content is set into your ascx file

then you can do 2 things to change it :

in default.aspx
or in default.aspx.vb

if you change any contentRegion into am ascx file it will erase the ascx file

bu what could be is a small function which will automaticly add "MySite Online" to the end of each title

david7777
05-07-2003, 04:00 PM
I though of the small function, but i figured it out...

I just had the following code:

'default.aspx:
<ms:content id="title_region" runat="server" >Home</ms:content>

'Nothing in the Page_Load event of default.aspx.vb

'template.ascx
<title><ms:region runat="server" id="title_region" /> : MySite Online</title>


I didnt realise that the default content of a region will be added to the end of any content inserted by the default.aspx page...

So the result is what i needed.

Once again - thanx a lot for all your help!:D :thumbsup: :D :thumbsup:

angiras
05-07-2003, 05:06 PM
and normally , it could be that asp net 2.0 (and future visual studio) implements directly this master Pages

then it is open on the future

if you want another good step in the direction of master pages
have a look at

wilsondotnet (http://wilsondotnet.com/Tips/Threads.aspx?Topic=3)

and

aspAlliance (http://www.aspalliance.com/PaulWilson/Articles/)

I have developped my own master pages from thsi articles

david7777
05-08-2003, 07:53 AM
Thanx angiras - some good articles there...