A SSIS (SQL Server Integration Services) package is very useful if you want to export data from your database. Recently I wanted to pass some input parameters to my SSIS package and had to struggle to figure out how this can be done. This really isn't very well documented and you can't find detailed instructions on the Internet so I thought I'd blog about it. Get a load of how complicated it turned out to be!

The first step is to add a variable to your SSIS package. In the Business Intelligence Development Studio (Visual Studio 2005), select SSIS > Variables

SSIS-Variables

The first button on the left is for Add Variable. Enter the variable name, scope, data type, and value. The variables will be added to the DTSX file:

   1: <DTS:Variable>
   2:     <DTS:Property DTS:Name="Expression"></DTS:Property>
   3:     <DTS:Property DTS:Name="EvaluateAsExpression">0</DTS:Property>
   4:     <DTS:Property DTS:Name="Namespace">User</DTS:Property>
   5:     <DTS:Property DTS:Name="ReadOnly">0</DTS:Property>
   6:     <DTS:Property DTS:Name="RaiseChangedEvent">0</DTS:Property>
   7:     <DTS:VariableValue DTS:DataType="7">1/1/1950</DTS:VariableValue>
   8:     <DTS:Property DTS:Name="ObjectName">varBirthDate</DTS:Property>
   9:     <DTS:Property DTS:Name="DTSID">{6CE1ED2D-3720-4FDB-9590-FEDC2D78C797}</DTS:Property>
  10:     <DTS:Property DTS:Name="Description"></DTS:Property><DTS:Property DTS:Name="CreationName"></DTS:Property>
  11: </DTS:Variable>

The next step is to map a parameter in your SQL statement to the variable.

  1. Select the Data Flow tab.
  2. Right click on the Source Query
  3. Select Edit
  4. Replace a hard coded value in the SQL statement with a question mark to create a parameter
  5. Click the Parameters... button
  6. Select the variable from the drop down list
  7. Enter the parameter name in the format @Name for a stored procedure parameter or the field name

SSIS-OLE-DB-Source-Editor

SSIS-Set-Query-Parameters

The third step is to add this variable to the package configuration so you can easily change the value in an XML configuration file.

  1. Select SSIS > Package Configurations
  2. Click the Edit button and then the Next button
  3. In the Select Properties to Export dialog box, check the Value property of the variable (which will not appear unless you complete the previous steps to create it first).

SSIS-Package-Configuration-Wizard

The variables will be added to the .dtsConfig file:

   1: <Configuration ConfiguredType="Property" Path="\Package.Variables[User::varBirthDate].Properties[Value]" ValueType="DateTime">
   2:         <ConfiguredValue>1/1/1950</ConfiguredValue>
   3: </Configuration>

The SSIS package can be run by an ASP.NET page or a web service by importing the Microsoft.SqlServer.Dts.Runtime namespace. The input parameter can easily by changed in the package configuration file by loading it as an XML document and editing the appropriate node.

You can use SSIS packages to do very complicated data transformations and exports. Basically it automates everything the SQL Server Import and Export Wizard does. So you can export your database to Access or Excel without repeating that whole process of going through the wizard steps. I've found this particularly useful to set up my own scheduled back up of a remote SQL Server database used by a hosted web application.

I recently read a new book published by Packt Publishing, “ASP.NET 3.5 Application Architecture and Design” by Vivek Thakur. I've noticed a lot of articles and blog posts about design patterns and domain models in the ASP.NET community but it really mystified me until I read this book. Although many of the blog posts I've read have tried to be an introduction to design patterns, I'd have to say they all did a poor job compared to Vivek Thakur's book which explains it all in plain English. I learned how application architecture applies to web development and what advantages it is meant to offer.

For example, the chapter on tiers and layers explains how the business layer, UI layer, and data access layer relates to namespaces and classes you could create to organize your project. The chapter on entity-relationships clarified how the domain model used in the object-oriented system may differ from the logical data model used in the relational database management system.

