Blake Caraway

Is Your SOA Strategy Justified? Nov 24

Still trying to determine what this SOA thing is all about? Or maybe you do know quite a bit, but are still struggling with how it can help your company or your client get to the next level (or merely survive)? Unfortunately, too many projects are being carried out in the name of SOA yet only deliver costly technical solutions that do not address the identified problems. Further complicating matters is the fact that the identified problems these SOA projects are supposed to solve have little to no business case justification.

This is the focus of an excellent article by Piet Jan Baarda, entitled 'Your SOA needs a business case'.

The promises of SOA can never be fully realized without a good amount of analysis on a company's goals, in addition to being open to changing how a business segment is structured (or even the whole organization, in a more extreme case). Notice technology decisions are not being discussed/determined here from the outset. If SOA efforts begin and end within an IT department...it's not SOA. You can bet a company in this situation is, at the very least, incurring avoidable expenses. At it's worst, lucrative business opportunities continue to pass by while a company fails to make the most of any competitive advantages.

So how do we ensure we are developing a solid SOA strategy? As Piet Jan teaches, it's all about the business case. Depending on a particular company and the market segment(s) it's located in (in addition to many other factors), technology may or may not play an important part in deciding upon an SOA strategy. Some companies' strategies will rely more on technology leadership and innovation to create and enhance their competitive advantages, some will not. These realities should help decide the appropriate level of technology investment. Often the decision NOT to invest in SOA is a valid one b/c the cost cannot be justified. However, it's important to always apply SOA thinking as a company faces new situations and opportunities.

I highly recommend Piet Jan's article and consider it a must read for anyone involved in planning and implementing technical solutions for a company where SOA is being considered.

Here are a few quotes from the article definitely worth remembering:

  • "SOA has benefits, by definition, only where agility is required."
  • "Many organizations are not able to create the enterprise architecture and governance competence that  is needed to achieve the benefits of the application of these [SOA] concepts.”
  • "Agility will only improve when a coherent set of business services is created that can be used in many orchestrations without a need to perform cumbersome transformations to translate information concepts (especially semantics!) from one silo to those of another."


Also, for what it’s worth, here are just a few of the blogs that discuss SOA and business agility that I always make a point to read:
    Udi Dahan - http://www.udidahan.com/?blog=true
    Bill Poole - http://bill-poole.blogspot.com/
    Jack van Hoof - http://soa-eda.blogspot.com/
    ZapThink - http://www.zapthink.com/
    Todd Biske - http://www.biske.com/blog
    Smart Enough Systems - http://smartenoughsystems.com/wp

Visual Studio and PowerShell Trick Aug 07

Every time I get to a point where I need to commit the code I've been working on (a.k.a 'The Check In Dance'), I typically ALT+Tab over to the explorer window where my source working directory is located. From here I execute our build.bat file that runs the developer build process that compiles the code and runs all the unit and integration tests locally before committing my changes.

I'd rather stay in Visual Studio to do this so I Googled for a solution and of course found that some smart person has already done this. I found Laurent Kempe's blog and he uses PowerShell to execute a batch file from within Visual Studio.

Simply install PowerShell (if you have not done so already). In Visual Studio's solution explorer, find your batch file, right-click it and choose 'Open With...'. Point it to the PowerShell.exe (located after installation by default in %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe). Make it the default app to open that file type with, and it's done. Every time you double click it, PowerShell will execute your .bat file.

I try to keep my hands off the mouse and on the keyboard (home row preferably for shortcuts and such) while coding. This includes doing The Check In Dance. With this tip, I'm able to use the Ctrl+Shift+N Resharper 'Find File' shortcut, punch in build.bat, hit enter, and the build runs. Nice.

You may already have a different/more clever way of doing something similar. If so, leave a comment or better yet, blog it. Thanks to Laurent's blog post, I was able to find a solution in a couple minutes. Thanks Laurent for sharing this tip!

 

openWith dialog

 

 

find buildWindow

Headspring Systems Jul 08

I recently took the opportunity to join Headspring Systems, the premier Agile software consulting practice here in Austin, TX. I'm very excited about getting to work with an incredibly talented Headspring team and look forward to helping the company continue it's fast-paced growth!

Headspring Systems
www.headspringsystems.com

WCF Client Proxy and IDisposable Issues Jul 06

This issue has been known since late last year, but there doesn't seem to be too much noise about it in the blogosphere. No doubt as we continue to create and consume more and more WCF services, troubleshooting configuration issues has become a common occurrence (can I get an amen?). Keep this in mind the next time you add a new service reference to your .Net projects.

Here's the scoop: when using a WCF proxy client object, simply having the typical Dispose() method fire off does not ensure the object is cleaned up. You see, Dispose() calls the Close() method, which actually makes a call across the wire to tell the remote service to do session clean-up before shutting down. We all know and respect the fallacies of distributed computing, right? Successfully disposing our client proxy involves a trip across the network (our particular situation here deals mainly with the two fallacies involving reliable networks and the whole latency thing). When the method call for session clean up to the server doesn't go as expected, Close() fires an exception and the client proxy is not disposed. When this happens, the Abort() method actually needs to be called in order to correctly clean up the object's state.

