Using Paypal Buy Now Buttons with ASP.NET

by Philip 20. July 2010 11:30

I usually use Paypal Web Services for ECommerce, however for the occasional ECommerce merchant, Paypal Web Services may not be appropriate because of the minimum monthly fee.  Depending on one’s preferences, Paypal Buy Now buttons may be suitable for ECommerce.  Buy Now buttons incur no minimum monthly fee and involve conducting a copy/paste operation of HTML into one’s HTML page, as illustrated below:

   1:      <form action="https://www.paypal.com/cgi-bin/webscr" 
   2:          method="post">
   3:          <input type="hidden" 
   4:              name="cmd" 
   5:              value="_s-xclick" />
   6:          <input type="hidden" 
   7:              name="hosted_button_id" 
   8:              value="F4E333HY55FXX" />
   9:          <input type="image" 
  10:              src="https://www.paypal.com/en_US/i/btn/btn_buynow_SM.gif" 
  11:              border="0" 
  12:              name="submit" alt="PayPal - The safer, easier way to pay online!" />
  13:          <img alt="" 
  14:              border="0" 
  15:              src="https://www.paypal.com/en_US/i/scr/pixel.gif" 
  16:              width="1" 
  17:              height="1" />
  18:      </form>

With ASP.NET the above Paypal Buy Now HTML snippet is problematic because ASP.NET WebForms is limited to a single “form” tag definition.  As an alternative one can use the revised HTML snippet to accomplish the same task.

   1:          <input type="hidden" 
   2:              name="cmd" 
   3:              value="_s-xclick" />
   4:          <input type="hidden" 
   5:              name="hosted_button_id" 
   6:              value="F4E333HY55FXX" />
   7:          <asp:ImageButton runat="server" 
   8:              ImageUrl="https://www.paypal.com/en_US/i/btn/btn_buynow_SM.gif" 
   9:              PostBackUrl="https://www.paypal.com/cgi-bin/webscr" />

You will note that the above HTML snippet has been revised such that the forms tag is removed and we are conducting a postback using the ASP.NET ImageButton control.  This works fine provided we have only a single Paypal Buy Now button per WebForm page.

Let’s consider the situation where we have several product definitions defined within SQL Server along with a Paypal Buy Now HTML button definition within SQL for each product.   Let’s also say we are attempting to use an ASP.NET ListView for conducting runtime data binding, illustrated as follows:

   1:  <asp:ListView GroupItemCount="3"
   2:      DataSourceID="dataSource"
   3:      DataKeyNames="GuidKey"
   4:      runat="server">                                
   5:      <LayoutTemplate>
   6:   
   7:          <table id="productTable" runat="server" 
   8:              cellpadding="0"
   9:              cellspacing="0"  
  10:              border="0">                                            
  11:                                  
  12:              <tr runat="server" id="groupPlaceholder" />    
  13:                                                  
  14:          </table>
  15:      </LayoutTemplate>
  16:      <GroupTemplate>
  17:          <tr>
  18:              <td runat="server" id="itemPlaceholder" />
  19:          </tr>
  20:      </GroupTemplate>
  21:      <ItemTemplate>                                            
  22:          <td>
  23:              <div>
  24:                  <div>
  25:                      <asp:Literal runat="server" 
  26:                          Text='<%# Eval("Title") %>' />    
  27:                  </div>
  28:                  <div>
  29:                      <asp:Literal runat="server" 
  30:                          Text='<%# Eval("Description") %>' />
  31:                  </div>    
  32:                  <div>
  33:                      <asp:Literal runat="server" 
  34:                          Text='<%# InjectImage(Eval("Url")) %>'  />    
  35:                  </div>
  36:                  <div>
  37:                      <asp:Literal runat="server" Text='<%# Eval("ButtonHTML") %>' />
  38:                      <asp:ImageButton runat="server" 
  39:                          ImageUrl="~/Themes/Images/ECommerce-Buttons/button-add-cart-blue.gif" 
  40:                          PostBackUrl="https://www.paypal.com/cgi-bin/webscr" />
  41:                  </div>
  42:              </div>                                
  43:          </td>
  44:      </ItemTemplate>    
  45:  </asp:ListView>

The above illustration assumes that the ButtonHTML SQL field being bound contains the Paypal Buy Now HTML snippet; the snippet that has been revised for ASP.NET.  The above implementation is problematic because Paypal will encounter errors when reading the Paypal hidden fields, because there will be multiple Paypal hidden fields with the same “name” attribute; “cmd” and “hosted_button_id”, etc.