I also found good explanations of; lazy loading, to defer the loading of all properties until they are really needed, the singleton pattern, which restricts and controls the number of objects instantiated for a particular object during the application life cycle,  the factory method, used to create objects without prior knowledge of the object using interfaces, and dependency injection, which allows you to plug-in an implementation that satisfies the interface requirements. Although I've come across these terms before I had no idea what they meant or how they could apply to ASP.NET. You'll find some really basic examples of how you can write code to use these design patterns.

If you are an expert on application architecture and expect in-depth coverage of how to apply the factory method in ASP.NET then you'll be disappointed. I'd say this book is more helpful for someone like me, a developer who is completely mystified by what everyone seems to be writing about these days. That is not to say you might not pick up a few tips from the material. For example, page 137 mentions a lock statement that can be used to ensure thread safety and I'd never encountered that before.

I also appreciated the author's practical approach to design patterns. He does not recommend them for small projects. This kind of lets me off the hook because none of my projects could really justify the additional overhead of a loosely-coupled design. However that is not to say you won't encounter such design patterns in your work. For example, I'm currently trying to customize the Elgg open source web application for social networking and its database schema is a peculiar attempt to incorporate entity relationships directly in the physical data layer. In any event, you are not meant to directly access the database. Instead you should get a reference to an ElggObject and use its properties. 

I have not been blogging here because I've been doing a lot of web design research lately which does not involve ASP.NET. I'm really slacking off on improving my programming skills. I went on a fabulous vacation and never came back mentally. However I'm still making the effort to master web design so I will share some of my recent discoveries.

Yesterday I learned about the "computed style" in CSS. I don't know why I've never come across this term before now. There are so many little details in web development. I'm always finding holes in my knowledge. Any way, a computed style is the value a CSS property will have when the browser needs to calculate the value based on a percentage or a value relative to another value. For example, if you specify a div to have a width of 50% and it contains an element that inherits its width from the div, then that element will have a computed value.

I had to figure this out because I'm using the http://www.plaintxt.org/themes/sandbox/ WordPress theme as a template for a custom theme. The web design community seems to be very keen on WordPress. You can find many tutorials on how to design for WordPress. I was working on the header for my design and found it would not appear at the top of the page in Firefox. There was a gap between the top of the page and my header. I examined the layout in Firebug and saw a 16 pixel offset on the top of the header element:

I could not figure out where that 16 offset was coming from. There was nothing in my CSS to set any height to 16px. Eventually I tried the developer tools in other browsers. Opera told me that there was a top: 16px computed style for my header element. So I had to learn about computed styles and how to deal with them.

The height for a block-level element is calculated in CSS. If such an element has no height defined, it will be set to auto, which is the default height for block-level elements. You have to change the height of the div by either adding a border or a padding to avoid the computed style.

So to eliminate that computed value I had to add a little padding to the top. As you can see I did have its height defined so I don't know why there was still a problem.

   1: #header {
   2:     background: #FFFFFF url(images/header_img.jpg);
   3:     height: 145px; /* height of image */
   4:     padding-top: 1px;
   5: }
The following CSS property values will result in a computed value; ‘auto’, ‘inherit’, ‘50%’, ’smaller’, ‘1.5em’ etc.

The web site I've been working on, Vloggerheads, will be opened to the public tomorrow. You can view the videos and blogs but you won't be able to comment or post videos unless you request membership and are approved. You might want to check out the video of the shrine that was built to me or the many videos thanking me for adding much needed features to the site. LOL

Vloggers make so many videos that it is not unusual for them to make a video about the site itself. I get a lot more feedback and appreciation for my work on this web site than I get on any other project. This alone makes it very worthwhile. If you are looking for recognition from users than you should definitely consider a video sharing site project.

