How to avoid lifecycle hacks?

G

Guest

The ASP.NET model is touted as a clean OO approach to developing web pages,
yet sometimes the page lifecycle poses silly obstacles that forces you revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

.... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB result
set; the ResultSetDisplay shows the currently selected page in a data list;
and the SubmitButton is used in case the user changed criteria and wants to
update the view.

Now, the PagingNav control needs to know the total number of records found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender event of the
ResultSetDisplay control since it will be executed after the PreRender event
of the PagingNav control (due to its position in the page). In other words,
it would be too late for the PageNavControl to figure out the total records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The problem
is, I want to reset the current page number to 1 whenever this button is
clicked. So I add code to do that in its SubmitButton_Click. Alas, this event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event that
takes place after the SubmitButton_Click event, which is the PreRender event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but it's too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
K

Ken Dopierala Jr.

Hi,

I would create a base page class and derive my pages from this class. The
base page's Page_Load event will fire first, you can then hit your data
access and business logic layers here. Retrieving the data you need and
setting custom properties for derived classes to check before they render.

I would also recommend buying some books on OOP and studying them carefully.
You attempted to solve your problem using an almost top-down approach. When
you are trying to implement an OO design you know you are on the wrong path
when you try to rig things up after the fact. Always try to think what
would come first. In this case a base class will solve your problem and
also make your code much more elegant and extensible. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
The ASP.NET model is touted as a clean OO approach to developing web pages,
yet sometimes the page lifecycle poses silly obstacles that forces you revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB result
set; the ResultSetDisplay shows the currently selected page in a data list;
and the SubmitButton is used in case the user changed criteria and wants to
update the view.

Now, the PagingNav control needs to know the total number of records found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender event of the
ResultSetDisplay control since it will be executed after the PreRender event
of the PagingNav control (due to its position in the page). In other words,
it would be too late for the PageNavControl to figure out the total records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The problem
is, I want to reset the current page number to 1 whenever this button is
clicked. So I add code to do that in its SubmitButton_Click. Alas, this event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event that
takes place after the SubmitButton_Click event, which is the PreRender event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but it's too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
S

Scott Allen

Hi Homan:

Here is one approach:

Factor all the querying code out of the PreRender and event handlers
into a distinct method of the class, say, PopulateDataList. If I
understand your scenario you might need to pass a page number to the
method.

During the first Page_Load event (!IsPostBack) you can initially
populate the data list by calling this method. Likewise, the submit
button click event could invoke this method passing a page number of
1.

What I may not understand is the problem you are having with the
paging navigation. I'd think this navigation control would fire events
that call PopulateDataList passing the proper page number.
PopulateDataList could also inform the nav control about the total
number of records. All of this happens before the controls render and
gets you out of having code inside PreRender that has to understand
what has happened on the page.

--
Scott
http://www.OdeToCode.com/blogs/scott/

The ASP.NET model is touted as a clean OO approach to developing web pages,
yet sometimes the page lifecycle poses silly obstacles that forces you revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB result
set; the ResultSetDisplay shows the currently selected page in a data list;
and the SubmitButton is used in case the user changed criteria and wants to
update the view.

Now, the PagingNav control needs to know the total number of records found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender event of the
ResultSetDisplay control since it will be executed after the PreRender event
of the PagingNav control (due to its position in the page). In other words,
it would be too late for the PageNavControl to figure out the total records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The problem
is, I want to reset the current page number to 1 whenever this button is
clicked. So I add code to do that in its SubmitButton_Click. Alas, this event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event that
takes place after the SubmitButton_Click event, which is the PreRender event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but it's too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
G

Guest

Hi Ken,

This wouldn't slove my problem because even when I add an intermediate
class, the overloaded Load event will still fire before the SubmitButton's
Click event. So if the user clicked on that button to update the criteria,
the current page will be set AFTER the query has already executed, and the
ResultSetDisplay will display the wrong page.

To illustrate, let's say that the user submitted a set of criteria C1 and
browsed to page number 5 of the its result set. Then he changed the criteria
to C2 and hit the SubmitButton. Now if I execute the query in the overloaded
Load event handler in the derived class, the query will retrieve page 5 of
C2, not page 1 as it should, because the page was set in the SubmitButton
event handler after the query got executed.

By the way, the code is executed in the Code Behind class, which is derived
from Page anyway.

I'm very well versed in OOA/D/P and all the design patterns paraphernalia (I
come from a J2EE background), but I'm still trying to figure out ASP.NET's
plumbing.

