<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SkyBlog :: A Navitaire NewSkies Development Blog &#187; SkySales</title>
	<atom:link href="http://blog.coltcooper.com/category/skysales/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.coltcooper.com</link>
	<description></description>
	<lastBuildDate>Thu, 22 Dec 2011 05:28:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Monarch Travel Commerce &#8211; Delivered By Navitaire (via Colt Cooper)</title>
		<link>http://blog.coltcooper.com/2011/12/monarch-travel-commerce-delivered-by-navitaire-via-colt-cooper/</link>
		<comments>http://blog.coltcooper.com/2011/12/monarch-travel-commerce-delivered-by-navitaire-via-colt-cooper/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 14:56:14 +0000</pubDate>
		<dc:creator>Colt</dc:creator>
				<category><![CDATA[New Skies]]></category>
		<category><![CDATA[SkySales]]></category>
		<category><![CDATA[Avis]]></category>
		<category><![CDATA[Car Hire]]></category>
		<category><![CDATA[Navitaire]]></category>
		<category><![CDATA[Travel Commerce]]></category>

		<guid isPermaLink="false">http://blog.coltcooper.com/?p=147</guid>
		<description><![CDATA[At the end of last month, Monarch Airlines switched on Navitaire&#8217;s Travel Commerce product to sell car hire in their SkySales booking path.  The article mentions that Monarch is the first carrier to use Travel Commerce in the European region.  Along with it being a first for Monarch, it was also a first for myself in working [...]]]></description>
			<content:encoded><![CDATA[<p>At the end of last month, <a href="http://nsknewsletter.wordpress.com/2011/12/22/monarch-airlines-becomes-newest-navitaire-travel-commerce-customer/" target="_blank">Monarch Airlines switched on Navitaire&#8217;s Travel Commerce product to sell car hire in their SkySales booking path</a>.  The article mentions that Monarch is the first carrier to use Travel Commerce in the European region.  Along with it being a first for Monarch, it was also a first for myself in working with Travel Commerce.</p>
<p>As I was solely responsible for the development of Monarch&#8217;s Avis car hire in SkySales, I quickly discovered that there wasn&#8217;t much information I could draw on to help with development issues.  Monarch had previously sold Avis rentals on the confirmation page using a separate site that was connected directly to the Avis API.  Irregardless of the quality of that API, it was easy to troubleshoot problems because it was a two-party handshake.  However, with Travel Commerce the simplicity of a two-party negotiation now turns into a contentious arbitration process.</p>
<p>An example of this was when the SkySales code was failing to pass certain required fields through to Avis.  Travel Commerce didn&#8217;t object and tried to sell the car (ignoring and not relaying any Avis error messages).  The result was a car that was considered sold as far as Travel Commerce was concerned, but awaiting confirmation (which Avis would never send).  It was only through asking Navitaire to dig through XML log messages on their side that we were able to discover the rejection messages Avis was sending.</p>
<p>I&#8217;m not sure if my experience developing against Travel Commerce is due to an immature Navitaire Avis connector or if it&#8217;s because just a few carriers are using Travel Commerce at the moment.  Regardless, I&#8217;ve got my battle scars now and am able to offer Travel Commerce customization to my list of professional service offerings.  If your airline is considering using Travel Commerce, feel free to contact me for a down to earth point of view.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.coltcooper.com/2011/12/monarch-travel-commerce-delivered-by-navitaire-via-colt-cooper/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PassengerContact Page Slowdown</title>
		<link>http://blog.coltcooper.com/2011/10/passengercontact-page-slowdown/</link>
		<comments>http://blog.coltcooper.com/2011/10/passengercontact-page-slowdown/#comments</comments>
		<pubDate>Sun, 16 Oct 2011 20:47:06 +0000</pubDate>
		<dc:creator>Colt</dc:creator>
				<category><![CDATA[SkySales]]></category>

		<guid isPermaLink="false">http://blog.coltcooper.com/?p=97</guid>
		<description><![CDATA[Back in 2006 when I was developing a customized solution for SkyBus, I was alarmed at the time it took for SkySales to initialize itself when it reached the passenger / contact page. On further investigation, I found that the call to the ResourceCache to get a list of countries and states was the culprit. [...]]]></description>
			<content:encoded><![CDATA[<p>Back in 2006 when I was developing a customized solution for SkyBus, I was alarmed at the time it took for SkySales to initialize itself when it reached the passenger / contact page.  On further investigation, I found that the call to the ResourceCache to get a list of countries and states was the culprit.</p>
<p>Normally, once the SkySales retrieves this information from the reservation core, it’s cached for future calls.  This is great unless you’re a developer who is constantly restarting the site.  In that case, developers will experience the empty Country / State cache slow down more often than not.</p>
<p>The problem lies in how Navitaire has structured the retrieval of states.  If you examine the GetStates method in the ResourcesCacheService class you’ll find that it’s performing a loop on each country in order to retrieve its states.  This amounts to about 75+ calls to core, which individually would be quick, but when combined together they equal a bothersome slowdown.</p>
<p>One solution to this would be to override the resource cache with your own custom cache.  You could then limit the amount of calls to, say, the US and Canada (where states are commonly used).  However, this approach is problematic because you’d also have to override any controls that used the original resource cache as they are bound to the Navitaire version and not any custom version you provide.</p>
<p>For issues like this, I suggest that Navitaire make the resources cache an interface contract that can be overridden (most everything else now is interface-based in their 3.x framework anyway).  However, for this specific issue, it definitely wouldn’t hurt for Navitaire to write a custom database call that brought back all countries and states in one shot, thus saving the repeated (unnecessary) round trips through core to the New Skies database.</p>
<p><small>Special note: Thanks to Greg from Spirit for helping track this annoyance down!</small></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.coltcooper.com/2011/10/passengercontact-page-slowdown/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Overriding SkySales Controls</title>
		<link>http://blog.coltcooper.com/2011/06/overriding-skysales-controls/</link>
		<comments>http://blog.coltcooper.com/2011/06/overriding-skysales-controls/#comments</comments>
		<pubDate>Mon, 13 Jun 2011 07:02:58 +0000</pubDate>
		<dc:creator>Colt</dc:creator>
				<category><![CDATA[New Skies]]></category>
		<category><![CDATA[SkySales]]></category>

		<guid isPermaLink="false">http://blog.coltcooper.com/?p=86</guid>
		<description><![CDATA[There will come a time at some point in your SkySales development efforts when you'll need to change some bit of code to work differently than what Navitaire delivers with a fresh New Skies install.  Since Navitaire does not ship the source of SkySales code to their clients, it can be a bit tricky to leverage 95% of what they've done in a control and just add the bare minimum to make it meet your business needs.]]></description>
			<content:encoded><![CDATA[<p>There will come a time at some point in your SkySales development efforts when you&#8217;ll need to change some bit of code to work differently than what Navitaire delivers with a fresh New Skies install.  Since Navitaire does not ship the SkySales source code to their clients, it can be a bit tricky to leverage 95% of what they&#8217;ve done in a control just to make the last 5% conform to your business needs.</p>
<p>Seasoned developers have in their toolbox a <a href="http://reflector.red-gate.com">handy tool called Reflector</a> that will allow them to examine and even debug into the assemblies that Navitaire ships.  For enhancing and working with SkySales controls, this is an absolute must.</p>
<blockquote><h4>Site Note</h4>
<p>Navitaire is aware that their customers routinely decompile the SkySales assemblies.  It&#8217;s not a big secret.  If they were concerned about this, they would obfuscate the code to make it very difficult to understand when viewed through a decompiler.  It makes you wonder why they don&#8217;t ship the plain code alongside the compiled code.</p></blockquote>
<p>Being able to snoop through SkySales code is invaluable.  However, there is a danger to having this decompiled code available to the novice developer.</p>
<p>I&#8217;ve seen many times where decompiled SkySales control code was taken wholesale from the decompiler and pasted into a new custom control (variables named &#8220;num3&#8243; are a dead giveaway).  Modifications are then implemented (usually without comments) to certain portions of the Navitaire code where needed.  Don&#8217;t get me wrong, this can be a time saver when a project deadline is looming.  However, what you gain in short-term development speed, you loose in long term maintenance.  Are future developers going to be able to understand all of that code you just dropped into the project?  Will they know exactly where the vendor&#8217;s code stops and your custom code stops?  And the biggest question of all:  How will that code be updated when your airline takes an upgrade?</p>
<p>If you&#8217;re doing at least a moderate level of customization to your SkySales solution, you&#8217;re going to have a situation where you must use some or all of a decompiled control.  But how can you do this with minimal maintenance issues?  Below is the best method I&#8217;ve found to have the best of both worlds.</p>
<p>In your project, create a special folder to place any classes you must decompile fully.  Examine the class and determine the best entry point for your modifications.  Once you fully understand what the Navitaire base class is doing, insert events at the points in the base methods where you need to insert your customizations.  Your modifications should be well commented and should be a single event line.  You will then create a new class that will contain your business logic and subscribe to the custom event you created in the parent control.  The following is an example of a custom event:</p>
<p><code>DisplayingBoardingPass(this, new DisplayingBoardingPassEventArgs(pass, segment, passenger));<br />
</code></p>
<p>This was done for a client in the notoriously monolithic OnActivatedPreRender method for the BoardingPassDisplay control.  In this case, the client just wanted to add some XML data inside the boarding pass node being constructed.  However, because the boarding pass node doesn&#8217;t use any events or virtual methods when creating it&#8217;s XML structure, the control had to be decompiled in order to allow an insertion at just the right point.  Events will also allow you to pass objects to child classes so you can implement some intended <a href="http://en.wikipedia.org/wiki/Side_effect_%28computer_science%29">side effects</a> on those base objects.</p>
<p>Now, when it comes time to take the next Navitaire upgrade, the client can reflect on the new BoardingPassDisplay control and run a compare to easily see what has been changed.  Since our modifications consisted of one line here or there, the original code is intact and devoid of the various business logic that creeps into custom controls over time.</p>
<p>While the method described above will work and has been tested as a viable way to reduce maintenance costs through upgrades, we should ask: &#8220;Why is this necessary&#8221;?  The SkySales team must believe that the methods they have marked as virtual are all any one will need to successfully modify the base control functionality.  This is not the case.  The SkySales controls were not written from an implementers point of view.  I suggest that Navitaire should run through their SkySales controls and sprinkle them with events.  As implementers, we need events in the middle of large loops, before and after objects are committed, and in methods that are not easily overridden because of their reliance on private methods.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.coltcooper.com/2011/06/overriding-skysales-controls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enable &#8216;Enter&#8217; Key in SkySales Forms</title>
		<link>http://blog.coltcooper.com/2010/06/enable-enter-key-in-skysales-forms/</link>
		<comments>http://blog.coltcooper.com/2010/06/enable-enter-key-in-skysales-forms/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 19:38:21 +0000</pubDate>
		<dc:creator>Colt</dc:creator>
				<category><![CDATA[New Skies]]></category>
		<category><![CDATA[SkySales]]></category>

		<guid isPermaLink="false">http://blog.coltcooper.com/?p=63</guid>
		<description><![CDATA[If you&#8217;ve developed in SkySales or even .NET Web Forms you probably have noticed the lack of support for traditional &#8216;enter&#8217; key behavior on forms. This is due to the .NET methodology of hijacking the return key behavior with some javascript events. Since SkySales is based on .NET Web Forms, the problem rears it&#8217;s ugly [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve developed in SkySales or even .NET Web Forms you probably have noticed the lack of support for traditional &#8216;enter&#8217; key behavior on forms.  This is due to the .NET methodology of hijacking the return key behavior with some javascript events.  Since SkySales is based on .NET Web Forms, the problem rears it&#8217;s ugly head there as well.  And, if it does end up working but you have multiple form inputs and buttons on the page, it may not trigger the right submit button.</p>
<p>Out of the box, SkySales loads up the submit form button with a few actions such as client-side validation in the form of javascript functions like: &#8220;validate(this)&#8221;.  That particular validate method determines which form elements are child members of the control submitting the form and then runs the appropriate validation for each element on the form.  We&#8217;ll use a similar method for tackling the enter key problem.</p>
<p>For this fix, I&#8217;m assuming the use of the jQuery framework (which has officially been shipping with SkySales since the 2.x version).  The following **code is how we&#8217;ll capture the enter key from the XSLT file:</p>
<p><code>&lt;script langugage="javascript"&gt;<br />
$(function()<br />
{<br />
$("input[@id^='&lt;xsl:value-of  select="/*/@clientID"/&gt;']").keydown( function(event) { checkEnter(event, '&lt;xsl:value-of select="//CONTROLS/LINKBUTTONSUBMIT/*/@id"/&gt;'); });<br />
});<br />
&lt;/script&gt;</code></p>
<p>Notice in the code above that we are just checking for inputs that start with the clientID of the SkySales control we are using.  If your control is inside a control group, this code should be in the control group XSLT so it covers all of the elements inside the group.  If you had some select boxes on your form that you wanted to add enter key support on, you would simply expand the jQuery selector to **include select elements:</p>
<p><code><br />
$("<strong>select[@id^='&lt;xsl:value-of  select="/*/@clientID"/&gt;'],</strong> [input[@id^='&lt;xsl:value-of  select="/*/@clientID"/&gt;']")... etc<br />
</code></p>
<p>The checkEnter function will basically create a new function for client script residing in the onClick method for the button id that is passed in, and then fire the href event.  This function should reside in a common javascript file that gets included on every page.  The source can be downloaded <a title="checkEnter" href="http://coltcooper.com/downloads/checkEnter.js" target="_blank">here</a>.</p>
<p>I believe this small bit of code can help your SkySales site out by helping it behave the way people expect pages to behave on the web.</p>
<h5>** Special note **:  The code samples work with earlier versions of jQuery.  The current version doesn&#8217;t require the @ symbol in front of attribute identifiers so modify your code appropriately.</h5>
]]></content:encoded>
			<wfw:commentRss>http://blog.coltcooper.com/2010/06/enable-enter-key-in-skysales-forms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Booking Modified By Another User&#8221; Error</title>
		<link>http://blog.coltcooper.com/2009/11/booking-modified-by-another-user-error/</link>
		<comments>http://blog.coltcooper.com/2009/11/booking-modified-by-another-user-error/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 14:06:29 +0000</pubDate>
		<dc:creator>Colt</dc:creator>
				<category><![CDATA[New Skies]]></category>
		<category><![CDATA[SkySales]]></category>

		<guid isPermaLink="false">http://blog.coltcooper.com/?p=19</guid>
		<description><![CDATA[On a recent implementation of NewSkies implementation of SkySales, I would occasionally run into a strange error from the NewSkies application server: “Booking Modified By Another User”.  It seemed to occur only after a booking was initially created, then was modified again...]]></description>
			<content:encoded><![CDATA[<p>On a recent implementation of SkySales, I would occasionally run into a strange error from the NewSkies application server: “Booking Modified By Another User”.  It seemed to occur only after a booking was initially created, then was modified again.  On the second attempt at committing the booking, core (the app server) would occasionally throw this error.</p>
<p>This error is triggered when the application server detects that the last updated date/time of the booking in the database doesn’t match what it has in memory.  While this is a valid sanity check to prevent the application server blindly overwriting a booking in the database, we had no idea who or what was modifying the booking in between our commits.</p>
<p>After some digging, we discovered that the last user updating the booking was a process account (ProcessMaster).  This can be seen when whatever action it took left a trace in the booking history (viewed in SkySpeed).  </p>
<p>As Navitaire doesn’t seem to have a solution for the problem, the best recommendation was to re-retrieve the booking when this error was found and try the commit again.  This would refresh the application server with the most recent copy of the booking and reset things on the web server as well.</p>
<p>This unfortunately has a side effect of killing any changes the user has just requested to their booking.  It’s less painful if they have to repeat just one screen of changes, but it’s worse if they just finished a change process involving a number of steps.</p>
<p>If you absolutely had to be graceful with the customer – you could write a lot of code to queue up and retry those changes made.  Unfortunately, the most common (and cheapest) approach is to throw up your hands with an error and blindly ask the customer to repeat to you what they just did.</p>
<p>The bottom line is this:  Don’t assume that once a booking is created, you’re the only one working with it.  What I’ve described above is a corner case, but a well-known one at that.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.coltcooper.com/2009/11/booking-modified-by-another-user-error/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Securing SkySales With Rules</title>
		<link>http://blog.coltcooper.com/2008/12/securing-skysales-with-rules/</link>
		<comments>http://blog.coltcooper.com/2008/12/securing-skysales-with-rules/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 05:13:36 +0000</pubDate>
		<dc:creator>Colt</dc:creator>
				<category><![CDATA[SkySales]]></category>

		<guid isPermaLink="false">http://blog.coltcooper.com/?p=3</guid>
		<description><![CDATA[An unsecured SkySales instance can allow customers to do unexpected things with a booking.  This article serves as a primer for securing your SkySales install with rules.]]></description>
			<content:encoded><![CDATA[<p>Version 1.3 of New Skies brought about a radical change in how SkySales handles page security.  Instead of restricting access based on the previous page, conditions can now checked before the page and it’s controls are processed and rendered. In transitioning to SkySales 1.3 and above, I’ve found that page security is often overlooked.  In the<br />
cases where security is addressed, I’ve seen many attempts (even a custom attempt to whitelist pages the way the old versions of SkySales worked).  I hope to address rules here and provide airlines the ability to secure their pages correctly.</p>
<h2>Why a World With Rules?</h2>
<p>An unsecured SkySales instance can allow customers to do unexpected things with a booking.  Here’s a real-world scenario that would make marketing teams roll over [in their sleep]:</p>
<p>3rd Party Travel Reseller (Screen Scraper) uses automated tools to book the lowest fares for highly desired markets as soon as the fares are made available.  Reseller then sells the fares on their site, Ebay, Craigslist, or some other channel for a nice markup. Once the fare is purchased by the actual customer, the reseller retrieves the booking, changes the name through the booking process and commits it through the wait page. (This scenario is assuming that name change fees are not set)</p>
<p>Strange things can happen when a customer retrieves a booking then types in a booking flow page name.  Most of the controls used in SkySales don’t care if the booking they are operating on is brand new or if it is a previously committed one.  This is not a fault of<br />
the product.  The SkySales developers were counting on the proper configuration of rules in the various flows a carrier sets up.  If Quality Assurance isn’t on top of their game, it’s entirely possible to overlook the implementation of rules during a conversion to New Skies.</p>
<h2>Rule Philosophy</h2>
<p>The most effective rule philosophy is to keep you rules very simple and descriptive. This allows developers the ability to understand the rule by just reading the name.  For instance, if we had a rule that required a booking to have at least one new flight, our rule should<br />
only be checking for a single, non-committed flight and should be called something like NonCommittedFlightRule.cs.  Don’t combine logic in rules, remember we can stack them in order of precedence!</p>
<p>Proper rule configuration allows us to not be concerned about what page the users are linking to.  If a user had, for instance, bookmarked their confirmation page &#8211; we could redirect them to the home page which would have a widget for the user to retrieve their booking.  Without a rule on the confirmation page, we may get a<br />
strange-looking page or a nasty error from the controls attempting to<br />
retrieve a booking in session that was empty.  If we decided to<br />
get really customer-centric and bookmark friendly, we could store the<br />
state we were attempting to access when the committed booking rule<br />
failed, take the visitor to a custom page that collects enough<br />
information for us to retrieve the booking, then take them back to the<br />
page they were attempting to link to (where it makes sense).</p>
<h2>Rule Bouncing</h2>
<p>While rules should not be overlooked, they can cause “bouncing” that may be hard to trace.  If you have a tiered set of rules that bounces the person back in a process flow until it reaches an acceptable state, it’s difficult (without some tracing or debug help) to know how many states the user has passed through or the rules that have failed.  Here’s an example of a bouncing flow:</p>
<p>User types in:  [airlinesite.com]/Payment.aspx in a new browser</p>
<p>The site attempts to load Payment.aspx, but it has a rule that there must be Flights on the booking.  The flights rule redirects to the Select.aspx page where the user may select a flight.</p>
<p>However, on entering the flight select page, a rule is run that looks for a flight search request in the session and it redirects to the homepage.</p>
<p>The effect is that we type in Payment.aspx and the homepage loads (with payment.aspx still sitting in the address bar).  It can be helpful to write in some rudimentary logging so that web testers can check that the rules are working.</p>
<h2>Custom Base Rule</h2>
<p>The best way I’ve found to gain control over the rules framework is to write your own abstract base rule inherited directly from the Navitaire BaseRule. What the out-of-the-box Navitaire SkySales rules fail to do is to supply a good base rule that gives you ready<br />
access to all of the objects you’ll need when writing your own rules, namely:  UserSession, Controllers, runtime attributes, ResourceCache, etc.  Child classes should not have to override<br />
methods just to store critical objects like the ObjectManager themselves.</p>
<p>Below is a link to a base rule I’ve created and a simple rule that checks the booking state to demonstrate how simple custom rules are that use that base class:</p>
<p><a href="http://www.coltcooper.com/etc/WebBaseRule.cs">WebBaseRule.cs File</a></p>
<p><a href="http://www.coltcooper.com/etc/NonComittedBookingRule.cs">NonCommittedBookingRule.cs</a></p>
<p>I hope this has been a decent introduction to the concept of rules.  If you’d like some help setting up rules on your site or have comments on the rules I’ve provided above, don’t hesitate to <a rel="external" href="http://www.coltcooper.com/contact.php">contact me</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.coltcooper.com/2008/12/securing-skysales-with-rules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

