Connecting Tech Pros Worldwide Forums | Help | Site Map

Guidelines for overloading Render method

sk
Guest
 
Posts: n/a
#1: Nov 19 '05
Hi,
I'm trying to override the Render method of my Page class. Are there any
standard guidelines for this?

Thanks.
Shardul



gaidar
Guest
 
Posts: n/a
#2: Nov 19 '05

re: Guidelines for overloading Render method



I don't know what about the guidlines but what I know is what overriding
Render method is a little bit difficult thing, because you should render
hidden fields, scripts, viewstate and and so forth, and so on.

This code I've found in google and it seems to me that this way ASP.NET Page
do it originally:

internal void OnFormRender(HtmlTextWriter writer, string formUniqueID)
{
if (_fOnFormRenderCalled)
{
throw new
HttpException(HttpRuntime.FormatResourceString("Mu ltiple_forms_not_allowed"));
}
_fOnFormRenderCalled = true;
_inOnFormRender = true;
RenderHiddenFields(writer);
if (_viewStateToPersist != null)
{
if (_formatter == null)
{
CreateLosFormatter();
}
writer.WriteLine();
writer.Write("<input type=\"hidden\" name=\"");
writer.Write("__VIEWSTATE");
writer.Write("\" value=\"");
_formatter.Serialize(writer, _viewStateToPersist);
writer.WriteLine("\" />");
}
else
{
writer.WriteLine();
writer.Write("<input type=\"hidden\" name=\"");
writer.Write("__VIEWSTATE");
writer.Write("\" value=\"\" />");
}
if (_fRequirePostBackScript)
{
RenderPostBackScript(writer, formUniqueID);
}
RenderScriptBlock(writer, _registeredClientScriptBlocks);
}

internal void OnFormPostRender(HtmlTextWriter writer, string
formUniqueID)
{
if (_registeredArrayDeclares != null)
{
writer.WriteLine();
writer.WriteLine("<script language=\"javascript\">\r\n<!--");
writer.Indent = writer.Indent + 1;
IDictionaryEnumerator iDictionaryEnumerator =
_registeredArrayDeclares.GetEnumerator();
while (iDictionaryEnumerator.MoveNext())
{
writer.Write("var ");
writer.Write(iDictionaryEnumerator.Key);
writer.Write(" = new Array(");
IEnumerator iEnumerator =
((ArrayList)iDictionaryEnumerator.Value).GetEnumer ator();
bool flag = true;
while (iEnumerator.MoveNext())
{
if (flag)
{
flag = false;
}
else
{
writer.Write(", ");
}
writer.Write(iEnumerator.Current);
}
writer.WriteLine(");");
}
writer.Indent = writer.Indent + 1;
writer.WriteLine("// -->\r\n</script>");
writer.WriteLine();
}
RenderHiddenFields(writer);
if (_fRequirePostBackScript && !_fPostBackScriptRendered)
{
RenderPostBackScript(writer, formUniqueID);
}
RenderScriptBlock(writer, _registeredClientStartupScripts);
_inOnFormRender = false;
}

private void RenderHiddenFields(HtmlTextWriter writer)
{
if (_registeredHiddenFields != null)
{
IDictionaryEnumerator iDictionaryEnumerator =
_registeredHiddenFields.GetEnumerator();
while (iDictionaryEnumerator.MoveNext())
{
writer.WriteLine();
writer.Write("<input type=\"hidden\" name=\"");
writer.Write((String)iDictionaryEnumerator.Key);
writer.Write("\" value=\"");
HttpUtility.HtmlEncode((String)iDictionaryEnumerat or.Value,
writer);
writer.Write("\" />");
}
_registeredHiddenFields = null;
}
}

private void RenderScriptBlock(HtmlTextWriter writer, IDictionary
scriptBlocks)
{
if (scriptBlocks != null)
{
writer.Indent = writer.Indent + 1;
IDictionaryEnumerator iDictionaryEnumerator =
scriptBlocks.GetEnumerator();
while (iDictionaryEnumerator.MoveNext())
{
writer.WriteLine((String)iDictionaryEnumerator.Val ue);
writer.WriteLine();
}
writer.Indent = writer.Indent - 1;
}
}

