<feed version="0.3" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://purl.org/atom/ns#" xml:lang="en-US"><title>Andreas Zenker - My OBJECTive Opinion</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/default.aspx" /><tagline type="text/html">Comments, observations and occasional rants about the addictive occupation that we call programming. An effort to share what I know and admit what I don't.</tagline><id>http://www.dotnetjunkies.com/WebLog/azenker/default.aspx</id><author><url>http://www.dotnetjunkies.com/WebLog/azenker/default.aspx</url></author><generator url="http://communityserver.org" version="1.0.1.50214">Community Server</generator><modified>2005-12-10T00:53:00Z</modified><entry><title>Blog Worthy</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2008/10/31/general_blogging.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:542590</id><created>2008-10-31T11:29:00Z</created><content type="text/html" mode="escaped">What is "blog worthy"? Obviously not much since I haven't written a new post for just about one year. It's not that I haven't had the desire to post, just not the follow thru. The main thing that seems to hold me back is this higher ideal of writing something that is "blog worthy" This ideal could be defined by a few basic ideas:

-Is something that hasn't been written up somewhere else
-Is well thought out and written
-Is technically sound, tested and documented with valid code samples
-Will be of value to someone who runs into the same or similar issues

Well after a year of working at a new company and dealing with some new and some new to me technology I had plenty of: "I should blog about this....oh, somebody already did.....oh, and I would need to write some test code to re-verify my findings....oh, and nobody cares....etc...." I've decided to stop caring so much about the content and just post as much as I can for the sheer pleasure of it. 

So, it may not amount to anything great outside of my mind, but......as I mentioned above...nobody really cares! I may be the only person reading it anyway ;-)

