how to return value from server.execute call

Discussion in 'ASP General' started by Jim Rodgers, Aug 5, 2007.

  1. Jim Rodgers

    Jim Rodgers Guest

    I am trying to replace a huge chunck of code that currently I incorporate
    with an #Include directive. The program rarely has to flow through that
    code, so I thought it would be better if I used Server.Execute.

    I found I can pass data TO the called asp file by creating an HTML <input>
    and erading it after I get there.

    However, I also need to read back ONE variable that the called file must
    set. I cannot figuer out how to do that. My backup positions are (1) I can
    keep on using the #Include technique, and (2) I can use a database to bridge
    the gap.

    BUT... Isn't there a way to carry data BACK TO the calling asp file FROM
    THE CALLED asp file?

    I certainly do appreciate the help!

    Thanks,

    Jim
    Jim Rodgers, Aug 5, 2007
    #1
    1. Advertising

  2. Jim Rodgers

    Evertjan. Guest

    =?Utf-8?B?SmltIFJvZGdlcnM=?= wrote on 05 aug 2007 in
    microsoft.public.inetserver.asp.general:

    > I am trying to replace a huge chunck of code that currently I
    > incorporate with an #Include directive. The program rarely has to
    > flow through that code, so I thought it would be better if I used
    > Server.Execute.
    >
    > I found I can pass data TO the called asp file by creating an HTML
    > <input> and erading it after I get there.
    >
    > However, I also need to read back ONE variable that the called file
    > must set. I cannot figuer out how to do that. My backup positions
    > are (1) I can keep on using the #Include technique, and (2) I can use
    > a database to bridge the gap.
    >
    > BUT... Isn't there a way to carry data BACK TO the calling asp file
    > FROM THE CALLED asp file?


    try session variables:

    ============== test.asp ==================
    <%
    response.write "running test.asp<br>"
    session("a") = "from test"
    response.write "1-A: "&session("a")&"<br>==========<br>"

    server.execute "testtest.asp"

    response.write "running test.asp<br>"
    response.write "2-A: "&session("a")&"<br>"
    response.write "3-B: "&session("b")&"<br>"
    %>
    ==========================================

    ============ testtest.asp ================
    <%
    response.write "running testtest.asp<br>"
    session("b") = "from testtest"
    response.write "A: "&session("a")&"<br>"
    response.write "B: "&session("b")&"<br>==========<br>"
    %>
    ==========================================

    ===== result from running test.asp ======
    running test.asp
    1-A: from test
    ==========
    running testtest.asp
    A: from test
    B: from testtest
    ==========
    running test.asp
    2-A: from test
    3-B: from testtest
    ==========================================


    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
    Evertjan., Aug 5, 2007
    #2
    1. Advertising

  3. Jim Rodgers

    Jim Rodgers Guest

    "Evertjan." wrote:

    > =?Utf-8?B?SmltIFJvZGdlcnM=?= wrote on 05 aug 2007 in
    > microsoft.public.inetserver.asp.general:
    >
    > > I am trying to replace a huge chunck of code that currently I
    > > incorporate with an #Include directive. The program rarely has to
    > > flow through that code, so I thought it would be better if I used
    > > Server.Execute.
    > >
    > > I found I can pass data TO the called asp file by creating an HTML
    > > <input> and erading it after I get there.
    > >
    > > However, I also need to read back ONE variable that the called file
    > > must set. I cannot figuer out how to do that. My backup positions
    > > are (1) I can keep on using the #Include technique, and (2) I can use
    > > a database to bridge the gap.
    > >
    > > BUT... Isn't there a way to carry data BACK TO the calling asp file
    > > FROM THE CALLED asp file?

    >
    >
    > try session variables:
    >
    > --
    > Evertjan.
    > The Netherlands.
    > (Please change the x'es to dots in my emailaddress)
    >


    Thanks, Evertjan. We made a design decision early on in the project not to
    use the Session object -- for various reasons, mostly related to scalability
    in some way. But you're right, of course; that would be perfect.

    This is why I described one of my fallback positions to be using a database,
    which is the way many developers implement Session functionality without the
    Session object. I believe MS eCommerce Server (correct name?) does it that
    way.

    It seems, except for the Session object, any "variables" that can be passed
    TO the CALLED asp file are essentially read-only in the sense they cannot be
    changed and passed back to the CALLING asp file.

    For example, I can create Request.Form(1) in the CALLING file using an
    <input> element, and I can read it in the CALLED file. However, this
    expression is not permitted on the left side of an equation, so it seems I
    cannot change that value.

    Moreover, if I create yet another Form name / value pair in the CALLED file,
    that one will NOT be visible to the CALLING file upon return.

    Can you think of any way a script can modify a passed value in the CALLED
    file so a script in the CALLING file can see it?
    Jim Rodgers, Aug 5, 2007
    #3
  4. Jim Rodgers

    Jim Rodgers Guest

    "Jon Paal [MSMD]" wrote:

    > Server.execute is a dynamic include, so any variables defined in the parent file will also be availabel in the "include" file, since
    > they execute within the same page scope.
    >
    > http://support.microsoft.com/kb/224363
    >


    Thank you, Jon Paal. The variables that are available to the script in the
    CALLED file are the ASP object variables like Server, Request, Response,
    Application, etc., and most importantly, variables in the Session object.
    The VBScript variables do not scope beyond the CALLING file as they do with
    the #Include directive. It's very frustrating.

    BTW, the article you mentioned has some problems; I think they should pull
    it. For example, the data stream to the client includes...

    <html>
    <body>
    <html>
    <body>
    ....
    </body>
    </html>
    </body>
    </html>

    ....which works, but, well they need to do more than just test their examples.

    An excellent (albeit somewhat verbose) alternative article is this one:

    http://msdn.microsoft.com/msdnmag/issues/0400/redir/

    Yet even that one fails to mention (I think) the subject of returning (or
    not...) values back to the CALLING script.

    Can you think of any other ways?

    Thanks,

    Jim
    Jim Rodgers, Aug 5, 2007
    #4
  5. "Jim Rodgers" <> wrote in message
    news:...
    > I am trying to replace a huge chunck of code that currently I incorporate
    > with an #Include directive. The program rarely has to flow through that
    > code, so I thought it would be better if I used Server.Execute.
    >
    > I found I can pass data TO the called asp file by creating an HTML <input>
    > and erading it after I get there.
    >
    > However, I also need to read back ONE variable that the called file must
    > set. I cannot figuer out how to do that. My backup positions are (1) I

    can
    > keep on using the #Include technique, and (2) I can use a database to

    bridge
    > the gap.
    >
    > BUT... Isn't there a way to carry data BACK TO the calling asp file FROM
    > THE CALLED asp file?
    >
    > I certainly do appreciate the help!
    >


    For this scenario the next step from an include file is a VB6 dll. Of
    course for various reasons that may not be an option.

    For an include file that contains a large set of functions enclosing them in
    a class helps to keep the global namespace free.

    Server.Execute is not an appropriate solution.

    How have you determined that having a large include file is a problem?


    --
    Anthony Jones - MVP ASP/ASP.NET
    Anthony Jones, Aug 5, 2007
    #5
  6. Jim Rodgers

    Jim Rodgers Guest

    "Anthony Jones" wrote:
    >
    > For this scenario the next step from an include file is a VB6 dll. Of
    > course for various reasons that may not be an option.
    >
    > For an include file that contains a large set of functions enclosing them in
    > a class helps to keep the global namespace free.
    >
    > Server.Execute is not an appropriate solution.
    >
    > How have you determined that having a large include file is a problem?
    >
    > --
    > Anthony Jones - MVP ASP/ASP.NET
    >


    Thanks, Anthony!

    I have not yet determined that having a large include file is a problem. I
    may keep what I have until it is a problem. However, I am not only creating
    a specific web application, but I am trying to keep my options open for code
    reuse since the project is turning into a decent platform for more work.

    Your idea about a VB6 DLL is excellent. I am planning to replace a lot of
    my #Includes (containing my VBScript Subs and Functions "library") with a DLL
    soon. But it will make more sense to you and everyone if I mention one more
    aspect of the problem I have in the current case.

    The subject asp file (which currently is #Included and which I would prefer
    to be Server.Execute'd) processes a huge number of Request.Form(i) variables
    for all kinds of input validation requirements. It is because of the
    Request.Form(i) variables that I felt Server.Execute would be a good choice.
    I hate having to pass all these TO the CALLED file.

    Since no one could tell me about [an obscure] technique for getting one or
    two answers back to the CALLING script, I have decided to write the
    validation results to a database. Thus, I need only to check the database
    when I return to the first file. Previously, I acted on the validation
    results (with Response.Write's) in the CALLED file. Now I will simply do
    that after I return. Even though the second file now does no output to the
    client side, it still makes sense to use Server.Execute because of the sheer
    volume of Request.Form(i) variables.

    Would you agree?

    Thanks again for your remarks.

    Jim
    Jim Rodgers, Aug 5, 2007
    #6
  7. Jim Rodgers

    Jim Rodgers Guest

    "Jon Paal [MSMD]" wrote:
    >
    > >
    > > Yet even that one fails to mention (I think) the subject of returning (or
    > > not...) values back to the CALLING script.
    > >
    > > Can you think of any other ways?
    > >
    > > Thanks,
    > >
    > > Jim
    > >

    >
    > You don't have to "return" them as they are available as part of the parent page scope. Just use the variable.
    >



    Jon,

    When I reference (in the VBScript in the "executed" file) any variable from
    the VBScript in the "parent" file, I get a variable not declared error.

    When I reference (in the VBScript in the "parent" file) any variable
    declared only in the VBScript in the "executed" file, I get a variable not
    declared error.

    And even though I can "see" variables in the Request.Form collection from
    the parent to the executed file, I cannot see any Request.Form items declared
    in the executed file. (Although this is perhaps not what you were referring
    to.)

    I am using "Dim" to declare these variables (and Option Explicit). I
    haven't tried "Public" yet, do you think that would work? I can see how it
    might. Frankly, I don't think the documentation is very good on this point.

    (I am referring to variables declared at what I guess you might call the
    "module" level -- that is, I am not referring to any variables declared only
    in a VBScript subprogram or function.)

    The reason I assumed (as you are also telling me) ...that the scope carried
    forward to the executed file, is the statement made in the documentation
    (somewhere!) that subs and functions declared in file #Includes in the parent
    file are not visible in the executed file. The documentation went on to say
    that one must also #Include these same files in the executed file for that
    "child" VBScript to see it.

    Later, I concluded this is just another example of the bizarre confusion
    caused by the ever-deteriorating MSDN documentation (especially, but not
    limited to ASP Classic). I further concluded, what they really meant was NO
    MATTER HOW these elements (variables, subs, and functions) are declared in
    the parent, the executed file simply will not see them. Of course, by
    putting copies (re-declaring) of the subs and function in the executed file,
    you are back in business. However, this does not imply a remedy for the
    scope of VBScript variables.

    Or does "Public" work? Jon, do you have any links to clear specs or
    examples. I would love to see this settled for sure one way or the other.

    Thanks for helping. I appreciate the time you spend help me clear this up.

    Cheers,

    Jim Rodgers
    Jim Rodgers, Aug 6, 2007
    #7
  8. Jim Rodgers

    Evertjan. Guest

    =?Utf-8?B?SmltIFJvZGdlcnM=?= wrote on 05 aug 2007 in
    microsoft.public.inetserver.asp.general:

    > "Evertjan." wrote:
    >
    >> =?Utf-8?B?SmltIFJvZGdlcnM=?= wrote on 05 aug 2007 in
    >> microsoft.public.inetserver.asp.general:
    >>
    >> > I am trying to replace a huge chunck of code that currently I
    >> > incorporate with an #Include directive. The program rarely has to
    >> > flow through that code, so I thought it would be better if I used
    >> > Server.Execute.
    >> >
    >> > I found I can pass data TO the called asp file by creating an HTML
    >> > <input> and erading it after I get there.
    >> >
    >> > However, I also need to read back ONE variable that the called file
    >> > must set. I cannot figuer out how to do that. My backup positions
    >> > are (1) I can keep on using the #Include technique, and (2) I can
    >> > use a database to bridge the gap.
    >> >
    >> > BUT... Isn't there a way to carry data BACK TO the calling asp
    >> > file FROM THE CALLED asp file?

    >>
    >>
    >> try session variables:
    >>


    >
    > Thanks, Evertjan. We made a design decision early on in the project
    > not to use the Session object -- for various reasons, mostly related
    > to scalability in some way. But you're right, of course; that would
    > be perfect.
    >
    > This is why I described one of my fallback positions to be using a
    > database, which is the way many developers implement Session
    > functionality without the Session object. I believe MS eCommerce
    > Server (correct name?) does it that way.


    That is duplicating the session object, and if that is done well, the
    solution should work the same.

    > It seems, except for the Session object, any "variables" that can be
    > passed TO the CALLED asp file are essentially read-only in the sense
    > they cannot be changed and passed back to the CALLING asp file.


    I don't see why not. A "variable" stored in a database should have the
    same workings as using the session database structure.

    > For example, I can create Request.Form(1) in the CALLING file using an
    > <input> element, and I can read it in the CALLED file.


    But that is not using a serverside daabase.

    > However, this
    > expression is not permitted on the left side of an equation, so it
    > seems I cannot change that value.


    And rightly so.

    > Moreover, if I create yet another Form name / value pair in the CALLED
    > file, that one will NOT be visible to the CALLING file upon return.
    >
    > Can you think of any way a script can modify a passed value in the
    > CALLED file so a script in the CALLING file can see it?


    I personally think you should keep to includes
    or change your design decision.

    It is never to late to improve on design decisions,
    they are only to be kept static at your peril.

    In the end:

    What is wrong with an include,
    where the whole code is contained in:

    If Not myBoolean Then
    ' whole code
    End If

    as opposed to a statement line

    If Not myBoolean Then Server.execute "...."

    ?


    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
    Evertjan., Aug 6, 2007
    #8
  9. Jim Rodgers

    Evertjan. Guest

    Jon Paal [MSMD] wrote on 06 aug 2007 in
    microsoft.public.inetserver.asp.general:

    > my bad, all page scope variables are not handled, see Dave's comment
    > below.


    Jon, what are you refering to?


    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
    Evertjan., Aug 6, 2007
    #9
  10. Jim Rodgers

    Evertjan. Guest

    Jon Paal [MSMD] wrote on 06 aug 2007 in
    microsoft.public.inetserver.asp.general:

    > you are correct..


    Jon, what and who are you referring to?


    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
    Evertjan., Aug 6, 2007
    #10
  11. "Evertjan." wrote:
    >> you are correct..

    >
    > Jon, what and who are you referring to?


    Me. And my post about what *IS* shared among scripts when Server.Execute()
    is used.



    --
    Dave Anderson

    Unsolicited commercial email will be read at a cost of $500 per message. Use
    of this email address implies consent to these terms.
    Dave Anderson, Aug 6, 2007
    #11
  12. "Evertjan." wrote:
    >> my bad, all page scope variables are not handled, see Dave's
    >> comment below.

    >
    > Jon, what are you refering to?


    Evertjan, you really ought to give it a rest. I may be your only defender in
    here, and even I tire of the constant policing.



    --
    Dave Anderson

    Unsolicited commercial email will be read at a cost of $500 per message. Use
    of this email address implies consent to these terms.
    Dave Anderson, Aug 6, 2007
    #12
  13. Jim Rodgers

    Evertjan. Guest

    Dave Anderson wrote on 06 aug 2007 in
    microsoft.public.inetserver.asp.general:

    > "Evertjan." wrote:
    >>> my bad, all page scope variables are not handled, see Dave's
    >>> comment below.

    >>
    >> Jon, what are you refering to?

    >
    > Evertjan, you really ought to give it a rest. I may be your only
    > defender in here, and even I tire of the constant policing.


    Dave, I think this is nonsense. Why even you?
    I am just asking. If you think that is policing, so be it.


    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
    Evertjan., Aug 6, 2007
    #13
  14. "Jim Rodgers" <> wrote in message
    news:...
    > "Anthony Jones" wrote:
    > >
    > > For this scenario the next step from an include file is a VB6 dll. Of
    > > course for various reasons that may not be an option.
    > >
    > > For an include file that contains a large set of functions enclosing

    them in
    > > a class helps to keep the global namespace free.
    > >
    > > Server.Execute is not an appropriate solution.
    > >
    > > How have you determined that having a large include file is a problem?
    > >
    > > --
    > > Anthony Jones - MVP ASP/ASP.NET
    > >

    >
    > Thanks, Anthony!
    >
    > I have not yet determined that having a large include file is a problem.

    I
    > may keep what I have until it is a problem. However, I am not only

    creating
    > a specific web application, but I am trying to keep my options open for

    code
    > reuse since the project is turning into a decent platform for more work.
    >
    > Your idea about a VB6 DLL is excellent. I am planning to replace a lot of
    > my #Includes (containing my VBScript Subs and Functions "library") with a

    DLL
    > soon. But it will make more sense to you and everyone if I mention one

    more
    > aspect of the problem I have in the current case.
    >
    > The subject asp file (which currently is #Included and which I would

    prefer
    > to be Server.Execute'd) processes a huge number of Request.Form(i)

    variables
    > for all kinds of input validation requirements. It is because of the
    > Request.Form(i) variables that I felt Server.Execute would be a good

    choice.
    > I hate having to pass all these TO the CALLED file.
    >


    What can't the function you call get the form values from the Request
    object?

    > Since no one could tell me about [an obscure] technique for getting one or
    > two answers back to the CALLING script, I have decided to write the
    > validation results to a database. Thus, I need only to check the database
    > when I return to the first file. Previously, I acted on the validation
    > results (with Response.Write's) in the CALLED file. Now I will simply do
    > that after I return. Even though the second file now does no output to

    the
    > client side, it still makes sense to use Server.Execute because of the

    sheer
    > volume of Request.Form(i) variables.
    >
    > Would you agree?
    >


    No. The volume of values is not a problem there are numerous solutions to
    this.

    The appropriate approach is a function call and/or the use of Classes.

    The fact that you need to jump through ugly hoops to attempt to force a
    server.execute into a function call semantic (ie you want it to return a
    value) indicates that it's not the right tool for the job.

    --
    Anthony Jones - MVP ASP/ASP.NET
    Anthony Jones, Aug 6, 2007
    #14
  15. Jim Rodgers

    Jim Rodgers Guest

    "Anthony Jones" wrote:

    > > Your idea about a VB6 DLL is excellent. I am planning to
    > > replace a lot of my #Includes (containing my VBScript
    > > Subs and Functions "library") with a DLL soon. But it will
    > > make more sense to you and everyone if I mention one
    > > more aspect of the problem I have in the current case.
    > >
    > > The subject asp file (which currently is #Included and
    > > which I would prefer to be Server.Execute'd) processes a
    > > huge number of Request.Form(i) variables for all kinds of
    > > input validation requirements. It is because of the
    > > Request.Form(i) variables that I felt Server.Execute would
    > > be a good choice. I hate having to pass all these TO the
    > > CALLED file.


    >
    > What can't the function you call get the form values from the
    > Request oject?
    >


    I was referring to the issue of passing the many Request.Form(i)
    variables to a DLL. I did not want to stop and write a DLL right
    now. Of course, with both the #Include and the Server.Execute,
    I do not have a problem with this since Request is valid in those
    cases. I would prefer not to write unplanned VB6 DLLs during
    the main stretch of an ASP Classic project. In "Phase 2," if you
    will, I can marshall together the opportunities for improvements
    and assign VB6 DLL development in the context of the big picture.

    > > Since no one could tell me about [an obscure] technique for
    > > getting one or two answers back to the CALLING script, I have
    > > decided to write the validation results to a database. Thus, I
    > > need only to check the database when I return to the first file.
    > > Previously, I acted on the validation results (with
    > > Response.Write's) in the CALLED file. Now I will simply do that
    > > after I return. Even though the second file now does no output
    > > to the client side, it still makes sense to use Server.Execute
    > > because of the sheer volume of Request.Form(i) variables.
    > >
    > > Would you agree?
    > >


    >
    > No. The volume of values is not a problem there are
    > numerous solutions to this.
    >
    > The appropriate approach is a function call and/or the use
    > of Classes.
    >
    > The fact that you need to jump through ugly hoops to attempt
    > to force a server.execute into a function call semantic (ie you
    > want it to return a value) indicates that it's not the right tool
    > for the job.
    >


    For me, writing the result to a database is not an inherently ugly
    hoop. It's akin to using Session, but without the scalability issues.
    Of course, potential problems could sometimes arise if the data
    model did not accommodate the subject information, but that did
    not happen here. If it had been a problem, then one might be
    concerned that the data model was effective, or that the project
    management issues (e.g., deadlines) would kick in. The point is
    the code was already done in-line, then became an #Include.

    All this time, there was one little boolean that was being carried
    forward to the rest of the program. I never embarked on using
    Server.Execute when I knew I needed something to come back
    from it. There was just this one little thing versus hundreds of
    lines of code, and it was not in the existing data model at the time.

    As it turns out, I now have re-written the whole thing. The large
    number of variables to be validated was creating a large volume
    of code. However, I had the variables formatting and limits specs
    in a database, so I took the additional time to write better code
    rather than to brute force it with a lot of easy code. The result
    was so tight, I no longer feel the need to extract it into either an
    #Include or a Server.Execute. (When we started, validation was
    somewhat generic. It became much more complex, however, as
    other parts of the project emerged into testing.)

    This code section is now back in-line with the "main" program.
    There no longer is an issue with Server.Execute.

    My original reason for putting it into an #Include was the code
    (i.e., the "main" program) was just getting too big. We did not
    anticipate how much the client needed this validation. Testing
    later revealed the core function, a complex financial simulation,
    required much more extensive input validation (including limits
    based on previous user inputs) to maintain simulation stability.

    Anyway, as the validation section gradually became horrendous,
    it first was #Included. Later, I wanted not to load all these lines
    of code unless I needed them, hence the Server.Execute idea,
    since the program logic could jump around it. About 1/3 of the
    time I was processing a tabbed dialog containing a sequence of
    input pages. The other 2/3 of the time, this validation section
    was non-value-added overhead.

    The reason for wanting the SINGLE piece of information back
    from the Server.Executed file was simply to know if Validation
    had in fact detected an error. If there were an error, the code
    would not process the State Transition Matrix; it would simply
    render the same tab page again (with error messages added)
    rather than navigate to the next state (i.e., user page). It is
    not easy to fully explain this here because there are many
    aspects both to the technical objectives of the code and to the
    history of the project and client relationship.

    It's always a judgement call when either scope creep or the
    revelation of unknown requirements causes more code to be
    developed. Do you write as "ingeniously" as you would like,
    or do you blast it out in a manner more consistent with what
    the customer is willing to pay? Sometimes you have to make
    what is essentially a business decision to write more without
    getting paid more in order to protect the client relationship for
    future business. Quality is a high level requirement, and that
    includes reliability and maintainability of the product. Hence,
    there is a need to go back and tighten-up code if it starts
    getting too loose or too big. Clients don't always understand
    this. I always endeavor to maintain the right (in the contract
    with the client) to "keep" code snippets for re-use – just as I
    draw on our code library to keep their price under control. I
    can justify the extra-and-sometimes-unpaid work this way.

    So, I believe the problem at hand is solved, and there are new
    problems already.

    Watch as I start new threads with deceptively naive questions.

    I really appreciate all the participation in this thread. Thank
    you for your time.

    Cheers,

    Jim Rodgers
    Jim Rodgers, Aug 7, 2007
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michele Petrazzo

    Execute external code and get return value

    Michele Petrazzo, Sep 29, 2006, in forum: Python
    Replies:
    4
    Views:
    309
    Peter Otten
    Sep 29, 2006
  2. Greenhorn
    Replies:
    15
    Views:
    811
    Keith Thompson
    Mar 6, 2005
  3. JT

    server.execute return value??

    JT, Sep 9, 2003, in forum: ASP General
    Replies:
    1
    Views:
    210
    Ray at
    Sep 9, 2003
  4. Savas Ates
    Replies:
    1
    Views:
    276
    Patrice
    Aug 17, 2004
  5. Raymond O'Connor
    Replies:
    1
    Views:
    146
    Raymond O'Connor
    Mar 8, 2007
Loading...

Share This Page