Master Pages, seems like it causes more problems than it fixes?

M

multiformity

So I have been working on an opensource project for a while, and
decided to really try to make it look better after focusing on the
functionality most of this time. Up to now, I have simply used a
standard ASPX page with minor modifications to it. All of my pages
inherit from a "BasePage.cs" class, that handles common things like
getting the user's information out of the session, determines if a page
should or should not be password protected, etc. Up until now it has
all been working fine, but if it ain't broke.. FIX IT right?

Thus I decided to attempt to incorporate MasterPages in my Visual Web
Developer Express since it seemed so easy and would give me much more
control over my pages and allow me to reduce extra ASPX content, etc...
wrong unfortunatly.

Briefly my problems are as follows:
1) I need to get rid of the "ctl001$contentPane$" prefix from my form
collection keynames.
2) I need to elliminate redundant properties that would have to exist
in both my BasePage.cs and MasterPage.cs that access login info, etc
from the session.

More detail follows:

1) The first thing I realized is that when I attempted to login, all of
the keys in the Request.Form NameValueCollection had "ctl001$content$"
prepended. I hacked a workaround for this just to see if there were
going to be any other problems, but I would rather NOT have my form
controls prepended with such nonsense, just makes my life more
difficult. I mean, only one server form can exist on a page, why do you
need to specify that it came from a specific content pane, and why is
ctl001 always there if it isn't supposed to change? I mean, this is
going to take another 5 hours to get all working and tested again if I
cannot get rid of this stupid prefix, and it will end up looking VERY
screwey, and I don't want that at all.

2) Again, my BasePage.cs holds userinfo, login status, etc as
properties who's values are actually obtained from the session
underneath. Now it would seem that my MasterPage.cs doesn't have access
to this information, so I would have to put the same properties in the
basepage class in the MasterPage class, so that they can get the info
from the session in a standard way. Then I could have all of the
BasePages actually get the properties from it's masterpage property, or
the code would be redundent otherwise. But this would pose a problem if
there was NO masterpage property of my basepage (IE, a page that didn't
use the masterpage concept). So I am back to having the same property
accessors of the session object repeated in two places. I am really at
a loss for the correct way to fix this. I mean, I am going to have
redundant code in my MasterPage.cs and BasePage.cs file all the ways I
can think of fixing it. I could make some helper class that actually
gets the info from the session that is passed in, but that seems VERY
cludgy, but at least the real guts of the code wouldn't be repeated.

Help help please, I mean, is it supposed to be this difficult to use
MasterPages? Is it realy a situation where you have to use them or not?
What can I do to fix this??
 
G

Guest

Base page versus master page: Your issue is breaking outside of the
methodology of ASP.NET 2.0, which is forcing dual inheritance. The master
page should eliminate having a separate base class for pages. If you need to
base, for some reason, the master page should inherit from the base to avoid
two paths. I hope this makes sense. I do not have an URL to show what I am
talking about, but it is far simpler than the model you are prescribing.

The $csdklf$asdfjklas format: Once again, methodology issue. While there are
certainly some rare instances you might have to "hack" at the formatting of
location strings, if you stay within the methodology prescribed, you should
not have to even concern yourself with this. In the rare instances you do,
there are generally methods to provide you with the location specific
formatting you are talking about. This was true in ASP.NET 1.x, as well.

Short Answer: Rather than attempting to recreate something you did elsewhere
in ASP.NET 2.0, take a bit of time experimenting with the model provided and
learn the methology. As it is still beta (well, RC), the documentation is
lagging a bit, but there are plenty of blog entries and websites that explore
master pages to help you out.

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

***************************
Think Outside the Box!
***************************
 
M

multiformity

Ok, not trying to argue, I appreciate your prompt answer, but I have a
few questions about what you suggested, also, here is a link that
explains the complexity of the project:

http://www.codeproject.com/aspnet/RapidWebAppDev.asp

1. Ok, I guess I can use a masterpage class to hold my stuff for every
page. But what happens if I don't want to use the masterpage, but still
want the functionality that a BasePage provides (IE a Login protected
Popup window). Also, the master page cannot inherit from the base as
you suggested because the BasePage inherits from a Page, not from a
MasterPage, thus turning my MasterPage.cs into a regular Page. Am I
missing something?