The most effective means that I have found to get around this problem is to continue to define the revised Paypal Buy Now HTML snippet as we doing above, because doing so will simplify the copy/paste operation from Paypal to our SQL Server app.  Ultimately, what we want to do is to transform all hidden field “name” attributes to “id” attributes during WebForm start-up, immediately after the ListView is rendered.  Using jQuery, we transform the productTable ListView as follows:

   1:   
   2:   
   3:  function OnAjaxLoad() {
   4:   
   5:     
   6:      jQuery(document).ready(function () {
   7:          InitializePaylBuyNowButtons();
   8:      });
   9:  }
  10:   
  11:  function InitializePaylBuyNowButtons() {
  12:   
  13:      jQuery("table[id$='_productTable']").children('tbody').children('tr').each(function () {
  14:          jQuery(this).children('td').each(function () {
  15:              jQuery(this).children('div').children('#paypalButton').each(function () {
  16:   
  17:                  var productContainer = jQuery(this);
  18:   
  19:                  // initialize standard Paypal Buy Now hidden fields - 
  20:                  // move name attribute value to id attribute
  21:                  // so these hidden fields will not be visible to Paypal
  22:                  productContainer.children('input:hidden').each(function () {
  23:   
  24:                      switch (jQuery(this).attr("name")) {
  25:                          case "cmd":
  26:                          case "hosted_button_id":
  27:                          case "currency_code":
  28:                              jQuery(this).attr("id", jQuery(this).attr("name"));
  29:                              jQuery(this).attr("name", "");
  30:                              break;
  31:                          default:
  32:                              break;
  33:                      }
  34:                  });
  35:   
  36:                  // find possible drop-down - used for multiple prices - 
  37:                  // do same name ==> id move
  38:                  productContainer.children('table').children('tbody').children('tr')
  39:                      .children('td').children('input:hidden').each(function () {
  40:   
  41:                      switch (jQuery(this).attr("name")) {
  42:                          case "on0":
  43:                              jQuery(this).attr("id", jQuery(this).attr("name"));
  44:                              jQuery(this).attr("name", "");
  45:                              break;
  46:                          default:
  47:                              break;
  48:                      }
  49:                  });
  50:   
  51:                  // find possible drop-down - used for multiple prices - 
  52:                  // do same name ==> id move
  53:                  productContainer.children('table').children('tbody').children('tr')
  54:                      .children('td').children('select').each(function () {
  55:   
  56:                      switch (jQuery(this).attr("name")) {
  57:                          case "os0":
  58:                              jQuery(this).attr("id", jQuery(this).attr("name"));
  59:                              jQuery(this).attr("name", "");
  60:                              break;
  61:                          default:
  62:                              break;
  63:                      }
  64:                  });
  65:   
  66:              });
  67:          });
  68:   
  69:      });
  70:  }
  71:   
  72:  Sys.Application.add_load(OnAjaxLoad);

After we have transformed all Paypal Buy Now button hidden fields, we want to revise our ListView definition to accommodate the above jQuery start-up transformation as follows:

   1:  <asp:ListView GroupItemCount="3"
   2:      DataSourceID="dataSource"
   3:      DataKeyNames="GuidKey"
   4:      runat="server">                                
   5:      <LayoutTemplate>
   6:   
   7:          <table id="productTable" runat="server" 
   8:              cellpadding="0"
   9:              cellspacing="0"  
  10:              border="0">                                            
  11:                                  
  12:              <tr runat="server" id="groupPlaceholder" />    
  13:                                                  
  14:          </table>
  15:      </LayoutTemplate>
  16:      <GroupTemplate>
  17:          <tr>
  18:              <td runat="server" id="itemPlaceholder" />
  19:          </tr>
  20:      </GroupTemplate>
  21:      <ItemTemplate>                                            
  22:          <td>
  23:              <div>
  24:                  <div>
  25:                      <asp:Literal runat="server" 
  26:                          Text='<%# Eval("Title") %>' />    
  27:                  </div>
  28:                  <div>
  29:                      <asp:Literal runat="server" 
  30:                          Text='<%# Eval("Description") %>' />
  31:                  </div>    
  32:                  <div>
  33:                      <asp:Literal runat="server" 
  34:                          Text='<%# InjectImage(Eval("Url")) %>'  />    
  35:                  </div>
  36:                  <div id="paypalButton">
  37:                      <asp:Literal runat="server" Text='<%# Eval("ButtonHTML") %>' />
  38:                      <asp:ImageButton runat="server" 
  39:                          ImageUrl="~/Themes/Images/ECommerce-Buttons/button-add-cart-blue.gif" 
  40:                          PostBackUrl="https://www.paypal.com/cgi-bin/webscr" 
  41:                          OnClientClick="PaypalBuyNowProductSelected(this);" />
  42:                  </div>
  43:              </div>                                
  44:          </td>
  45:      </ItemTemplate>    
  46:  </asp:ListView>