I've added several features to this Ning site which everyone was used to having on YouTube or LiveVideo. Leaving comments on videos is an important aspect of the communication in the community so I added comment threading and comment replies. I also implemented email notification for comment replies. Working with the Ning platform is painfully difficult. Just sending an email proved to be a major hassle because Ning does not give me direct access to a member's email address. I have to use their built-in classes to send emails. And I cannot query for more than 100 content items at a time so I need to write a loop to get all the comments. Ning fights me every step of the way and frustrates me with its caching system and poor error reporting tools.

Ning is dropping the old version of the Dojo JavaScript library they were using and replacing it with jQuery. So I'm glad that ASP.NET will officially support jQuery as I'll be using it on all my projects. I've already included jQuery in my two remaining ASP.NET projects and I imported it into my Ning sites. I even use jQuery in my help files that I use for documentation.

I wrote some very complicated JavaScript to handle the comment pagination so I've been using every tool available to me to troubleshoot my JavaScript. Since the Ning platform caches JavaScript on the server side I've found it useful to load my recently changed scripts in Firebug to double check the version downloaded by Firefox. I've even resorted to using some console.log("string") lines in my code to avoid annoying alerts. My JavaScript is loading and manipulating XML so I've had to view my JavaScript objects in the DOM pane to carefully review available properties and methods. However, I haven't neglected the new debugging tools in Internet Explorer 8.0 Beta. I even have to use Opera to get an error message for a Dojo library error that won't show up in Firefox or Internet Explorer. I was uncertain as to what values the Ning platform was expecting for a POST request so I learned how to use Firebug to view what was being sent in a typical POST request.

During a recent Skype conference I was surprised to learn that both YouTube and LiveVideo were more disinterested in the vlogging community than I suspected. This surprises me because I think the social networking potential of vlogging is obvious. Vlogging is clearly more effective than blogging and other forms of text in fostering a genuine sense of online community. You can form real friendships through vlogging that would never take place among bloggers. Unfortunately, too many Web 2.0 entrepreneurs focus on valuations and numbers and neglect to consider the most important factor of business value, providing a service that meets real needs. You can never go wrong betting on a business that meets the needs of the general public. Vlogging clearly meets many crucial needs. It provides social interaction for the socially isolated. It provides recognition for creative people. It provides entertainment and communication that is more interactive than the mass media can offer. To dismiss vlogging as something that will never catch on with the general public is as stupid as it was two years ago to dismiss blogging as a fad.

Recently I was working on some complicated JavaScript to nest unordered lists and list items to match an Atom feed's XML structure. I had to spend an entire day researching JavaScript's XML parsing capabilities because there is no place on the Internet where this information is gathered to my satisfaction. I created a JavaScript cheat sheet on XML for my notes. I thought I would share it with you in order to get some feedback for improving my notes. Let me know if you know of a JavaScript library that eases the pain of working with XML in JavaScript. jQuery is somewhat useful for this if you use its DOM selectors on an XML document instead of the web page document. var entryNode = $('entry',xmlDoc).eq(5);

Load XML

You can load XML from a file on the web server or from a remote source via XMLHttpRequest. The code below shows the number of child nodes below the root element.

   1: (document).ready(function(){ 
   2:     // Load XML from a file on the web server
   3:     if (window.ActiveXObject) {
   4:         var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
   5:         xmlDoc.async = false;
   6:         xmlDoc.load("xml/video-comments.xml");
   7:     }
   8:     else {
   9:         var mXHR = new XMLHttpRequest();
  10:         mXHR.open("GET", "xml/video-comments.xml", false);
  11:         mXHR.send(null);
  12:         xmlDoc = mXHR.responseXML;
  13:     }
  14:     var root = xmlDoc.documentElement;
  15:     $("#response").append(root.childNodes.length);
  16: }); 

NOTE: Firefox, Opera, and Safari counts any whitespace as text nodes so their node counts may be higher.

getElementsByTagName

You can get an array of elements by tag name which returns all occurrences even when the elements are nested within each other.

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: $("#response").append("Entry Nodes: " + nodelist.length);