Dispose No Workie

Correctly disposing the proxy object won't work if everything doesn't go well with the remote call during Close().


I found a couple good blog posts that discuss the issue in more detail with helpful solutions. Check them out:

http://www.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx

http://geekswithblogs.net/DavidBarrett/archive/2007/11/22/117058.aspx

 

Hopefully this knowledge will help prevent needless service debugging and troubleshooting as we try to quickly develop working software. So be mindful of the fact that we often need to pay special attention to how we use WCF client proxy objects.

Change Is Good...You Go First May 28

I've picked up more experience recently in dealing with the issues that face a company as it deals with the pains of growth. It's a phase of business that all successful companies have to go through at some point. Moving from "survival focused startup" to "growth oriented performer" exerts some interesting forces on a company.

In a company's early years, the "startup mentality" is in full effect. Some qualities of this mentality are as follows:

  • People's time and effort are cheap...therefore Heroes are required
  • Little to no focus on process, much less process improvement
  • Most/all time is spent "Keeping the lights on"

When a company begins enjoying some initial sustained success, many of these qualities are validated and even reinforced. Indeed some or all of these qualities are often described as reasons for initial success or even perceived as part of a company's competitive advantage.

Heroes Work Here

As customers and their needs increase, the approaches in dealing with these demands begin to strain the current organizational capabilities.  Unless changes are made, working harder is the primary if not only method of maintaining the same level of success. Working harder takes on different forms. This is where we typically witness things like swivel chair integration, as well as entire organizations that accept (indeed relish) manual and tedious processes. These processes involve the usage of half-baked and misguided technical solutions, where business people, IT nerds, and maybe a warehouse worker or two constantly engage in unrepeatable, heroic efforts to help keep normal day to day business going.

Grow Up and Work Smarter (Duh)

So how can a company mature? I think one of the most important qualities about a company's culture is it's commitment to continuous improvement. At every level there should be an almost hostile aversion to inefficiency and waste. If you have worked on Agile teams before, you know many of the XP practices promote the concept of helping to eliminate waste through consistent feedback on progress of work being done. Through constant team collaboration Agile teams have a much greater ability to frequently assess their performance to ensure the optimal amount of business value is being realized as early as possible, taking every opportunity to eliminate things that don't deliver value.

lundbergLundberg says: Ask yourself...Is This Good For The Company?

Lundberg says: Ask yourself...Is This Good For The Company?

Clearly this drive for excellence isn't only reserved for technology teams. EVERY person in each organization within a company should be encouraged and inspired to continuously improve how they provide value to the company. It sounds silly, but it's apparent we have to continue to remind ourselves to work smarter, not harder. When we begin to value our time and effort, the repetitive and tedious tasks become more apparent and should be addressed by either instilling a more defined process around these tasks (to help reduce risk) or simply improve the work being done (or even eliminate altogether) by using a combination of process and technology to achieve efficiency through automation.

Yipe!

This part might scare some employees because they may perceive the effort and toil of carrying out business functions by working harder (rather than smarter) as their main value add to the company. This is where good management really earns the country club membership fees because this is an opportunity to promote and inspire change within his or her organization by helping direct reports to break free of the usual toil and instead visualize and transform a particular business function to better align with the company's long term vision and goals (presuming they have a long term vision and goals).

Company Maturity Is a Difficult Process

Difficult changes facing a growing company is one of the main reasons for turnover in an organization at this stage. Some people yearn to work in "startup mode". The prospect of high risk, high reward with a tactical approach brings out the best in some. Others might want a more controlled, repeatable work environment where all efforts are measured and the perceived speed of the organization might be more stable. Promoting and inspiring this change isn't easy. Human nature is involved. If the majority of a work force is too set in its heroic ways and unable or unwilling to think differently and adapt, a change in personnel might be necessary in order to mature effectively. By the same token, if real change is being blocked by management at any level, a change in leadership may be called for.

farley

 

Bring It

Regardless of how high or low on the organization chart you might be, make every effort to foster an environment of continuous improvement. Be mindful of wasteful behaviors and/or processes. Be a leader, inspire positive change, and see what happens.

Twitter Apr 19

I wanted to keep up with the altnet conference in Seattle this weekend so I took the time to create my twitter account - http://twitter.com/bcaraway -as I've been tracking the altdotnet tweets. This is a great way to communicate. Very Web 2.0.

Mike Cohn Coming To Austin Apr 18

Mike Cohn, founder of Mountain Goat Software and long-time vocal proponent of Scrum is coming to Austin next month as part of the Agile Austin Distinguished Speaker Series. Mike is the author of Agile Estimating and Planning and User Stories Applied for Agile Software Development, among other development/programming books. He's served as technology executive and helped with the adoption of agile processes at various companies.