You will note that we have revised the following:

  • Added an OnClientClick event handler ( PaypalBuyNowProductSelected(this) ) on the ImageButton ASP.NET control, the purpose of which will be to reverse the effect of the hidden fields start-up transformation, but only for the single selected product.  This will ensure that only a single product is communicating with Paypal during the Buy Now postback operation.
  • Add the “id=paypalButton” attribute to the DIV section containing the Paypal Buy Now HTML snippet for each product and the ImageButton control.  This revision makes the jQuery parsing easier.

Now we need to drop in a jQuery ImageButton OnClientClick event handler:

   1:  function PaypalBuyNowProductSelected(o) {
   2:   
   3:      var productContainer = jQuery(o).parent('div');
   4:   
   5:      // activate Paypal hidden fields to properly 
   6:      // associate Paypal product being selected
   7:      productContainer.children('input:hidden').each(function () {
   8:   
   9:          switch (jQuery(this).attr("id")) {
  10:              case "cmd":
  11:              case "hosted_button_id":
  12:              case "currency_code":
  13:                  jQuery(this).attr("name", jQuery(this).attr("id"));
  14:                  break;
  15:              default:
  16:                  break;
  17:          }
  18:      });
  19:   
  20:      // find possible drop-down - used for multiple prices - 
  21:      // locate hidden input field
  22:      productContainer.children('table').children('tbody')
  23:          .children('tr').children('td')
  24:          .children('input:hidden').each(function () {
  25:   
  26:          switch (jQuery(this).attr("id")) {
  27:              case "on0":                 
  28:                  jQuery(this).attr("name", jQuery(this).attr("id"));
  29:                  break;
  30:              default:
  31:                  break;
  32:          }
  33:      });
  34:   
  35:      // find possible drop-down - used for multiple prices - 
  36:      // locate select field
  37:      productContainer.children('table').children('tbody')
  38:          .children('tr').children('td')
  39:          .children('select').each(function () {
  40:   
  41:          switch (jQuery(this).attr("id")) {
  42:              case "os0":                 
  43:                  jQuery(this).attr("name", jQuery(this).attr("id"));
  44:                  break;
  45:              default:
  46:                  break;
  47:          }
  48:      });
  49:   
  50:      return true;
  51:  }

You will note that the OnClientClick event handler is simply transforming Paypal hidden field “id” attributes to “name” attributes for the single product being selected; thus reversing the effect of the original WebForm start-up transformation for the single product only.

That is it.  Now we have working ASP.NET and jQuery code such that Paypal Buy Now buttons will work with ASP.NET and multiple product definitions.  If we use other Paypal hidden fields they can be manipulated in the same manner as the “cmd” and “hosted_button_id” hidden fields.

Tags: , ,

Technology

ESX Server Snapshot Backups

by Philip 27. June 2010 10:01

One of the more compelling reasons to use ESX/ESXi Server for virtual server management is the feature called Snapshot backups.  Snapshot backups provide the ESX/ESXi Server administrator with the ability to essentially freeze a virtual machine (VMDK virtual server) at a point in time while scheduled updates or upgrades are being attempted.  Snapshot backups are managed using the VMWare VI Client, discussed in a earlier post.

Take Snapshot When a snapshot is taken all updates (regardless of origin) which occur to the virtual machine will be written to a set of snapshot files, rather than the VMDK virtual machine image; thus providing the administrator with the opportunity to copy the VMDK virtual machine image.  A snapshot can be taken for two reasons;  1) if an administrator wants to copy the VMDK virtual machine, or 2)  if the administrator wants to apply updates or upgrades (update from Microsoft, application upgrades, etc) to the virtual machine. 

Deleting Snapshot Once the VMDK virtual machine has been copied successfully, using simply copy/paste commands against the VMDK Virtual machine, or once the updates/upgrades have been verified as having applied successfully, then the snapshot is customarily deleted.  Snapshot deletion will force ESX/ESXi Server to apply all queued updates/ upgrades (queued in the snapshot set of files) to the actual VMDK virtual machine.

Reverting to Snapshot If the updates/upgrades failed for some reason then the administrator can revert the VMDK virtual machine back to the point in time when the snapshot was originally taken.  If the VMDK virtual machine is reverted to the point in time when the snapshot was originally taken then all updates/upgrades after that point in time will be lost, including the failed updates/ upgrades.

Snapshot backups are indeed a handy tool for virtual machine management.   How many times have you applied an upgrade only to sadly find out that the upgrade failed and it needed to be backed out.