Thanks for your feedback.




Ken Dopierala Jr. said:
Hi,

I would create a base page class and derive my pages from this class. The
base page's Page_Load event will fire first, you can then hit your data
access and business logic layers here. Retrieving the data you need and
setting custom properties for derived classes to check before they render.

I would also recommend buying some books on OOP and studying them carefully.
You attempted to solve your problem using an almost top-down approach. When
you are trying to implement an OO design you know you are on the wrong path
when you try to rig things up after the fact. Always try to think what
would come first. In this case a base class will solve your problem and
also make your code much more elegant and extensible. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
The ASP.NET model is touted as a clean OO approach to developing web pages,
yet sometimes the page lifecycle poses silly obstacles that forces you revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB result
set; the ResultSetDisplay shows the currently selected page in a data list;
and the SubmitButton is used in case the user changed criteria and wants to
update the view.

Now, the PagingNav control needs to know the total number of records found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender event of the
ResultSetDisplay control since it will be executed after the PreRender event
of the PagingNav control (due to its position in the page). In other words,
it would be too late for the PageNavControl to figure out the total records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The problem
is, I want to reset the current page number to 1 whenever this button is
clicked. So I add code to do that in its SubmitButton_Click. Alas, this event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event that
takes place after the SubmitButton_Click event, which is the PreRender event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but it's too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
G

Guest

Hi Scott,

Actually the code that retrieves the result set is factored as you
indicated, and you're right, it's passed a page number. Currently I'm calling
it from the Load event handler of the ResultSetDisplay.

Your proposed solution (i.e. calling this function from either
SubmitButton's Click event handler XOR the Load event handler) requires the
same hack. That's because I have to call this function from the Load event
while making sure the SubmitButton control wasn't clicked (so that I don't
end up calling it twice, once in the Load event handler and once in the
SubmitButton's Click event handler). And there's no way of knowing during the
execution of the Load event handler if the SubmitButton was clicked other
than that hack that I mentioned in my original message. IsPostBack won't cut
it here because other controls could also submit the page (e.g. the
PagingNav), not just the SubmitButton.

Thanks for your feedback.

Homam



Scott Allen said:
Hi Homan:

Here is one approach:

Factor all the querying code out of the PreRender and event handlers
into a distinct method of the class, say, PopulateDataList. If I
understand your scenario you might need to pass a page number to the
method.

During the first Page_Load event (!IsPostBack) you can initially
populate the data list by calling this method. Likewise, the submit
button click event could invoke this method passing a page number of
1.

What I may not understand is the problem you are having with the
paging navigation. I'd think this navigation control would fire events
that call PopulateDataList passing the proper page number.
PopulateDataList could also inform the nav control about the total
number of records. All of this happens before the controls render and
gets you out of having code inside PreRender that has to understand
what has happened on the page.

--
Scott
http://www.OdeToCode.com/blogs/scott/

The ASP.NET model is touted as a clean OO approach to developing web pages,
yet sometimes the page lifecycle poses silly obstacles that forces you revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB result
set; the ResultSetDisplay shows the currently selected page in a data list;
and the SubmitButton is used in case the user changed criteria and wants to
update the view.

Now, the PagingNav control needs to know the total number of records found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender event of the
ResultSetDisplay control since it will be executed after the PreRender event
of the PagingNav control (due to its position in the page). In other words,
it would be too late for the PageNavControl to figure out the total records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The problem
is, I want to reset the current page number to 1 whenever this button is
clicked. So I add code to do that in its SubmitButton_Click. Alas, this event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event that
takes place after the SubmitButton_Click event, which is the PreRender event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but it's too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
K

Ken Dopierala Jr.

Hi,

I think implementing a Master Pages type scenario is what you are looking
for. They are built into v2.0 of the framework but here are some link for
implementing them in v1.1:

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

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

Also read through this from Microsoft's Patterns & Practices:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesMVC.asp

For your paging navigation I would recommend creating your own custom
control with all UI necessary to page (i.e. page selection links or
dropdown, submit button, previous/next links). This will allow you to make
it very generic and at the same time expose a number of custom properties
that can be changed in the property window of the IDE to customize for any
scenario. For example in one scenario you may show the current page and
links to the two pages behind or ahead of it. Where as in another scenario
you may show the page you are on, the immediate pages around it and links to
also go all the way to the beginning or end of the data. In your custom
control include the javascript necessary to set a hidden input to the
correct page when the submit button is clicked. Then have your base page
check this hidden input before loading the data. Now you'll know where to
go before the submit button click even fires. In fact, you wouldn't even
need to capture the click event on the server-side. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
Hi Ken,

This wouldn't slove my problem because even when I add an intermediate
class, the overloaded Load event will still fire before the SubmitButton's
Click event. So if the user clicked on that button to update the criteria,
the current page will be set AFTER the query has already executed, and the
ResultSetDisplay will display the wrong page.

To illustrate, let's say that the user submitted a set of criteria C1 and
browsed to page number 5 of the its result set. Then he changed the criteria
to C2 and hit the SubmitButton. Now if I execute the query in the overloaded
Load event handler in the derived class, the query will retrieve page 5 of
C2, not page 1 as it should, because the page was set in the SubmitButton
event handler after the query got executed.

By the way, the code is executed in the Code Behind class, which is derived
from Page anyway.

I'm very well versed in OOA/D/P and all the design patterns paraphernalia (I
come from a J2EE background), but I'm still trying to figure out ASP.NET's
plumbing.