If anyone does happen to read anything I have posted and has a comment I would love to hear it. I have disabled anonymous comments because of the spam, so please create a free account or email me, and I will post it for you.&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=542590" width="1" height="1"&gt;</content><slash:comments>2</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=542590</wfw:commentRss></entry><entry><title>The Achilles Thread</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2007/11/18/371830.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:371830</id><created>2007-11-18T21:42:21Z</created><content type="text/html" mode="escaped">&lt;p&gt;"[when debugging] If you see hoof prints think horses, not zebras".&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Hunt and Thomas, in &lt;a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Developing in the brave new world of managed memory and garbage collection we, in most cases, don't have to worry about the details of memory allocation and clean-up. However, when our application starts having memory issues, we can easily have a tendency to fall into one of two camps:&lt;/p&gt; &lt;blockquote&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Assuming all memory issues are memory leaks (i.e. objects not being disposed of properly)  &lt;li&gt;Assuming that garbage collection is not working as stated.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Both of these assumptions are flawed in one common way: they narrow our focus to a limited set of possibilities and that affects the way we approach the problem. Sparing you the cutesy saying about what happens when we ass-u-me, it is fair to say that assumptions cripple any debugging effort. Once we assume we lose control over the "scientific" process of debugging a problem. In this case we had a utility application consuming egregious amounts of data, 1 to 1.5 gb of memory just to process a queue. I immediately assumed a traditional memory leak, as we were dealing with MSMQ, MessageEnumerators, Messages, SqlConnections, SqlCommands etc, I figured something was not getting disposed of or was still gcroot-ed somewhere in the code.&lt;/p&gt; &lt;p&gt;Problem scenario: In a console application we are iterating thru 85,000 messages in a "dead-letter" queue to see if we can salvage the data that never made it to its destination, the database. As we iterate thru the queue we pass off each message to a handler designed for that particular type of message using a factory. The handler de-serializes the message body back into the original object, generates a SQL insert based on the message contents and inserts a row in the database. As each handler returns a result, messages are removed from or left on the MessageQueue. Rinse, repeat. &lt;/p&gt; &lt;p&gt;If we remove the call to the datalayer component that is writing the new rows in the DB, the memory issue goes away. So clearly we have some SqlProvider objects not getting disposed of, right? Wrong. In surgically adding back in the datalayer functionality one method at a time it becomes clear that just opening a connection to the database once is all it takes to create the issue. Comment out the line that creates the connection, no memory issue, add it back in the death spiral returns. &lt;/p&gt; &lt;p&gt;To see if I could reproduce that scenario with fresh code, I reproduce the functionality from the ground up in a Windows Form application to make debugging more friendly. I set up a few different scenarios and, just to make the experience more lively, I add some counters to the forms so I can see how many messages have been processed etc. I take all the same steps as described above and..... no memory issue. I start reviewing the code method by method to see what I am doing differently. I find nothing, everything is exactly the same.....except.....in the windows form I am publishing messages to the GUI using a quick and dirty "DoEvents" call in the loop, who wants to stare at a frozen form? Then it hits me, I remove the DoEvents and the memory issue is back. Now that I have, not an assumption, but the real problem description it doesn't take long to find the answer as the links below will point you to. &lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/maoni/archive/2004/11/04/252697.aspx"&gt;Maoni Article on Finalizers&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/828988"&gt;Microsoft Whitepaper&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://groups.google.com/group/microsoft.public.dotnet.framework.clr/browse_thread/thread/7740b1d7afcd3b7e/90e2812cf55da065?lnk=st&amp;q=stathread"&gt;Google Groups Thread&lt;/a&gt;&lt;/p&gt; &lt;p&gt; The short answer proved to be this: In console apps the Main() form is launched by default on a Single Threaded Apartment Thread (STA). The same is true of a Windows form app and it's GUI thread. The STA model keeps that thread safe from multi-threading issues, especially when using COM objects that are acting like they are all alone in the world. So, when a COM component is created, used and released on an STA thread, it needs to be finalized. The finalizer thread has to wait until it is "invited to the party" in order to finalize that object. If the STA thread is in a long running loop, and is not publishing messages (ala DoEvents, Thread.Join() etc) then the finalizer is blocked until the loop is done and the STA thread takes a breath. This explains how one database connection could kill this app. The connection was ready to be finalized, the finalizer queues up to process that but is blocked waiting for the STA thread to take a breath. Meanwhile the STA thread is cranking thru a huge Queue and leaving an Exxon Valdez size slick of managed objects who are waiting on guess who, the finalizer thread. &lt;/p&gt; &lt;p&gt;The suggested solution: add an MTAThread() attribute to the entry point of your application (Sub Main() ) to prompt the runtime to load your main thread in Multi Thread Apartment (MTA) mode, now the finalizer can sneak in and do its clean up even though the main loop is not making any effort to share.&lt;/p&gt; &lt;p&gt;So, it wansn't quite horses, but not full-bred zebras either. Either way it was a fun ride.&lt;/p&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=371830" width="1" height="1"&gt;</content><slash:comments>0</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=371830</wfw:commentRss></entry><entry><title>Forest for the trees - Don't forget the compiler</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2007/06/06/241227.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:241227</id><created>2007-06-06T09:56:53Z</created><content type="text/html" mode="escaped">&lt;p&gt;Back in school my teacher was not much on the formal aspects of the course he was teaching.He was instead, as I describe him, the kind of guy you could imagine living in his room with his PC, hacking away, his mom pushing crackers under the door and begging "You really should go out and get some friends dear." Perhaps because of that we spent less time in the text book and more time digging into just what the IDE, along with COM and MTS at the time, were doing underneath the hood to be "helpful". He often said that memorizing the text book would help you pass but that knowing what was really happening based on your code would give you a better ability to figure things out when debugging "weirdness". For some reason I thought of him just today. :-)&lt;/p&gt; &lt;p&gt;The "weirdness" in this case was that my IDE was doing strange stuff in debug mode, or so I thought at the time. I was trying to see why my property based on a config setting was never getting populated with the correct value. So I did the natural thing, I set a break point on the property get and fired it up. The basic code of the getter was this&lt;/p&gt; &lt;p&gt;&lt;/p&gt;Get&lt;br&gt;     Dim prop As Boolean = False&lt;br&gt;     Dim configVal As String = System.Configuration.ConfigurationSettings.AppSettings.Item("MyConfigKey")&lt;br&gt;     &lt;font color="#0000ff"&gt;If Not configval Is Nothing Then&lt;br&gt;          prop = CBool(configVal)&lt;br&gt;     End If&lt;br&gt;&lt;/font&gt;     Return prop &lt;br&gt;End Get &lt;p&gt;Nothing fancy, but when debugging I found that the If statement never seemed to evaluate to true, and the if block never executed. The debugger would always jump to End If no matter what I set the value of configVal to in the command window. Somebody wiser than me once said something along the lines of "always look for the stupidest solution first", however with this "weirdness" I immediately launched into the "weirdness countermeasures". These included restarting the IDE, rebuilding the solution, bleaching the temp files in case I was somehow stuck with an old version of the file from a previous life, rebooting, rinse repeat. All of the maneuvers that have served well in the past when bizarre things happen in the IDE. No dice, still same issue every time. &lt;/p&gt; &lt;p&gt;&lt;br&gt;Now it's time for last resort "I have no idea, but I'll try this" measures. In the past I have had lines of code that would not compile with no apparent error and only way to resolve the issue was to retype the line, visually identical to the "bad" line, and all-of-a-sudden the IDE was happy again and we moved on. Whatever! So I figured I would give that a try. As I was re-typing the code I found a bug, seemed stupid and meaningless at first, but it then hit me that it had been the issue all along. In my getter the actual code looked like this&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Get&lt;br&gt;     Dim prop As Boolean = False&lt;br&gt;     Dim configVal As String = System.Configuration.ConfigurationSettings.AppSettings.Item("MyConfigKey")&lt;br&gt;     If Not configval Is Nothing Then&lt;br&gt;          prop = CBool(&lt;font color="#ff0000"&gt;prop&lt;/font&gt;)&lt;br&gt;     End If &lt;br&gt;     Return prop &lt;br&gt;End Get&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I was setting the prop variable to the result of CBool(prop) as boolean of itself, which would always mean no change to the variable. Then the lights in my dark and scary brain started to go on! The compiler was &lt;em&gt;helping&lt;/em&gt; me! I compiled the code again and looked at the disassembly, first with the bug&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;     &lt;strong&gt;&lt;font color="#000080"&gt;If Not configval Is Nothing Then&lt;br&gt;&lt;/font&gt;&lt;/strong&gt;&lt;font color="#808080"&gt;00000036 test ebx,ebx &lt;br&gt;00000038 je 0000003A &lt;br&gt;&lt;/font&gt;     &lt;strong&gt;&lt;font color="#000080"&gt;End If&lt;/font&gt;&lt;/strong&gt; &lt;p&gt;and then without&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;     &lt;strong&gt;&lt;font color="#000080"&gt;If Not configval Is Nothing Then&lt;br&gt;&lt;/font&gt;&lt;/strong&gt;&lt;font color="#808080"&gt;00000036 test esi,esi &lt;br&gt;00000038 je 0000004E &lt;br&gt;&lt;/font&gt;     &lt;strong&gt;&lt;font color="#000080"&gt;prop = CBool(configVal)&lt;br&gt;&lt;/font&gt;&lt;/strong&gt;&lt;font color="#808080"&gt;0000003a mov ecx,esi &lt;br&gt;0000003c call FFB91FD0 &lt;br&gt;00000041 movzx edi,al &lt;br&gt;00000044 mov eax,edi &lt;br&gt;00000046 and eax,0FFh &lt;br&gt;0000004b mov dword ptr [ebp-8],eax&lt;/font&gt; &lt;br&gt;     &lt;strong&gt;&lt;font color="#000080"&gt;End If&lt;/font&gt;&lt;/strong&gt; &lt;p&gt;The compile decided that the stupid line of code was irrelevant and simply removed it. So in debugging, since we are actually stepping through the debug symbols, not the code, there &lt;em&gt;was&lt;/em&gt; no line of code to hit in that If block. So the supposed "weirdness" just turned out to be a bad cut and paste. Doh! If the compiler had left it in I would have seen the line execute with no change to the value of prop and found the bug right away. Instead I get all commando. &lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;Anyway, I just had to share my brain cramp. When things seem "weird" don't forget:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;a) the "always look for the stupidest solution first" rule still applies&lt;/p&gt; &lt;p&gt;b) don't forget what might be trying to "help" you under the hood.&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=241227" width="1" height="1"&gt;</content><slash:comments>2</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=241227</wfw:commentRss></entry><entry><title>What is a clustered index anyway?</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2007/02/17/197951.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:197951</id><created>2007-02-17T17:51:44Z</created><content type="text/html" mode="escaped">&lt;p&gt;Wanted to drop a quick post for two reasons: 1) To prove I have not died, been abducted by aliens, or&amp;nbsp;been confined to a room with soft, cushy walls and a nerf PC for my own&amp;nbsp;"protection". 2) To give a plug for someone I had an opportunity to work with this past week.&lt;/p&gt; &lt;p&gt;Our shop was in need of some SQL Server performance tuning. Not having the expertise in house we called in an outside consultant. Not having had the best experiences with outside "experts" in the past, I was skeptical. However, &lt;a href="http://www.gothamconsulting.com/"&gt;Ray Rankins and his Gotham Consulting&lt;/a&gt; seem to be the real deal. Not living in the SQL world day in and day out, I tend to leave the "deeper thoughts" to the DBA's and worry about the procs doing what I need when I need it. However, when it does come down to a proc that is dogging our application down, it would be nice to really understand &lt;em&gt;why&lt;/em&gt; one syntax or set of indexes works so much better than another. Usually the approach to tuning a long running proc&amp;nbsp;from a developer standpoint is "Well, that sucks, let's try something else" and "Wow, that sucks a lot less, let's do that!" Speaking with Ray this past week I found a man who knows, and seems to&amp;nbsp;care, about what is happening under the hood in SQL Server as much as I do about the inner workings of the CLR. The longer I work in this field the more I realize that this kind of person is hard to find. In&amp;nbsp;one ten minute conversation I now&amp;nbsp;have a&amp;nbsp;really good idea what a Clustered vs. a Non-Clustered index is, why it&amp;nbsp;matters, what situations&amp;nbsp;you would want to use either of them&amp;nbsp;etc.&amp;nbsp;Ray has written &lt;a href="http://www.amazon.com/Microsoft-SQL-Server-2000-Unleashed/dp/0672324679/sr=1-5/qid=1171752276/ref=sr_1_5/102-3049860-2538563?ie=UTF8&amp;amp;s=books"&gt;"the book"&lt;/a&gt; on SQL Server and is just making the final edits on the SQL 2005 edition. I think I will add it to my ever growing stack of books to read one rainy day.&lt;/p&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=197951" width="1" height="1"&gt;</content><slash:comments>0</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=197951</wfw:commentRss></entry><entry><title>slidingExpiration=NotReally timeout=NotWhatIThinkItIs</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2006/10/25/151807.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:151807</id><created>2006-10-25T18:20:07Z</created><content type="text/html" mode="escaped">&lt;p&gt;As a new approach to some meaningful blogging, as I work on debugging some new bug/issue, the info I collect and my deductions I record right in my LiveWriter window so that I can save any links, code snippets etc. This way, with little effort, at the end of the day I can do some quick editing and post something "useful" (you may choose to retain your own definition of that word). A fringe benefit is that I can find this info again the next time I need it.&lt;/p&gt; &lt;p&gt;So here was the situation:&lt;/p&gt; &lt;p&gt;An ASP.NET application that leverages FormsAuthentication. The timeout is set in the web.config to 20 minutes in the authentication tag something like this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Users were reporting intermittent timeouts that were significantly less than the 20 minutes. In testing we were unable to duplicate this scenario. &lt;p&gt;The other important detail, that we have omitted until now, is that we are "rolling our own" authentication ticket in order to have more control over what that ticket contains etc. So in code the default ticket timeout value (set as a constant) was 20 minutes. &lt;p&gt;So, now onto the mistaken assumptions. I had assumed that the web.config setting would come into effect the first time the ticket was updated. Being that it is a sliding expiration I had thought that the ticket would be updated to the web.config timeout the next time a page was requested. Since the user is redirected from the login page as a matter of course it was &lt;em&gt;assumed (doh!) &lt;/em&gt;that the hard-coded timeout value would not last longer than a second or two. So, the first thing I did was set the web.config timeout to be 1 minute so that I could test without waiting 20 minutes. Waited a minute .... posted back  ... no dice, still logged in. No matter what I set that value to I could not get kicked out if I tried. Only when I changed to constant to 1 in the code and recompiled was I able to get kicked out as expected. Ok, bad assumption, no big deal, we'll just change the code to read the config value when it sets the original ticket and then all will be in sync, right? Not so easy. &lt;p&gt;First of all, the values in that section of the config are protected, even from the guy writing the application. The normal system.configuration approach does not expose these values and the FormsAuthentication classes do not expose what you would think is a fairly useful property. So how do you make sure you are in sync with the config file? Doing some googling we find that Scott Hanselman ran into the same thing years ago, no surprise. &lt;a href="http://www.hanselman.com/blog/AccessingTheASPNETFormsAuthenticationTimeoutValue.aspx"&gt;Scott details his thought process in solving the same issue.&lt;/a&gt; &lt;p&gt;Scott addresses the pain of accessing the config setting from code so that the first creation of the ticket can match the desired setting from the web config. He considers the approach of creating an additional, accessible, config setting that would require being set in two places or creating an invalid situation. (i.e. one setting says expire in 20 minutes, one says 10 etc). He considers reflection, but deems it too ugly. Finally he settles on dynamically "discovering" the web.config, loading into a DOM and xpathing his way to the setting and storing in cache so he only has to do it once. Basically there is no clean work-around so you have to settle for a lesser of the evils approach.&lt;/p&gt; &lt;p&gt;So, armed with that information we start testing with our new found knowledge. We had written a test page to dump out the contents of the ticket to a text box so that we could see what expiration was actually being set. We set the original ticket being written by the code to a nice small value of 4 minutes and started to post the page back. Here comes the strangeness. As we post the page back the expiration time of the ticket does not change. We keep posting the page back every 15 seconds or so and &lt;em&gt;eventually&lt;/em&gt; it decided it was time to update the ticket with a new expiration time. Now were really confused, this was, after all, a sliding expiration wasn't it? Every time the page posts back it was supposed to update the time to give another &lt;em&gt;n&lt;/em&gt; minutes before it would be timed out. So back to digging, this time we pull up the MSDN documentation on the  tag and the  element. &lt;a href="http://msdn2.microsoft.com/en-us/library/1d3t3c61(vs.71).aspx"&gt;MSDN documentation on element attributes.&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The msdn docs indicate that a sliding expiration does not really slide as you might imagine, and certainly may expire when you do not expect it to. Here is a priceless, if not a bit contradictory bit of MS wisdom: "&lt;em&gt;If the SlidingExpiration attribute is true, the timeout attribute is a sliding value, expiring at the specified number of minutes after the time the last request was received. To prevent compromised performance, and to avoid multiple browser warnings for users that have cookie warnings turned on, the cookie is updated when more than half the specified time has elapsed. &lt;strong&gt;This might result in a loss of precision.&lt;/strong&gt;&lt;/em&gt;.", I guess! A "loss of precision"? Is that what we call a sliding expiration that doesn't slide and results in an effective timeout of only half what you think you set it to? So, because some people are afraid of the big bad cookie monster we are going to totally hose the well understood concept of a sliding expiration, with no "override this stupid default behavior" attribute in sight? That is insane. Now it's time to pull out Reflector and look for a clever workaround.&lt;/p&gt; &lt;p&gt;Inside the &lt;font face="Verdana"&gt;FormsAuthentication&lt;/font&gt; class we find the method that does just as described, renews the ticket only if the time left till expiration is greater than the time since the current ticket was issued.&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;pre&gt;Public Shared Function &lt;b&gt;RenewTicketIfOld&lt;/b&gt;(ByVal &lt;b&gt;tOld&lt;/b&gt; As &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=1"&gt;FormsAuthenticationTicket&lt;/a&gt;) As &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=2"&gt;FormsAuthenticationTicket&lt;/a&gt;
      If (&lt;a&gt;tOld&lt;/a&gt; Is Nothing) Then
            Return Nothing
      End If
      Dim &lt;b&gt;time1&lt;/b&gt; As &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=3"&gt;DateTime&lt;/a&gt; = &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=4"&gt;DateTime&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=5"&gt;Now&lt;/a&gt;
      Dim &lt;b&gt;span1&lt;/b&gt; As &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=6"&gt;TimeSpan&lt;/a&gt; = DirectCast((&lt;a&gt;time1&lt;/a&gt; - &lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=7"&gt;IssueDate&lt;/a&gt;), &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=8"&gt;TimeSpan&lt;/a&gt;)
      Dim &lt;b&gt;span2&lt;/b&gt; As &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=9"&gt;TimeSpan&lt;/a&gt; = DirectCast((&lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=10"&gt;Expiration&lt;/a&gt; - &lt;a&gt;time1&lt;/a&gt;), &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=11"&gt;TimeSpan&lt;/a&gt;)
      If (&lt;a&gt;span2&lt;/a&gt; &gt; &lt;a&gt;span1&lt;/a&gt;) Then
            Return &lt;a&gt;tOld&lt;/a&gt;
      End If
      Return New &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=12"&gt;FormsAuthenticationTicket&lt;/a&gt;(&lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=13"&gt;Version&lt;/a&gt;, &lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=14"&gt;Name&lt;/a&gt;, &lt;a&gt;time1&lt;/a&gt;, (&lt;a&gt;time1&lt;/a&gt; + (&lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=15"&gt;Expiration&lt;/a&gt; - &lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=16"&gt;IssueDate&lt;/a&gt;)), &lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=17"&gt;IsPersistent&lt;/a&gt;, &lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=18"&gt;UserData&lt;/a&gt;, &lt;a&gt;tOld&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=19"&gt;CookiePath&lt;/a&gt;)