Tags: , , ,

Technology

ESX/ESXi Server – Single Server Management Tools

by Philip 22. June 2010 01:38

The functionality and performance of VMware ESX and ESXi are the same; the difference between the two hypervisors resides in their architecture and operational management.  VMware ESXi is the latest hypervisor architecture from VMware. It has an ultra thin Linux kernel footprint with no reliance on a general-purpose OS, setting a new bar for security and reliability. The small footprint and hardware-like reliability of VMware ESXi enable it to also be available preinstalled on industry standard x86 servers.

ESXi Server is also available as a no-cost entry level hypervisor.  During my deployment of ESXi Server I found a lack of available information on when ESXi Server is free and at what point ESXi Server incurs a license fee.   Even internal VMWare personnel were unclear about the differentiation between an ESXi no-cost option versus ESXi Server available on a license fee basis. 

One can download ESXi Server for a 60 day evaluation trial period.  The 60 day trial provides one with a restricted function ESXi Server.  It is not always clear what features are restricted, however during my use it appears that functions relating to cloning and backing up of virtual machines are indeed restricted.  One can register their no-cost ESXi Server license to ensure one has a working ESXi Server longer than 60 days, however the functions relating to cloning and backup are still restricted.   The functions relating to cloning and backup appear to only be available once one licenses a VMWare product, such as VSphere Essentials, which includes what is referred to a VMWare Consolidated Backup (VCB).

VI Client The VI Client is a desktop application used to communicate with ESXi Server.   The VI Client can be used to configure an ESXi Server, monitor ESXi Server performance and take snapshot backups, however VI Client cannot easily be used to backup a virtual machine outside of a single ESXi Server environment.   With the VI Client, the best backup one can hope to achieve is taking a snapshot backup to an alternate hard drive, also attached to the same ESXi Server.   ESXi Server backups will be explorer in detail in another blog post.

Other available interfaces for managing the ESXi Server include the VI Command Level interface, essentially a batch like command level interface; commands being issued from a PC to the ESXi Server.

A Secure Shell (SSH) interface can also be enabledvia the ESXi console.   Once enabled, programs like PuTTY and WinSCP can be used to communicate with the ESXi Server.  SSH is available for diagnostic purposes (in theory), however I found the SSH interface to be essential for a stable on-going ESXi Server environment.  I have found PuTTY necessary for monitoring the Linux based file system.  I have had problems where the Linux based file system will fill up due to ESXi log file usage.   I have to login via PuTTY and move log file out of the base Linux file system using either Linux commands or WinSCP.  Once the Linux based file system starts filling up the ESXi Server will either become quite sluggish or an unexpected re-boots may occur.

In summary, I find essential single ESXi Server management tools to be VI Client, PuTTY and WinSCP.   With SSH enabled, I had very little use for the VI Client command level interface.  Having SSH enabled allows me to use PuTTY for what is essentially ESXi Server console access.   I can issue Linux commands and ESXi Server specific commands directly.

Tags: , , , , ,

Technology

VMWare ESX Server Deployment

by Philip 20. June 2010 00:36

products_esx_diagram

Over the next several weeks I will be making posts related to my recent experience of deploying VMWare ESX Server.  ESX Server is a bare metal hypervisor offered by VMWare.  Supported guest operating systems include just about any Windows or Linux based server based OS.  For me, I am initially deploying four instances of Windows Web Server 2008 R2.

My principal objective in deploying ESX Server was/is the ability to snapshot backup a running guest OS, thus simplifying software upgrades.  Other reasons include the ability to start-up a new guest server OS for any reason without the need for deploying new hardware.

The principal candidates in the virtualization marketplace include VMWare, Microsoft and the Citrix XEN offering.  I have always found Microsoft to be several steps behind the marketplace with respect to virtualization technology.  I was quite disappointed with Microsoft’s virtualization offerings for the desktop at the time of the Windows 7 release, and as a result I moved from Microsoft Virtual PC 2007 to VMWare’s Workstation 7.0 for my development environment.   I had my share of problems in moving to VMWare Workstation, however I now consider it a smart move.  Many of the issues encountered with the VMWare Workstation migration are outlined in my Sep/Oct 2009 blog posts.

I also had many problems in migrating to VMWare ESX Server, however again, I think it was worth the move.   The forthcoming blog posts will discuss some of the challenges.

Tags: , ,

Technology

Photoshop Containers for Dummies

by Philip 25. April 2010 03:25

