CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Peter's Gekko

public Blog MyNotepad : Imho { }

Smartnavigation not so smart when it comes to a Response.Redirect

This post is about something which is widely found on the net, you will find many hits with google on the (at first sight) unlogical combination of Smartnavigation and Redirect. Nevertheless it kept me busy for some time. There seemed to be no relation between the two things untill I found out what was going on. Maybe this will save some of you a little time.

In an application I have implemented a general error handling routine. It collects some information and redirects the application to an error page which sums up all. Everything worked like a snap up till last version, which only produced blank screens. In this last version I had also set the smartnavigation property of the pages and that was exactly what messed up my error handling. Smartnavigation takes care of a couple of things

  • Prevent all postbacks of the same page building up in the navigation history of the browser
  • Eliminate "navigation flash"
  • Persist scroll position over postbacks
  • Persist focus over postbacks

The last two points are not always what you want. Consider changing the selected item in a datagrid from an item in the top of the list to one in the bottom. More on that in an upcoming article. But the first point is reason enough to switch smartnavigation on. What the docs don't tell you (but what you could have guessed) is that smartnav fiddles with the context of your response. The Redirect method of the response no longer works, breaking my error handler. The docs advise you In most circumstances, do not set this property in code, but that was exactly the way to repair my errorhandler. In the snippet p is the page on which the error occured, the code will redirect the app to newURL, a string which contains the URL of the error displaying page. The info is in the querystring.

p.SmartNavigation =

false;
context.Response.Redirect(newURL,
true);

Smartnavigation does not seem to have an influence on the request. A member of the request is an URLreferrer property, it is the URL your app last visited before arriving on this page. The first time the page is requested it is the page you came from but after a postback it is always the same as the URL of the page itself. With and without smartnavigation. Considering the first of the reasons to use smartnav it might seem logical that the property would keep pointing at the last different page visited. But it's hard to mimic state.

Blog on,

Peter



Comments

Peter van Ooijen said:

Smartnavigation does have a lot to do with a Response.Redirect.
When you browse to the previous page
<AirCode>Response.Redirect(PrevPage;</AirCode>,
smartnav takes care what that previous page is. The previouse webform and not the previous roundtrip. Doing so it messes up the "normal" redirect.
# March 4, 2005 6:55 AM

Bill said:

Thank You!
With this idea, I did it too! :))
# April 5, 2005 6:42 AM

John said:

You just saved me hours of work. Thanks!
# April 27, 2005 6:03 AM

Michael Freidgeim said:

Your post helps to solve one of SmartNavigation problems, but there are a lot more, so it's better to avoid using SmartNavigation.
http://www.thespoke.net/MyBlog/MNF/MyBlog_Comments.aspx?ID=92144
# May 3, 2005 9:10 PM

Peter's Gekko said:

SmartNavigation is a feature which can cause quite a lot of trouble. It is a property of an asp.net webpage...
# January 11, 2006 7:28 AM

Ron Hough said:

Thanks for the fix. It worked like a dream for the Response.Redirect problem...
# February 10, 2006 3:54 PM

CodeDoctor said:

Greetings all,

(Below is a Sub-Class technique for SmartNavigation and setting focus to work together)

Well the infamous SmartNavigation.  Actually, all it is, is a javascript file someone at microsoft cooked up for dealing with current visual page state in IE.  And the way it works is simply through an invisible IFRAME it post to.

Along with the rest of you, I have researched this issue quite extensively.  But have found a technique that works.

I've found that the issue is not that SmartNavigation doesn't work, because it does, however if you plan to use it, then your own techniques for submitting client script must change.

SmartNavigation needs the window onload event handler to do its stuff.  And unfortunately this effectively disables it for all of us who normally would post some javascript function there to set a focus to something.

So, let change the way we think about it.  The Window loading isn't the only event available.  Actually it makes more sense to use the Body onload event handler to control what we need.  Because this handler is for the content of the page, and not just the window.

Below is an example Page Wrapper class written with .NET 1.1 (VB.NET)
I've tested this extensively with a Webform, with over 14 custom web user controls on it, and all works perfectly fine.

SMARTNAVIGATION and Setting Focus (FIXED)
Fully Tested with .NET 1.1

I, like the rest of you, have the need to have SmartNavigation on.  However, setting focus will not work regardless of what attempts are made.  I've attempted many suggested posted around the web, using
the javascript functions for the Window_onload event simply stop functioning as soon as you
enabled SmartNavigation to the page.

