Passing parameters to PageMethods via HttpSessionState

100 views
Skip to first unread message

christianacca

unread,
Sep 20, 2007, 7:13:36 AM9/20/07
to PageMethods
Always passing parameters to PageMethods as QueryString parameters is
somewhat limited. Maybe the parameter a page needs is not
serializable, maybe the parameter will contain sensitive data or
perhaps be too large. There are lots of reasons why you wouldn't want
to include these parameters in the QueryString. This leads you
inevitably to passing them via Session state. None the less the
contract that defines what the page expects from its caller stays the
same regardless of the mechanics of how those parameters are being
passed.

So how about being able to decorate a PageMethod with a further
attribute for each parameter that is to be passed via Session state.
For example

[PageMethod, SessionParameter(typeof(List<Order>), "Orders")]
protected void EditCustomer(int custID)
{
txtID.Text = custID.ToString();
List<Order> orders = Session["Orders_Key"] as List<Order>;
}

This would generate a PageMethod that looked something like:

public static string EditCustomer(int custID, List<Order> orders)
{
HttpContext.Current.Session.Add("Orders_Key", orders);
string paramData =
PageMethodsEngine.BuildQueryString("EditCustomer", new
UrlParam("custID", custID, null, false, null));
if (string.IsNullOrEmpty(PageMethodsSettings.BaseUrl)) {
return string.Concat(TildePageUrl, paramData);
}
else {
return string.Concat(PageMethodsSettings.BaseUrl, PageUrl,
paramData);
}
}

What do you think fabrice?

Christian

Fabrice Marguerie

unread,
Sep 24, 2007, 1:47:33 PM9/24/07
to PageMethods
Hi Christian,

I think that I understand what you are trying to achieve. In your
example, you want to avoid passing (or cannot pass) a list of orders
to a page as a parameter in the URL. I understand the problem, but
using the Session is not a good solution. In fact, using Session as
you suggest is considered a bad practice, and this for several
reasons. Just to name a few that come to my mind:
- A Session can expire, possibly before the user clicks on the link.
This means that when the target page is displayed, the data about the
orders may not be in the Session any more. Worse maybe, it can have
changed.
- Let's imagine that you have a list of customers displayed on a page,
and for each of them you have and Edit link generated by a call to the
EditCustomer page method. What happens? Each time the method is
invoked, the data in the session is different (if the orders parameter
is different) or the Orders_Key entry is added several times to the
Session (which is not possible).
- What identifies the data in Session for a given page? If two pages
point to the same URL, will they (should they) see the same orders?
- What happens to the data you have put in the Session after the page
has been processed? Does it stay there forever or does the page remove
it?

The Session can be used to store the data a user is working on, for
example a list of orders if you wish, but why pass them to the method
that creates page URLs? It looks like you are trying to do some
contract-based programming. In your example, it's a bit as if you
wished to say: "this page cannot be displayed if there isn't a list of
orders in Session".

In other cases, like when some parameters may contain sensitive data,
I'd suggest other solutions. I planned to add a feature for encrypting
parameters, but I haven't found the time to implement it. Now that
PageMethods is open source, people interested in this feature may
contact me to help...

Whenever possible, I would stay away from the session. People tend to
use it for all situations, but end up doing bad things with it.
Maybe you could describe the scenario you are trying to implement? The
EditCustomer is not the best use case you can come up with, I think.
If you describe your exact scenario, maybe we'll be able to think
about another approach?

Fabrice

christianacca

unread,
Sep 25, 2007, 3:45:55 PM9/25/07
to PageMethods
Hi Fabrice, thanks for the taking the time to reply.

> It looks like you are trying to do some contract-based programming. In your example, it's a bit as if you wished to say: "this page cannot be displayed if there isn't a list of orders in Session".

Precisely! I've been looking at ways to make this contract explicit. I
recently found a "pattern" that addressed it here:
http://polymorphicpodcast.com/shows/webnavigator/
My idea was really the melding of what you've done with PageMethods
and this pattern.

> The Session can be used to store the data a user is working on, for example a list of orders if you wish, but why pass them to the method that creates page URLs?

Hopefully you'll get the flavour of my intent by looking at the
WebNavigator pattern that I link to above. The intent of the pattern
is to encapsulate the actual mechanism for passing parameters between
pages, but I agree that it looks a bit strange to pass a parameter
using the Session when the method returns a url string.

I suspect that your reaction could be "why not write the WebNavigator
class to define the contract for a page and have this class delegate
to PageMethods build the url's and managing query strings". I tried
this, but it really smacked of duplication. The WebNavigator class
ended up being a parallel of the generated PageMethods classes except
the PageMethod's themselves could not specify the full contract for
those parameters that are not suitable for passing as query string
parameters.

> Whenever possible, I would stay away from the session. People tend to use it for all situations, but end up doing bad things with it.

I totally agree with you on this one. Personally, I think Session
state share most of the problems of global variables (untyped ones at
that). I detest the fact that global variables make it very difficult
to determine how the various parts of a program will communicate with
each other. This contrasts starkly to the immediacy you get when one
object passes parameters to other objects as arguments to methods and
class constructors. The problem is that in a stateless environment
what alternatives are there?

> EditCustomer is not the best use case you can come up with, I think. If you describe your exact scenario, maybe we'll be able to think about another approach?

I agree that this is a bad example - it was simply the easiest snippet
I could come up with given that I was working through the PageMethod's
tutorial! I am actually just getting into Web development so I can't
help but think in terms of statefull WinForms where I'm used to
passing around a reference to an Aggregate object that is being worked
on within multiple forms. The closest translation to this in a Web
environment is to pass the reference using Session state (although I
have tinkered with passing state between pages using Context.Items and
Server.Transfer which is a *little* better than using Session). Maybe
its because I haven't made the mental paradigm shift of how to develop
an object-oriented program (think rich domain model) in a stateless
world?

Anyway I would be interested to hear whether your thinking has changed
any, and whether its a good idea to stretch PageMethods to include the
concept of specifying a contract for how a Page should be used while
encapsulating the mechanism for passing parameter as per the
WebNavigator pattern.

Thanks
Christian

On Sep 24, 6:47 pm, Fabrice Marguerie <fabrice.margue...@gmail.com>
wrote:

Reply all
Reply to author
Forward
0 new messages