{STATIC} hippo

...on becoming a great developer...
MCTS: .NET Framework 3.5, ASP.NET Applications
posts - 27, comments - 3, trackbacks - 0

My Links

Twitter

Archives

Post Categories

Wednesday, February 03, 2010

Response.Flush and the crimes against Page Caching

In a previous post (http://blog.statichippo.com/archive/2009/11/16/findreplace-on-render-ndash-an-mvc-alternative-to-response-filters.aspx), I wrote about how to render a ViewPage to a string before writing it to the OutputStream.  This would be helpful, for instance, to replace certain text with other text (in my case, I used this to replace special tags with other content).  The method used basically worked like this:

  1. Add MemoryStream as a ResponseFilter
  2. Render output
  3. Flush the Response so that now the text is in the MemoryStream
  4. Use a StreamReader to ReadToEnd
  5. Do the transformations and Write to the Response stream

As it turns out this effectively disabled Page Caching.  We tracked it down to step 3 – Response.Flush.  To me this call looked innocuous, but that’s not how it looks to IIS.  I posted the issue to StackOverflow (http://stackoverflow.com/questions/2193628/response-flush-breaking-page-caching) and user Womp referred me to this blog post at IIS.NET.

If some module already flushed the response by the time request reaches UpdateRequestCache stage or if headers are suppressed, response is not cached in output cache module.

That sort of makes sense though, since caching the response requires the entire response to be available.

I have a solution I’m working on, and I plan to write about it soon.  In the meantime, don’t flush your response if you need page caching.

posted @ Wednesday, February 03, 2010 1:56 PM | Feedback (0) |

Thursday, January 28, 2010

Rx Framework Subscriber Actions are blocking

The NY ALT.NET Meetup group met last night and Scott Weinstein delivered a terrific presentation on the Reactive Framework (also known as Rx Framework).  If you haven’t heard about it, the Rx Framework is a framework for composing (and consuming) asynchronous events.

The way that the framework works is that you subscribe to an IObservable and get notified of new events.  Since this is all done async, one of my questions was whether a single subscriber’s consumption of these events is blocking (to itself) or not.  That’s probably not the best way to phrase the question, but the code’s easy enough to understand.  Anyway, Scott said he thought so, but it would be worth testing, so I did.

   1: static void Main(string[] args)
   2: {
   3:     var range = Observable.Range(1, 5)
   4:         .Subscribe((int i) =>
   5:     {
   6:         DateTime future = DateTime.Now.AddSeconds(5);
   7:         DateTime lastPrint = DateTime.MinValue;
   8:         if (i % 2 == 0)
   9:         {
  10:             while (DateTime.Now < future)
  11:             {
  12:                 if (DateTime.Now.Subtract(lastPrint).Milliseconds >= 900)
  13:                 {
  14:                     Console.WriteLine("Sleeping...");
  15:                     lastPrint = DateTime.Now;
  16:                 }
  17:             }
  18:         }
  19:         Console.WriteLine("Sleeper {0}", i);
  20:     });
  21:     Console.ReadLine();
  22: }

Basically, my IObservable is counting from 1 to 5 but taking it’s time on 2 and 4.  So the question was, will the Action passed to the subscribe be called in order (each one blocks) or will we have some (like 3 and 5) called before others (like 2 and 4, which means they don’t block).

And the output shows that they block, which is what Scott (and I) expected since it really is the only way that makes sense, but it was worth a look-see.

Sleeper 1
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeper 2
Sleeper 3
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeper 4
Sleeper 5

In case you were worried though, other subscribers are not blocked just because one subscriber blocks itself.

   1: static void Main(string[] args)
   2: {
   3:     var range = Observable.Range(1, 5);
   4:     range.Subscribe((int i) =>
   5:     {
   6:         DateTime future = DateTime.Now.AddSeconds(5);
   7:         DateTime lastPrint = DateTime.MinValue;
   8:         if (i % 2 == 0)
   9:         {
  10:             while (DateTime.Now < future)
  11:             {
  12:                 if (DateTime.Now.Subtract(lastPrint).Milliseconds >= 900)
  13:                 {
  14:                     Console.WriteLine("Sleeping...");
  15:                     lastPrint = DateTime.Now;
  16:                 }
  17:             }
  18:         }
  19:         Console.WriteLine("Sleeper {0}", i);
  20:     });
  21:     range.Subscribe((int i) => { Console.WriteLine(i); });
  22:     Console.ReadLine();
  23: }

 

renders (and this obviously isn’t deterministic because this is all async, so it may be slightly different order every run, but it proves the point):

1
Sleeper 1
2
3
4
5
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeper 2
Sleeper 3
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeping...
Sleeper 4
Sleeper 5

posted @ Thursday, January 28, 2010 10:46 AM | Feedback (0) | Filed Under [ c# Rx Framework ]

Wednesday, January 20, 2010

Mapping Serializable types using Fluent NHibernate

Yesterday I posted a question to StackOverflow (http://stackoverflow.com/questions/2097364/mapping-to-serializabletype-in-fluent-nhibernate) asking whether anyone could tell me how to map a Serializable type using Fluent NHibernate.  The outcome was disappointing to say the least.  In 24 hours there have been less than 20 views.  It was voted up twice, but no comments or answers were posted.

Even worse, there’s another post on StackOverflow (http://stackoverflow.com/questions/2000798/map-to-serializable-in-fluent-nhibernate) that asks this same question and has an answer that’s incorrect (it compiles but throws an exception at runtime).

Serializable types in NHibernate (XML)

Before I continue, I’ll give a little background.  Feel free to skip this part.  Suppose you want to map the following object (contrived, I know):

   1: public class Person
   2: {
   3:     public virtual string FirstName { get; set; }
   4:     public virtual string LastName { get; set; }
   5:     public virtual BirthCertificate BirthCertificate { get; set; }
   6: }
   1: public class BirthCertificate
   2: {
   3:     public virtual DateTime DOB { get; set;}
   4:     public virtual string BirthCity { get; set; }
   5:     public virtual string BirthState { get; set; }
   6:     public virtual string HospitalName { get; set;}
   7: }

Imagine, however, that you don’t want to map the BirthCertificate fields to a table.  Imagine you want to serialize the BirthCertificate object and store it in a single column in the Person table.

NHibernate makes this really easy.  When mapping the BirthCertificate property on Person, you would write something like this:

   1: <property name="BirthCertificate" column="BirthCertificate" type="Serializable"  />

and of course you would have to add a [Serializable] attribute to the BirthCertificate class like so:

   1: [Serializable]
   2: public class BirthCertificate
   3: {
   4: .......

Mapping Serializable using Fluent NHibernate

This is actually surprisingly easy.

The Fluent interface provides a CustomType method that allows you to map your entity to a custom, IUserType.  The incorrect answer that was posted on the old StackOverflow post (link above) mentioned combining this CustomType method with the SerializableType type, like this:

   1: CustomType<NHibernate.Type.SerializableType>();

That will build, but it throws an Exception at runtime:

An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.

InnerException:

Could not instantiate IType SerializableType: System.MissingMethodException: No parameterless constructor defined for this object.
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache)
   at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at NHibernate.Bytecode.ActivatorObjectsFactory.CreateInstance(Type type)
   at NHibernate.Type.TypeFactory.HeuristicType(String typeName, IDictionary`2 parameters)

I’m not a contributor to the Fluent NHibernate project (though I’m considering it after some other things calm down and I have more time), so I wasn’t particularly familiar with the codebase.  In order to find the solution, I downloaded the latest code and stepped through it to see how it works.

Basically, the fluent interface collects all your mapping settings and then outputs the appropriate hbm’s at configure-time.  Using the incorrect answer above resulted in the following mapping for the BirthCertificate property:

   1: <property name="BirthCertificate" 
   2: type="NHibernate.Type.SerializableType, NHibernate, 
   3: Version=2.1.2.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4">
   4:   <column name="`BirthCertificate`" /> 
   5: </property>

Hey – that should read type=”Serializable”!  We don’t want the whole Type info there!

Turns out one of the overloads of the CustomType method takes….. you guessed it (!)…. a String!

The following is the correct way of mapping a Serializable type in Fluent NHibernate

   1: CustomType("Serializable");

Yes I feel stupid for not figuring this out from the start!  One comfort though is that it doesn’t seem that many people know this, even though it seems so obvious.

Stupid as I feel, I also feel like I gained a lot from the hour I spent on this; I finally got to delve into the Fluent NHibernate code.

posted @ Wednesday, January 20, 2010 11:35 AM | Feedback (0) | Filed Under [ NHibernate ]

Friday, January 08, 2010

ASP.NET MVC & State Pattern: Choose your view

Problem

I have a model that uses the State pattern.  Some States allow read/write access to the Model’s properties and some are read-only.  I wanted a good way to separate the logic for this from my Views; the View shouldn’t have to decide whether properties are displayed as TextBoxes or inside Divs.

First Thought

At first I was going to create a custom ViewEngine.  That ViewEngine would be responsible for choosing the right View – that is, if the View was called “Edit” but the model was in a readonly state, it would change the View to “ReadOnly”.  However, that just didn’t sound right – why was that responsibility falling on the ViewEngine?  Plus, it’s kind of inflexible – what if some editable Views are called “Edit” but some are called “Details”.

Solution

I ended up with a mixture of a custom ActionFilter and a base Controller class.  Before I show you the code, let me show you the usage:

   1: [AcceptVerbs(HttpVerbs.Get)]
   2: [StateItemEditView("ReadOnly")]
   3: public ActionResult Edit(int id)
   4: {
   5:     var module = _Repository.GetByID(id);
   6:     return View(module);
   7: }

Notice Line 2 – this specifies that:

  1. The current action has editable content
  2. The ReadOnly View name is called “ReadOnly”

The code for the controller, which I use as a base class for my controllers that act upon StateItems:

   1: public class StateItemController : Controller
   2: {
   3:     protected override ViewResult View(string viewName, string masterName, object model)
   4:     {
   5:         object readOnlyViewName;
   6:         if (ControllerContext.Controller.TempData
   7:             .TryGetValue(StateItemEditViewAttribute.key_ReadOnlyView, out readOnlyViewName))
   8:         {
   9:             var stateItem = model as IStateItem;
  10:             if (workflowItem != null && stateItem.CurrentState.IsReadOnly)
  11:                 viewName = readOnlyViewName as string;
  12:         }
  13:         return base.View(viewName, masterName, model);
  14:     }
  15: }

Before returning the View, which has a ViewName string, we want to make sure the ViewName is correct.  We check the Controller’s TempData for a predefined key.  If that key exists, the value will be the name of the View to display for ReadOnly states.  We then check if the Model exists and is a StateItem, and if it’s ReadOnly we change the ViewName before returning the View.

The StateItemEditViewAttribute is just responsible for setting the TempData key:

   1: public class StateItemEditViewAttribute : ActionFilterAttribute
   2: {
   3:     public StateItemEditViewAttribute(string readOnlyView)
   4:     {
   5:         _ReadOnlyView = readOnlyView;
   6:     }
   7:     private string _ReadOnlyView;
   8:     public const string key_ReadOnlyView = "ReadOnlyView";
   9:     public override void OnActionExecuting(ActionExecutingContext filterContext)
  10:     {
  11:         filterContext.Controller.TempData.Add(key_ReadOnlyView, _ReadOnlyView);
  12:     }
  13: }

I’m using this for a binary dicision – Edit/ReadOnly – but this could be used for a lot of other purposes too.

posted @ Friday, January 08, 2010 2:10 PM | Feedback (0) | Filed Under [ ASP.NET MVC ]

Thursday, January 07, 2010

Calendar sizes: DateTime vs Nullable SqlDateTime in NHibernate

 

Does size matter?

.NET’s DateTime class supports a range between 01/01/0001 00:00:00 and 12/31/9999 23:59:59.9999999.  Sql Server’s calendar is not quite as big – it starts at 1/1/1753.  Therefore, if you have an object with a DateTime that’s set to DateTime.MinValue (or any other date before 1/1/1753) and you try to save that to a database, you’ll get the following exception:

SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.

This recently got in my way.  I’m building an application on top of a legacy database.  There’s a table with a CreatedDate column that’s nullable.  However, in my domain model I didn’t want CreatedDate to be a Nullable<DateTime> because everything should have a CreatedDate – is there anything that wasn’t created at some point in time?

My object looks like this:

   1: public class MyObject
   2: {
   3:     public MyObject()
   4:     {
   5:         CreatedDate = DateTime.Now;
   6:     }
   7:  
   8:     public virtual string Name { get; set; }
   9:     public virtual DateTime CreatedDate { get; protected set; }
  10: }

Existing data in legacy database

The problem is that many of the existing entries in the database have a NULL entry for CreatedDate.  Because of this, CreatedDate will be set to DateTime.MinValue.  When I tried to save the object back to the database I got the above mentioned SqlDateTime overflow exception.

Going forward I don’t want any more NULL entries, but I don’t have the ability to update all existing NULLs to some arbitrary date (without having a whole back and forth with the DBAs).  What I decided would be the best idea would be to support NULL entries in the DB transparently – NULL entries will map to DateTime.MinValue on the GET side, and DateTime.MinValue will map to NULL on the UPDATE/SAVE side.  Since a new object always has its CreatedDate property set to DateTime.Now on instantiation, only really old objects will show 1/1/0001 as their created date in the system.

Implementation of IUserType

NHibernate has an IUserType interface which allows you to specify your own type for saving and retrieving data.  Here’s what I wrote to handle my requirements:

   1: public class NullDateTimeAsMinDateType : IUserType
   2:     {
   3:         public new bool Equals(object x, object y)
   4:         {
   5:             if (ReferenceEquals(x, y))
   6:                 return true;
   7:             if (x == null || y == null)
   8:                 return false;
   9:             return x.Equals(y);
  10:         }
  11:         #region IUserType Members
  12:  
  13:         public object Assemble(object cached, object owner)
  14:         {
  15:             return cached;
  16:         }
  17:  
  18:         public object DeepCopy(object value)
  19:         {
  20:             return value;
  21:         }
  22:  
  23:         public object Disassemble(object value)
  24:         {
  25:             return value;
  26:         }
  27:  
  28:         public int GetHashCode(object x)
  29:         {
  30:             return x == null ? typeof(DateTime).GetHashCode() : x.GetHashCode();
  31:         }
  32:  
  33:         public bool IsMutable
  34:         {
  35:             get { return false; }
  36:         }
  37:  
  38:         public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
  39:         {
  40:             var obj = NHibernateUtil.DateTime.NullSafeGet(rs, names[0]);
  41:             if (obj == null)
  42:                 return DateTime.MinValue;
  43:  
  44:             DateTime dateTime = (DateTime) obj;
  45:             return dateTime;
  46:         }
  47:  
  48:         public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
  49:         {
  50:             if (value == null)
  51:             {
  52:                 ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
  53:                 return;
  54:             }
  55:             DateTime dateTime = (DateTime)value;
  56:             if (dateTime.CompareTo(System.Data.SqlTypes.SqlDateTime.MinValue.Value) < 0)
  57:                 ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
  58:             else
  59:                 ((IDataParameter)cmd.Parameters[index]).Value = dateTime;
  60:         }
  61:  
  62:         public object Replace(object original, object target, object owner)
  63:         {
  64:             return original;
  65:         }
  66:  
  67:         public Type ReturnedType
  68:         {
  69:             get { return typeof(DateTime); }
  70:         }
  71:  
  72:         public NHibernate.SqlTypes.SqlType[] SqlTypes
  73:         {
  74:             get { return new[] { NHibernateUtil.DateTime.SqlType }; }
  75:         }
  76:  
  77:         #endregion
  78:     }

 

I’m using FluentNHibernate, so my mapping looks like:

   1: Map(x => x.CreateDDate)
   2:     .Column("create_date")
   3:     .CustomType<NullDateTimeAsMinDateType>()
   4:     .Nullable();

 

That’s it.  Now the CreatedDate column in the DB doesn’t have to get touched and SQL Server’s date fields play nice with .NET DateTime.

posted @ Thursday, January 07, 2010 1:06 PM | Feedback (0) |

Sunday, December 27, 2009

Fresh Install List

My laptop has not been behaving lately and I figured it’s time for a wipe & a fresh install.  I was compiling a list of all the apps I need to install and figured I’d share it with the world.  My current feeling is that anything not on this list will have to be installed on a VM, but we’ll see how long that lasts.  I really just want my new install to be clean and tidy.

 

Development

Visual Studio 2008

Expression Studio 3

SQL Server 2008

CodeRush & Refactor! Pro – you’d have to be a masochist not to use some sort of code assistance plugin

TortoiseSVN

VisualSVN – integrates SVN (runs on top of TortoiseSVN) straight into Visual Studio.  $49 and worth every penny!

WinMerge – it’s free and so much better than WinDiff

Fiddler2 – a terrific web debugging proxy.  It’s free and worth every penny (and then some)

Communication

Pidgin – my officemates use AIM (and probably Win95 too), but I use GTalk for everything else.  1 (free) app is better than 2

uTorrent – I was an Azureus guy until they turned into Vuze and increased their bloat exponentially.  uTorrent does the job, and does it well.

Windows Live Writer – it’s actually a great blogging software.  Seriously!
- CodeSnippet plugin

TweetDeck – my twitter client of choice

Tools

Notepad++ – because notepad sucks

VirtualBox – really great Virtualization software, and it’s free

Paint.NET – comes in handy way more than I thought

PeaZip – open source, handles tons of file formats, and it’s prettier than 7zip

Virtual CloneDrive – freeware tool to mount ISO and other images.  Don’t ask me why Windows doesn’t come with this!

Firefox Plugins

Firebug

YSlow

Adblock Plus

Windows Media Player Plugin

posted @ Sunday, December 27, 2009 9:43 PM | Feedback (0) | Filed Under [ Tools ]

Tuesday, December 08, 2009

Getting started with 3D Elements in WPF

I was watching the video entitled How Do I: Get started with 3D Elements in WPF and was just completely thrown off by author, Todd Miranda’s, complete lack of visuals.  So I played around with his example until I better understood what was going on and I figured I’d share.  Please understand that I am not a XAML master and certainly not in 3D, so if you find any errors please let me know.

The XAML that Todd starts off with is:

   1: <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:  xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
   3:   <Grid>
   4:     <Viewport3D>
   5:         <Viewport3D.Camera>
   6:             <PerspectiveCamera Position="-50,20,15" LookDirection="50,-15,-10" UpDirection="0,0,1" />
   7:         </Viewport3D.Camera>
   8:         <ModelVisual3D>
   9:             <ModelVisual3D.Content>
  10:                 <Model3DGroup>
  11:                     <DirectionalLight Color="White" Direction="-1,-1,-3" />
  12:                     <GeometryModel3D>
  13:                         <GeometryModel3D.Geometry>
  14:                             <MeshGeometry3D Positions="0,0,0 10,0,0 10,10,0 0,10,0 0,0,10 0,10,10"
  15:                                         TriangleIndices="0 1 3  1 2 3  0 4 3  4 5 3" />
  16:                         </GeometryModel3D.Geometry>
  17:                         <GeometryModel3D.Material>
  18:                             <DiffuseMaterial Brush="Red" />
  19:                         </GeometryModel3D.Material>
  20:                     </GeometryModel3D>
  21:                 </Model3DGroup>
  22:             </ModelVisual3D.Content>
  23:         </ModelVisual3D>
  24:     </Viewport3D>
  25:   </Grid>
  26: </Page>

The output is:

xaml_3d_1 

Camera Perspective

First off, let’s play with the Camera perspective.  I think the best way to do this is first to define the different parts of the Camera Perspective, the most important being Position and LookDirection.

wpf_3d_grid_1

Take the grid above.  It’s hard to show a Z axis, so I made the font smaller to try to trick your eye into believing it’s farther away.

Position

So the grid above is akin to a room, right?  You have a top & bottom, right & left, and depth – we’ll call Z0 Backward and Z50 Forward so that if you’re walking into the room you’re walking Forward, ok?

xaml_3d_2 

Now here we have a video camera pointed at a box.  It’s way too close to the box, as you can see, since all you can see in the viewfinder is part of the box.  Well to get a better picture we have 3 directions to move the camera: forward/back, right/left, up/down:

xaml_3d_3 (This might be a Position of -5(Z), 25(X), and 25(Y))

 

So in this instance, I might want to move the camera backwards, like so:

xaml_3d_4 (This might be a position of –25,25,25)

Now notice how I moved the camera backwards and got the whole box in the viewfinder.  I’m farther away from the box so I can see the whole thing.

The same principle holds true for the X & Y axis:

xaml_3d_5  Perhaps this is –25,5,25 -- I moved the camera too far to the right and only see the right most part of the box.

The above is all the job of the Position attribute.  But there’s another important element to how the camera picks up the image and that is the angle of the camera

LookDirection

“Well my head went back and to the left.”

In WPF, just like in real life, once you have your camera setup where you want it, you also need to angle the camera to point in the direction of the object you want to see.  For instance, if you want to catch a right-hand side (from your view) shot of a box, what would you need to do?  You would place your camera to the right side of the box at a depth that was equal with the center of the box.  Then you would need to turn your camera to the left in order for the lens to face the box.

Step 1, move your camera to the side of the box

xaml_3d_6

Step 2, turn your camera to the left:

xaml_3d_7

XAML

This post was actually a lot of work to write.  I think I’ll have to break up the other elements into other blog posts and write those at another time.  However, for the sake of completion, let’s fold these new concepts back into the XAML from before.

Suppose you want to look change the direction so that you’re facing the red shape head-on.  In other words, you want to look at the shape so that it looks just like a square (instead of an L shaped 3D shape).  You might change the XAML so that line 3 reads

   1: <PerspectiveCamera Position="-50,0,15" LookDirection="50,0,-10" UpDirection="0,0,1" />

The output looks like this:

xaml_3d_8

Now don’t mind that it’s black on top – that has to do with the light source and is out of the context of this post.  But let’s just see how we got here.  Here are the two lines juxtaposed (I added spacing so that everything lines up):

   1: <PerspectiveCamera Position="-50,20,15" LookDirection="50,-15,-10" UpDirection="0,0,1" />
   2: <PerspectiveCamera Position="-50,0 ,15" LookDirection="50, 0 ,-10" UpDirection="0,0,1" />

 

So first I changed the Position’s X to 0 from 20, so I’m moving the camera to the right.  Now if I didn’t change the LookDirection it would mean that the camera would be facing slightly downwards (-10)  and slightly to the left (-15), so you’re not looking at it straight on.  That’s why I dropped the X value of LookDirection up from –15 to 0.

Just keep in mind that it is very easy to place the Postion and/or LookDirection of the camera so that the shape is completely out of view.

Hopefully this helps put some of what Todd says in his video in context.

posted @ Tuesday, December 08, 2009 9:33 PM | Feedback (0) | Filed Under [ XAML ]

Thursday, December 03, 2009

.NET, XPath, and XmlNamespaceManager

Take the following XML fragment

   1: <?xml version="1.0" encoding="iso-8859-1"?>
   2: <con:search-results 
   3: xmlns:con="http://namespace.contoso.com/business-objects" 
   4: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   5: xsi:noNamespaceSchemaLocation="http://www.contoso.com/dtd/syndication/biz-objects.xsd">
   6:     <con:search-query>ipod</con:search-query>
   7:     <con:result-count>2207</con:result-count>
   8:     <con:start-index>0</con:start-index>
   9:     <con:result-count>15</con:result-count>
  10:     <con:results>
  11:         <con:result>
  12:             ...
  13:             

Now suppose you loaded this XML into an XmlDocument, how would you query for all the <con:result> nodes?  Using XPath you’d write something like

   1: /search-results/results/result

So you might try writing something like

   1: XmlDocument doc = new XmlDocument();
   2: doc.LoadXml(response);
   3: var resultNodes = doc.SelectNodes("/search-results/results/result");

but you would find that resuldNodes would be null.  You have to instantiate an XmlNamespaceManager to help correctly maneuver your namespaces.  That’s done like so:

   1: XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
   2: nsmgr.AddNamespace("con", "http://namespace.contoso.com/business-objects");

Then you would query your xml like so:

   1: var resultNodes = doc.SelectNodes("/con:search-results/con:results/con:result")

That took me a little searching to dig up, but it makes sense, right?

posted @ Thursday, December 03, 2009 2:16 PM | Feedback (0) | Filed Under [ c# XML ]

Gunnar Optiks glasses update

All I can say is I love my Gunnar Optiks Rx computer glasses.  My whole body just feels better at the end of the day and I have a lot less sensitivity to light at 10pm.  In general, during my day, I concentrate more and lose myself in my work more since I got these glasses.  I highly recommend them to everyone who spends most of their day in front of a computer monitor.

posted @ Thursday, December 03, 2009 1:55 PM | Feedback (0) | Filed Under [ Misc ]

Wednesday, November 18, 2009

Gunnar glasses – first impressions

I’m typing this while looking at my computer through my brand new pair of Gunnar Optiks Rx glasses.  They were waiting for me this evening when I came home from work.

There’s not much to say yet,  I’ll update this post after I use them for a while, but I think it’s worthwhile putting down my first impressions.

First off, my order took two and a half weeks to get to me.  Apparently there was some mix-up at the lab and Gunnar received the wrong frames the first time around, so they refunded my $10 shipping fee and tried again.  When the glasses did come, it was via 2nd day FedEx but I don’t know if that’s Gunnar’s standard shipping or if they expedited the shipping because of the mix-up.

There are plenty of un-boxing pics and videos available on the interweb, so in DRY fashion, I won’t go into too much detail.  Suffice it to say that the packaging is very sturdy and attractive and definitely gives off a very up-market feeling (although the “made in china” sticker on the inside of the pouch/cloth did undermine that a little).

100_1889_Vga

(Very impressed with how good this picture came out – you know I took it myself pointing the camera at the bathroom mirror!)

I think the glasses look pretty good!  The color of the lenses is certainly interesting, but I don’t really notice while wearing them.  I find myself reminding myself every so often that the world isn’t really this muted (at first things looked yellow-ish but now I just notice that colors are a bit muted).

The glasses are also really light.  My regular glasses were the lightest I could find and I paid extra for lighter lenses, but these Gunnars are definitely even lighter.  That’s really nice, because at the end of a long day I always feel my glasses weighing my face down.

 

I’ve worn the glasses for about 2 hours so far: 1+ hour doing normal, everyday tasks (eating dinner, talking to my wife, bathing my son), and a little under 1 hour looking at my computer.  I don’t notice any real difference in everyday tasks, although I thought I felt my eyes relax when I replaced my other glasses with these, but that could be psychosomatic. 

However, I do notice a difference when looking at my monitor!  I’ve got this sort of tunnel vision and everything outside of the current few lines of text has sort of blurred into the background.  That could be the time of day and the fact that I’m pretty tired, but I think it has something to do with the glasses because I’ve never noticed it before.  And the white background of Windows Live Writer isn’t bothering my eyes, but it’s sort of bothering my sense of style since I’m looking at what looks like slightly green-ish black text on a very off-white background.  My dark theme in Visual Studio looks really nice though (but man do I need to clean my screen!)

So far, I’m impressed.  Even if these glasses do nothing for my eye fatigue and other computer-related ailments, they are stylish, feel very well made, and are priced in the same range as regular Rx glasses, even less if you’re used to buying many higher-end (fashion-wise, not necessarily craftsmanship) frames.

posted @ Wednesday, November 18, 2009 9:32 PM | Feedback (0) |

Powered by: