Tech Off Thread

16 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Problem with HTMLAnchor and ASP.Net Cache

Back to Forum: Tech Off
  • User profile image
    Stitch 2.0

    Hi guys,

    long time no post, but now I'm in need of the help of this great community Wink

    I have some trouble with the Cache object of ASP.Net

    I have a table with several 5 rows and 5 cells in each row, each containing a link to google. (demo purposes only)

    I build this table dynamically and want to cache it (for several users), instead of rebuilding it during every request.

    Here is how I build the table:

    HtmlTable tbl = new HtmlTable();
    for (int i = 0; i < 5; i++)
    {
       HtmlTableRow tblrow = new HtmlTableRow();
       for (int j = 0; j < 5; j++)
       {
          HtmlTableCell cell = new HtmlTableCell();
          HtmlAnchor href = new HtmlAnchor();
          href.InnerText = "Google.com";
          href.HRef = http://www.google.com/">http://www.google.com;
          cell.Controls.Add(href);
          tblrow.Cells.Add(cell);
       }
       tbl.Rows.Add(tblrow);
    }
    tbl.Border = 1;

    So I add the table to the cache first and afterward to the page using the following code:

    Cache.Add("object", tbl, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(2,0,0), System.Web.Caching.CacheItemPriority.Normal, null);

    this.Controls.Add(tbl);

    During the onLoad, I check if the object is available in the cache. If it is, I retrieve it and add it to the page, using the following code:

    tbl = (HtmlTable)this.Cache["object"];

    this.Controls.Add(tbl);

    However, when loading the table from the cache, all HTMLAnchors inside the table are missing the href-tag.

    Any ideas, why this happens? And maybe even on how to avoid it?

    Thanks in Advance!

    Stitch 2.0

  • User profile image
    stevef100

    What a bizarre bug!!

    Try changing the key to which you cache the table under from 'object' to 'tbl' (or basically anything else apart from a keyword

    This doesnt work BTW, it seemed to but then started to lose the href.

    I think it must have something to do with the dodgy cache.......I will find out

  • User profile image
    Stitch 2.0

    The reason, that I used the "object" as the key, was for demo purposes only.
    In the actual implementation, the cache key is called "LinkTable".

    Thanks for looking into it!

    Stitch 2.0

  • User profile image
    stevo_

    I would look in to fragment caching the resulting html rather than the table which needs to be databound and rendered to html.

  • User profile image
    Stitch 2.0

    Well, I've just tried caching the complete HTML of the table and that works fine.... I think we will try it this way.

    But it would definitely be interesting to find out the reason for this bug and how to work around it...

  • User profile image
    stevo_

    I think its because the HRef is stored within the attribute collection that is inherited from HtmlControl.

    InnerText literally just adds a new LiteralControl inside the HRef controls and also adds the content to the viewstate.

    Not entirely sure why its doing this, but if its a problem with the AttributeCollection, you can expect it to lose the Title attribute as well, since that is also stored in the base classes AttributeCollection.

  • User profile image
    njapp

    stevo_ said:
    I think its because the HRef is stored within the attribute collection that is inherited from HtmlControl.

    InnerText literally just adds a new LiteralControl inside the HRef controls and also adds the content to the viewstate.

    Not entirely sure why its doing this, but if its a problem with the AttributeCollection, you can expect it to lose the Title attribute as well, since that is also stored in the base classes AttributeCollection.
    stevo_ the problem seems to lie somewhere else because the Title attribute appears after retrieving the Cached control

  • User profile image
    njapp

    A work around is to use the HtmlGenericControl instead of the HtmlAnchor.


                        HtmlGenericControl href = new HtmlGenericControl("a");
                        href.Attributes.Add("href", "http://www.google.com/">http://www.google.com");
                        href.Attributes.Add("title", "Word!");
                        href.InnerText = "Google.com";

    I'm still interested in determining what causes the href to be removed from the control when cached as a HtmlAnchor.

    We've ruled out an overall problem with the AttributeCollection since the Title attribute is cached properly.  Anyone else have an idea?

  • User profile image
    stevo_

    njapp said:

    A work around is to use the HtmlGenericControl instead of the HtmlAnchor.


                        HtmlGenericControl href = new HtmlGenericControl("a");
                        href.Attributes.Add("href", "http://www.google.com/">http://www.google.com");
                        href.Attributes.Add("title", "Word!");
                        href.InnerText = "Google.com";

    I'm still interested in determining what causes the href to be removed from the control when cached as a HtmlAnchor.

    We've ruled out an overall problem with the AttributeCollection since the Title attribute is cached properly.  Anyone else have an idea?

    I think its a 'bug', the HtmlAnchor control doesn't render the attributes in the usual way, as well as intercepting the href to check if a server side event was attached (in which case it will replace the href), if there isn't a server side event, the href is first resolved (incase the url is an app relative one (ie, ~/foo)), and then the result of that resolution is rendered.. strangely then the resolution code removes the original attribute from the attributes collection..

    This essentually means that a HtmlAnchor that doesn't use a server side event, is a one hit wonder.. once its rendered it .. renders (hurrrr!) itself broken.

    Using a generic control just uses the default attribute rendering and so doesn't suffer this.

  • User profile image
    JChung2006

    Don't cache ASP.NET control object instances.  Cache the HTML and construct a new HtmlLiteralControl from it, or encapsulate the control into a User Control and use page fragment caching instead.

  • User profile image
    stevo_

    JChung2006 said:
    Don't cache ASP.NET control object instances.  Cache the HTML and construct a new HtmlLiteralControl from it, or encapsulate the control into a User Control and use page fragment caching instead.
    That was already suggested over a year ago, the topic has since changed to a request about why HtmlAnchor acts like this.. but yes caching asp.net controls isn't suggested, theres potentially a lot of complex interactions with context that can go wrong given that controls can do absolutely anything.. and then theres weird bugs like this..

  • User profile image
    njapp

    stevo_ said:
    JChung2006 said:
    *snip*
    That was already suggested over a year ago, the topic has since changed to a request about why HtmlAnchor acts like this.. but yes caching asp.net controls isn't suggested, theres potentially a lot of complex interactions with context that can go wrong given that controls can do absolutely anything.. and then theres weird bugs like this..
    J, I definitely wasn't suggesting that anyone caches control instances.  I was just interested in why this bug occurs.  More to the point, why this bug still occurs in 3.5 SP1

  • User profile image
    Ion Todirel

    njapp said:
    stevo_ said:
    *snip*
    J, I definitely wasn't suggesting that anyone caches control instances.  I was just interested in why this bug occurs.  More to the point, why this bug still occurs in 3.5 SP1
    no sane person will cache an entire control, it just doesn't makes sense, they should trow an exception if someone is trying to push a Control in Cache, how is that for a fix? Tongue Out we now have .NET source code you could debug and see what's up

  • User profile image
    stevo_

    Ion Todirel said:
    njapp said:
    *snip*
    no sane person will cache an entire control, it just doesn't makes sense, they should trow an exception if someone is trying to push a Control in Cache, how is that for a fix? Tongue Out we now have .NET source code you could debug and see what's up

    Like I said, its certainly the HtmlAnchor's design, it calls into an internal helper function from the generic html control base which handles resolving the urls, it also removes the given attribute (its generically given an attribute name vs knowing to look for href) from the attribute collection..

    I've gotta be honest its some of the weirdest code I've seen in some time, might add it to my scrap book of piss-poor code inside the .NET framework.. find it quite a lot in System.Web.

  • User profile image
    JChung2006

    Re: don't cache ASP.NET controls, it bears repeating.  Here's another example of why you shouldn't cache ASP.NET control instances or store them in session state - ASP.NET Memory Issues: High Memory Usage with AjaxPro [blogs.msdn.com/tess].

    The HtmlAnchor class can resolve virtual paths if you use the HRef property but can't if you set the attribute via the Attributes collection, I think. Definitely, it has screwy behavior, particularly if you're trying to use named anchors, e.g., <a href="#foo">Go to foo</a> and <a id="foo">Here's foo</a>. ASP.NET overriding the id attribute for its own purposes particularly sucks for this HtmlAnchor use case and is one of many reasons I am getting sick of WebForms. I love the low-level ASP.NET/IIS platform, but I'm looking forward to booting WebForms as soon as ASP.NET MVC is golden.

  • User profile image
    stevo_

    JChung2006 said:

    Re: don't cache ASP.NET controls, it bears repeating.  Here's another example of why you shouldn't cache ASP.NET control instances or store them in session state - ASP.NET Memory Issues: High Memory Usage with AjaxPro [blogs.msdn.com/tess].

    The HtmlAnchor class can resolve virtual paths if you use the HRef property but can't if you set the attribute via the Attributes collection, I think. Definitely, it has screwy behavior, particularly if you're trying to use named anchors, e.g., <a href="#foo">Go to foo</a> and <a id="foo">Here's foo</a>. ASP.NET overriding the id attribute for its own purposes particularly sucks for this HtmlAnchor use case and is one of many reasons I am getting sick of WebForms. I love the low-level ASP.NET/IIS platform, but I'm looking forward to booting WebForms as soon as ASP.NET MVC is golden.

    I like the mvc and I use it now a lot more than webforms and I can't say I've had any real problems considering you can really fix bugs yourself atm if needed.

    The only thing I don't like is that its still using a lot of asp.net, it uses the webforms page base http handler, which is great for transitional stuff, but theres a hell of a lot of crap code in asp.net thats there to suit webforms operations..

    I'm certainly not excited about the monolithic extension methods approach to rendering html either, I really want them to do a new httphandler and page base and control architecture, something thats much more evolved and designer inolved like webforms is.. I also want some really lightweight control requirements.. like even to the degree that the rendering is reliant on a single interface thats maybe something like:

    IHtmlRenderable
    {
      void Render(HtmlTextWriter writer);
    }

    You can easily abstract a control system on top of that, and more importantly jump out of that and do really lightweight controls.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.