Thanks for your feedback.




Ken Dopierala Jr. said:
Hi,

I would create a base page class and derive my pages from this class. The
base page's Page_Load event will fire first, you can then hit your data
access and business logic layers here. Retrieving the data you need and
setting custom properties for derived classes to check before they render.

I would also recommend buying some books on OOP and studying them carefully.
You attempted to solve your problem using an almost top-down approach. When
you are trying to implement an OO design you know you are on the wrong path
when you try to rig things up after the fact. Always try to think what
would come first. In this case a base class will solve your problem and
also make your code much more elegant and extensible. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
The ASP.NET model is touted as a clean OO approach to developing web pages,
yet sometimes the page lifecycle poses silly obstacles that forces you revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB result
set; the ResultSetDisplay shows the currently selected page in a data list;
and the SubmitButton is used in case the user changed criteria and
wants
to
update the view.

Now, the PagingNav control needs to know the total number of records found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender event
of
the
ResultSetDisplay control since it will be executed after the PreRender event
of the PagingNav control (due to its position in the page). In other words,
it would be too late for the PageNavControl to figure out the total records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The problem
is, I want to reset the current page number to 1 whenever this button is
clicked. So I add code to do that in its SubmitButton_Click. Alas,
this
event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event that
takes place after the SubmitButton_Click event, which is the PreRender event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but it's too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
G

Guest

Hi Ken,

Using JavaScript and hidden form fields is pretty much the same hack as
checking whether the SubmitButton exists in the form object. I'm just trying
to figure out a solution along the line of ASP.NET's event-driven, OO model.

Thanks,

Homam




Ken Dopierala Jr. said:
Hi,

I think implementing a Master Pages type scenario is what you are looking
for. They are built into v2.0 of the framework but here are some link for
implementing them in v1.1:

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

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

Also read through this from Microsoft's Patterns & Practices:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesMVC.asp

For your paging navigation I would recommend creating your own custom
control with all UI necessary to page (i.e. page selection links or
dropdown, submit button, previous/next links). This will allow you to make
it very generic and at the same time expose a number of custom properties
that can be changed in the property window of the IDE to customize for any
scenario. For example in one scenario you may show the current page and
links to the two pages behind or ahead of it. Where as in another scenario
you may show the page you are on, the immediate pages around it and links to
also go all the way to the beginning or end of the data. In your custom
control include the javascript necessary to set a hidden input to the
correct page when the submit button is clicked. Then have your base page
check this hidden input before loading the data. Now you'll know where to
go before the submit button click even fires. In fact, you wouldn't even
need to capture the click event on the server-side. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
Hi Ken,

This wouldn't slove my problem because even when I add an intermediate
class, the overloaded Load event will still fire before the SubmitButton's
Click event. So if the user clicked on that button to update the criteria,
the current page will be set AFTER the query has already executed, and the
ResultSetDisplay will display the wrong page.

To illustrate, let's say that the user submitted a set of criteria C1 and
browsed to page number 5 of the its result set. Then he changed the criteria
to C2 and hit the SubmitButton. Now if I execute the query in the overloaded
Load event handler in the derived class, the query will retrieve page 5 of
C2, not page 1 as it should, because the page was set in the SubmitButton
event handler after the query got executed.

By the way, the code is executed in the Code Behind class, which is derived
from Page anyway.

I'm very well versed in OOA/D/P and all the design patterns paraphernalia (I
come from a J2EE background), but I'm still trying to figure out ASP.NET's
plumbing.

