pátek 3. února 2012

How to notify parent page from a page running in iframe

Imagine you have PageA which has an iframe element.  Inside iframe PageB is hosted. Page B somewhere in it's lifecycle wants to notify PageA. What are the possibilities?
  1. use window.parent.__dopostback() javascript call which causes a postback in PageA. This works only in situation where PageA and PageB are running on same domain. When PageB is a completely different application under different domain parent is not accessible due to security reasons.
  2. use html5 messaging capabilities. HTML5 offers a postMessage method using which PageB can send a message to it's parent element. PageA can register for receiving specific events. This works under different domains too. Details are in the example below.
PageB:
<script type="text/javascript">
    window.parent.postMessage('par1', '*');
</script>

First argument to postMessage is the message that you are sending, second is the target origin which could be used in Page A to filter messages = Page A registers for receiving messages, and anyone can send a message to it. Target origin is a parameter on which the client and the receiver can agree and the receiver can filtrate  the incoming meesages based on it. '*' sign means you are accepting messages from everyone.

PageA:
<script type="text/javascript">
   function receiver(e) {
      alert(e.origin);
      alert(e.data);
   }
   if (!window.addEventListener) {
      window.attachEvent('onmessage', receiver);
   } else {
      window.addEventListener('message', receiver, false);  
   }               
</script>

addEventListener registers an event handler for receiving messages, when a message is received the receiver function is called where you have the origin and data available to work with. In the example there is also an attachEvent call, this is because of IE8 which goes on it's own way and doesn't support addEventListener. Instead of it it uses the attachEvent call. Code first checks whether addEventListener is available if not it registers the event using attachEvent. 

I did tests in IE, Firefox and Chrome, it worked great.

Links:
http://dev.w3.org/html5/postmsg/
http://rubayathasan.com/tutorial/ie8-addeventlistener-alternative-example/  

čtvrtek 26. ledna 2012

Conditional compilation/execution


Sometimes you need to execute a code based on some settings in the execution environment, debug mode is typical example for this. An example from the real world: when I’m in debug mode I don’t want to check the incoming IP address of the client against my list of allowed IP addresses, but in production environment this is a required feature. How to achieve this?
  1. Comment and uncomment the call to CheckIpAddress manually – well, it works but I can bet all my money that you forget to uncomment it before doing deployment to release environment :)
  2. Use conditional compilation directives - #if #elif #endif etc., these work against some defined symbol in the assembly, the code block inside #if is compiled or skipped based the symbol in the condition. Skipped means that the code block won’t be in the assembly. This is better solution but the code can become quickly messy, fragmented and hard to read

    public void TestMethod()
         {
             #if IPCHECK
                 CheckIpAddress();         
             #endif         
         }
         
         private void CheckIpAddress()
         {
             // TODO ip check logic
         }

  3. Use the Conditional attribute – a method marked with this attribute is called only when the symbol defined in the attribute is present in the calling environment (e.g. assembly). This results in a clearer code than in  the previous case. The method is compiled to assembly, but it is not executed. This is a difference between conditional compilation and conditional attribute 

    public void TestMethod()
         {
             CheckIpAddress();  
         }

         [Conditional("IPCHECK")]
         private void CheckIpAddress()
         {
             // TODO ip check logic
         }

How can you define such a symbol? 
  1. Use the #define directive in code - #define IPCHECK
  2. In Visual Studio 2010 there is a possibility to set such symbols directly in the UI at the level of project and build configuration   
Project Properties in VS2010

Just a final note, on the picture you can see a checkbox define DEBUG constant, this is checked by default in the Debug configuration, this is why you can by default use the DEBUG symbol in your code (I didn’t recognize this and worked with DEBUG naturally without knowing how it works)

Links:
http://msdn.microsoft.com/en-us/library/aa664622%28v=vs.71%29.aspx
http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=420