You can also use a wildcard character to get all elements with a tag name:

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('*');
   3: $("#response").append("<b>All tags count: </b>" + nodelist.length);

Find A Child Node By Tag Name

Internet Explorer has a text property for a node while the other browsers use textContent:

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: var strID = "";
   4: // loop through the sixth node's children
   5: for (var i = 0; i < nodelist[5].childNodes.length; i++) {
   6:     var child = nodelist[5].childNodes[i];
   7:     // find the child node by tag name
   8:     if (child.tagName == "id") {
   9:         // IE supports the text property
  10:         if (window.ActiveXObject) {
  11:             strID = child.text
  12:         }
  13:         // Other browsers use textContent
  14:         else {
  15:             strID = child.textContent;
  16:         }
  17:     }
  18: }

Internet Explorer's Xml Property

Internet Explorer has an xml property for a node but the other browsers do not.

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: var strID = "";
   4: // loop through the sixth node's children
   5: for (var i = 0; i < nodelist[5].childNodes.length; i++) {
   6:     var child = nodelist[5].childNodes[i];
   7:     // find the child node by tag name
   8:     if (child.tagName == "id") {
   9:         // IE supports the xml property
  10:         if (window.ActiveXObject) {
  11:             strID = child.xml
  12:         }
  13:     }
  14: }
  15: $("#response").append("<b>5th Entry Element: </b>" + htmlentities(strID));

NOTE: The xml namespace will be added to the xml tag.

Get The First Child Element

Remember that the other browsers may count whitespace as a child node:

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: var strText = "";
   4: // Get the first child of a node in IE 
   5: if (window.ActiveXObject) {
   6:     child = nodelist[5].firstChild;
   7:     strText = child.text;
   8: }
   9: // In other browsers the first child would be whitespace so get the next sibling
  10: else {
  11:     child = nodelist[5].childNodes[0].nextSibling;
  12:     strText = child.textContent;
  13: }
  14: $("#response").append("<b>6th Node's First Child: </b>" + strText);

Get The Last Child Element

Remember that the other browsers may count whitespace as a child node:

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: var strText = "";
   4: // Get the last child of a node in IE 
   5: if (window.ActiveXObject) {
   6:     child = nodelist[5].lastChild;
   7:     strText = child.text;
   8: }
   9: // In other browsers the last child would be whitespace so get the previous sibling
  10: else {
  11:     child = nodelist[5].lastChild.previousSibling;
  12:     strText = child.textContent;
  13: }
  14: $("#response").append("<b>6th Node's Last Child: </b>" + strText);

Get The Parent Node

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: var strText = "";
   4: child = nodelist[5].parentNode;
   5: strText = child.tagName;
   6: $("#response").append("<b>6th Node's Parent Tag Name: </b>" + strText);

Node Types

nodeType returns the type of the node; 1 is an element node, 2 is an attribute and 3 is text.

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: // node type 1 = element
   4: var type = nodelist[7].nodeType;
   5: $("#response").append("<b>Node Type: </b>" + type + "<br>");
   6: // node type 2 = attribute
   7: var type = nodelist[7].childNodes[5].attributes[0].nodeType;
   8: $("#response").append("<b>Node Type: </b>" + type + "<br>");
   9: // node type 3 = text
  10: var type = nodelist[7].childNodes[0].nodeType;
  11: $("#response").append("<b>Node Type: </b>" + type + "<br>")

Get An Attribute Of An Element

   1: var root = xmlDoc.documentElement;
   2: var nodelist = root.getElementsByTagName('entry');
   3: // get an attribute
   4: if (window.ActiveXObject) {
   5:     var attr = nodelist[7].childNodes[3].getAttribute("type");
   6: }
   7: // In other browsers whitespace counts as child nodes
   8: else {
   9:     var attr = nodelist[7].childNodes[5].getAttribute("type");
  10: }
  11: $("#response").append("<b>Attribute: </b>" + attr);