** Action ** I am going to move forward with this suggestion, but I
still want to know how Microsoft expects us to have both a Regular Page
and MasterPage that inherit some common functionality? Seems that they
should have made EVERY page "MasterPage" capable, but they split the
two out for some reason. Fortunatly in my situation, there would not be
a lot of code that would be duplicated, but that may not be true
elsewhere, and I want to avoid that if at all possible.

2. I cannot think of a reason to qualify the input names in such a way,
all controls must have a unique ID, so there would be no ambigious
references. Having to prepend mu collection key with the SAME thing
over and over again seems redundant. Also, the code will break if the
pane changes names (IE code re-used in another project). This is going
to require lots of work for people to modify their existing ASP.Net
code. Do you have any insight as to what the advantage of this is?
Everyone I have talked to about this agrees with me, qualifying input
names in such a manner simply isn't needed. The only thing I can think
of is that you could have the same control ID in different content pane
pages, but you should get a parser error from the server in that case.

** Action ** I am currently just thinking to make a new namevalue
collection (since Request.From is readonly) and key it's values with
everything to the right of the last $ sign, and replacing all
"request.form" with "OriginalForm" or something similar. And while it
would be a relativly simple fix, this is something that shouldn't have
been broken in the first place IMHO.

Again, not trying to argue, trying to understand :D

AB
 
S

Scott Allen

Help help please, I mean, is it supposed to be this difficult to use
MasterPages? Is it realy a situation where you have to use them or not?
What can I do to fix this??


I have great reservations about putting common functionality into a
master page, I wrote about the topic here:

Master Page Anti-pattern
http://odetocode.com/Blogs/scott/archive/2005/09/10/2179.aspx

I'd stick with a base page for my web forms. If this base page class
lives in App_Code you can always cast the Page property of the master
to that type and interact with the page in a stronly typed manner.

Am I making sense?
 
G

Guest

Oops! I was the one off track on this one (brain death?). I have been jumping
from 2.0 to DotNetNuke to a custom portal a friend wrote that I messed up on
which used an inherited master page and which implemented a master page as a
control. A quick look at the 2.0 bits showed my stupidity. I apologize for
jumping without checking myself.

Please note, I have not played around with the code you reference
completely, so I am still being a bit generic here.

1. You can inherit from your base page and put functionality into the base
page. Be careful which elements you place here and which are best placed in
the master page. The main thing the master page does for you is make it so
you can avoid repeating elements in multiple pages. If you are handling this
through inheritance, the master page may be unnecessary. In other words,
master pages help you more when you are using the designer than when you are
coding your own elements.

2. The master page is a control when rendered (kind of strange, perhaps, but
the UI handles it for you (this is my brain death element, of course)). To
get events from the master to the page, you can bubble up through delegates
(events in VB.NET). Just have your basepage class handle the delegate or
implement in pages where it should be handled and ignore in others (do not
prefer the later, however, as a good design should not have clicks to
nowhere). This can help with some of your common elements. As it renders as a
control on the page, grabbing the content areas when compiled, your page can
still handle the calls. Hope this makes sense.

3. To avoid naming issues, set up your controls (master page, user controls,
etc.) as black boxes. This means that you have to access the members via
methods and properties. This gives you a couple of options:

a) page as handler: The page grabs from the various controls and submits any
information in one pass. You can use a strongly typed dataset to handle data
access and populate the different tables from different controls. Make the
ToString() method return your dataTable as XML, for example.

b) control as handler: Each control is responsible for its own data. This
makes the app a bit chattier, but encapsulates the code better. If you head
this route, you should set up, at mimimum, an interface that checks validity
of the data in each control (IsValid() method, for example) and only call the
save method on the user control when all controls on the page that implement
the interface give a true for IsValid(). You can reduce chatter, a bit, by
having the page connect and pass the connection to each control, but this can
be troublesome, as well. The benefit of this method is user controls can map
directly to user objects, which can inherit from strongly typed DataSets.
Nice, easy model.