If you are working on agile teams right now or are just interested in learning about agile methods and agile company adoption and are close enough to Austin on May 8th, then be sure to attend this event for some very highly valuable information. The title of Mike's talk is 'Succeeding With Agile: A Guide to Transition' and will cover such topics as why agile transitions fail as well as discussing several specific ways of getting started with agile and the advantages of each.

Date: May 8, 2008

Time: 6:00 - 8:00 PM

Location: Austin Community College, Highland Business Center Campus, Room 201,0, 5930 Middle Fiskville Rd.

 

See all of the event information at http://www.agileaustin.org.

 

 

See you there!

Company Morale Improves As a Result of Break-In Apr 18

There was a break-in at our company the other night. We had some nice products on visible display through the front door in our office's small reception area that evidently made for an easy target of a smash and grab operation. The entire caper was recorded on our internal security video system. The perpetrators (one inside taking things to the door, the other just outside receiving) broke the glass out of the front door and proceeded to carried out the items on display.


At one point during the ~1 minute heist, the thief looked into the conference room just off the reception area near the front door and noticed an LCD projector on the table. He quickly ran into the conference room, grabbed the projector, and dragged it from the building by its cabling.

break-in 

The buzz in the office the next morning was mainly around the fact that our really crappy LCD projector was now gone and that we finally had the necessary justification to purchase a new projector actually good at, you know, projecting video images and displaying visual information.

Thanks, degenerate criminals!

Wow, We ARE Agile...or Choose Your Partner Wisely Apr 10

New Partner
Our company is growing and the processes that support our e-commerce efforts must be ready to grow along with the business. Looking to ensure our abilities to effectively manage this growth, we recently decided to form a strategic partnership with another outfit that will develop, operate, and maintain our various e-commerce sites, as well as replace our internal sales and customer service applications. You could say our company's strength is in quickly executing our e-commerce, marketing, and merchandising initiatives. In other words, we are
SaaS'ing our core competencies and processes.


Background
All of our company's technology is totally home grown (except for the usage of Microsoft Commerce Server which our sites were built upon). Up to this point, our internal IT staff has developed, operated, and maintained all of our e-commerce sites. We've also created from scratch the entire suite of applications and tools that serve as the back end operations to our business.


Kick Off
Our partner arrived at our offices last week to officially "kick off" the relationship by discussing the first project we will work together on. The project manager began things by presenting their engagement model and how they run projects with each of their clients. The slide in his deck that helped describe their project process was a very nice looking diagram that appeared to be split up into various phases that included sequential steps, all flowing in a downhill manner, marching toward a completion date ~3 months into the future.

Wait a minute....
    hold on here....is that...
        yes...I think it is...
            that appears to be a....
                Waterfall!!!!!   NOOOOOO!!!!!!