XPath

The main interface to using XPath is the evaluate function of the document object.

The evaluate function takes a total of five parameters:

  • xpathExpression: A string containing the XPath expression to be evaluated.
  • contextNode: A node in the document against which the xpathExpression should be evaluated, including any and all of its child nodes. The document node is the most commonly used.
  • namespaceResolver: A function that will be passed any namespace prefixes contained within xpathExpression which returns a string representing the namespace URI associated with that prefix. This enables conversion between the prefixes used in the XPath expressions and the possibly different prefixes used in the document. The function can be either:
    Created by using the createNSResolver method of a XPathEvaluator object. You should use this virtually all of the time.
    null, which can be used for HTML documents or when no namespace prefixes are used. Note that, if the xpathExpression contains a namespace prefix, this will result in a DOMException being thrown with the code NAMESPACE_ERR.
    A custom user-defined function.
  • resultType: A constant that specifies the desired result type to be returned as a result of the evaluation. The most commonly passed constant is XPathResult.ANY_TYPE which will return the results of the XPath expression as the most natural type.
  • result: If an existing XPathResult object is specified, it will be reused to return the results. Specifying null will create a new XPathResult object.
   1: var root = xmlDoc.documentElement;
   2: var nsResolver = xmlDoc.createNSResolver(xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement);
   3: var xpathResult = xmlDoc.evaluate('count(//*)', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
   4: $("#response").append("<b>Number of Nodes: </b>" + xpathResult.numberValue + "<br>");
   5: // @ Selects attributes
   6: var xpathResult = xmlDoc.evaluate('count(//*/@*)', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
   7: $("#response").append("<b>Number of Nodes: </b>" + xpathResult.numberValue + "<br>");
   8: // . Selects the current node
   9: var xpathResult = xmlDoc.evaluate('count(.)', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
  10: $("#response").append("<b>Number of Nodes: </b>" + xpathResult.numberValue + "<br>");
  11: // / Selects from the root node
  12: var xpathResult = xmlDoc.evaluate('count(/)', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
  13: $("#response").append("<b>Number of Nodes: </b>" + xpathResult.numberValue + "<br>");
  14: // Predicates are always embedded in square brackets.
  15: var xpathResult = xmlDoc.evaluate('count(//*[1])', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
  16: $("#response").append("<b>Number of Nodes: </b>" + xpathResult.numberValue + "<br>");
  17: // node() Matches any node of any kind 
  18: var xpathResult = xmlDoc.evaluate('count(//node())', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
  19: $("#response").append("<b>Number of Nodes: </b>" + xpathResult.numberValue + "<br>");
  20: // NUMBER_TYPE = 1
  21: // A result containing a single number. This is useful for example, in an XPath expression using the count() function.
  22: $("#response").append("<b>Result Type: </b>" + xpathResult.resultType + "<br>");
  23: // //*[2] Selects every second child node of all the nodes
  24: var xpathResult = xmlDoc.evaluate('//*[2]', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
  25: // UNORDERED_NODE_ITERATOR_TYPE = 4
  26: // A result node-set containing all the nodes matching the expression. 
  27: // The nodes may not necessarily be in the same order that they appear in the document.
  28: $("#response").append("<b>Result Type: </b>" + xpathResult.resultType + "<br>");
  29: var result = xpathResult.iterateNext();
  30: while (result) {
  31:     $("#response").append("<b>Child Node: </b>" + result.tagName + "<br>");
  32:     result = xpathResult.iterateNext();
  33: }

NOTE: This is not supported in Internet Explorer. There isn't much sample code to be found using this method and it gave me a lot of trouble. These are the only XPaths that worked for me.

Select Nodes

You can only use the functions selectNodes or selectSingleNode in Internet Explorer:

   1: var root = xmlDoc.documentElement;
   2: $("#response").append("<b>Feed Title: </b>" + xmlDoc.selectSingleNode("/feed/title").text + "<br>");
   3: // Items
   4: var entries = xmlDoc.selectNodes("/feed/entry");
   5: for (var i = 0; i < entries.length; i++) {
   6:     $("#response").append("<b>Entry ID: </b>" + entries[i].selectSingleNode("./id").text + "<br>");
   7: }

Client Side XSL Transformations

   1: <script type="text/javascript">
   2:     // Load XML 
   3:     var xml = new ActiveXObject("Microsoft.XMLDOM")
   4:     xml.async = false
   5:     xml.load("file.xml")
   6:     // Load XSL
   7:     var xsl = new ActiveXObject("Microsoft.XMLDOM")
   8:     xsl.async = false
   9:     xsl.load("file.xsl")
  10:     // Transform
  11:     document.write(xml.transformNode(xsl))
  12: </script>

I'm currently working on threaded comment systems. Comment threads allow you to reply to a comment. This is a feature that the users are clamoring for on Vloggerheads because it is a popular feature on YouTube .  Even the trolls are wondering when we are going to have this feature. One of the more amusing aspects of this project is the ongoing video commentary from the peanut gallery. It is like having Bill O'Reilly doing vicious news reports about the progress, or lack of progress, of your project.

There are surprisingly few examples of threaded comment systems. I can't think of any good examples. Let me know of any open source web applications that have this feature. WordPress does not allow replies to blog comments. Community Server also does not have this feature.

The Ning platform is proving to be a bad choice for building a social networking site. Recently there was a huge controversy over their decision to ban Widget Laboratory, an independent software company that provided many widgets for Ning Network Creators. There have been many articles about this on TechCrunch so the whole blogosphere is abuzz about this nasty public fight. You can read about it at: Ning Shuts Down Premium Developer WidgetLaboratory.  I think Vloggerheads was using widgets from WidgetLaboratory and planned to have them develop a few features. For two days Ning even suspended my SFTP and WebDav access to my site's file system so I was unable to continue my work. So I'm really not happy with the capricious control Ning has over this project.

I've been exploring various options for creating a social networking site for vlogging. Unfortunately there are web applications for video sharing sites and web applications for social networks but nothing that combines the two. Currently I'm considering PHPMotion for the video sharing side of things and Elgg for the social networking groundwork. They are both open source web applications based on PHP, MySQL, and Apache. So you may be wondering why I don't consider something based on ASP.NET, my area of expertise.

I think the primary reason for not going with ASP.NET is the lack of open source web applications based on ASP.NET. The only thing we have is DotNetNuke. DotNetNuke is a content management system and I doubt that it can be customized to have both social networking and video sharing features. However, the PHP community has a wealth of open source web applications; WordPress, Joomla, Elgg, PHPMotion, CakePHP, MediaWiki, OsCommerce, etc. Although I would be sacrificing my experience, I gain a considerable amount of groundwork if I lean towards PHP, MySQL, and Apache. ASP.NET really needs a lot more sophisticated open source web applications and frameworks to compete with the LAMP stack.

At the moment, I am translating my VB.NET code for comment threads into PHP so I can use it on Ning or Elgg or PHPMotion. This is proving to be very time consuming and difficult but not impossible because PHP has DOM classes for XML manipulation which closely correspond  to .NET's XmlDocument class. I need to reorganize the comments into a hierarchy that reflects the comment thread. This can then be applied to nested ordered list HTML tags. XML is a good choice for the necessary hierarchy although other options would be sorted arrays, XSL using JavaScript, pure JavaScript to manipulate the DOM, or directly sorting and ordering database records. 

I've finally gotten around to using something from the AJAX Control Toolkit in an actual project. My client was dissatisfied with the <asp:calendar> control so I offered to AJAX enable the site and replace it with the fancier Calendar control from the ASP.NET AJAX Control Toolkit. Naturally the client found something he wanted to work a little different. This calendar control was for entering your birth date and he did not want the user to scroll back decades to find that date. He wanted the calendar to show up with the 1990-1999 decade already visible so the user could start from there. Fortunately I remembered that the ASP.NET AJAX Control Toolkit comes with all the source code so you can customize it to suite your needs.

This requirement was extremely easy to implement. All you really need to do is set the calendar mode to "years" when you first show it. However there was no property for initial mode so I had to create one. This was virtually a cut and paste hack because there are existing properties to base it on.

1. Open CalendarExtender.cs and create a new ExtenderControlProperty:

   1: [DefaultValue("")]
   2: [ExtenderControlProperty]
   3: [ClientPropertyName("initialMode")]
   4: public virtual string InitialMode
   5: {
   6:    get { return GetPropertyValue("InitialMode", string.Empty); }
   7:    set { SetPropertyValue("InitialMode", value); }
   8: }

2. Open CalendarBehavior.js and create a new member:

   1: this._initialMode = null;

3. Also in CalendarBehavior.js add new get and set functions for the property access:

   1: get_initialMode : function() { 
   2:     /// <value type="String">
   3:     /// The initial mode of the calendar
   4:     /// </value>
   5:  
   6:     return this._initialMode; 
   7: },
   8: set_initialMode : function(value) { 
   9:     if (this._initialMode != value) {
  10:         this._initialMode = value; 
  11:         this.raisePropertyChanged("initialMode");
  12:     }
  13: }, 

4. And finally set the _switchMode in the show : function() with this new line of code:

   1: this._switchMode(this._initialMode, true);

Compile the AjaxControlToolkit project and copy the AjaxControlToolkit.dll file to your bin directory. Now you can use your new property in the Calendar control like so:

   1: <ajaxToolkit:CalendarExtender ID="calendarButtonExtender" runat="server" TargetControlID="Date5" 
   2:             PopupButtonID="Image1" InitialMode="years" />
Calendar-Years-Mode[4]

I'm finally working on a project with the potential to be a really high profile web site. I've offered my services as a volunteer programmer to the http://www.vloggerheads.com web site which is being built on the Ning social networking platform. This site is an attempt by prominent vloggers from YouTube and LiveVideo to take control of their community.

Vloggers have been plagued by trolls, hackers, haters, and cyberbullies who are allowed to run amuck on the video sharing sites. This has been a major problem for a very long time and the sites where people vlog have ignored the frequent complaints from their users. Vloggers feel unappreciated. They don't think the video sharing sites are interested in creating a safe environment for the community. I've been outraged over the shoddy customer service and total indifference to the user base for quite some time. YouTube is like a convenience store in a bad section of town where the business owner allows hoodlums to lounge outside the store and harass its customers. The hoodlums are even allowed inside the store to give the customers grief as they shop and a hoodlum may even become customer of the month. Trolls have been featured on YouTube!

This has led to a revolt among the user base. It is an inspiring example of the collaboration that social networking is said to foster. Vloggers have come together to plan their own video sharing site that will provide a safe environment to do what they love to do. Personally, if I was managing a web site and my user base left en masse to form their own site out of disgust with how I was running things, I would feel professionally mortified.

The Ning social networking platform is surprisingly customizable. They provide more than the usual XML and JSON data feeds as an API. You can actually script your site in PHP. They don't use a proper database though. You have to add custom developer attributes to a set number of content objects to extend their data schema. Ning rolled their own Model View Controller framework. My brief study of CakePHP was useful in understanding this architecture but I still need to brush up on my PHP. Ning also uses the Dojo JavaScript toolkit which is worth studying. So far I have learned enough on this project to make it well worth my time.

As far as ASP.NET goes, the only interesting aspect to the project so far has been using PHP as a SOAP client to an ASP.NET web service. This proved to be tricky because you must specify the data type of the parameters in PHP and send them as an associative array.

Although the Ning site has energized the community by providing it with a sense of ownership and control, there is still an awareness that basing the site on Ning could be limiting. Nobody wants to be at the mercy of another indifferent social networking site that will not enforce its terms of service. I've already recommended http://www.codeplex.com/videoshow as a potential vlogger platform but it lacks any social networking features and I don't relish the prospect of building that from scratch.

I regularly browse the ASP.NET Weblogs for hot tips so when Hosam Kamel and Jose R. Guay Paz announced the release of the SQL Server 2005 Driver for PHP I decided to give it a try.

The download includes a compiled help file SQLServerDriverForPHP.chm with installation instructions and sample code. I won't repeat anything you can already find there but below is a screen shot of a new section that appears when you call phpinfo:

I already had some sample code to export data from SQL Server to JSON using PHP so I just converted it to use this new driver:

   1: /* Specify the server and connection string attributes. */
   2: $serverName = "(local)";
   3: $connectionInfo = array( "UID"=>"sa",
   4:                          "PWD"=>"password",
   5:                          "Database"=>"Northwind");
   6:                          
   7: /* Connect using SQL Server Authentication. */
   8: $conn = sqlsrv_connect( $serverName, $connectionInfo);
   9: if( $conn === false )
  10: {
  11:      echo "Unable to connect.</br>";
  12:      die( print_r( sqlsrv_errors(), true));
  13: }
  14:  
  15: $tsql = "SELECT * FROM Customers";
  16: $stmt = sqlsrv_query( $conn, $tsql);
  17: if( $stmt === false )
  18: {
  19:      echo "Error in executing query.</br>";
  20:      die( print_r( sqlsrv_errors(), true));
  21: }
  22: $data = "["; 
  23: while($row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC))
  24: {
  25:     $data = $data . json_encode($row) . ", ";
  26: }    
  27: $data = $data . "]";   
  28: echo $data;
  29:  
  30: /* Free statement and connection resources. */
  31: sqlsrv_free_stmt( $stmt);
  32: sqlsrv_close( $conn);
NOTE: The code snippit plug-in does not support PHP code so you get no syntax highlighting.

Since we have not moved to Visual Studio 2008 at work, I have been unable to keep up with the progress in ASP.NET technology. I can't get into Silverlight 2.0 or ASP.NET MVC without Visual Studio 2008. 

I won't be blogging much here for awhile because I'm studying CakePHP and Flash which have nothing to do with ASP.NET. CakePHP is an attempt to bring MVC to the PHP community. Sometimes CakePHP seems half-baked to me. Sorry, I could not resist that joke. Actually CakePHP is a very promising way to rapidly prototype web applications. By studying CakePHP I'll get many of the concepts behind Model View Controller. I'm really not interested in architectural patterns used in software engineering but MVC takes a lot of the drudgery out of web development and even I can appreciate that. At the very least, you can use it to get a basic CRUD application up and going in minutes. CakePHP supports scaffolding and unit testing. I imagine it is based on Ruby On Rails and emulates many Rail features but I'm more familiar with PHP than Ruby.

I'm studying Flash because it is used for animation. There is a lot of material available on how to animate in Flash. Ultimately I may do all my animation in After Effects though because it is far more versatile than Flash. Flash animation is only the standard for online animation because its vector graphics make it light weight. However, if you are doing all your animation for video then there is less reason to use Flash. Flash is also used to deliver video on the Internet and I'm heavily involved in online video so I should learn all aspects of the technology.

There are some interesting features in Flash that designers don't seem to be taking advantage of. For instance, there is a web service component for Flash but I have not seen many web service clients done in Flash. You can also automate the Flash authoring application using JavaScript and I suspect very little has been done with that.

Over the weekend I went to Philadelphia for a YouTube gathering. I shot lots of footage of historical sites and colonial buildings. This gives me plenty of material to use for my editing experiments.

More Posts « Previous page - Next page »