One common practice in web site design is the use of visual containers.   Containers can take the form of rounded corner containers, shadowed containers and many other variations.   There are also many techniques for simplifying the implementation of containers.  There are many JavaScript based solutions for rounding corners or for expressing a shadow, however the JavaScript solutions are never as visually effective as containers based on a layered Photoshop design.  The Photoshop slice tool is used to cut the needed elements (as small as possible) to be used within a layered DIV container approach, along with cascading style sheet (CSS) styling.  The Photoshop slice tool is used to cut the top header row left and right corners and then a 1 pixel wide element to be repeated between the left and right corners to form a complete header row.  The slice tool is then used to cut the same elements for the bottom footer row, and lastly the slice tool is used to cut the variable height content section left and right edges and 1 pixel wide inner content background.

Using the Photoshop slice tool cannot be avoided, however the ASP.NET implementation can be greatly simplified for repeated container implementations.  The focus of this article is to show how a custom server control can be written and used to programmatically generate variable width and height containers such that the DIV layering complexity is completely abstracted away within the server control.

To illustrate, the following sample web page contains one such custom server control:

   1:  <body>
   2:      <form id="form1" runat="server">
   3:      <div>
   4:          <socrates:InjectContainer ID="test" runat="server">
   5:              <ContentTemplate>
   6:                  <br />
   7:                  <br />
   8:                  <asp:Button ID="btnStart" runat="server" Text="Start" 
   9:                      OnClick="btnStart_Click" />
  10:                  <br />
  11:                  <asp:Label ID="lblStatus" runat="server" />
  12:                  <br />
  13:              </ContentTemplate>
  14:          </socrates:InjectContainer>
  15:      </div>
  16:      </form>
  17:  </body>

 

The ContentTemplate contains a combination of HTML and ASP.NET server controls; in this case a very simple button and status line to display Hello World when the button is depressed, as rendered below:

Image-0001

 

The InjectContainer control will enclose the content within the ContentTemplate template with the various DIV layers necessary to achieve an effective cross browser container implementation.  The Container size is NOT limited in any respects, fully controlled by the cascading style sheet.  In the above example the following HTML is generated and injected into the web page.

   1:  <div id="test">
   2:      <div class="Header">
   3:          <div class="HeaderLeft">
   4:              <div class="HeaderRight">
   5:                  <div class="HeaderContent">
   6:                  </div>
   7:              </div>
   8:          </div>
   9:      </div>
  10:      <div class="Body">
  11:          <div class="BodyLeft">
  12:              <div class="BodyRight">
  13:                  <div class="BodyContent">
  14:                      <br />
  15:                      <br />
  16:                      <input type="submit" 
  17:                          name="test$ctl08$btnStart" 
  18:                          value="Start"    
  19:                          id="test_ctl08_btnStart" />
  20:                      <br />
  21:                      <span id="test_ctl08_lblStatus"></span>
  22:                      <br />
  23:                  </div>
  24:              </div>
  25:          </div>
  26:      </div>
  27:      <div class="Footer">
  28:          <div class="FooterLeft">
  29:              <div class="FooterRight">
  30:                  <div class="FooterContent">
  31:                  </div>
  32:              </div>
  33:          </div>
  34:      </div>
  35:      </div>
  36:  </div>