Thanks for your feedback.




Ken Dopierala Jr. said:
Hi,

I would create a base page class and derive my pages from this class. The
base page's Page_Load event will fire first, you can then hit your data
access and business logic layers here. Retrieving the data you need and
setting custom properties for derived classes to check before they render.

I would also recommend buying some books on OOP and studying them carefully.
You attempted to solve your problem using an almost top-down approach. When
you are trying to implement an OO design you know you are on the wrong path
when you try to rig things up after the fact. Always try to think what
would come first. In this case a base class will solve your problem and
also make your code much more elegant and extensible. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

The ASP.NET model is touted as a clean OO approach to developing web
pages,
yet sometimes the page lifecycle poses silly obstacles that forces you
revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB result
set; the ResultSetDisplay shows the currently selected page in a data
list;
and the SubmitButton is used in case the user changed criteria and wants
to
update the view.

Now, the PagingNav control needs to know the total number of records found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender event of
the
ResultSetDisplay control since it will be executed after the PreRender
event
of the PagingNav control (due to its position in the page). In other
words,
it would be too late for the PageNavControl to figure out the total
records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The
problem
is, I want to reset the current page number to 1 whenever this button is
clicked. So I add code to do that in its SubmitButton_Click. Alas, this
event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event that
takes place after the SubmitButton_Click event, which is the PreRender
event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but it's too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add
something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
A

Andy Fish

I didn't have time to fully digest your exact scenario but I have certainly
found problems in some pages regarding the order of firing events,
especially with user controls in the page.

One solution I have used on several occasions is have all the postback type
events (button clicks etc) just set instance variables to indicate what was
happening, then leave all the real work until the pre-render method.

Andy
 
K

Ken Dopierala Jr.

Hi Homam,

I don't see how firing a js function to set a flag that notifies the server
that the criteria has changed causes any problems. Especially once you
encapsulate this functionality into a custom control and simply drop it on
any page you need it. As you know the page load event will always fire
before the button click. Without using any type of smart-client
functionality all your work needs to be done on the server. The only way to
do this is to maintain state. You can do that with the Session object. In
your page load, compare the new criteria to the old criteria. If it doesn't
match then you know what you need to do. However once your pages become
more complicated, specifically post backs can be made from actions other
than the submit button click, you may find that simply having the client
tell you what they need instead of making the server figure it out, is the
way to go. Good luck! I hope more people can join this conversation and
help put together the right solution for you. Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
Hi Ken,

Using JavaScript and hidden form fields is pretty much the same hack as
checking whether the SubmitButton exists in the form object. I'm just trying
to figure out a solution along the line of ASP.NET's event-driven, OO model.

Thanks,

Homam




Ken Dopierala Jr. said:
Hi,

I think implementing a Master Pages type scenario is what you are looking
for. They are built into v2.0 of the framework but here are some link for
implementing them in v1.1:

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

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

Also read through this from Microsoft's Patterns & Practices:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesMVC.asp

For your paging navigation I would recommend creating your own custom
control with all UI necessary to page (i.e. page selection links or
dropdown, submit button, previous/next links). This will allow you to make
it very generic and at the same time expose a number of custom properties
that can be changed in the property window of the IDE to customize for any
scenario. For example in one scenario you may show the current page and
links to the two pages behind or ahead of it. Where as in another scenario
you may show the page you are on, the immediate pages around it and links to
also go all the way to the beginning or end of the data. In your custom
control include the javascript necessary to set a hidden input to the
correct page when the submit button is clicked. Then have your base page
check this hidden input before loading the data. Now you'll know where to
go before the submit button click even fires. In fact, you wouldn't even
need to capture the click event on the server-side. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
Hi Ken,

This wouldn't slove my problem because even when I add an intermediate
class, the overloaded Load event will still fire before the SubmitButton's
Click event. So if the user clicked on that button to update the criteria,
the current page will be set AFTER the query has already executed, and the
ResultSetDisplay will display the wrong page.

To illustrate, let's say that the user submitted a set of criteria C1 and
browsed to page number 5 of the its result set. Then he changed the criteria
to C2 and hit the SubmitButton. Now if I execute the query in the overloaded
Load event handler in the derived class, the query will retrieve page 5 of
C2, not page 1 as it should, because the page was set in the SubmitButton
event handler after the query got executed.

By the way, the code is executed in the Code Behind class, which is derived
from Page anyway.