End Function
&lt;/pre&gt;
&lt;p&gt;Unfortunately the method is completely self contained and is not using any other settings to determine its results. It bases the decision on whether or not to update the ticket completely on the lifespan of the current ticket and the current time. If more then half the time has elapsed then you get a new one, period. So no work-around presents itself.&lt;/p&gt;
&lt;p&gt;Something else we learn from this code is that, if you are manually setting the original ticket, the setting in the web.config, if different, never comes into play, since the renew method is basing its renew length on the originally set length of the ticket not your silly little timeout setting. This setting just gets more useless as we go on!&lt;/p&gt;
&lt;p&gt;Now, if you use the out-of-the-box authorization that is provided in the framework and set your ticket using the &lt;font face="Verdana"&gt;FormsAuthentication.SetAuthCookie(username,isPersistent,cookiePath)&lt;/font&gt; method, the config setting will hold true when the ticket is created for you, however the non-sliding expiration issue still holds true.&lt;/p&gt;
&lt;p&gt;So, enough pain for one day, how are we going to "fix" this so that the user has the result they expect, a 20 minute timeout? First we have to sync up our code creation of the first ticket with the web.config value. I wasn't fond of Scott's xml loading solution, although it would work. Since we found that, &lt;em&gt;in our case&lt;/em&gt;, the web.config setting was moot anyway We opt for adding a new value to the web.config to explicitly set the value the code would use, afterward the framework would continue to re-apply this value as it refreshed the cookie. This does not provide any actual conflict, but it may provide some confusion as the app is deployed and maintained. The nice thing, for once, is that the timeout attribute on the  element is optional and defaults to 30 minutes. Since it is never going to be applied, what do we care? So we remove the attribute and thus remove the &lt;em&gt;apparent&lt;/em&gt; conflict in settings. &lt;/p&gt;
&lt;p&gt;Now, what can we do about the non-sliding expiration? Well, it's been a long enough day, so we opt for the easy: "Just double it stupid" approach. This could, if we were relying completely on the forms authentication for timeouts, allow users, in some cases, to get anywhere from 20 to 40 minutes timeout, which would be considered a problem as well. However, since we are also requiring a fresh login when the session times out, we are covered. We set the config timeout to twice what the session timeout is and we are good. The shortest the ticket will live is 20 minutes between clicks, and if it lives longer than that the session will tank and all is well.&lt;/p&gt;
&lt;p&gt;Now you may have a more elegant solution, so feel free to share...&lt;/p&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=151807" width="1" height="1"&gt;</content><slash:comments>1</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=151807</wfw:commentRss></entry><entry><title>A free test environment anyone?</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2006/07/13/141974.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:141974</id><created>2006-07-13T04:51:00Z</created><content type="text/html" mode="escaped">Had to pass this along when I saw it here at &lt;A href="http://www.sitepoint.com/blogs/2006/07/13/ms-virtual-pc-now-free/"&gt;sitepoint&lt;/A&gt;, VirtualPC is now available for free! &lt;EM&gt;Virtually&lt;/EM&gt; unheard of! Here is link to the download for &lt;A href="http://www.microsoft.com/windows/virtualpc/downloads/sp1.mspx"&gt;VirtualPC 2004 SP1&lt;/A&gt;.&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=141974" width="1" height="1"&gt;</content><slash:comments>0</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=141974</wfw:commentRss></entry><entry><title>That, which we call a Namespace, by any other name would just smell.</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2006/06/27/141273.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:141273</id><created>2006-06-27T12:59:00Z</created><content type="text/html" mode="escaped">&lt;P&gt;There is nothing sweet about spending hours, days, evenings and weekends chasing "ghosts" in your code.&amp;nbsp;In this context&amp;nbsp;"ghosts" mean compile or runtime errors that are not constant, only dreadfully persistent. Perhaps you also have been faced with the intermittent errors that look something along the lines of this:&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;FONT&gt;Could not load type Foospace.FooWebService.FooWS.FooInfo from assembly mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/FONT&gt;&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;FONT&gt;or&lt;/FONT&gt;&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;FONT&gt;&lt;EM&gt;Could not load type 'FooSpace.Global'.&lt;BR&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Now, huge caveat here, these types of error could be caused by a plethora of things, even perhaps a &lt;A href="http://www.garnersclassics.com/qamigos.htm"&gt;plethora of pinatas,&amp;nbsp;&lt;/A&gt;but most would provide constant errors on every build or execution. I have found a surprising dearth of information on this scenario, its cause and resolution. So the situation I am about to describe may not match yours, but if it does I hope it helps. &lt;/P&gt;
&lt;P&gt;Note first of all that the type I am failing to load is a type defined in a Web Service that my project is calling into. We can imagine that the &lt;FONT&gt;FooWebService&lt;/FONT&gt; returns a type of &lt;FONT&gt;FooInfo&lt;/FONT&gt; from a method called &lt;FONT&gt;GetFoo&lt;/FONT&gt;. (&lt;EM&gt;What would we doo without foo?&lt;/EM&gt;) This is a standalone service and as such does not share any references with our main application so that is enough info about that. Our main application, to start will just have one project: &lt;FONT&gt;FooApp&lt;/FONT&gt;, it has a Web Reference defined pointing to &lt;FONT&gt;FooWS&lt;/FONT&gt; and uses that to get and display &lt;FONT&gt;FooInfo&lt;/FONT&gt; properties on the page when it loads. So far so good.&lt;/P&gt;
&lt;P&gt;Now we start to build our application into a solution that we expect to get quite large so we start using Namespaces to categorize our projects. So now we go to our project properties and change the Root Namespace from the default &lt;FONT&gt;FooApp&lt;/FONT&gt; to &lt;FONT&gt;FooSpace&lt;/FONT&gt;.&amp;nbsp;When we do this now our project won't run because our global.asax and our webform.aspx files have statements like this: &lt;FONT&gt;Inherits="FooApp.WebForm1"&lt;/FONT&gt; that need to be changed to read &lt;FONT&gt;Inherits="FooSpace.WebForm1".&lt;/FONT&gt; At this point something should be telling us that namespaces are more than just a way to organize our code and get pretty little intellisense dropdowns when we are defining our objects. Anyway, we shake off the annoyance and move on, once again our project loads and we are good. We also do the same for the &lt;FONT&gt;FooWebService&lt;/FONT&gt; Project, as the first segment of the namespace is often a company or overall product name, this makes sense.&lt;/P&gt;
&lt;P&gt;Now we add the ever essential &lt;FONT&gt;FooLibrary&lt;/FONT&gt; project to our solution. To keep in form we change its root namespace to match our new structure, "&lt;FONT&gt;Foospace&lt;/FONT&gt;". Notice the typo? the &lt;FONT&gt;&lt;STRONG&gt;"S"&lt;/STRONG&gt;&lt;/FONT&gt; is not the same case as our FooApp Root Namespace. Now Visual Basic is case insensitive, so it shouldn't care, right? Wrong, way wrong. In fact, it seems, the compiler can't tell the two apart so sometimes when it is looking for a resource to load it will use the correct namespace, other times it will not. To prove it to yourself, add a reference in your FooApp web project to the new FooLibrary. You don't even need to call anything, or add any import statements. You should start having issues right away. I was going to try to document all the different variations you might see based on your setup but here are a few.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV&gt;If your Web Reference is static you may get compile errors right away. Lucky you!&lt;/DIV&gt;
&lt;LI&gt;If your Web Reference is Dynamic you may get past the compile but will likely fail on loading the global.asax for no apparent reason. 
&lt;LI&gt;If your reference to the badly namespaced project lives in another project, say a business object layer that calls upon the FooLibrary, the code could&amp;nbsp;compile and even run. Until one day you start to get weird "Could not load type" messages.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;So the basic point of this post is: A Namespace is case sensitive! Whatever .NET language you call home. Our shop ran into this well over a year ago. Just recently it came back into our solution by way of some new project namespacing that had been done and its "avatar" was completely different. On the first go-round we mostly had the issues loading global.asax, still intermittently build by build. On the latest flare up we had the error calling a Web Service well down in the application, once again random build to build. Because the evidence was so different we chased some ghosts before we, once again, identify the culprit. To be fair, I did find &lt;A href="http://www.davidcrowell.com/"&gt;one blog that did mention this issue quite some time ago&lt;/A&gt;, so I will link to it here. Scroll down the page and look for the header: "&lt;EM&gt;&lt;FONT&gt;VB &amp;amp; C# Casing Issues with VS.NET "&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;FONT&gt;&lt;/FONT&gt;&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;
&lt;H1&gt;&lt;FONT&gt;&lt;EM&gt;&lt;/EM&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/H1&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=141273" width="1" height="1"&gt;</content><slash:comments>0</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=141273</wfw:commentRss></entry><entry><title>It is truly the simple pleasures in life</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2006/04/24/137219.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:137219</id><created>2006-04-24T14:48:00Z</created><content type="text/html" mode="escaped">&lt;P&gt;The recent project list on the start page of the Visual Studio IDE seems like such a cool thing at first glance. However, very quickly it degrades into the "How many times do I have to be reminded that I called my test project 'Son of Foo'" list. We end up with junk in there that is just plain annoying. Recently our shop made a move to Subversion for source control, finally giving Visual Source Safe the merciful lethal injection that it so deserved. In the process I cleaned up and moved my local working copy of code to a new folder. So now I not only was reminded of every time I created a test project named "WebApplication1" in the past month, but I also was faced with duplicate entries of "My Solution" in the list, one real one just a mirage. Needless to say I clicked on the mirage enough times to be motivated to google on how to clean up the recent project list. In doing so I found this very light-weight, and useful, util &lt;A href="http://www.codeproject.com/dotnet/VSProjectListEditor.asp"&gt;here&lt;/A&gt;. Thanks to Josh Beach (whoever you are)&amp;nbsp;and the guys at &lt;A href="http://www.codeproject.com/index.asp"&gt;CodeProject&lt;/A&gt; for this useful little number. It truly made my day.&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=137219" width="1" height="1"&gt;</content><slash:comments>0</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=137219</wfw:commentRss></entry><entry><title>You get what you pay for</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2006/01/17/134768.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:134768</id><created>2006-01-17T00:16:00Z</created><content type="text/html" mode="escaped">&lt;P&gt;Just a quick note on the quality level you can achieve when, out of an insane desire to have "a life",&amp;nbsp; you throw together a blog after working till 2AM one night. Thanks to &lt;A href="http://codebetter.com/blogs/john.papa/default.aspx"&gt;Johnny &lt;/A&gt;,&amp;nbsp;not only for &lt;A href="http://codebetter.com/blogs/john.papa/archive/2006/01/16/136589.aspx"&gt;plugging my blog&lt;/A&gt;, but also for the heads up on the typo in my blog subtitle. No I don't have any "ovservations" to share with you today, but perhaps, some day soon an "observation" or two might show up. :-) &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=134768" width="1" height="1"&gt;</content><slash:comments>1</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=134768</wfw:commentRss></entry><entry><title>Doing it with style</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2005/12/27/134477.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:134477</id><created>2005-12-27T14:25:00Z</created><content type="text/html" mode="escaped">&lt;P&gt;Most of my personal (read: "for fun") programming time lately has been involved with web design. Being much more comfortable hiding behind a nice solid business object, this is largely uncharted territory for me and, as such, provides the comfortable, nearly vertical, learning curve that we know and love. I decided up front that I was going to "do it right" and not fall back on the old &amp;lt;table&amp;gt; method of laying out the page contents. I had read, and heard, about the advantages of CSS based page layout, but had not had any direct exposure. In my research of what is available on the web I have collected a short list of valuable CSS resources that I wanted to share. So here goes...&lt;/P&gt;
&lt;P&gt;The site that will make you a believer:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;A href="http://www.csszengarden.com/"&gt;CSS Zen Garden&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Practical layout tips and tutorials:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;A href="http://www.alistapart.com/"&gt;A List Apart&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;A href="http://glish.com/css/"&gt;glish.com&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I would say that, hands down, the AListApart site has been the most valuable so far, especially this article on how to use negative margin values along with column defining background images to define your 2 or 3 column layout all in CSS and have it degrade nicely. &lt;A href="http://www.alistapart.com/articles/negativemargins/"&gt;Sweet!&lt;/A&gt;&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=134477" width="1" height="1"&gt;</content><slash:comments>2</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=134477</wfw:commentRss></entry><entry><title>I feel like a kid in a candy store</title><link rel="alternate" type="text/html" href="http://www.dotnetjunkies.com/WebLog/azenker/archive/2005/12/10/134241.aspx" /><id>58df7014-fd75-437c-9641-150997716d1c:134241</id><created>2005-12-09T16:53:00Z</created><content type="text/html" mode="escaped">&lt;P&gt;I have wanted to blog for about two years now. With all of the blog sites out there what held me back you ask? Two big questions: Where and What. The where was answered for me when &lt;A href="http://dotnetjunkies.com/WebLog/donnymack/"&gt;Donny Mack&lt;/A&gt; responded to my request to blog here at &lt;A href="http://dotnetjunkies.com/"&gt;DotNetJunkies&lt;/A&gt;. I can only imagine that he is not making an abundance, if any, profit from this venture so I appreciate very much the opportunity he is giving me to enter into the world of blogging on this site.&lt;/P&gt;
&lt;P&gt;Some bloggers that I have worked with that are worthy of mention. &lt;A href="http://dotnetjunkies.com/WebLog/sstewart/default.aspx"&gt;Scott Stewart &lt;/A&gt;a mentor and friend who not only helped me get my first job programming in .NET but also helped me with the unavoidable learning curve coming from VB 6.0. Also, a brief encounter with &lt;A href="http://codebetter.com/blogs/john.papa/default.aspx"&gt;Johnny Papa &lt;/A&gt;has left me with appreciation for, not only his prolific blogging skills, but also his project management abilities. Not many men come along that can walk the tightrope as effectively as he can. &lt;/P&gt;
&lt;P&gt;Now for some bloggers that I wish I had worked with: &lt;A href="http://www.lhotka.net/WeBlog/"&gt;Rocky&lt;/A&gt;, &lt;A href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/A&gt;, &lt;A href="http://www.joelonsoftware.com"&gt;Joel&lt;/A&gt;, &lt;A href="http://pluralsight.com/blogs/dbox/"&gt;Don Box&lt;/A&gt; just to name a few. Makes you wonder if some day "Andreas" will be enough to identify my blog, that's when I will know that I have really made it!&lt;/P&gt;
&lt;P&gt;So, now that the "where" of my blogging aspirations has been addressed, the "what" comes to bear. As my blog theme indicates, I favor an object oriented approach to software development. I have come to appreciate, over time, that the "quick and easy" solutions are never really quick and are often less than easy to maintain. A true object model has saved me many an hour "hacking" what I would have built otherwise. I don't consider myself a purist by any means, but I will assert that most "programmers" that I have interacted with just do not get it. Somehow there seems to be a bit switch somewhere in the VB.Net&amp;nbsp;(and beyond?) &amp;nbsp;programing world; either you are a "just barely above Access" &amp;nbsp;programmer who has heart palpitations whenever the "drag and drop" method doesn't work and you actually have to (shudder) edit the actual code, or you are an &lt;A href="http://www.joelonsoftware.com/articles/fog0000000018.html"&gt;astronaut &lt;/A&gt;who is too intellectual to actually write code that works, you are far too busy discussing SOA, and other mystical Design Patterns. Not that design patterns are bad but let's be real; words &lt;EM&gt;mean&lt;/EM&gt; things. If we are going to &lt;EM&gt;say&lt;/EM&gt; we are "Object Oriented" let's actually &lt;EM&gt;do&lt;/EM&gt; it, or if our decision is to be "Service Oriented"; that's OK, just &lt;EM&gt;be&lt;/EM&gt; "Service Oriented". &lt;/P&gt;
&lt;P&gt;That is all I have to say, for now. If you want more you will just have to wait along with all of the rest of the desperate masses. ;-)&lt;/P&gt;&lt;img src="http://www.dotnetjunkies.com/WebLog/aggbug.aspx?PostID=134241" width="1" height="1"&gt;</content><slash:comments>3</slash:comments><wfw:commentRss>http://www.dotnetjunkies.com/WebLog/azenker/commentrss.aspx?PostID=134241</wfw:commentRss></entry></feed>