Best regards,
Gaidar


"sk" <sk@sk.com> wrote in message news:112qjjcmahatre7@corp.supernews.com...[color=blue]
> Hi,
> I'm trying to override the Render method of my Page class. Are there any
> standard guidelines for this?
>
> Thanks.
> Shardul
>
>[/color]


Scott Allen
Guest
 
Posts: n/a
#3: Nov 19 '05

re: Guidelines for overloading Render method


Hi Shardul:

It depends - what are you trying to achieve?

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

On Tue, 8 Mar 2005 12:34:10 +0530, "sk" <sk@sk.com> wrote:
[color=blue]
>Hi,
>I'm trying to override the Render method of my Page class. Are there any
>standard guidelines for this?
>
>Thanks.
>Shardul
>[/color]

Shardul Kulkarni
Guest
 
Posts: n/a
#4: Nov 19 '05

re: Guidelines for overloading Render method


Hi Scott,
My company markets a helpdesk application that is web based and for
performing database administration tasks we have a custom application (.exe)
that is client/server based. This app is written using pure SDK (no
MFC/ATL/OWL). This code is pretty old (nearly a decade) and it supports only
English characters. It comprises of 3 main dlls which are pure C dlls (no
COM) with exported C++ classes. For the next release of our main app, we
intend to support multiple languages and so the management decided to
convert this legacy app also to web based. We have written a .NET wrapper
(written in C# and managed C++) which eventually calls into the low-level
dll's and the UI is in ASP.NET. The UI calls into the wrapper which in turn
calls into the legacy dlls. And for the most parts this works ok. But in the
old app, whenever you performed any operation a small window would open and
display status messages. For example when you performed an operation to
check the database for correctness, it would show messages like 'Checking
views...', 'Checking tables'... and so on. The calls to display these
messages are placed in the low-level dlls.

Now my job is to display these progress messages through the ASP.NET UI.
This is quite a challenge and we have figured out how to get the progress
message calls to end-up at the ASP level using delegates at the wrapper
level and function pointers at the dll level and this also works just fine.
So when the dll makes a call to show a progress message, it calls a method
at the low-level which calls the function pointer which points to the
delegate in the UI. So when my UI method is called, I just have to send it
the client (which is a browser). And this is anything but trivial.

I looked at a very good article on MSDN by Dino Esposito (Build your ASP.NET
pages on a richer Bedrock) but his solution just tells you when the
operation completes. Its not interactive. I have to mimic the exact behavior
of the old app, which is to open a small window and display the messages
within that window and then to close the window once the operation
completes.

For testing purposes I created a test page (Test2.aspx) that does NOT have a
code-behind class. And took the following steps:
1. Created a marker interface IRequireProgressMessage.
2. Put a <%@ Implements interface="IRequireProgressMessage" %> directive at
the top of my page Test2.aspx.
3. I wrote a server-side script inline within the page inside the <body> tag
and just before the <form> tag.
4. Within the block I put a check for postback and if it succeeds then I
emitted the following client-side script:
<script >
var oWin = window.showModelessDialog("blank.html",'','');
var oDoc = oWin.document;
</script>
5. After emitting this I flush the buffer just to be sure. At this point we
haven't yet called into the wrapper and the client has opened a modeless
window for displaying the progress messages. blank.html contains a single
<div> element with the id 'msgDiv'.
6. After this I setup the infrastructure to receive calls to SetMessage from
the dlls. This involves implementing an interface with one method
SetMessage(string strMessage). The implementation of SetMessage emits the
following client side script:
"<script>oDoc.all.msgDiv.innerHTML= '" +strMessage + "' </script>"
after checking whether the current handler
(System.Web.HttpContext.Current.Handler) is of the type
IRequireProgressMessage.
7. Call a method of the wrapper object. For this I created a test() method
on the wrapper which wraps a test() method on one of the lower level
objects. This method sends 2 messages with a delay of 2 seconds.

This works fine and the two messages are displayed in the modeless dialog.
However, this works only when you have the script within the .aspx page. But
the UI guys have already finished most of their work and they have used
code-behind throughout. The calls into the wrapper are placed from within
the Page_Load method. Now the problem with Page_Load is that if I emit my
script there and even if I flush the buffer, it won't get sent to the
browser. I don't know what goes on behind, but I think it just gets buffered
into another intermediate buffer and is emitted when Render gets called. So
I thought of overriding the Render method, move all of the processing from
Page_Load into the overridden method and then call into the wrapper after
rendering the <body> tag. For this I derived a new class from
System.Web.UI.Page, overrode the Render method. In this method I loop the
Controls collection and keep a check whether we rendered a LiteralControl
with the text "<body" in it. If it does it calls a virtual method
PostBodyRender. This method will be overridden by the code-behind class and
from within this do the processing that Page_Load used to do. It will first
emit the script that gets the modeless dialog to display if the page is
posted back and then do the rest of the processing, which involves setting
up the messaging infrastructure and calling into the wrapper method.

And this too works fine, but (and a big bad BUT) it gets munged if there is
some in-line script within the page!!! All aspx pages set the <title> from
server-side code. When this happens there's only one item in the Controls
collection which is the HtmlForm object representing the single <form>
element in the page. I just can't figure out when is the rest of the html
rendered and what happens to the <body> element. I figured, I must be doing
something wrong in Render and felt that there must be some standard way of
overriding the Render method which led me to post this here.

Whew! This turned out to be quite a big post! I tried to be verbose just to
be sure you have all the information. Let me know if you need anything else.

Thanks in advance.
Shardul.


"Scott Allen" <scott@nospam.odetocode.com> wrote in message
news:fklr219ncvhgv3a9u5vrsnk99smkfd7cgt@4ax.com...[color=blue]
> Hi Shardul:
>
> It depends - what are you trying to achieve?
>
> --
> Scott
> http://www.OdeToCode.com/blogs/scott/
>
> On Tue, 8 Mar 2005 12:34:10 +0530, "sk" <sk@sk.com> wrote:
>[color=green]
> >Hi,
> >I'm trying to override the Render method of my Page class. Are there any
> >standard guidelines for this?
> >
> >Thanks.
> >Shardul
> >[/color]
>[/color]


Scott Allen
Guest
 
Posts: n/a
#5: Nov 19 '05

re: Guidelines for overloading Render method


Hi Shardul:

Quite an explanation here! It's always a pain to provide immediate
feedback to a web app - I feel your pain.

After reading your description my concern would be that whatever
solution you come up with would be fragile - in the sense that an
unknowing developer could change functionality in the ASP.NET page and
break the feedback mechanism.

Did you consider a polling mechanism? The message from the lower level
could be saved on the server, the client window could refresh or
postback every 5 seconds and check the status. Messages would still be
pretty much real time - but the solution I feel would be much easier
to maintain.




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

On Wed, 9 Mar 2005 13:53:19 +0530, "Shardul Kulkarni"
<kshardul77@yahoo.co.uk> wrote:
[color=blue]
>Hi Scott,
>My company markets a helpdesk application that is web based and for
>performing database administration tasks we have a custom application (.exe)
>that is client/server based. This app is written using pure SDK (no
>MFC/ATL/OWL). This code is pretty old (nearly a decade) and it supports only
>English characters. It comprises of 3 main dlls which are pure C dlls (no
>COM) with exported C++ classes. For the next release of our main app, we
>intend to support multiple languages and so the management decided to
>convert this legacy app also to web based. We have written a .NET wrapper
>(written in C# and managed C++) which eventually calls into the low-level
>dll's and the UI is in ASP.NET. The UI calls into the wrapper which in turn
>calls into the legacy dlls. And for the most parts this works ok. But in the
>old app, whenever you performed any operation a small window would open and
>display status messages. For example when you performed an operation to
>check the database for correctness, it would show messages like 'Checking
>views...', 'Checking tables'... and so on. The calls to display these
>messages are placed in the low-level dlls.
>
>Now my job is to display these progress messages through the ASP.NET UI.
>This is quite a challenge and we have figured out how to get the progress
>message calls to end-up at the ASP level using delegates at the wrapper
>level and function pointers at the dll level and this also works just fine.
>So when the dll makes a call to show a progress message, it calls a method
>at the low-level which calls the function pointer which points to the
>delegate in the UI. So when my UI method is called, I just have to send it
>the client (which is a browser). And this is anything but trivial.
>[/color]

Agreed!
[color=blue]
>I looked at a very good article on MSDN by Dino Esposito (Build your ASP.NET
>pages on a richer Bedrock) but his solution just tells you when the
>operation completes. Its not interactive. I have to mimic the exact behavior
>of the old app, which is to open a small window and display the messages
>within that window and then to close the window once the operation
>completes.
>
>For testing purposes I created a test page (Test2.aspx) that does NOT have a
>code-behind class. And took the following steps:
>1. Created a marker interface IRequireProgressMessage.
>2. Put a <%@ Implements interface="IRequireProgressMessage" %> directive at
>the top of my page Test2.aspx.
>3. I wrote a server-side script inline within the page inside the <body> tag
>and just before the <form> tag.
>4. Within the block I put a check for postback and if it succeeds then I
>emitted the following client-side script:
><script >
>var oWin = window.showModelessDialog("blank.html",'','');
>var oDoc = oWin.document;
></script>
>5. After emitting this I flush the buffer just to be sure. At this point we
>haven't yet called into the wrapper and the client has opened a modeless
>window for displaying the progress messages. blank.html contains a single
><div> element with the id 'msgDiv'.
>6. After this I setup the infrastructure to receive calls to SetMessage from
>the dlls. This involves implementing an interface with one method
>SetMessage(string strMessage). The implementation of SetMessage emits the
>following client side script:
>"<script>oDoc.all.msgDiv.innerHTML= '" +strMessage + "' </script>"
>after checking whether the current handler
>(System.Web.HttpContext.Current.Handler) is of the type
>IRequireProgressMessage.
>7. Call a method of the wrapper object. For this I created a test() method
>on the wrapper which wraps a test() method on one of the lower level
>objects. This method sends 2 messages with a delay of 2 seconds.
>
>This works fine and the two messages are displayed in the modeless dialog.
>However, this works only when you have the script within the .aspx page. But
>the UI guys have already finished most of their work and they have used
>code-behind throughout. The calls into the wrapper are placed from within
>the Page_Load method. Now the problem with Page_Load is that if I emit my
>script there and even if I flush the buffer, it won't get sent to the
>browser. I don't know what goes on behind, but I think it just gets buffered
>into another intermediate buffer and is emitted when Render gets called. So
>I thought of overriding the Render method, move all of the processing from
>Page_Load into the overridden method and then call into the wrapper after
>rendering the <body> tag. For this I derived a new class from
>System.Web.UI.Page, overrode the Render method. In this method I loop the
>Controls collection and keep a check whether we rendered a LiteralControl
>with the text "<body" in it. If it does it calls a virtual method
>PostBodyRender. This method will be overridden by the code-behind class and
>from within this do the processing that Page_Load used to do. It will first
>emit the script that gets the modeless dialog to display if the page is
>posted back and then do the rest of the processing, which involves setting
>up the messaging infrastructure and calling into the wrapper method.
>
>And this too works fine, but (and a big bad BUT) it gets munged if there is
>some in-line script within the page!!! All aspx pages set the <title> from
>server-side code. When this happens there's only one item in the Controls
>collection which is the HtmlForm object representing the single <form>
>element in the page. I just can't figure out when is the rest of the html
>rendered and what happens to the <body> element. I figured, I must be doing
>something wrong in Render and felt that there must be some standard way of
>overriding the Render method which led me to post this here.
>
>Whew! This turned out to be quite a big post! I tried to be verbose just to
>be sure you have all the information. Let me know if you need anything else.
>[/color]


Shardul Kulkarni
Guest
 
Posts: n/a
#6: Nov 19 '05

re: Guidelines for overloading Render method


Hi Scott,

A polling solution was among the first things that I thought of. But theres
a problem. If the polling interval is 5 soconds and say there are 5 messages
that are generated, then it will take a whole 25 seconds before all those
messages are displayed to the user, and the operation most likely will
complete before 25 seconds have elapsed since it was invoked. So if you
reduce the polling interval, then you will be hitting the server a lot more
and it may impair the performance of the server.

-Shardul

"Scott Allen" <scott@nospam.odetocode.com> wrote in message
news:rq6u219dussndtc3c6jss9sc5dja922r6t@4ax.com...[color=blue]
> Hi Shardul:
>
> Quite an explanation here! It's always a pain to provide immediate
> feedback to a web app - I feel your pain.
>
> After reading your description my concern would be that whatever
> solution you come up with would be fragile - in the sense that an
> unknowing developer could change functionality in the ASP.NET page and
> break the feedback mechanism.
>
> Did you consider a polling mechanism? The message from the lower level
> could be saved on the server, the client window could refresh or
> postback every 5 seconds and check the status. Messages would still be
> pretty much real time - but the solution I feel would be much easier
> to maintain.
>
>
>
>
> --
> Scott
> http://www.OdeToCode.com/blogs/scott/
>
> On Wed, 9 Mar 2005 13:53:19 +0530, "Shardul Kulkarni"
> <kshardul77@yahoo.co.uk> wrote:
>[color=green]
> >Hi Scott,
> >My company markets a helpdesk application that is web based and for
> >performing database administration tasks we have a custom application[/color][/color]
(.exe)[color=blue][color=green]
> >that is client/server based. This app is written using pure SDK (no
> >MFC/ATL/OWL). This code is pretty old (nearly a decade) and it supports[/color][/color]
only[color=blue][color=green]
> >English characters. It comprises of 3 main dlls which are pure C dlls (no
> >COM) with exported C++ classes. For the next release of our main app, we
> >intend to support multiple languages and so the management decided to
> >convert this legacy app also to web based. We have written a .NET wrapper
> >(written in C# and managed C++) which eventually calls into the low-level
> >dll's and the UI is in ASP.NET. The UI calls into the wrapper which in[/color][/color]
turn[color=blue][color=green]
> >calls into the legacy dlls. And for the most parts this works ok. But in[/color][/color]
the[color=blue][color=green]
> >old app, whenever you performed any operation a small window would open[/color][/color]
and[color=blue][color=green]
> >display status messages. For example when you performed an operation to
> >check the database for correctness, it would show messages like 'Checking
> >views...', 'Checking tables'... and so on. The calls to display these
> >messages are placed in the low-level dlls.
> >
> >Now my job is to display these progress messages through the ASP.NET UI.
> >This is quite a challenge and we have figured out how to get the progress
> >message calls to end-up at the ASP level using delegates at the wrapper
> >level and function pointers at the dll level and this also works just[/color][/color]
fine.[color=blue][color=green]
> >So when the dll makes a call to show a progress message, it calls a[/color][/color]
method[color=blue][color=green]
> >at the low-level which calls the function pointer which points to the
> >delegate in the UI. So when my UI method is called, I just have to send[/color][/color]
it[color=blue][color=green]
> >the client (which is a browser). And this is anything but trivial.
> >[/color]
>
> Agreed!
>[color=green]
> >I looked at a very good article on MSDN by Dino Esposito (Build your[/color][/color]
ASP.NET[color=blue][color=green]
> >pages on a richer Bedrock) but his solution just tells you when the
> >operation completes. Its not interactive. I have to mimic the exact[/color][/color]
behavior[color=blue][color=green]
> >of the old app, which is to open a small window and display the messages
> >within that window and then to close the window once the operation
> >completes.
> >
> >For testing purposes I created a test page (Test2.aspx) that does NOT[/color][/color]
have a[color=blue][color=green]
> >code-behind class. And took the following steps:
> >1. Created a marker interface IRequireProgressMessage.
> >2. Put a <%@ Implements interface="IRequireProgressMessage" %> directive[/color][/color]
at[color=blue][color=green]
> >the top of my page Test2.aspx.
> >3. I wrote a server-side script inline within the page inside the <body>[/color][/color]
tag[color=blue][color=green]
> >and just before the <form> tag.
> >4. Within the block I put a check for postback and if it succeeds then I
> >emitted the following client-side script:
> ><script >
> >var oWin = window.showModelessDialog("blank.html",'','');
> >var oDoc = oWin.document;
> ></script>
> >5. After emitting this I flush the buffer just to be sure. At this point[/color][/color]
we[color=blue][color=green]
> >haven't yet called into the wrapper and the client has opened a modeless
> >window for displaying the progress messages. blank.html contains a single
> ><div> element with the id 'msgDiv'.
> >6. After this I setup the infrastructure to receive calls to SetMessage[/color][/color]
from[color=blue][color=green]
> >the dlls. This involves implementing an interface with one method
> >SetMessage(string strMessage). The implementation of SetMessage emits the
> >following client side script:
> >"<script>oDoc.all.msgDiv.innerHTML= '" +strMessage + "' </script>"
> >after checking whether the current handler
> >(System.Web.HttpContext.Current.Handler) is of the type
> >IRequireProgressMessage.
> >7. Call a method of the wrapper object. For this I created a test()[/color][/color]
method[color=blue][color=green]
> >on the wrapper which wraps a test() method on one of the lower level
> >objects. This method sends 2 messages with a delay of 2 seconds.
> >
> >This works fine and the two messages are displayed in the modeless[/color][/color]
dialog.[color=blue][color=green]
> >However, this works only when you have the script within the .aspx page.[/color][/color]
But[color=blue][color=green]
> >the UI guys have already finished most of their work and they have used
> >code-behind throughout. The calls into the wrapper are placed from within
> >the Page_Load method. Now the problem with Page_Load is that if I emit my
> >script there and even if I flush the buffer, it won't get sent to the
> >browser. I don't know what goes on behind, but I think it just gets[/color][/color]
buffered[color=blue][color=green]
> >into another intermediate buffer and is emitted when Render gets called.[/color][/color]
So[color=blue][color=green]
> >I thought of overriding the Render method, move all of the processing[/color][/color]
from[color=blue][color=green]
> >Page_Load into the overridden method and then call into the wrapper after
> >rendering the <body> tag. For this I derived a new class from
> >System.Web.UI.Page, overrode the Render method. In this method I loop the
> >Controls collection and keep a check whether we rendered a LiteralControl
> >with the text "<body" in it. If it does it calls a virtual method
> >PostBodyRender. This method will be overridden by the code-behind class[/color][/color]
and[color=blue][color=green]
> >from within this do the processing that Page_Load used to do. It will[/color][/color]
first[color=blue][color=green]
> >emit the script that gets the modeless dialog to display if the page is
> >posted back and then do the rest of the processing, which involves[/color][/color]
setting[color=blue][color=green]
> >up the messaging infrastructure and calling into the wrapper method.
> >
> >And this too works fine, but (and a big bad BUT) it gets munged if there[/color][/color]
is[color=blue][color=green]
> >some in-line script within the page!!! All aspx pages set the <title>[/color][/color]
from[color=blue][color=green]
> >server-side code. When this happens there's only one item in the Controls
> >collection which is the HtmlForm object representing the single <form>
> >element in the page. I just can't figure out when is the rest of the html
> >rendered and what happens to the <body> element. I figured, I must be[/color][/color]
doing[color=blue][color=green]
> >something wrong in Render and felt that there must be some standard way[/color][/color]
of[color=blue][color=green]
> >overriding the Render method which led me to post this here.
> >
> >Whew! This turned out to be quite a big post! I tried to be verbose just[/color][/color]
to[color=blue][color=green]
> >be sure you have all the information. Let me know if you need anything[/color][/color]
else.[color=blue][color=green]
> >[/color]
>
>[/color]


Closed Thread