As you can see, most of the generated HTML are the layers of DIV sections; necessary to achieve the visually effective container.  Most of the heavy lifting is done by the InjectContainer custom server control, as well as the CSS style sheet, shown below:

   1:     <style type="text/css">
   2:          
   3:          body
   4:          {
   5:              background-color: Beige;
   6:              margin-top: 100px;
   7:              margin-left: 100px;
   8:          }
   9:          
  10:          #test
  11:          {
  12:              width: 310px;
  13:          }
  14:          
  15:          #test .Header
  16:          {
  17:          }
  18:      
  19:          #test .HeaderLeft 
  20:          {
  21:              padding-left: 2px;
  22:              height: 3px;
  23:              background-image: url(/Images/Containers/White-Block/HeaderLeftEdge.png);
  24:              background-repeat: no-repeat;
  25:              background-position: top left;
  26:          }
  27:          
  28:          #test .HeaderContent
  29:          {
  30:              height: 3px;
  31:              background-image: url(/Images/Containers/White-Block/HeaderContent.png);
  32:              background-repeat: repeat-x;
  33:              background-position: top left;
  34:          }
  35:          
  36:          #test .HeaderRight
  37:          {
  38:              padding-right: 8px;
  39:              height: 3px;
  40:              background-image: url(/Images/Containers/White-Block/HeaderRightEdge.png);
  41:              background-repeat: no-repeat;
  42:              background-position: top right;
  43:          }
  44:          
  45:          #test .Body
  46:          {
  47:          }
  48:          
  49:          #test .BodyLeft 
  50:          {
  51:              padding-left: 2px;
  52:              height: 200px;
  53:              background-image: url(/Images/Containers/White-Block/BodyLeftEdge.png);
  54:              background-repeat: repeat-y;
  55:              background-position: top left;
  56:          }
  57:          
  58:          #test .BodyContent
  59:          {
  60:              height: 200px;
  61:              background-image: url(/Images/Containers/White-Block/BodyContent.png);
  62:              background-repeat: repeat;
  63:              background-position: top left;            
  64:              text-align: center;
  65:          }
  66:          
  67:          #test .BodyRight
  68:          {
  69:              padding-right: 8px;
  70:              height: 200px;
  71:              background-image: url(/Images/Containers/White-Block/BodyRightEdge.png);
  72:              background-repeat: repeat-y;
  73:              background-position: top right;
  74:          }
  75:          
  76:          #test .Footer
  77:          {
  78:          }
  79:          
  80:          #test .FooterLeft 
  81:          {
  82:              padding-left: 2px;
  83:              height: 9px;
  84:              background-image: url(/Images/Containers/White-Block/FooterLeftEdge.png);
  85:              background-repeat: no-repeat;
  86:              background-position: top left;
  87:          }
  88:          
  89:          #test .FooterContent
  90:          {
  91:              height: 9px;
  92:              background-image: url(/Images/Containers/White-Block/FooterContent.png);
  93:              background-repeat: repeat-x;
  94:              background-position: top left;
  95:          }
  96:          
  97:          #test .FooterRight
  98:          {
  99:              padding-right: 8px;
 100:              height: 9px;
 101:              background-image: url(/Images/Containers/White-Block/FooterRightEdge.png);
 102:              background-repeat: no-repeat;
 103:              background-position: top right;
 104:          }
 105:      
 106:      </style>

The InjectContainer control can also be used in a nested manner to generate a different container within a container, provided of course the ID= attribute is different for each InjectContainer instance so each container can be uniquely styled within its companion cascading style sheet.

The C# source code for the InjectContainer custom server control is as follows:

   1:  using System;
   2:  using System.ComponentModel;
   3:  using System.Text;
   4:  using System.IO;
   5:  using System.Web;
   6:  using System.Web.UI;
   7:  using System.Web.UI.WebControls;
   8:  using System.Web.UI.HtmlControls;
   9:  using System.Drawing;
  10:  using System.Resources;
  11:   
  12:  namespace Socrates.CustomControls.Containers
  13:  {
  14:      public class MyTemplateContainer : Control, INamingContainer
  15:      {
  16:          /// <summary>
  17:          /// MyTemplateContainer.
  18:          /// </summary>
  19:          public MyTemplateContainer()
  20:          {
  21:          }
  22:      }
  23:   
  24:      [
  25:          ToolboxData("<{0}:InjectContainer runat=server></{0}:InjectContainer>"),
  26:          ParseChildren(true),
  27:          PersistChildren(true)
  28:      ]
  29:      public class InjectContainer : CompositeControl
  30:      {
  31:          private ITemplate m_ContentTemplate = null;
  32:   
  33:          private Control RenderHeader()
  34:          {
  35:              return RenderBlock("Header", null);
  36:          }
  37:   
  38:          private Control RenderBody(MyTemplateContainer i)
  39:          {
  40:              return RenderBlock("Body", i);
  41:          }
  42:   
  43:          private Control RenderFooter()
  44:          {
  45:              return RenderBlock("Footer", null);
  46:          }
  47:   
  48:          private Control RenderBlock(string BlockName, 
  49:              MyTemplateContainer i)
  50:          {
  51:              HtmlGenericControl divContainer = new HtmlGenericControl("div");
  52:              divContainer.Attributes.Add("class", BlockName);
  53:              HtmlGenericControl divLeft = new HtmlGenericControl("div");
  54:              divLeft.Attributes.Add("class", BlockName + "Left");
  55:              HtmlGenericControl divContent = new HtmlGenericControl("div");
  56:              divContent.Attributes.Add("class", BlockName + "Content");
  57:              HtmlGenericControl divRight = new HtmlGenericControl("div");
  58:              divRight.Attributes.Add("class", BlockName + "Right");
  59:   
  60:              if (i != null)
  61:              {
  62:                  divContent.Controls.Add(i);
  63:              }
  64:   
  65:              divRight.Controls.Add(divContent);
  66:              divLeft.Controls.Add(divRight);
  67:              divContainer.Controls.Add(divLeft);
  68:   
  69:              return divContainer;
  70:          }
  71:   
  72:          protected override HtmlTextWriterTag TagKey
  73:          {
  74:              get
  75:              {
  76:                  return HtmlTextWriterTag.Div;
  77:              }
  78:          }
  79:   
  80:          protected override void CreateChildControls()
  81:          {
  82:              Controls.Clear();
  83:   
  84:              if (ContainerClass.Length > 0)
  85:              {
  86:                  if (base.Attributes["class"] == null)
  87:                  {
  88:                      base.Attributes.Add("class", ContainerClass);
  89:                  }
  90:              }
  91:   
  92:              base.Controls.Add(RenderHeader());
  93:   
  94:              if (ContentTemplate != null)
  95:              {
  96:                  MyTemplateContainer i = new MyTemplateContainer();
  97:                  ContentTemplate.InstantiateIn(i);
  98:                  base.Controls.Add(RenderBody(i));
  99:              }
 100:              else
 101:              {
 102:                  base.Controls.Add(RenderBody(null));
 103:              }
 104:   
 105:              base.Controls.Add(RenderFooter());
 106:          }
 107:   
 108:          [
 109:              PersistenceMode(PersistenceMode.InnerProperty),
 110:              TemplateContainer(typeof(MyTemplateContainer))
 111:          ]
 112:          public ITemplate ContentTemplate
 113:          {
 114:              get
 115:              {
 116:                  return m_ContentTemplate;
 117:              }
 118:              set
 119:              {
 120:                  m_ContentTemplate = value;
 121:              }
 122:          }
 123:   
 124:          public string ContainerClass
 125:          {
 126:              get
 127:              {
 128:                  return (this.ViewState["_ContainerClass"] == null) ? "" : (string)this.ViewState["_ContainerClass"];
 129:              }
 130:              set
 131:              {
 132:                  this.ViewState["_ContainerClass"] = value;
 133:              }
 134:          }
 135:      }
 136:  }