I will have to look at the popup login to get a better idea of what you are
aiming at. The code sample you reference does not appear to have the master
page (http://www.codeproject.com/aspnet/RapidWebAppDev.asp), so I am not sure
if that is the full 2.0 implementation you are talking about or not.

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

***************************
Think Outside the Box!
***************************
 
C

clintonG

It certainly does require the study of the scant tutorials and documentation
that are available and it seems to me the use of a base class is a common
sense requirement as the Master Page is said to be a compiled as if it were
a user control and does not support the new Page_PreInit event which is the
only event which supports programatically changing the master or themes.
Given no use of a base class each page that inherits from System.Web.UI.Page
would require redundant code throughout the entire application.

The Cowboy has the experience but I'm confused about his claim regarding two
paths of inheritence. Noting I have little experience using base class
inheritence and shorten the declaration for brevity about three weeks ago I
tried the following...

.... MyMaster : System.Web.UI.MasterPage, System.Web.UI.Page

and...

.... MyMaster : System.Web.UI.MasterPage, MyBaseClass

neither of which would compile.

So I've adopted the use of a base class as I require its support for the
Page_PreInit event to change masters and themes programmatically.
I've also been compelled to use a base class to maintain control state of
styles applied to tabbed navigation I created using LinkButtons. I'm sure
there's so much more value using base classes and I'm sure there's likely
other strategies to achieve the same objectives but the need to use the
Page_PreInit event puts the entire arguement to rest as there's no way I
want to develop and maintain what may be dozens of pages with redundant
events that only need to be raised and managed once in a base class. That's
how I understand it at this point in time.

search: page_preinit
search: page_preinit site:msdn2.microsoft.com

As for other Master Page issues, besides others, you also need to do this
search...

search: MasterType site:msdn2.microsoft.com

I've learned referencing controls is done two ways: FindControl method (late
bound0 and Properties (early bound). I've been using both and now work on
learning how to choose when and where using either is most beneficial. The
FindControl method is tricky to learn to use with Master Pages when a
control is contained within another control. Trying to find a LinkButton
within a Panel in a Master Page comes to mind.

As for the naming of the control tree items each apparently remains
addressable in the client or from the server but doing so is brittle as any
change to the page reorders and renames items in the control tree.As I
recall, disabling the Visible property of a control for example will remove
the control from the tree and ruffle new values through that section of the
tree. Very challenging for an intermediate like myself to really master.

<%= Clinton Gallagher
 
C

clintonG

Your tutorials have been making sense for me Scott. Thank you for being one
of the few guys who has taken the time to do this work although there's been
a time or two I wanted to put both hands around your scrawny little neck and
squeeze until your eyes popped out :) (I think I've watched too much TV).
Some of the tutorials lead to a critical point in understanding the context
of the topic and then poop out and stop right then and there. No, I'm, sorry
I don't remember which one(s).

<%= Clinton Gallagher
 
S

Scott Allen

Your tutorials have been making sense for me Scott. Thank you for being one
of the few guys who has taken the time to do this work although there's been
a time or two I wanted to put both hands around your scrawny little neck and
squeeze until your eyes popped out :) (I think I've watched too much TV).
Some of the tutorials lead to a critical point in understanding the context
of the topic and then poop out and stop right then and there. No, I'm, sorry
I don't remember which one(s).

Thanks for the compliment, Clinton. At least I think it was a
compliment :)
 
G

Guest

It was a bit backhanded, but it sure sounded like a complement. :)

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

***************************
Think Outside the Box!
***************************
 
C

clintonG

Yes, it was.

<%= Clinton Gallagher

Cowboy (Gregory A. Beamer) - MVP said:
It was a bit backhanded, but it sure sounded like a complement. :)

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

***************************
Think Outside the Box!
***************************
 
M

multiformity

Ok, if I come off as rude, ungratefull or pissy, that is not my
intention :D

Ok, forgive my ignorance, here, but I don't really think that I got an
answer. I have also realized a third issue, but let me explain why I
still don't understand why this is so difficult.