Their plan included a 3 month project schedule with a ~1 month "iteration" somewhere in the middle. This followed an exhaustive requirements and UI wireframe gathering period where we would sign off on the deliverables. After we waive our ability to change our mind sign off on the requirements, our partner would then go away (this is the iterative part, I guess?) and do the work. At the end of this period, the web site (that's the main deliverable that can be demonstrated) would be unveiled to us and at that point the initial requirements would be open for modification and all bugs will be worked on and fixed until the day the first site launches.

Death March!


While this was being explained to us, our team (which included all the main business owners within my company as well as a few of us technical guys) immediately began asking about feedback, backlogs, demonstration of working software during the project, communication channels, etc. The responses to our inquiries** served to paint a very clear picture regarding just how Agile our group has been in delivering business value over the past year....and how non-Agile our partner seems to be. At that point, I think we all recognized how good we had it while working as an internal team, co-located and committed to a common purpose for a company we all worked for.

We ARE Agile!!! It's All About TEAM
We ARE Agile
Our attempts at delivering working software internally over the past year have followed the Agile/Scrum process. We very much believe in and implement the tenants of the
Agile Manifesto. We communicate. We adapt. We don't lock in our stakeholders to agreements, statements, or requests made weeks(months!) in the past. Key implementers don't go away and create solutions for weeks at a time with no customer interaction. We are open and available, not hidden away.We work at a predictable pace.Once we started holding daily stand-ups and displaying our sprint burndowns, our stakeholders became addicted to the constant feedback they receive on the progress of work being completed and business value provided. When we voiced the concerns with our new partner, the response we received was "We don't work that way, but we'll see what we can do...".

 Partnership? -- Lessons Learned
Right from the beginning, the relationship can be seen as adversarial, due mainly to a stark contrast in expected communication patterns and a drastic change in how business solutions are collaborated on and delivered for our company. When you ask someone to sign off on something, that's an agreement and a waiver of sorts. That's definitely not a partnership from the outset. It's a transaction.

Please note that I'm not claiming ultimate demise on this new partnership. Clearly, this doesn't mean everything won't work out in the end as very capable professionals at both companies will no doubt do whatever it takes to make this thing succeed. However, it's a tough thing for a company like ours to become pretty good at working in an Agile manner and then turn over implementation to another team from another company in another state that doesn't value the same things as we do.

It's clear that any business today will need to have a solid strategy for how to effectively leverage technology to achieve it's vision. When evaluating these strategic options that include partnering with another company or consulting firm, it's VERY important to keep in mind your company/team culture to ensure that the team concept is not lost in the shuffle. Culture in the situation described in this post means 'the processes, methods, and communication patterns that allow a team to get things done'. Mismatches in culture between companies and teams brings more obstacles to an already difficult task.

Feedback
I'd like to know...how do you think strategic technology partnerships should operate today? What are your success/failure stories? Is it too much to expect third party vendors to adapt to their clients' way of working/culture? What are reasonable expectations here?

 

** Both the project manager and the technical architect from our partner expressed their company's inability to easily create a tenant's (that's us) environment in isolation so 1) at any moment we can easily see the progress on the deliverables and 2) it can be tested, among the other benefits of having the capability to automate environment/application deployments.

How Firefox Handles Empty SRC tags Aug 24

I ran into a crazy issue while working on my ASP.Net 2.0 application in Firefox this week and thought I'd share...

When a certain ASPX page completed rendering and emitted it's final markup to the browser, I noticed the status bar read 'Done' for an instant, but then immediately changed to 'Waiting for localhost...' again. It definitely seemed as if the page was being requested twice. I immediately looked at FireBug to see what was loading, and indeed the same page showed up twice in the 'Net' listing. To see it in action, I ran the site in DEBUG mode and put a break on Page_Load. Sure enough, the page WAS being requested twice. IE(7) worked just fine. It was not behaving in this odd manner, so I set out to figure out what was causing this strange behavior in Firefox.

 

Two Browsers - Two Different Behaviors

After many Google searches, I finally found a few message board posts talking about pages being loaded twice. It seems that an empty src attribute (like in an <img> tag) will cause this undesirable behavior in Firefox. The browser's rendering engine sees an empty src attribute and tries to put the current page name (URI) in it's place.

So, when Firefox sees this...

<IMG id="fooImage" src="" />

...it substitutes the empty attribute value like this...

Firefox
<IMG id="fooImage" src="http://localhost/foo/bar.aspx" />

Inserting the current page within the src attribute will of course cause the browser to request the page once again. That's why I was seeing the 'waiting for localhost...' browser status message fire up again after the page had already visually rendered. IE (7) handles the empty src attribute by adding '/null' rather than the actual page name, like this...

IE7
<IMG id="fooImage" src="http://localhost/foo/null" />

 

AJAX Extender Control To Blame

The reason this strange behavior started to occur was because I recently began using the ASP.Net AJAX DropDown extender on the problematic ASPX page in question. The DropDown extender has several properties that you can configure to fit your display needs. One of these properties is the 'DropArrowImageUrl'. Since I didn't have the need to override this image, I didn't assign a value to this property. When ASP.Net renders the image tag for this control, the src attribute is left empty because I didn't specify a particular image.

 

The Fix (Hack)

It was clear that some sort of valid image needed to be set on this control in order to prevent Firefox from requesting the page twice. So we plugged in a 1 pixel transparent image and the problem went away. I've provided a few links below to a good blog post and a couple forum threads that discuss the issue and helped point me to a solution. In the blog post there's a comment about the URI specification and how Firefox seems to adhere to the specification - which doesn't really make sense for <img> tags.

Either way, it's silly that I had to go through this in order to prevent a (potentially expensive - depending on the page in question) needless page request. The AJAX extender controls have some nice behaviors that can really help out your UI development. But since these controls are fairly new, we should be mindful of potential side effects our sites may experience due to the fact that these controls probably have not been as rigorously tested as the standard ASP.Net controls have.

 

Links

http://brian.pontarelli.com/2006/05/02/is-your-browser-requesting-a-page-twice/

http://forums.asp.net/t/978268.aspx?PageIndex=2

http://forums.mozillazine.org/viewtopic.php?p=3022038&

Decouple Your Code For Testability Aug 12

I've received a handful of comments/questions surrounding part of the code sample from my previous post.

The comments I received have to do with the few lines of code in the Authentication WebService that included a custom interface and a call to a third party tool. Here's the code in question:

public class Authentication : WebService
{
private IWebContext _webContext = ObjectFactory.GetInstance<IWebContext>();

[WebMethod]
public bool IsLoggedIn()
{
return this._webContext.IsUserAuthenticated;
}
}

 

Create An Abstraction

IWebContext is an interface I created for use within my web site that abstracts calls to lower level ASP.Net stuff like QueryString, Session, and Identity thru the HTTPContext object. Often I want to have a testable object in an ASP.Net web project that will depend on something at the ASP.Net lower level. The way to put a seam in my code that decouples the object I want to test from the ASP.Net stuff is to abstract it away...into something like IWebContext. Here's the IWebContext interface definition:

public interface IWebContext
{
bool IsUserAuthenticated { get; }
void Clear();
void Save(string key, object value);
object Get(string key);
string GetQuerystringValue(string key);
void Set(string s, object value);
}
 

Dependency Inversion / Inversion of Control

Regarding the ObjectFactory.GetInstance<IWebContext>(); line of code -- to help with decoupling, I use the Dependency Inversion Principle (DIP). Another name for DIP is Inversion of Control (IoC). The DIP has been proposed by Robert C. Martin. It states that:

High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.

In short, strive to make your classes depend upon abstractions, not concretions. When you see the keyword 'new' - that's a tight coupling to a specific concrete type. If you cannot easily isolate an object from it's dependencies, and if this makes it more difficult to test, then that's a tight coupling that needs to be addressed. You need to invert the dependencies.

 

The Flavors of DIP - Inverting with StructureMap

There are two main flavors of Dependency Inversion - Dependency Injection and Service Location. Beyond that, Dependency Injection has two main forms - Constructor Injection and Setter Injection. Constructor Injection is when an object is instantiated with a dependency. Setter Injection is when a dependency is provided through some sort of setting method/property.

The other main form of Dependency Injection is Service Location. Using a method like StructureMap's ObjectFactory.GetInstance() is another way to locate a service/dependency. In the code sample, the ObjectFactory object lives in a third party tool called StructureMap ( http://structuremap.sourceforge.net ). We ask StructureMap.ObjectFactory to return an instance of a certain type (i.e. IWebContext). This effectively inverts the control of resolving dependencies from the object needing to use the dependency to a third party, adhering to the DIP, and promoting looser object coupling.

If you are interested in learning more about the open source project StructureMap, visit the project page on SourceForge at http://structuremap.sourceforge.net/. I won't try and detail all of the implementation details of StructureMap, but here's a quick rundown of the basic usage.

StructureMap allows us to decorate abstractions with a [PluginFamily] attribute, as well as a [Pluggable] attribute on the types that implement the abstraction. When a call is made to ObjectFactory.GetInstance<IWebContext>(), StructureMap finds the classes that implement the type being requested and resolves, instantiates, and returns the correct concrete instance. Let's look at an example:

Interface: This is the IAccountRepository interface, decorated with the PluginFamily attribute and key name of 'Default'.

   1:  [PluginFamily("Default")]
   2:  public interface IAccountRepository
   3:  {
   4:      BillToAccount[] GetBillingAccountsForUser(User user);
   5:      ShipToAccount GetShipToAccount(AccountIdentifier accountIdentifier);
   6:      BillToAccount GetBillToAccount(AccountIdentifier accountIdentifier);
   7:  }

 

Default Implementation: Here we have an implementation of the IAccountRepository interface decorated with the Pluggable attribute and a key name of 'Default'.

   1:  [Pluggable("Default")]
   2:  public class AccountRepository : AccountRepositoryBase
   3:  {
   4:      ...
   5:  }

 

Cached Implementation: Here we have another implementation of the IAccountRepository interface decorated with the Pluggable attribute and a key name of 'Cached'.

   1:  [Pluggable("Cached")]
   2:  public class CachedAccountRepository : IAccountRepository
   3:  {
   4:      ...
   5:  }
 

When code needs to make use of a dependency like IAccountRepository, it can ask ObjectFactory for the default instance in this way:

_accountRepository = ObjectFactory.GetInstance<IAccountRepository>();

You can have StructureMap return specific implementations of IAccountRepository in a couple easy ways: you can set the PluginFamily attribute's key on the interface to match that of the desired "default" Pluggable instance like this:

   1:  [PluginFamily("Cached")]
   2:  public interface IAccountRepository
   3:  {
   4:      ...
   5:  }

 

...Or you may ask for a particular instance by name, like this:

_cachedAccountRepository = ObjectFactory.GetNamedInstance<IAccountRepository>("Cached");

 

Dynamic Behavior / Configuration

StructureMap also allows you to specify type configurations (and all sorts of other behaviors your system might need) in a config file. Some may prefer the config file method because it's a little more obvious (in a file, rather than living inside the code at various locations) as to what objects implement certain interfaces and what the default behavior is for a particular abstraction. Having these settings in a config file can also be helpful when you have an automated build that might require different system behavior (i.e. different implementation of various abstractions) based on the particular environment you are deploying to or maybe the state of an entire subsystem.

When deploying your system, behavior can be switched around by having your build tool like NAnt issue an 'XMLPoke' command to change key names inside the StructureMap.config file. Also, your application may need to behave differently based on some runtime situations like database or service availability (think 'offline mode'). This can easily be achieved by using a tool like StructureMap. Simply request a different implementation of a type using the 'ObjectFactory.GetNamedInstance' method as shown above and your system can gracefully adapt to any unexpected environmental situation.

 

Hopefully I've shown here the importance of abstracting away the factors that can make code more difficult to get under test, as well as a couple mechanics on how to approach the problem.

 

/bc

 

 

AJAX UpdatePanel Callback And Expired Forms Auth Ticket Jun 02

I have an UpdatePanel on a page within a web application that is using Forms Authentication. The UpdatePanel callback executes as a result of a custom JavaScript function that calls __doPostback.

If a user loads the page in question, but then allows the forms auth ticket to expire on the server due to inactivity (i.e. goes to lunch, goes home for the day, etc) and then interacts with the web page to fire off the UpdatePanel callback, the partial postback fails b/c the forms auth ticket is expired. The partial postback is short-circuited b/c the forms authentication has done its job and has issued the redirect to the login.aspx page. The UpdatePanel does not handle this. Instead, it tries to parse the page response which is directing the browser to redirect. AJAX (thru the ScriptManager/UpdatePanel) throws an error about not being able to parse the response.

Obviously, I would rather detect that the forms auth expired BEFORE attempting the __doPostback and have the user redirected to the login page to authenticate once again. What I needed was a way to see (from the browser) if a user had a valid forms auth cookie on the server or not.

I was able to find a solution by using the ASP.NET 2.0 AJAX Extensions that enable the seamless proxy generation for Web services for client-side JavaScript running from the browser.

Here's what I did:

Web Service

Create a web service and decorate it with the [ScriptService] attribute. This declares to ASP.NET that it should provide a JavaScript proxy class for use in calling the web service. After doing this, you can then call this web service directly (append /js to the end) in the browser to see the generated JavaScript proxy code necessary to invoke the web method on the server from client-side script.

    [ScriptService] 
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    public class Authentication : WebService 
    {
        private IWebContext _webContext = ObjectFactory.GetInstance<IWebContext>();
 
        [WebMethod]
        public bool IsLoggedIn()
        {
            return this._webContext.IsUserAuthenticated;
        }
    }
 

Service Reference

Next add a ServiceReference within the ScriptManager pointing to the web service you just created. Just by doing this you should be able to load the page that you AJAX-ified in your browser and see the generated JavaScript code in the page source that will enable the page to "phone home" to the web service. You will see that to call the web service method, the JavaScript function will take three arguments: a success method callback, a failure method callback, and a variable to hold something useful from the calling context (note: this context info is NOT passed across the wire, it's just "forwarded" on to the client side callback functions after the call completes).

    <asp:ScriptManager ID="Manager" runat="server" EnablePartialRendering="true" EnablePageMethods="true"> 
        <Services> 
            <asp:ServiceReference path="~/WebServices/Authentication.asmx" InlineScript="true" /> 
        </Services> 
    </asp:ScriptManager> 


JavaScript

After this, I just wrote the necessary JavaScript methods to call the proxy method that handles the call across the wire. In my code below, the loadSKUs() method is the entry point. This method makes the call across the wire, indicating the callback methods that should fire after completion. In the successfulAuthCallback() method, the result is inspected to determine if we are still logged in or not. All I'm looking for is a value of 'true' coming back from the call to my WebMethod. If this is the case, then we are still considered to be 'logged in' and I can allow the UpdatePanel to do it's magic. If not, then I tell the entire page to reload b/c it will then be a real/normal full page postback and the normal flow will occur where the forms auth will validate the session and redirect to the login URL or allow the page to proceed normally.

When we make the async call once the forms auth cookie has expired, the result that comes back is actually the HTML response telling the browser to redirect -- and is the markup that the UpdatePanel was choking on to begin with b/c it didn't know what to do with it -- hence the parser error.


         function loadSKUs(selectedProductAndHand) {
            WebServices.Authentication.IsLoggedIn(successfulAuthCallback, failedAuthCallback, selectedProductAndHand);
         }


 
         function setProductAndHandAndPostBack(selectedProductAndHand)
         {
            var hiddenField = $get(hiddenProductAndHandField);
 
            if (hiddenField) {
                if (hiddenField.value != selectedProductAndHand)
                {
                    hiddenField.value = selectedProductAndHand;
                    __doPostBack(hiddenProductAndHandField,'');
                }
            }
         }
 
 
         function successfulAuthCallback(isLoggedInResult, selectedProductAndHand)
         {
            if (isLoggedInResult == true)
            {
                setProductAndHandAndPostBack(selectedProductAndHand);
            }
            else 
            {
                // reload the entire page so the Forms Auth will see that the cookie has expired and redirect to login                 window.location.reload(true);
            }
         }
 
         function failedAuthCallback(result, selectedProductAndHand)
         {
            alert("Auth Callback failed: Reason -- " + result);
         }



One other thing I had to add in my web.config is add an AJAX HTTP Handler for .asmx files:

    <httpHandlers> 
      <add verb="GET,HEAD" path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, 
            Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
validate="false"/> 
      <remove verb="*" path="*.asmx"/> 
      <add verb="*" path="*.asmx"      type="System.Web.Script.Services.ScriptHandlerFactory"
validate="false"/>       
    </httpHandlers> 


So that's it. Now a user won't get an ugly parsing error from AJAX when an async call is made from the client after the forms auth cookie has expired on the server.


Problem Solved...Final Thought

I think this is too involved. I don't think we should be forced to write any custom code to handle the async calls to the server in order for forms auth to work properly within the AJAX space. Shouldn't the partial postback play nicely and handle this situation automatically somehow?

It's entirely possible I'm missing something here, though. This was a pain to overcome. I Googled extensively and posted a message on the ASP.Net AJAX forum looking for guidance on this issue, but didn't find any help. Please feel free to leave comments if you have solved this same problem -- especially if you have a different/easier solution.

 

          

Technorati :
Del.icio.us :

Does Your Code Work? Nov 01

two basic questions

It seems silly and awfully fundamental, but ask any professional software developer this question:
    Does your code work correctly?
When faced with answering this question, most developers will - and should - undoubtedly reply with a resounding "hell yes, my code works!". Now follow that up by asking another question:
    Can you prove the claim that your code works correctly in the next 10 minutes?
The answer to this second question speaks volumes not only about a developer's skillset, but also the team he or she works with, specifically that team's ability to provide solid business value in a timely and efficient manner.


proving code works: the debugger is not the answer

Debugger. The name says it all. It exists so one can fire it up to determine what's going on inside an application line by line b/c the behavior is in question - i.e. there's a bug and you need to determine where it is and what conditions are causing it (duh). If the sole method of determining that your code does (or likely does not) work as expected is by firing up a fully-functional system and actually using the debugger to put the application through its paces by hand, then you are putting your business at risk. It's that simple. The more applications your company has in play, the bigger the risk. Developing - not to mention trying to sustain - business applications in this way is lunacy.

You must be able to prove that a particular system component is working before the final product is assembled. In my experience, this is not how the majority of software is developed throughout the industry. Unfortunately, I've seen (and continue to see) too many developers blindly bang out a new feature and then fire up the debugger to step through the code in order to see it in action for the first time, trying to make sure the new feature plays nicely within the application. Why do we accept this risky behavior that continually jeopardizes our business' ability to generate revenue by constantly turning loose half-baked, untested software applications full of goo into the production environment? Why do we then complain about the amount of time spent supporting said goo-filled application, as if we had nothing to do with bringing about this sad state of affairs?

Using the debugger as the only code verification method carries with it some of the following bad habits:
  • FEAR & UNCERTAINTY -- A developer is afraid of the code he just wrote, thus the constant need of stepping into the code and watching it run all the time in a fully functional system.
  • WASTED TIME -- Requiring a complete, fully functional, end-to-end application environment on your dev box so you can employ the 'code and debug' method of feature development can take a lot of time to set up just right. Making sure you have a fully-loaded database on your system, live web services running somewhere, a message queuing infrastructure configured and running, and/or maybe even a security/authorization infrastructure in place can take a lot of time to configure and keep in working order -- all so a developer can fire up the application and step through the code to see if it works or (more likely) not.
  • GREATER CHANCE OF DEVELOPER ERROR - The manual act of using the debugger to step through code verifying application behavior requires the developer to think about, remember, and reproduce all valid (and invalid) usages of a system component, making sure it can handle all the different imaginable scenarios. Without some sort of test automation, it's almost a certainty the developer will forget to run through one or more scenarios when stepping through the code manually.
I've actually seen developers test entire order systems by hand over a number of days thinking about all the various scenarios that *could* occur, generating actual XML files, waiting for services to pick up said orders, process them into the system, then query data 10 different ways from Sunday to determine SUCCESS or FAILURE. Wow. So now the part of the business that enables revenue generation relies completely on a single developer's memory and uncommon ability to work in this insane manner. Thusly, this developer is the ONLY person on the team that knows about this system b/c there's way too much tribal knowledge to share with others.


testing, testing...is this thing on?

A very obvious fix to this problem is, of course, automated testing. By supporting our code with unit (written before the code - i.e. Test Driven), integration, and user-acceptance tests (and automating them so they run regularly), we help ourselves out immensely by assuring we have a working codebase every step of the way. This feedback is priceless! That sound you hear when some poor, unsuspecting user discovers/proves your application doesn't work is the sound of potential revenue running to your closest competitor and then telling everyone about the terrible experience they had with your company. The earlier on in the development cycle you receive feedback from your code that it's satisfying all business requirements and behaving as expected, the better.

For some time now, we've been aware of the virtues of a software QA organization within a business. But for too long developers have viewed QA organizations as corporate 'bus boys'; there to clean up the mess made during a project's design and development cycle. I recently had a colleague tell me he needed someone else to test the code he's written over the past month (this is days before the code is going to be put into production - doh!). No doubt having multiple parties exercise code is valuable, but if you don't know your code works as expected and you are waiting for others to prove it, then it's time to rethink your approach. This irresponsible behavior on the part of individuals and entire software development teams alike must be extinguished.

Despite the rising popularity in test-driven design and the increased discussion of topics like automated testing and continuous integration, it's clear that most developers have not taken enough interest in these concepts so as to improve themselves by adding these skillsets to their development abilities.


on the road to improvement

Okay, so what are the concepts that go into developing good code supported by a battery of tests? In the blog posts to come, I'll discuss concepts and practices that will (hopefully) help transform developers from fearful, time wasting, error-prone hackers into confident, focused, efficient developers.

Team Smells...Refactoring For A Better Tomorrow (Part Two) Mar 30

In a previous post I detailed some conditions existing on development teams that would suggest some changes need to be made in order to bring about better performance and ultimately higher quality software. In this post I will identify a couple more Team Smells and discuss how these issues can be remedied and why these conditions should be addressed in the first place.

Smell: Developers Spent Way Too Much In The Debugger (AKA Debugger Junkies)
A good feature-rich debugger like the one that comes with Microsoft Visual Studio is a nice tool. It allows you to easily get a view into the runtime state of your code. Unfortunately, developers can use this tool as the sole form of verification that the code they wrote is functioning properly. There should be one obvious, overriding reason to step through code using the debugger: tracking down a bug (duh!). A valid debugging scenario would entail watching a particular piece of code execute to determine why it’s behaving in an unexpected manner. A Debugger Junkie commonly works in this way:

  • 1. * fingers crossed *
  • 2. Hit F5 and see if the solution compiles
  • 3. Wait for the entire application to load up
  • 4. Navigate to the specific point in the application where the breakpoint or breakpoints are ready and waiting
  • 5. Interact with the application to try and re-create the unexpected behavior
  • 6. When Step 5 uncovers some indication as to where the problem might be, investigate the objects’ state in and around the perceived problem area to uncover the root cause
  • 7. Devise a plan for where the code should be modified to make the feature behave as expected
  • 8. Make code change and GoTo Step 1

  • Not only is this an unbelievably inefficient way to work, it can often make for a confusing and miserable work experience. No wonder developers on a team that exhibit these smells don’t want/are afraid to modify their code – they are sick of looking at it! Because of the dependency on the debugger to validate their efforts, by the time these junkies have completed a couple medium-sized application features, they are experiencing no small amount of frustration from the debugging monotony they have put themselves through. There _is_ a better way…

    Refactor: The key to ridding your team of this poor habit is to implement measures that help developers gain confidence in the code they are producing. Getting a development team to change the way they work and weaning them from the perceived security of the debugger can be a rough ride in the beginning. J. Peterman, of Seinfeld fame, said it best when demanding Elaine help her office ‘boyfriend’ Zach break his drug habit –

    PETERMAN: … Uh, P.S., the first twenty-four hours are the worst. Better bring a pancho.

    Yep, it can get messy. There will be no limit to the number of excuses offered up as to why this new approach won’t work. But Test Driven Development (TDD) is perfectly suited for ridding a development team of their debugger dependency. The very process of creating a unit test before writing any live code provides the developer with an accurate measurement of how the code should work. When code is written to make a unit test pass, there should be a large amount of confidence that the code is doing exactly what it needs to do. When all requirements for an application feature are satisfied by a battery of unit tests – THE FEATURE IS COMPLETE. Some other things have to change in order to for this approach to work. Separation of concerns among application layers and coding to interfaces across these layer boundaries must occur so that isolating code for unit testing can take place. Doing this effectively also allows developers to work without having every layer functioning – i.e. no need for a working, populated database, web services, or active directory services.

    When these dependency endpoints can be ‘faked’ through some sort of abstraction (like an interface), application logic can be created and tested effectively – one test at a time. When the time comes for a true build process and deployment to an integrated, end-to-end environment, there should be fewer surprises as to how the code works when it’s all put together – all because of the effort taken to develop test first and receive feedback from the very beginning regarding how the code is behaving. See Scott Bellware’s excellent post on TDD and failing tests meaningfully for a much more elaborate discussion surrounding the benefits of good unit tests.

    That’s it for now.

    Oh, and for no apparent reason, here are a few more Seinfeld quotes talking about Zach’s drug problem:

    PETERMAN: I'm afraid the problem with Zach is more serious. He's back on the horse, Elaine. Smack. White palace. The Chinaman's nightcap.

    PETERMAN: And, in a tiny way, I almost feel responsible. I'm the one who sent him to Thailand - in search of low-cost whistles. Filled his head with pseudoerotic tales of my own Opium excursions. Plus, I have him some phone numbers of places he could score near the hotel.

    PETERMAN: Damn it, Elaine. That wasn't Zach. That was the yam-yam. Now, he is going cold turkey. (Ordering) And you will be at his side.

    FireFox SessionSaver Mar 28

    I've been looking for a FireFox extension that will remember what tab/web pages I had opened after closing and re-opening browser instances. I found one yesterday after searching, again, (I've looked for something like this for sometime now) through the myriad of extensions - in the Navigation, Tabbed Browsing sections. I give you...

    SessionSaver. This extension seems to do exactly what I've been looking for. I have not experienced any issues with installing subsequent extensions like a couple of the comments I read on the extension download page. Give it a shot.