If you have any questions, please feel free to send me an email.

Tags: , , ,

Technology

Monotouch - Worth an Evaluation

by Philip 13. January 2010 09:57

MonoTouchBoxPersonal There are a number of third party offerings which provide a iPhone look and feel for the Microsoft development environment.  Such alternatives usually require that any deployment must run within the iPhone based Safari browser.  Unlike these third party offerings, Novell (a name from the past) is offering a product named Monotouch, which runs on a Mac along with the iPhone Development SDK (Cocoa Touch, Objective C, etc) and Monotouch wraps the iPhone framework APIs such that .Net C# can be used as the development language.  The Monotouch user must continue to be a member of the iPhone Development Program.

Not sure if all the effort of learning all the restrictions of interfacing .Net and C# as an iPhone Development SDK wrapper would be worth the effort, but clearly it is worth consideration.  After careful study it may be that the only reason for considering Monotouch would be for those in the Development community who are simply opposed to learning Objective C.

Tags: , , ,

Technology

More Problems for Windows Mobile

by Philip 13. January 2010 09:43

With all the positive visibility for the iPhone and the open-source Android OS, Windows Mobile from Microsoft continues to loose market share.  Only 7.9 percent of smart phones sold last quarter were equipped with Windows Mobile, down from 11.1 percent during the same period last year. According to the report, 3.2 million devices were Windows Mobile-based, compared with 4 million last year.  Read the entire article...

Tags: ,

Technology

Every Man Deserves To Have His Play Toys

by Philip 30. November 2009 05:15

My play toy just happens to be 8GB of memory.

8GB Installed on Thinkpad T61p My 8GB of Kingston memory arrived today for my Thinkpad T61p (two 4GB cards).  I did realize a performance gain, and over the next few days I will assess whether multiple concurrent virtual machines perform faster and smoother.  As you can see in the left-most image, my T61p now has 8GB installed with a Windows 7 64 bit host OS.

Windows 7 64 Bit Host Performance After Kingston Memory Installation As far as a performance gain, the right-most AFTER image shows the improved performance using the Windows 7 performance metrics. 
Windows 7 64 Bit Host Performance Before Kingston Memory Installation The right-most BEFORE image shows comparable performance before the Kingston memory installation.
As you may recall from my original Sep-2009 blog post I have pursued several steps in getting ready for 64 bit Windows 7 and also extending the life of and improving the performance of my Thinkpad T61p.  My principal objective has been to migrate my host OS and eventually all guest OSs to 64 bit, however in doing so I also wanted to speed up the hard drives while also adding additional memory to assist with the 64 bit host OS improved performance.  To summarize the steps taken since Sep-2009:
 
  • Replace original T61p hard drives with faster Hitachi drives; both primary and Ultra-Bay drive.  All VMs are on Ultra-Bay drive.
  • Consider which virtual machine management software I want to use with Windows 7 64 bit host OS.  After a few problems, I realized that Microsoft had taken a significant step backwards with the Windows 7 version of Windows Virtual PC (WVP) support and I settled on using the new Windows 7 compatible version of VMWare Workstation; version 7.0. My biggest problem with VMWare Workstation was a problem in conducting an iPhone synchronization within a VMWare virtual machine; which ultimately was resolved as an iPhone data corruption problem.
  • Replace my existing 4GB of memory with 8GB of faster Kingston memory.  The obvious goal here was to provide memory beyond the 4GB limit for 32 bit OSs, so that Windows 7 64 bit can freely use all addressable memory, thus hopefully realizing faster and smoother virtual machine performance.

 