First lemmie say that I understand Scotts blog, but all it says is
"Don't put the code into masterpage.cs", I understand that then.

1. All of the answers I got still don't explain how to get my
masterpage codebehind to access code from basepage.cs. Again, I am
trying to elliminate redundant code, no big deal, but ohh well if I
have to have redundencay at this point, considering it is such a small
amount (one page or so).
2. Still haven't heard why my form inputs are being prepended with
"ctl001$ContentPaneName$", this is going to require that I change a lot
of code to get this working correctly, and I will be constantly
prepending input keys with the same thing over and over, and my code
won't work if someone uses a different Masterpage.
3. I have remembered a third problem, where this.findcontrol isn't
working in my login page. The control ( a button ) is defined IN the
login.aspx page, it should be in the login pages codebehind file
accessible via this.controls. I mean, this code worked before, but it
isn't working anymore, I mean, what the hell were they (Microsoft)
thinking changing something like this??

A note to Cowboy, the code that attempts to use MasterPages is not
avaiable for download, the code you downloaded was my last release
before trying to incorporate MasterPages. I wouldn't mind you
incorporating a working login and "display.aspx" with masterpages,
because...

Honestly I am about to simply give up and curse Masterpages till my
dying days. I think that it has some good features, but if it is going
to require for all of my code to be modified, screw it. Instead I will
come up with a template concept of my own and override the basepage's
Render method or whatever it is. I mean issues 2 and 3 I listed above
are the real show stoppers for me in my situation. again, I like the
concept, but it's not worth the global overhaul and hacking that it
seems to require.

Cowboy, prove me wrong.. PLEASE, again, I am NOT trying to argue, just
trying to understand :D

AB
 
K

Ken Dopierala Jr.

Hi,

I don't have a solution but I think I can point you in the right direction.

You know what your control name is and you know what your content pane name
is. So that is easy enough to assign to a hidden variable (maybe
programtically) and and always have your client side code use the value of
this hidden field. The ctl00 is the tough one. You need to figure out a
way to programatically get this on the server side and assign it to a hidden
field. Then you can reference your controls easy enough by concat'ing
ctl00_pane_ to control. You could make this functionality uniform and even
put it in a base page that all your content pages inherit from.

I havn't really used VS2005 but I created a quick test project. I entered
debug mode in the Page_Load of a content page and worked through the object
model.

The ctl00 appears here: Me.Master.ClientID

So if I put a hidden input and in the page load of my content page assigned
it's value to: Me.Master.ClientID + "_" + "pane name" + "_"

I could then reference all my javascript like:

document.getElementById(hidPrefix.Value + "controlname).disabled = true;

Now, with more than 1 content page I 'm sure this changes thing but a
mechanism could be developed to overcome this since we know we can get at
the prefix and assign it to something as we dish the page out to the client.
As I said it isn't a solution, but maybe it's a start. I'll be tackling
this when I move to ASP 2.0 so I'd rather have you guys figure it out before
I get there. ;-} Good luck! Ken.
 
C

clintonG

I'm on my way to an ineta meeting this evening. I might be able to reply
later myself but till then perhaps the other guys will fill in the blanks.

<%= Clinton Gallagher
 
S

Scott Allen

Hi AB:

Don't worry as coming of as ungrateful - I know it can be frustrating.
I'm dealing with a hotel right now that charges US $11 for 24 hours of
Internet access and I can't seem to get more than 5 minutes at a time.
Thieves. I'm the pissy one.

Anyway, before I lose connectivity again...

Ken hits the nail on the head when suggesting the ClientID property.
ClientID is the only 100% guaranteed way of making sure you get the
"munged" control names. ASP.NET 1.x and 2.0 both do this to make sure
you have unique IDs inside of a container.

The tricky part about a master page is it derives from UserControl,
and UserControl is an INamingContainer, which means it will munge
control names on the clientside unfortunately. For JavaScript, the
best approach is to mix in the ClientID.

I have some details on this behavior, as well as some FindControl tips
in this article:

In Search Of ASP.NET Controls
http://odetocode.com/Articles/116.aspx

Hope that gives some additional insight.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top