SOLUTION:

First, create a new VB Class

'PageHelper.vb

Public Class PageHelper
   Inherits System.Web.UI.Page
   Protected WithEvents PageBody As _ System.Web.UI.HtmlControls.HtmlGenericControl

   Public Property NewSmartPageNavigation() As Boolean
       Get
           NewSmartPageNavigation = MyBase.Page.SmartNavigation
       End Get
       Set(ByVal Value As Boolean)
           MyBase.Page.SmartNavigation = Value
       End Set
   End Property
   Public ReadOnly Property oPageBody() As HtmlGenericControl
       Get
           oPageBody = PageBody
       End Get
   End Property
End Class

This class becomes the top level Page class that your MAIN "code behind" files must implement.  

In the Code behind of the MAIN page, change the following line

   Inherits System.Web.UI.Page
to:
   Inherits <yourproject>.PageHelper

Now the page will be inherited from your new class, which inherits
the page class.  

Once this is done, ensure you open up the HTML of the MAIN page you are using, and do the following to the Body Tag.  
#Note:  This MAIN page can be the page housing many different Web User controls.

<body runat=server id=PageBody>

This makes it a server level control (HTMLGenericControl) to be specific, that is capable of being accessed in VB code.  (We will use this in our main sub-class for the page)

In the Page_Load of the MAIN html page put:

Me.NewSmartPageNavigation = True

And finally, in each of your user controls, where you are clicking an action to go into edit mode, or navigating.  Put the following code there.

Dim PH As PageHelper
     PH = Me.Page
     PH.oPageBody.Attributes.Add("onload", "javascript:document.forms[0]['" & TextBox1.UniqueID & "'].focus();")

(Replace TextBox1.UniqueID with any other control that has a javascript focus method)

This implementation allows for setting the BODY onload event, instead of the Window onload event.  This way, smart nav can still operate, and allow for its implementation of saving screen position and focus data of a page during the window onload event.

I hope that this saves you a ton of time, it would have saved me a ton.



CodeDoctor
# April 6, 2006 4:41 PM

Boldpilot said:

It will work when you turn on the smartnav . Only you should place the aspnet_client folder to the root of the web site. Cause this folder contains the smartnav js script files and if you turn on the smartnav and if you donot have this aspnet_client folder at your website root, the redirections are not working. I spent hours to find out that I forgot to copy the aspnet_client folder to the production server.
# June 20, 2006 11:19 AM

pvanooijen said:

True. But the redirect still won't work :(
# June 21, 2006 5:31 AM

Bertrand LEGA said:

Hello,

Sometimes it's due to the IE settings (IE 6.0 + Windows XP SP2)

The problem I had : the redirection didn't work. IIS returns a blank page. In the source of the page, some weird tags namely a SMARTNAV tag.

But the redirection wasn't properly handled. Funnily it worked with Firefox 1.5.

I opened the IE settings dialog, 'advanced' tab, hit the reset to defaults, and tada ! It did the trick.

Don't ask how or why (i didn't change any of the advanced parameter).

But it works now. Until next time .... :)

B.

# September 6, 2006 10:05 AM

pvanooijen said:

Firefox doesn't support anything like smartnavigation. There every back is back to the previous roundtrip of the same page. IE with smartnav will direct you back to the previous distinct page.

# September 7, 2006 1:31 PM

Chris Brooksbank said:

Thanks from a coder in London. I was wondering why the banner links didnt work on our webapp. But only at one clients and on two pages. These pages were only ones which turned smartnavigation on !

# October 12, 2006 10:06 AM

ASP Vava said:

I was having problem for redirecting pages but solved the issue when  aspnet_client/system_web adedd in the default directory(not wwwroot)

# April 5, 2007 11:22 AM

Pril said:

Smart navigation is not smart at all. I did turn it off. I spent two days and made my own smart navigation that supports all browsers, redirects, link clicks and do not need postaback at all. With all functionalities: focus, scroll, flicker-prevent etc.Why m$ people can't do this??? It takes only two days...

# April 6, 2007 6:00 PM

Drew.Allen said:

Setting smartNavigation to True also breaks document.forms[0].submit() producing an error stating that states "contentWindow.document is null or not an object" and "Object doesn't support this property or method".

# April 24, 2007 2:44 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!