Four VMs on Windows 7 64 Bit Host With the above steps now completely realized, here is a sampling of the end result; four concurrent executing virtual machines.....from left to right....1) My old Vista 32 bit Development VM, now converted from VPC 2007 to a VMWare VMDK VM...2) My new 64 bit Windows 7 Development VM; loaded with VS.NET 2010 Beta 2 and all the newly announced products from PDC Nov-2009....3) My 32 bit Windows 7 Administrative VM; containing Outlook, Quicken, etc....and lastly... 4) A small Windows XP image containing IE6 and Firefox 1.5, which I use for legacy testing.  The 1st three VMs are assigned 2GB of memory each, while the Windows XP VM is assigned 256MB.   Of course, the host OS is 64 bit Windows 7.   Sure beats the COMPAQ arm stretcher portable I used to carry through airports in the mid to late 1980s.

Now....is this cool or what ?

Tags: ,

Technology

iPhone Backup/Syncing VMWare Issue Resolved

by Philip 25. November 2009 13:03

iPhone Corruption After moving to VMWare Workstation 7.0 using Windows 7 64 bit as the host OS, the one remaining problem I had was the inability to backup/sync my iPhone in a VMDK virtual machine.  After opening a problem with VMWare and spending many hours testing various tests with VMWare the problem has resolved to being a problem with the iPhone firmware.  It appears that a corruption problem can occur when moving the iPhone firmware from version 2 to version 3.  The symptom of the problem is extreme slowness when backing up one's iPhone.

For me, the extreme slowness in backing up/syncing the iPhone showed up as the complete inability to backup/sync my iPhone within a VMDK virtual machine.  The iPhone backup/sync would come to a complete halt for some reason.

To resolve the iPhone corruption problem, I removed all of my free iPhone applications, which number 20-30 such applications (I am too cheap to actually purchase many iPhone apps).   I then conduct a hard reset on the iPhone, after which I reinstall all of the 20-30 applications.  At this point, my iPhone backup runs in only about 5 minutes, which was taking over 2 hours with the iPhone corruption problem.

Working with VMWare on this problem was frustrating at times, however they did provide excellent support, even though the problem is with the iPhone.

Using VMWare for my virtual machine support along with a Windows 7 64 bit host OS has been an excellent combination.

My 8gb is on the way via UPS from California.  As you know from my prior blog posts the 8gb is part of the master plan in moving to a 64 bit host OS.   I should see some improved performance, especially when executing multiple concurrent virtual machines.

Tags: ,

Technology

Facebook Integration with MSFT Facebook SDK

by Philip 18. November 2009 00:44

Facebook Development I gave a presentation last night on Facebook Integration using the Facebook Developer's Toolkit (FDT).  FDT is available on CodePlex and effective with FDT release 3.0 has been renamed to the Microsoft Facebook SDK.   Click HERE to download my Power Point presentation and sample C# projects from last night's event.

Facebook offers several ways to implement Facebook applications.   When integrated within the context of the Facebook web site, such applications are referred to as Facebook Canvas applications.  Canvas application take on two major flavors; IFrame constructed applications and Facebook Markup Language (FBML) applications.  External web sites can also enable Facebook users to use their Facebook login IDs within respective external web sites, referred to as the Facebook Connect feature.  Windows desktop applications can also be written to benefit from Facebook and gain access to Facebook data, either as Windows Winforms or WPF applications.

The Microsoft Facebook SDK wraps the Facebook REST API to simplify and facilitate ease of development of each of the above application/ deployment types.

Download the Power Point and code from the 1st paragraph to learn more.

Tags: , , , ,

Technology

Powered by BlogEngine.NET 1.6.1.0
Theme by Philip Lippard  (Original by Mads Kristensen)

Philip Lippard

Philip Lippard is a resident of Sanibel Island, Florida USA.  Philip develops and hosts enterprise web sites for a select group of corporate clients.

Calendar

<<  July 2010  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar

RecentPosts