Howdy! It's Dr. Dotnetsky,
back again for some fun and cool ideas!
ViewState, Server.Transfer, Response.Redirect, and related issues
We've
been getting a number of posts related to ViewState, Server.Transfer,
and related issues lately, so I thought it might be a good idea to put
together
some information from a variety of sources, and some links to helpful resources
on these.
What ViewState isn't:
ViewState does not help restore posted values to form
controls, although you will read this often. If you
disable a control's ViewState you can watch its value be restored. This
is done
automatically, although it only works for controls that are created by
the time
the Load event is completed.
ViewState also does not auto-recreate any controls that were dynamically
created in the code. Any controls that you
dynamically create in your code must be recreated in the code.
ViewState can, however, be used to track this information, but it must be manually
coded.
ViewState is not intended for user or session data, nor for
transferring across pages. ViewState is only designed for state data
related to the current page and its various controls. It does not get
sent
to a new page in any case, not through links, redirects, or server
transfers. There may be things that you want to access on multiple pages,
due to redirects or transfers, but the solutions involve using either
cookies, session, the request context, or custom overrides of the LoadPageState
and SavePageState methods as referenced below.
What ViewState Is:
ViewState, which is a Base64 encoded string stored in the__VIEWSTATE hidden
formfield, is used to track and restore the state values of controls
that would otherwise be lost, either because those values do not post
with
the
form or because they are not in the page's html. So a control
totally defined in your page html, with no changes made in the code,
will
have no ViewState at all. Instead, ViewState only holds the values of
properties that
are dynamically changed somehow, usually in code, data-binding, or user
interactions, so that they can be restored on each request.
So, ViewState holds properties that you change in code, any data that
you bind
to a control in code, and any changes that occur as a result of user
interactions that were triggered with a PostBack. An example of a user
interaction is a user selecting a date or moving a month in the calendar,
which triggers a PostBack that changes properties of the calendar to
match
the user's request. The new date selected or month being viewed must
be
persisted in the calendar's ViewState since these are properties that
will
need to be restored but which will not be posted next time.
ViewState also provides a StateBag, which is a special collection or
dictionary, for each page that you can use to store any object or value,
associated with a key, to retain across PostBacks. This is useful for
your
own custom items that are relevant to only that specific page instance,
since these values will automatically post with that page, but not transfer
to any other pages. One very good use of custom ViewState is to keep
track
of any dynamically created controls, which you can then manually recreate
on each post based on your tracking data in ViewState. You can also add
custom items to the ViewState collection just as you would with Session,
for example: ViewState["item1"]=whatever or, string whatever = (string)ViewState["item1"].
You can start your study of Viewstate and how to override its default
members
by reading the Control Execution Lifecycle page here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcontrolexecutionlifecycle.asp
ViewState is "translated" into workable types through the use of
the undocumented LOSFormatter class. You can read up on how this works
in
Peter Bromberg's article here at eggheadcafe.com:
http://www.nullskull.com/articles/20021127.asp
Server.Transfer and SmartNavigation BUG?
Lots of questions about Server.Transfer not working with SmartNavigation,
etc. One thing to remember about SmartNavigation is how SmartNavigation
works. It takes postbacks and renders all the changed items to a
hidden IFRAME, then replaces all
the innerHTML control elements on the page with the results. This is
what gives the illusion of a page that doesn't "jump" when
reloaded.
1)There are other ways to do this (e.g., with anchor tags in the refresh
url so the focus lands on the anchor tag location in the page)
2) If you have javascript that is required to initialize in order to
work properly,
then with SmartNavigation because of the above, it may no longer work
because all the "stuff" in the "main" page is never
reloaded.
3) You can "cheat" by writing script to the page such as:
Response.Write("<script>window.location.href="mynewpage.aspx";</script>");
Server.Transfer() executes the referred page in the current context
and does not actually readdress to it. It just clears the output
buffer and executes another page producing output in the same buffer.
Response.Redirect() returns HTTP 302 status code to the client which
signals that there must be an actual redirect to the specified page.
In other words, the BROWSER is instructed to request the new page and
makes a new server roundtrip.
In order for smartNav to work properly going from one page to a new
page, you would need to enable SmartNav on BOTH pages (the one that executes
the
Server.Transfer,
and
the target
page) and have a form tag with runat=server on the target page.
What’s happening with loss of control state is that after post
back the controls' events lose the connection to the delegates of the
events.
One possible workaround
is to reattach the control event to the delegate.
On the server side: xxx.attributes.add("onclick","myEvent")).
Client
side (vbscript): window.document.all("x").attachEvent("onclick",
getref("myFunc")).
ViewState is invalid Message:
PRB: "View State Is Invalid" Error Message When You Use Server.Transfer
http://support.microsoft.com/default.aspx?scid=kb;en-us;q316920
This problem occurs because the EnableViewStateMac attribute of the <pages> element
is set to true by default. When this attribute is set to true, ASP.NET
runs a message authentication check (MAC) on the view state of the page
when the page is posted back from the client. This check determines if
the view state of the page was modified on the client.
When you call the Server.Transfer method and set the second parameter
to true, you preserve the QueryString and the Form collections. One of
the form fields is the hidden __VIEWSTATE form field, which holds the
view state for the page. The view state message authentication check
fails because the message authentication check only checks each page.
The view state from the page that calls Server.Transfer is not valid
on the destination page.
The simplest solution: Do not pass the second parameter (which is false
by default) when you call Server.Transfer.
For example: Server.Transfer("<page name>")
Other solutions can be found in the KB referenced above and similar
KB articles. One in particular deals with passing control values
between pages:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconpassingservercontrolvaluesbetweenpages.asp
ThreadAbortException when you use Response.End, Response.Redirect or
Server.Transfer:
"PRB: ThreadAbortException Occurs If You Use Response.End,
Response.Redirect, or Server.Transfer"
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312629
To work around this problem, use one of the following methods: For Response.End, call the ApplicationInstance.CompleteRequest method
instead of Response.End to bypass the code execution to the Application_EndRequest
event.
For Response.Redirect, use an overload, Response.Redirect(String url,
bool endResponse) that passes false for the endResponse parameter to
suppress the internal call to Response.End. For example: Response.Redirect
("nextpage.aspx", false);
If you use this workaround, the code that follows Response.Redirect is
executed.
For Server.Transfer, you can use the Server.Execute method instead.
There's a lot more, but I think the above items and links should give
you a good start on these and similar issues.
Dr. Dexter Dotnetsky is the alter-ego of the Eggheadcafe.com forums, where he often pitches in to help answer particularly difficult questions and make snide comments. Dr. Dotnetsky holds no certifications, and does not have a resume. Always the consummate gentleman, Dr. Dotnetsky can be reached at youbetcha@mindless.com. Dr. Dotnetsky's motto: "If we were all meant to get along, there would be no people who wait for all the groceries to be rung up before starting to look for their damn checkbook."
|