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

Grant Killian's Blog

No, this has nothing to do with beer -- but maybe it should?

December 2003 - Posts

  • Spare a DIME?

    No, I'm not raising money for a charity -- I'm doing work with files and binary data via .Net web services.  You probably don't hear that in the same sentence very often!  Several months ago, DIME (Direct Internet Message Encapsulation) was the latest buzz-word in transmitting files over http for web services; web service enhancements (WS-E) relied on DIME for attachments; there was a flurry of articles (like this one) on how DIME was THE way to include documents in your web service communications.  Recently, however, luminaries such as Don Box and Gudge have reported DIME is dead.  They offer an alternative:  Proposed Infoset Addendum to SOAP Messages with Attachments (or the catchy acronym: PASWA). But as far as I know, this is an abstract alternative.  There isn't a concrete implementation of PASWA or WS-E version that incorporates PASWA. 

    What's a guy with a laptop and a customer with a large document-centric web service requirement to do?  I don't want to use DIME if it's current implementation is not likely to continue, but DIME via WS-E (WS-E Attachments as it's known) is considerably faster than xml encoding all the bytes in a file.  If you're curious, WS-E Attachment is well-documented in articles such as this one by Mike Gunerloy; the “old fashion“ way is to move your attachment into a byte array and shuttle it like any normal web service parameter, like this from the client side:

    FileStream fsm = File.Open( "File.doc", FileMode.Open, FileAccess.Read );
    byte[] byteArray = new byte[ fsm.Length ];
    fsm.Read( byteArray, 0, int.Parse( fsm.Length.ToString() );
    //invoke webservice, passing byteArray as a parameter . . .

    And this from the webservice side:

    MemoryStream mem = new MemoryStream( byteArrayParam ) );
    FileStream fsm = new FileStream( "New File Name", FileMode.Create );
    mem.WriteTo( fsm ); mem.Close(); fsm.Close();

    Simple and sophisticated, but not quick.  So, the 10 cent question is do I stick with the slower option or go with the “Dead“ DIME solution?  Is there another path?  I'm sure if I'm patient enough, I could wait for a new release of some package and be up and running with PASWA; if I was more enterprising and had more time, I might take a stab at implementing PASWA as an extension to what I've got right now -- sounds fun, but not a viable option.

    I guess I avoid DIME (afraid that future web service / SOAP stacks won't implement it) and go with the byte array approach?  Am I missing something?

    Happy .Netting!

    Grant

     

  • Will the real Grant Killian please stand up?

    I just got wind of the “trend” in IT hiring where employers google their job candidates.  By googling my name the first result is:

    http://dotnetjunkies.com/weblog/grant.killian

     

    No problem there.  A few results down the list, however, is:

    http://www.killiangrant.com

     

    I have nothing to do with the site, and am NOT Killian Grant.  The coincidences are disturbing.  Apparently both Killian Grant and Grant Killian[myself] grew up in Wheat Ridge, Colorado and we both work in IT.  No offense intended to Killian Grant, but I wouldn't want a potential employer to mistake me for this person based on a google search (and I'm sure Killian Grant feels the same about me!) -- so if you're evaluating job candidates based on a google search, take the time to make sure you are reviewing information on your candidate and not just somebody with a similar name!

     

    Happy .Netting!

  • Chocolate Milk and Full Control for Everyone?

    When you encounter security issues, is your first inclination to enable Full Control on the everyone account?  I certainly hope not, and if it is, you won't be developing software for very long.  Maybe you should be campaigning for Student Council president: “Chocolate Milk for Everyone!”  If you struggle with knowing which account is accessing which resource, check out FileMon from SysInternals (www.SysInternals.com).  It's free.  It's powerful.  I should point out that virtual buddy Brendan Tompkins (a virtual buddy is one you've never met face-to-face) blogged about another SysInternals tool here.

    FileMon (and many other tools from SysInternals) has been around for a long time, but since many of my student's haven't been around software development or at least .Net for a long time, I feel obliged to share this FileMon story with you.

    Many web applications require some sort of writing to the file system (log files, uploaded documents or images, etc).  The app I'm working on generates some report graphics that need to be saved on the sever (in case you were concerned about server disk space management, they get erased once they've aged over 1 day; creating them in memory is not an option in this case).  My first attempts to write to the server file system failed, returning a generic "Error in GDI+" message; .Net graphics handling is great, but the error messages can be a bit vague. 

    Instinctively, I suspected a permission issue so I checked out the security on the folder I was writing to.  Besides the default system permissions, the folder had Modify permissions for the Domain\ASPNet account and the Machine\IUSR_MachineName account.  It looked ok at first glance.  When I gave Everyone Full Control to the folder (just as a test!), the application wrote the files out without any problem -- so this was certainly a permission issue.  I cleaned up my "Full Control" test with the Everyone account; that's an unacceptable work around, even for a dev box!

    What to do?  I could start experimenting with Impersonation via web.config, or try any number of other things, but I decided to fire up FileMon.exe to get a look at what's going on.  FileMon, as the name suggests, monitors the file system and tracks file activity.  You can download it from www.SysInternals.com (in the utilities section -- here). 

    FileMon generates a lot of output (amazing how many requests the OS and other services generate), so only start it up right before you being the activity you're investigating.  I started FileMon, went to the File Menu, and unchecked the Capture Events option (this stops FileMon from tracking activity).  Then I went to the Edit Menu and clicked on Clear Display to give me a blank log to work with.  I started my web app, and right before clicking the button that generated my exception, I toggled over to FileMon and rechecked the Capture Events option to start the monitoring session.  I clicked my button and waited patiently for the exception to be raised -- FileMon will slow your apps down a good bit.

    Once my exception was displayed on the screen, I unchecked the Capture Events option in FileMon; I didn't want FileMon to keep tracking activity while I reviewed the log.  I had over 100 entries already!

    Starting at the end of the log, I reviewed each entry, looking for a "Failure" in the Result column.  I quickly found my failed request, and the Path column displayed the folder my web app was writing to.  In the Other column was the account that was requesting permission to the folder . . . this was it . . . to my chagrin, Machine\ASPNet was displayed.  I realized then that the Domain\ASPNet account was configured for the folder INSTEAD OF Machine\ASPNet.  I quickly gave Machine\ASPNet write and modify permissions to the folder and my web application was off and running fine again.

    FileMon made this oversight easy to identify, and saved me -potentially- lots of wasted time.  It took me only a few minutes to diagnose and resolve the issue. 

    Happy .Netting

  • I'm thankful PDW is no more!

    With Thanksgiving just behind me, I thought I'd share one of the software development things I'm thankful for.  I'm thankful that Microsoft did away with Package And Deployment Wizard (PDW).  The tools for creating setup and deployment packages in VS.Net are far more powerful and easier to work with; they may not put Wise out of business, but at least VS.Net includes a solid tool for creating installations!  Customizing and extending an installation package is very straightforward, and the whole thing is completely integrated into Visual Studio .Net.

    MSDN offers a lot of guidance on this subject: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsintro7/html/vbcondeploymentscenarios.asp.  This one is particularly interesting, as setting values in Web.Config is the sort of thing we end up doing a lot: http://msdn.microsoft.com/library/en-us/vsintro7/html/vxwlkwalkthroughredirectingapplicationtotargetdifferentxmlwebserviceduringinstallation.asp.

    We use custom actions to attach our SQL database creation scripts to the installation.  I'll create a new assembly to contain the special logic, and then reference the assembly from the Install (and Uninstall) custom action options of our setup project.  I was going to go into detail on this, but Doug Doedens has an article that covers things fairly well: http://www.c-sharpcorner.com/Code/2002/Nov/CustomUI.asp; the key is using the Context.Parameters collection in your custom installer routine (the article covers it in detail).

    A few additional tips I can offer for your Installation work . . .
    -The .Net Framework isn't installed with your setup application; it's a "launch condition" (which means your installation will not run without it), but you'll need to take special steps to add the Framework to you install.  See this link for adding DotNetFX (the .Net framework redistributable):
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetdep/html/dotnetframedepguid.asp.
    -Check out the command line installutil (
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptools/html/cpconInstallerUtilityInstallutilexe.asp) if you want to do "silent" installations or just to test your custom action.  Installutil /i assemblyName.dll will launch your installation and InstallUtil /u will launch the uninstall.
    -In the process of all these installations and uninstallations, you may encounter the following windows error message:
    "The Windows Installer Service could not be accessed.
    This can occur if you are running Windows in safe
    mode, or if the Windows Installer is not correctly
    installed. Contact your support personnel for assistance."
    This happens from time to time in our organization, usually because of an unhandled exception in an install routine.  The fix is easy, go to the command line and run msiexec.exe /unregister [Press Enter]; then run msiexec.exe /regserver [Press Enter].  This will set you straight.

    Happy .Netting!

  • Disappearing Session Objects

    I guess this is my night to share .Net issues my students have uncovered . . . here's one I don't have an answer for . . .

    The asp.net session objects (and cache objects) in her application are consistenly destroyed after a few page requests.  This only happens on this one particular machine (isn't it often that way?), so we immediately check the Session settings in Web.config and in IIS (session timeout property); everything checks out normally. 

    The Cache object is an easy one . . . when a server is running low on resources, the Cache dictionary can be scavenged by the server; it's a “too few resources” thing.  All work with a Cache object should begin by testing for the presence of the item in the Cache; you never know when you may have to recreate an object that was stored in the Cache.  As an aside, check out this tip for a way to respond when an item is deleted from (it uses Delegates . . . a favorite topic of mine).

    The Session object, however, is an odd one.  I haven't heard of Session objects being scavenged like Cache objects, but this was certainly looking that way -- although Task Manager doesn't show a heavy burden weighing on the machine.  The Session object would have get a new Session ID, so the server is discarding the old session and regenerating a completely new one.

    Requests from computers other than the server would still manifest this Session problem -- so I eliminated the client browser configuration issue from consideration (thinking that, perhaps, the cookie that Session State relies on by default was being deleted or blocked by privacy software -- no luck there). 

    So, while I'd like to share the solution to the student's dilemma, we haven't found one.  She is going to work on a different server with “normal“ behaviour or avoid session state while playing with .Net on that server.  I realize this isn't an acceptable solution for the “real“ world, but so far this problem has only manifested itself in the “unreal“ world of academic licensed server and application software -- and only one computer at that.

    If anyone has any ideas I'm all ears!

    Happy .Netting

  • Debug Server Control

    A student and I wrestled with a Server Control issue tonight.  We couldn't debug the server control, despite following the conventional wisdom of having 2 projects (one control project and one asp.net project), referencing the control project from the asp.net project and adding the control to a page, and launching the asp.net project as the “Start Up” project with breakpoints set in the control project.

    I googled for “Debug Server Control” along with asp.net, c#, and vb.net and found very slim pickings -- mostly irrelevant stuff, so this post is partially an attempt to fill the void . . .

    We solved our problem by deleting the control project assembly and debugging file (.pdb file) from the bin directory of the asp.net project.  We ran our asp.net project again (as “Start Up” project, again) and the referenced assembly was automagically added to the bin directory again.  This time it worked.  It works ok from now on.

    Now, I know if you're using an external assembly you change the control code you'll have to make sure the assembly version is appropriate in the client applications, but this is the first I've seen of this when the projects were contained in the same Solution and the asp.net application was referencing the control project from within the solution.  The fact our rebuild generated fresh versions of the assembly (and the .pdb file) indicates VS.Net is sophisticated enough to recognize the relationship between the two projects.

    Strange.

    Anyway, by deleting the referenced assembly and rebuilding our project, it solved the problem.

    Happy .Netting

More Posts