Archives / 2008 / August
  • Memorystream Not Expandable: Invalid Operation Exception

    There's a little gotcha with the MemoryStream class that I just found out. It has 7 constructors. The default constructor has the stream set as expandable, with an initial capacity of 0. The ctors that take the capacity set the capacity to the param, but also keeps the stream expandable. If, however, you use a ctor with the byte[] param, it initializes the stream with the contents of the buffer, but the stream becomes non-expandable.

    So, if you have something like this:

    byte[] buffer = File.ReadAllBytes("filaname.docx");

    MemoryStream ms = new MemoryStream(buffer);

    MemoryStream ms2 = new MemoryStream();

    ms2.Write(buffer, 0, buffer.Length);

    then, ms will NOT be expandable, ms2 will be. So, if you are modifying the stream and the size may increase, the first ctor will not work, but the second approach will work just fine.


    Hope that helps :)


  • .Net 3.5 SP1...finally

    Fate has a weird sense of humour. I held out from installing .net 3.5 sp1 all through the CTPs, then beta 1 and beta 2. This is also the first time I restrained myself from installing new stuff (coz simply put, having to uninstall a bunch of betas and patches and what not was getting to me). Well, I couldn't hold out any longer. I downloaded the entire thing. My internet is pretty crap, so I had to download the packages individually, then run a command line switch to download the final files. After that, was a quite long install. It failed. I removed silverlight tools. Tried again. Worked perfectly. I played around for a few hours. Made a few apps. Liked the new stuff quite a bit. And then, at 4 am, I went to bed.

    I wake up, and what do I see? Damn you just released the final .net 3.5 sp1 bits while I was asleep. Couldn't you have done it ONE day earlier or a month later? It HAD to be today, right? Why God, WHY?!?!?!

    Ah well...guess I'll be downloading it all over again. And I gues I can forgive MS as the sp1 is actually available as an ISO. That is SO much more convenient to me. Thanks guys.

    You can download .net 3.5 sp1 from bootstrapper here. You can download the FULL .net 3.5 sp1 from here. You can download the Visual Studio 2008 sp1 bootstrapper here. And you can download the FULL VS 2008 sp1 from here. Please note that the VS 2008 sp1s contain .net 3.5 sp1. Also note that the bootsrappers will require internet connectivity during installation, while the full versions will not.


  • Refresh Button and Double Insert / Updates

    I saw a few questions on the forums about double posting of data because of users using the refresh buttons in the browser.

    Ideally, I'd want to have my insert / update mechanisms be done by AJAX calls to a web service. While this will work nicely regardless of back / refresh buttons being pressed, there is a necessary overhead, and a lot of people (including me, in a hurry) find the default features of a gridview very attractive. Granted, I could just put the gridview in an update panel and be done with it, but there's a quick fix in case you're not using AJAX:

    After the insert/update is done, if it was successful, just do a Response.Redirect to the same page.

     UPDATE: As pointed out by the always helpful anas, tmorton has an excellent and in depth article on this topic. She presents various commonly used methods that DON'T WORK, and also some that do. It seems like the only viable options are doing what I suggested above, or actually changing the db so that it doesn't allow duplicates by using unique constraints (which isn't always what we want) or to check the db before indexing to see if the insert/update does something we don't want. The last option is ideally the best, but would require quite a bit of code for each and every insert. I'm as surprised as she was that the last method achieved the best performance in her tests. I could be wrong, but it seemed that her tests were made taking into account that users would be hitting the refresh button after insert most, if not all of the time. I wonder if the last method would be as fast compared to the others if most inserts were just inserts and no refresh button were clicked (as would be the most expected case). If the checks are always made, then they would be redundant only when the checks weren't needed. And most of the time, they would not be needed.

    The problem with the method I suggested has the problem that the ViewState is cleared for the controls. If there is no problem with that, then it can work very well, while maintaining a lot of simplicity. If we wanted some controls to retain their values, we could easily save them in Session, and retrieve them after redirect. This would add complexity, but nowhere near the complexity needed to make all the checks everytime. Still, ideally, we should all be checking the db everytime. But when we want a quick solution, the redirect would work great.

    Of course, on my pages, I always use AJAX to handle the inserts, whether in an updatepanel or by calling a webservice. That, IMO is the best way and it doesn't have to deal with that pesky double posting thing at all.