I'm very well versed in OOA/D/P and all the design patterns
paraphernalia
(I
come from a J2EE background), but I'm still trying to figure out ASP.NET's
plumbing.

Thanks for your feedback.




:

Hi,

I would create a base page class and derive my pages from this
class.
The
base page's Page_Load event will fire first, you can then hit your data
access and business logic layers here. Retrieving the data you need and
setting custom properties for derived classes to check before they render.

I would also recommend buying some books on OOP and studying them carefully.
You attempted to solve your problem using an almost top-down
approach.
When
you are trying to implement an OO design you know you are on the
wrong
path
when you try to rig things up after the fact. Always try to think what
would come first. In this case a base class will solve your problem and
also make your code much more elegant and extensible. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

The ASP.NET model is touted as a clean OO approach to developing web
pages,
yet sometimes the page lifecycle poses silly obstacles that forces you
revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the
DB
result
set; the ResultSetDisplay shows the currently selected page in a data
list;
and the SubmitButton is used in case the user changed criteria and wants
to
update the view.

Now, the PagingNav control needs to know the total number of
records
found
in the DB, so the query must be exectued before it's rendered. Therefore I
have to execute the query before the PreRender event of PagingNav, which
means I cannot, for example, execute the query in the PreRender
event
of
the
ResultSetDisplay control since it will be executed after the PreRender
event
of the PagingNav control (due to its position in the page). In other
words,
it would be too late for the PageNavControl to figure out the total
records
the query found. I can execute the query in any event of ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The
problem
is, I want to reset the current page number to 1 whenever this
button
is
clicked. So I add code to do that in its SubmitButton_Click. Alas, this
event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an
event
that
takes place after the SubmitButton_Click event, which is the PreRender
event.
But that pretty much screws up the PagingNav control since, as explained
above, it needs to find out how many records the query found, but
it's
too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add
something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 
S

Scott Allen

Hi Scott,

Actually the code that retrieves the result set is factored as you
indicated, and you're right, it's passed a page number. Currently I'm calling
it from the Load event handler of the ResultSetDisplay.

Your proposed solution (i.e. calling this function from either
SubmitButton's Click event handler XOR the Load event handler) requires the
same hack. That's because I have to call this function from the Load event
while making sure the SubmitButton control wasn't clicked (so that I don't
end up calling it twice, once in the Load event handler and once in the
SubmitButton's Click event handler). And there's no way of knowing during the
execution of the Load event handler if the SubmitButton was clicked other
than that hack that I mentioned in my original message. IsPostBack won't cut
it here because other controls could also submit the page (e.g. the
PagingNav), not just the SubmitButton.

Think of this way - if IsPostBack is true, one of the other controls
raised a postback event, so do not do any queries or data binding from
page load. Do the data binding from an event handler for the postback,
be it the submit button or the nav controls.
 
G

Guest

Scott,

Calling the he function from all the post event handlers (SubmitButton,
PagingNav, etc) and from the page's Load event handler if it's not IsPostBack
works pretty well!

Thanks for your help,

Homam
 
G

Guest

Thanks, Ken, for the tips.

Scott Allen solved my problem (factor out code, call it from all postback
handlers, in addition to load handler if IsPostBack is false).

But you're right, taking advantage of ASP.NET custom controls and
client-side script event postbacks (e.g. the Page classes methods) is another
long-term solution to it.

Homam




Ken Dopierala Jr. said:
Hi Homam,

I don't see how firing a js function to set a flag that notifies the server
that the criteria has changed causes any problems. Especially once you
encapsulate this functionality into a custom control and simply drop it on
any page you need it. As you know the page load event will always fire
before the button click. Without using any type of smart-client
functionality all your work needs to be done on the server. The only way to
do this is to maintain state. You can do that with the Session object. In
your page load, compare the new criteria to the old criteria. If it doesn't
match then you know what you need to do. However once your pages become
more complicated, specifically post backs can be made from actions other
than the submit button click, you may find that simply having the client
tell you what they need instead of making the server figure it out, is the
way to go. Good luck! I hope more people can join this conversation and
help put together the right solution for you. Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Homam said:
Hi Ken,

Using JavaScript and hidden form fields is pretty much the same hack as
checking whether the SubmitButton exists in the form object. I'm just trying
to figure out a solution along the line of ASP.NET's event-driven, OO model.

Thanks,

Homam




Ken Dopierala Jr. said:
Hi,

I think implementing a Master Pages type scenario is what you are looking
for. They are built into v2.0 of the framework but here are some link for
implementing them in v1.1:

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

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

Also read through this from Microsoft's Patterns & Practices:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesMVC.asp

For your paging navigation I would recommend creating your own custom
control with all UI necessary to page (i.e. page selection links or
dropdown, submit button, previous/next links). This will allow you to make
it very generic and at the same time expose a number of custom properties
that can be changed in the property window of the IDE to customize for any
scenario. For example in one scenario you may show the current page and
links to the two pages behind or ahead of it. Where as in another scenario
you may show the page you are on, the immediate pages around it and links to
also go all the way to the beginning or end of the data. In your custom
control include the javascript necessary to set a hidden input to the
correct page when the submit button is clicked. Then have your base page
check this hidden input before loading the data. Now you'll know where to
go before the submit button click even fires. In fact, you wouldn't even
need to capture the click event on the server-side. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

Hi Ken,

This wouldn't slove my problem because even when I add an intermediate
class, the overloaded Load event will still fire before the SubmitButton's
Click event. So if the user clicked on that button to update the criteria,
the current page will be set AFTER the query has already executed, and the
ResultSetDisplay will display the wrong page.

To illustrate, let's say that the user submitted a set of criteria C1 and
browsed to page number 5 of the its result set. Then he changed the
criteria
to C2 and hit the SubmitButton. Now if I execute the query in the
overloaded
Load event handler in the derived class, the query will retrieve page 5 of
C2, not page 1 as it should, because the page was set in the SubmitButton
event handler after the query got executed.

By the way, the code is executed in the Code Behind class, which is
derived
from Page anyway.

I'm very well versed in OOA/D/P and all the design patterns paraphernalia
(I
come from a J2EE background), but I'm still trying to figure out ASP.NET's
plumbing.

Thanks for your feedback.




:

Hi,

I would create a base page class and derive my pages from this class.
The
base page's Page_Load event will fire first, you can then hit your data
access and business logic layers here. Retrieving the data you need and
setting custom properties for derived classes to check before they
render.

I would also recommend buying some books on OOP and studying them
carefully.
You attempted to solve your problem using an almost top-down approach.
When
you are trying to implement an OO design you know you are on the wrong
path
when you try to rig things up after the fact. Always try to think what
would come first. In this case a base class will solve your problem and
also make your code much more elegant and extensible. Good luck! Ken.

--
Ken Dopierala Jr.
For great ASP.Net web hosting try:
http://www.webhost4life.com/default.asp?refid=Spinlight
If you sign up under me and need help, email me.

The ASP.NET model is touted as a clean OO approach to developing web
pages,
yet sometimes the page lifecycle poses silly obstacles that forces you
revert
to the Olde ASP 3.0 Ways.

Here's a rough outline of an ASPX page:

... a bunch of criteria controls...
PagingNav
ResultSetDisplay
SubmitButton

Basically, the PagingNav allows the user to navigate through the DB
result
set; the ResultSetDisplay shows the currently selected page in a data
list;
and the SubmitButton is used in case the user changed criteria and
wants
to
update the view.

Now, the PagingNav control needs to know the total number of records
found
in the DB, so the query must be exectued before it's rendered.
Therefore I
have to execute the query before the PreRender event of PagingNav,
which
means I cannot, for example, execute the query in the PreRender event
of
the
ResultSetDisplay control since it will be executed after the PreRender
event
of the PagingNav control (due to its position in the page). In other
words,
it would be too late for the PageNavControl to figure out the total
records
the query found. I can execute the query in any event of
ResultSetDisplay
that fires before PreRender. So far so good.

Enter the SubmitButton control, which messes up the whole plan. The
problem
is, I want to reset the current page number to 1 whenever this button
is
clicked. So I add code to do that in its SubmitButton_Click. Alas,
this
event
executes AFTER the Load event of the ResultSetDisplay and BEFORE its
PreRender event. This means to get the ResultSetDisplay to dispay the
appropriate page (i.e. # 1), I have to excute the query in an event
that
takes place after the SubmitButton_Click event, which is the PreRender
event.
But that pretty much screws up the PagingNav control since, as
explained
above, it needs to find out how many records the query found, but it's
too
late now.

So, to fix the problem, I have to revert to ASP 3.0 hacks and add
something
in the Load event of the ResultSetDispay such as:

if (Request.Form["update"] != null)
this.currentPage = 1;

which is totally against the OO style of ASP.NET.

So my question is, how would you guys solve such a problem neatly?
 

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

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top