<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-22643768</id><updated>2011-10-20T05:07:06.701-04:00</updated><category term='WF'/><category term='Database'/><category term='Office'/><category term='Biztalk'/><category term='SharePoint'/><category term='Tools'/><category term='AJAX'/><category term='Misc'/><category term='Compact Framework'/><category term='SOA'/><category term='Taiji'/><category term='Business Intelligence'/><category term='General .NET'/><category term='ASP.NET'/><title type='text'>Jun Meng's blog</title><subtitle type='html'>Technology about computer and ... our body</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>77</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-22643768.post-5098578662793943994</id><published>2010-02-04T12:22:00.003-05:00</published><updated>2010-02-04T12:34:45.881-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>Migrating ASP.NET applications to another Windows Domain</title><content type='html'>You may have to migrate Intranet software applications to another Windows Domain (e.g. Due to company restructure). As Intranet applications normally uses Domain account to authorize user access, changing domain means you have to change user group settings, sometimes source code and sometimes even worse your third-party applications will not work properly -- e.g. old data uses old domain account so that user cannot change their data using new domain account.&lt;br /&gt;&lt;br /&gt;If your applications were based on ASP.NET framework, then there is a simple solution to ease the pain at least temporarily: you keep all those ASP.NET applications in original domain and add a &lt;a href="http://msdn.microsoft.com/en-us/library/ms178468%28VS.85%29.aspx"&gt;HttpModule&lt;/a&gt; (defined in web.config) to map new domain account to old domain account. When users in new domain access those applications in old domain, the ASP.NET application will only see the old domain account so the users still work in the exact same way as before.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_bVjNlhxO13c/S2r-TCdx88I/AAAAAAAAAGA/AH4tjW04LCA/s1600-h/DomainMappingHttpModule.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_bVjNlhxO13c/S2r-TCdx88I/AAAAAAAAAGA/AH4tjW04LCA/s320/DomainMappingHttpModule.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The main code logic for domain mapping HttpModule is as below:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;// Get user's domain account&lt;br /&gt;string strDomainUserAccount = HttpContext.Current.User.Identity.Name.ToUpper();&lt;br /&gt;&lt;br /&gt;// Remove domain name from the account&lt;br /&gt;string strUserAccount = strDomainUserAccount;&lt;br /&gt;if (strDomainUserAccount.StartsWith("NewDomain\\")) {&lt;br /&gt; strUserAccount = strUserAccount.Substring(10);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Fetch cached user mappings&lt;br /&gt;Dictionary&lt;string, string&gt; userMap = (Dictionary&lt;string, string&gt;)HttpRuntime.Cache(USER_CACHE_KEY);&lt;br /&gt;if (userMap == null) {&lt;br /&gt; // If no cache is available, reload the cache from database &lt;br /&gt; // and try to get the item again&lt;br /&gt; this.ReloadUserMap();&lt;br /&gt; &lt;br /&gt; userMap = (Dictionary&lt;string, string&gt;)HttpRuntime.Cache(USER_CACHE_KEY);&lt;br /&gt; if (userMap == null) {&lt;br /&gt;  // Throw exception here!!&lt;br /&gt;  return;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Get user's NTUserName from the mapping in cache &lt;br /&gt;// and create a new user for Http context&lt;br /&gt;if (userMap.ContainsKey(strUserAccount)) {&lt;br /&gt; string strNewAccount = userMap[strUserAccount];&lt;br /&gt; &lt;br /&gt; if (!string.IsNullOrEmpty(strNewAccount)) {&lt;br /&gt;  // New Identity&lt;br /&gt;  string strAuthenticateType = HttpContext.Current.User.Identity.AuthenticationType;&lt;br /&gt;  System.Security.Principal.GenericIdentity newID = &lt;br /&gt;   new System.Security.Principal.GenericIdentity(strNewAccount, strAuthenticateType);&lt;br /&gt;  &lt;br /&gt;  // Get cached roles in mapped domain. &lt;br /&gt;  // If no cache is available, get from AD and put into cache&lt;br /&gt;  string[] strRoles = this.GetDomainGroupsForUserFromCache[strNewAccount];&lt;br /&gt;  System.Security.Principal.GenericPrincipal newP = &lt;br /&gt;   new System.Security.Principal.GenericPrincipal(newID, strRoles);&lt;br /&gt;  &lt;br /&gt;  HttpContext.Current.User = newP;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-5098578662793943994?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/5098578662793943994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=5098578662793943994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5098578662793943994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5098578662793943994'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2010/02/migrating-aspnet-applications-to.html' title='Migrating ASP.NET applications to another Windows Domain'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_bVjNlhxO13c/S2r-TCdx88I/AAAAAAAAAGA/AH4tjW04LCA/s72-c/DomainMappingHttpModule.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-5821389699362794829</id><published>2010-02-03T14:55:00.006-05:00</published><updated>2010-02-03T15:23:39.071-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Compact Framework'/><title type='text'>FlowLayoutPanel for .NET Compact Framework</title><content type='html'>It is quite complex to arrange Windows Form layout dynamically in .NET Compact Framework (CF) when you try to show/hide a control between other controls. Although you can use FlowLayoutPanel in desktop Windows Form application, there is no such kind of layout manager for CF. &lt;br /&gt;&lt;br /&gt;I found &lt;a href="http://www.codeproject.com/KB/miscctrl/CSharpFlowLayoutPanel.aspx"&gt;an old article on CodeProject&lt;/a&gt; about FlowLayoutPanel, but that code cannot work on CF because CF Panel does not have OnLayout event. Also the code logic has bugs too.&lt;br /&gt;&lt;br /&gt;After searching for a while, I decided to make a FlowLayoutPanel for CF by myself. It turns out the code is not hard to write:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;Protected Overloads Overrides Sub OnPaint(ByVal pEvent As PaintEventArgs)&lt;br /&gt; Dim nextTop As Integer = 0, nextLeft As Integer = 0&lt;br /&gt; Dim maxHeight As Integer = 0&lt;br /&gt; Dim ParentWidth As Integer&lt;br /&gt; &lt;br /&gt; If Me.Parent IsNot Nothing Then&lt;br /&gt;  ParentWidth = Me.Parent.Width&lt;br /&gt; Else&lt;br /&gt;  ParentWidth = Me.Width&lt;br /&gt; End If&lt;br /&gt;&lt;br /&gt; ' Modify control location for the layout&lt;br /&gt; For Each myControl As Control In Me.Controls&lt;br /&gt;  ' Ignore invisible controls&lt;br /&gt;  If myControl.Visible = False Then&lt;br /&gt;   Continue For&lt;br /&gt;  End If&lt;br /&gt;&lt;br /&gt;  If (nextLeft + myControl.Width) &amp;gt; ParentWidth Then&lt;br /&gt;   nextTop += maxHeight&lt;br /&gt;   nextLeft = 0&lt;br /&gt;   ' Reset maxHeight&lt;br /&gt;   maxHeight = 0&lt;br /&gt;  End If&lt;br /&gt;&lt;br /&gt;  myControl.Top = nextTop&lt;br /&gt;  myControl.Left = nextLeft&lt;br /&gt;&lt;br /&gt;  If myControl.Height &amp;gt; maxHeight Then&lt;br /&gt;   maxHeight = myControl.Height&lt;br /&gt;  End If&lt;br /&gt;&lt;br /&gt;  nextLeft += myControl.Width&lt;br /&gt; Next&lt;br /&gt; Me.AutoScrollPosition = New System.Drawing.Point(0, 0)&lt;br /&gt;&lt;br /&gt; MyBase.OnPaint(pEvent)&lt;br /&gt;End Sub&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Below is a sample using the logic above:&lt;br /&gt;&lt;br /&gt;&lt;div style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_bVjNlhxO13c/S2nSIBgZ4oI/AAAAAAAAAFw/mY1vrli65S4/s1600-h/ShowPanel3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_bVjNlhxO13c/S2nSIBgZ4oI/AAAAAAAAAFw/mY1vrli65S4/s320/ShowPanel3.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;To make layout easier, I put several panels inside the FlowLayoutPanel. You can see all the controls are arranged properly. When I click the "Hide Panel 3" button, the Form becomes this:&lt;br /&gt;&lt;br /&gt;&lt;div style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_bVjNlhxO13c/S2nTQXHeULI/AAAAAAAAAF4/axQyvamep0I/s1600-h/HidePanel3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_bVjNlhxO13c/S2nTQXHeULI/AAAAAAAAAF4/axQyvamep0I/s320/HidePanel3.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The controls below Panel 3 are moved up automatically. If I click "Show Panel 3" button, the Panel 3 will be displayed at original place and all the controls below it are moved down accordingly.&lt;br /&gt;&lt;br /&gt;The code for the button is like below:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;Private Sub btnHide_Click(ByVal sender As Object, ByVal e As EventArgs)&lt;br /&gt; If btnHide.Text = "Hide Panel 3" Then&lt;br /&gt;  Panel3.Visible = False&lt;br /&gt;  btnHide.Text = "Show Panel 3"&lt;br /&gt; Else&lt;br /&gt;  Panel3.Visible = True&lt;br /&gt;  btnHide.Text = "Hide Panel 3"&lt;br /&gt; End If&lt;br /&gt;&lt;br /&gt; ' Refresh the flow layout panel&lt;br /&gt; Me.FlowLayoutPanel1.Invalidate()&lt;br /&gt;End Sub&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;There is a small problem in Visual Studio though: when you drag-drop a control to the FlowLayoutPanel, Visual Studio always puts the control as the first one inside the FlowLayoutPanel. You need to modify the designer file to manually put those controls in order:&lt;br /&gt;&lt;br /&gt;'FlowLayoutPanel1&lt;br /&gt;'&lt;br /&gt;Me.FlowLayoutPanel1.Controls.Add(Me.Panel1)&lt;br /&gt;Me.FlowLayoutPanel1.Controls.Add(Me.Panel2)&lt;br /&gt;Me.FlowLayoutPanel1.Controls.Add(Me.Panel3)&lt;br /&gt;Me.FlowLayoutPanel1.Controls.Add(Me.Panel5)&lt;br /&gt;Me.FlowLayoutPanel1.Controls.Add(Me.Panel6)&lt;br /&gt;Me.FlowLayoutPanel1.Controls.Add(Me.Panel4)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-5821389699362794829?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/5821389699362794829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=5821389699362794829' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5821389699362794829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5821389699362794829'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2010/02/flowlayoutpanel-for-net-compact.html' title='FlowLayoutPanel for .NET Compact Framework'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_bVjNlhxO13c/S2nSIBgZ4oI/AAAAAAAAAFw/mY1vrli65S4/s72-c/ShowPanel3.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-1539349563607012636</id><published>2008-05-23T13:13:00.003-04:00</published><updated>2008-05-23T13:29:58.631-04:00</updated><title type='text'>Set up Reporting Services in SharePoint Integration Mode</title><content type='html'>I followed &lt;a href="http://msdn.microsoft.com/en-us/library/bb677365.aspx"&gt;How to: Configure SharePoint Integration on Multiple Servers&lt;/a&gt; step-by-step to configure SharePoint Integration on two servers. But on the step "Set server defaults" of "&lt;a href="http://msdn.microsoft.com/en-us/library/bb326213.aspx"&gt;Configure the Report Server Integration Feature in SharePoint Central Administration&lt;/a&gt;", I only saw this error:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;An unexpected error occurred while connecting to the report server. Verify that the report server is available and configured for SharePoint integrated mode.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I was sure I followed the steps carefully. Then I tried to look for error details in Web and Database log files, but there was no any error message. After many hours of investigation, I found somebody mentioned Kerberos/NTLM on &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1282744&amp;SiteID=1"&gt;MSDN Forum&lt;/a&gt;. As my environment did not allow me to use Kerberos, I tried to set up NTLM on both SharePoint server and Report server:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;cscript adsutil.vbs set w3svc/NTAuthenticationProviders "NTLM"&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Then I was so happy to see the error disappeared! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-1539349563607012636?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/1539349563607012636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=1539349563607012636' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/1539349563607012636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/1539349563607012636'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2008/05/set-up-reporting-services-in-sharepoint.html' title='Set up Reporting Services in SharePoint Integration Mode'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-7692266925906611444</id><published>2008-05-09T11:37:00.004-04:00</published><updated>2008-11-15T03:18:07.174-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Business Intelligence'/><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>SSAS Permission for Least-Privilege User Account</title><content type='html'>When using LUA (Least-Privilege User Account) on development machine, I normally add myself as sysadmin for SQL server, so that I can create database freely.&lt;br /&gt;&lt;br /&gt;As SSAS is part of SQL Server, I took it for granted that my account was also sysadmin in SSAS. But it turned out that SSAS has different permission settings from SQL Server.&lt;br /&gt;&lt;br /&gt;When I tried to deploy an SSAS project, Visual Studio threw the error:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Error -1055391738 : Either the '[domain]\[account]' user does not have permission to create a new object in '[machine]', or the object does not exist.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So I went to SQL Server Management Studio and connected to SSAS, but I had no permission to create SSAS database manually:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Either the '[domain]\[account]' user does not have permission to create a new object in '[machine]', or the object does not exist. (Microsoft.AnalysisServices)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One way to solve the problem is to add my account to the SSAS' server role, which means to grant server-wide security privileges to my account in SSAS:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Run SQL Server Management Studio as Administrator account&lt;/li&gt;&lt;li&gt;Connect to the SSAS server&lt;/li&gt;&lt;li&gt;Right-click the SSAS server name and select Properties from the popup menu&lt;/li&gt;&lt;li&gt;Select Security to add account to server role&lt;/li&gt;&lt;/ol&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bVjNlhxO13c/SCR0Y2Hyc8I/AAAAAAAAACk/8706NL7YQU4/s1600-h/SSAS_Security.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_bVjNlhxO13c/SCR0Y2Hyc8I/AAAAAAAAACk/8706NL7YQU4/s400/SSAS_Security.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198407840086258626" /&gt;&lt;/a&gt;&lt;br /&gt;Now, I can deploy SSAS project in Visual Studio without problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-7692266925906611444?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/7692266925906611444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=7692266925906611444' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7692266925906611444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7692266925906611444'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2008/05/ssas-permission-for-least-privilege.html' title='SSAS Permission for Least-Privilege User Account'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_bVjNlhxO13c/SCR0Y2Hyc8I/AAAAAAAAACk/8706NL7YQU4/s72-c/SSAS_Security.PNG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-3719496833556784181</id><published>2008-05-08T15:50:00.005-04:00</published><updated>2008-05-08T16:26:32.882-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>SharePoint can not find user in its domain</title><content type='html'>It's quite weird that SharePoint (WSS 3.0) could not find any Active Directory user account from its own domain!&lt;br /&gt;&lt;br /&gt;According to its log, WSS complained it could not get trusted domains:&lt;br /&gt; &lt;br /&gt;&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;05/08/2008 10:09:18.72  Error when trying to get trusted forests and domains. Exception message: Access is denied.  , callstack:    at System.DirectoryServices.ActiveDirectory.Forest.GetTrustsHelper(String targetForestName)     at System.DirectoryServices.ActiveDirectory.Forest.GetAllTrustRelationships()     at Microsoft.SharePoint.Utilities.SPUserUtility.GetTrustedDomains(List`1 trustedForestNames, List`1 trustedDomainNames)  &lt;br /&gt;05/08/2008 10:09:18.72  Found 1 trusted forests ad.int.com.  &lt;br /&gt;05/08/2008 10:09:18.72  Found 0 trusted domains   &lt;br /&gt;05/08/2008 10:09:18.87  Error in searching user 'Bob' : System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.       at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)     at System.DirectoryServices.DirectoryEntry.Bind()     at System.DirectoryServices.DirectoryEntry.get_AdsObject()     at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)     at System.DirectoryServices.DirectorySearcher.FindAll()     at Microsoft.SharePoint.WebControls.PeopleEditor.SearchFromGC(SPActiveDirectoryDomain domain, String strFilter, String[] rgstrProp, Int32 nTimeout, Int32 nSizeLimit, SPUserCollection spUsers, ArrayList&amp; rgResults)     at Microsoft.SharePoint.Utilities.SPUserUtility.SearchAgainstAD(String input, SPActiveDirect...  &lt;br /&gt;05/08/2008 10:09:18.87* ...oryDomain domainController, SPPrincipalType scopes, SPUserCollection usersContainer, Int32 maxCount, String customQuery, String customFilter, TimeSpan searchTimeout, Boolean&amp; reachMaxCount)     at Microsoft.SharePoint.Utilities.SPActiveDirectoryPrincipalResolver.SearchPrincipals(String input, SPPrincipalType scopes, SPPrincipalSource sources, SPUserCollection usersContainer, Int32 maxCount, Boolean&amp; reachMaxCount)     at Microsoft.SharePoint.Utilities.SPUtility.SearchPrincipalFromResolvers(List`1 resolvers, String input, SPPrincipalType scopes, SPPrincipalSource sources, SPUserCollection usersContainer, Int32 maxCount, Boolean&amp; reachMaxCount, Dictionary`2 usersDict).  &lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;But do I need care if the domain is "trusted" or not when only one domain exists? What I wanted was to get users from the same domain. &lt;a href="http://technet.microsoft.com/en-us/library/cc263460.aspx"&gt;MSDN&lt;/a&gt; also said "Users in the forest that the server is in (that is, a resource forest) are displayed automatically." But the reality was the opposite.&lt;br /&gt;&lt;br /&gt;Finally, I had a try to add the WSS server's local domain using stsadm:&lt;br /&gt;&lt;br /&gt;stsadm -o setproperty -url http://localhost:82&lt;br /&gt;-pn "peoplepicker-searchadforests" -pv "domain:ad.int.com"&lt;br /&gt;&lt;br /&gt;Although I had thought that the command should do nothing because I was not supposed to do that, ironically I could see users in the PeoplePicker control! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-3719496833556784181?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/3719496833556784181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=3719496833556784181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3719496833556784181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3719496833556784181'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2008/05/sharepoint-can-not-find-user-in-its.html' title='SharePoint can not find user in its domain'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-8244494098198173847</id><published>2008-04-02T11:24:00.006-04:00</published><updated>2008-05-08T16:24:00.101-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>SharePoint XML Web Part and proxy setting</title><content type='html'>XML Web Part is quite useful when you want to collect data from other sites (e.g. RSS).  Yesterday I wanted to display local weather information using &lt;a href="http://www.weather.com/services/xmloap.html"&gt;Weather.com XML Data Feed&lt;/a&gt;. I followed these steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Registered to &lt;a href="http://www.weather.com/services/xmloap.html"&gt;weather.com&lt;/a&gt; to download the SDK (to use weather images)&lt;/li&gt;&lt;li&gt;Copied SDK images to TEMPLATE\Images\weather\&lt;/li&gt;&lt;li&gt;Added XML Web Part to WSS site and set URL to &lt;pre&gt;http://xoap.weather.com/weather/local/(zipcode)?cc=*&amp;amp;prod=xoap&lt;br /&gt;&amp;amp;unit=e&amp;amp;par=null&amp;amp;key=(license key)&lt;/pre&gt;[Update] Weather.com has changed the URL to &lt;pre&gt;http://xoap.weather.com/weather/local/[zipcode]?cc=*&amp;dayf=5&lt;br /&gt;&amp;link=xoap&amp;prod=xoap&amp;par=[PartnerID]&amp;key=[LicenseKey]&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Set up XSLT to display weather images&lt;/li&gt;&lt;/ol&gt;But I got errors on different WSS machines:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;"Cannot retrieve the URL specified in the XML Link property"&lt;/li&gt;&lt;li&gt;"The web part has timed out"&lt;/li&gt;&lt;/ol&gt;The reason was my WSS sites were behind a proxy server. WSS XML Web Part need know proxy settings, otherwise it can not access the URL.&lt;br /&gt;&lt;br /&gt;The first error happens when the WSS application pool does not use a domain account; the second error happens when a domain account is used.&lt;br /&gt;&lt;br /&gt;After I added proxy settings in web.config, the problem was solved:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!-- Proxy setting --&amp;gt;&lt;br /&gt;&amp;lt;system.net&amp;gt;&lt;br /&gt;  &amp;lt;defaultproxy useDefaultCredentials="true"&amp;gt;&lt;br /&gt;    &amp;lt;proxy usesystemdefault="false"&lt;br /&gt;              proxyaddress="http://proxyServer:port"&lt;br /&gt;              bypassonlocal="true"&amp;gt;&lt;br /&gt;    &amp;lt;/proxy&amp;gt;&lt;br /&gt;  &amp;lt;/defaultproxy&amp;gt;&lt;br /&gt;&amp;lt;/system.net&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-8244494098198173847?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/8244494098198173847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=8244494098198173847' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8244494098198173847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8244494098198173847'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2008/04/sharepoint-xml-web-part-and-proxy.html' title='SharePoint XML Web Part and proxy setting'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-7364436065391471837</id><published>2008-02-15T09:57:00.003-05:00</published><updated>2008-11-15T03:18:07.485-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>ZoomIt</title><content type='html'>This post is mainly for my own recall.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://rshelton.com/archive/2008/02/14/free-download-free-zoom-utility-for-windows.aspx"&gt;Robert Shelton&lt;/a&gt; provides a link for the excellent &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897434.aspx"&gt; screen zoom and annotation tool&lt;/a&gt; for Windows. It is quite useful for presentation of course, but also useful to zoom in/out high resolution screen during normal work.&lt;br /&gt;&lt;br /&gt;I tried on my computer just now:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bVjNlhxO13c/R7Wqc_tLbYI/AAAAAAAAACc/mEbNYdJAFoc/s1600-h/ZoomIt.GIF"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_bVjNlhxO13c/R7Wqc_tLbYI/AAAAAAAAACc/mEbNYdJAFoc/s400/ZoomIt.GIF" border="0" alt=""id="BLOGGER_PHOTO_ID_5167223562591497602" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-7364436065391471837?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/7364436065391471837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=7364436065391471837' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7364436065391471837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7364436065391471837'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2008/02/zoomit.html' title='ZoomIt'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_bVjNlhxO13c/R7Wqc_tLbYI/AAAAAAAAACc/mEbNYdJAFoc/s72-c/ZoomIt.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-2922074185779724820</id><published>2008-01-31T13:42:00.000-05:00</published><updated>2008-01-31T14:00:54.558-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>Reports cannot be deployed from VS 2005 to Reporting Services in WSS integration mode</title><content type='html'>I tried to deploy reports from VS 2005 from Dev machine to Prod Report Server across different domains, but VS 2005 did not allow me to deploy. &lt;br /&gt;&lt;br /&gt;The Reporting Services on Prod was set up in WSS integration mode. I set up TargetDataSourceFolder, TargetReportFolder and TargetServerURL in VS 2005 on my Dev machine as mentioned in MSDN article "&lt;a href="http://msdn2.microsoft.com/en-us/library/bb326288.aspx"&gt;Deploying Reports, Models, and Shared Data Sources to a SharePoint Site&lt;/a&gt;". Then I tried to deploy reports to Prod machine. But VS 2005 keeps showing "Report Services Login" window, even when I used Administrator account of Prod.&lt;br /&gt;&lt;br /&gt;The WSS log file on the Prod machine shows this error: "The file you are attempting to save or retrieve has been blocked from this Web site by the server administrators."&lt;br /&gt;&lt;br /&gt;Solution? After two-day frustration and research, then the problem was solved: I need use Internet Explorer to log into WSS and check the "Remember my password" checkbox (Very important!). Then I could deploy from VS 2005 without seeing the login dialog window. The deployed report on Prod showed the author was the same account that I used to login from IE.&lt;br /&gt;&lt;br /&gt;The same trick can be applied to Report Builder. When user tries to use Report Builder in WSS to build ad-hoc report, he/she should make sure to check the "Remember my password" checkbox in the login window. Otherwise, the user will see "unauthorized" error when downloading Report Builder application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-2922074185779724820?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/2922074185779724820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=2922074185779724820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/2922074185779724820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/2922074185779724820'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2008/01/reports-cannot-be-deployed-from-vs-2005.html' title='Reports cannot be deployed from VS 2005 to Reporting Services in WSS integration mode'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-7756927684788207050</id><published>2008-01-15T14:36:00.000-05:00</published><updated>2008-01-15T14:44:43.222-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>Do not remove VS 2005 and install VS 2008 if ...</title><content type='html'>Do not remove VS 2005 from your computer and install VS 2008 if:&lt;br /&gt;&lt;br /&gt;1. You want to develop Business Intelligence solutions with SQL Server 2005, because VS 2008 does not support those projects (Report Designer, Report Model ...). Or to say, Microsoft does not want you to work on SQL Server 2005 with their own latest IDE!&lt;br /&gt;&lt;br /&gt;2. You want to build Workflow (WF) solution for SharePoint. You will realize the old way in VS 2005 to install Features.xml is easier to use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-7756927684788207050?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/7756927684788207050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=7756927684788207050' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7756927684788207050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7756927684788207050'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2008/01/do-not-remove-vs-2005-and-install-vs.html' title='Do not remove VS 2005 and install VS 2008 if ...'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-9105212905139563593</id><published>2007-12-31T15:23:00.000-05:00</published><updated>2008-11-15T03:18:08.045-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>WSS Workflow Modification Form</title><content type='html'>It is easy to find WSS ASP.NET samples for Instantiation and Task Edit forms, but it is hard to find sample for Modification form. Maybe many people think there is no much difference, but is that true?&lt;br /&gt;&lt;br /&gt;Modification form is quite useful in WSS work flow. For example, after a long running task has been assigned to an analyst, the analyst takes vacation for weeks. At this point, the Modification form can be used to reassign the task to another person.&lt;br /&gt;&lt;br /&gt;You can define Modification form in Feature file with the similar way for Instantiation form. But how about the workflow part?&lt;br /&gt;&lt;br /&gt;Instantiation form happens at the very beginning of a workflow, but Modification can happen anywhere in a scope. &lt;br /&gt;&lt;br /&gt;A common way to define Modification in workflow is to put EnableWorkflowModification activity inside an EventHandlingScope activity. Other activities inside the same scope do the normal work. When Modification form is accessed, an event will raised to the workflow, so that the EventHandlingScope activity can handle the event and call event handler.&lt;br /&gt;&lt;br /&gt;In Visual Studio, right-click the EventHandlingScope activity and select "view event handlers":&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bVjNlhxO13c/R3lSnzHb8kI/AAAAAAAAACE/F30a9nUXoVE/s1600-h/EventHandlingScope_1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_bVjNlhxO13c/R3lSnzHb8kI/AAAAAAAAACE/F30a9nUXoVE/s320/EventHandlingScope_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5150238492564648514" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then you can add OnWorkflowModified and UpdateTask activities to the EventHandlersActivity:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bVjNlhxO13c/R3lTJTHb8lI/AAAAAAAAACM/Cypw2iUovrU/s1600-h/EventHandlingScope_2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_bVjNlhxO13c/R3lTJTHb8lI/AAAAAAAAACM/Cypw2iUovrU/s320/EventHandlingScope_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5150239068090266194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Modification activities have their own ContextData and CorrelationToken, because they are actually outside the normal workflow.&lt;br /&gt;&lt;br /&gt;One issue I saw: If there is an OnTaskChanged activity already defined in the EventHandlingScope (like below), you had better not add another OnTaskChanged activity inside the EventHandlersActivity; otherwise, you would be surprised to see only one OnTaskChanged activity is called.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_bVjNlhxO13c/R3lT5jHb8mI/AAAAAAAAACU/j05pHF6swYU/s1600-h/EventHandlingScope_3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_bVjNlhxO13c/R3lT5jHb8mI/AAAAAAAAACU/j05pHF6swYU/s320/EventHandlingScope_3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5150239897018954338" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-9105212905139563593?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/9105212905139563593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=9105212905139563593' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/9105212905139563593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/9105212905139563593'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/12/wss-workflow-modification-form.html' title='WSS Workflow Modification Form'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_bVjNlhxO13c/R3lSnzHb8kI/AAAAAAAAACE/F30a9nUXoVE/s72-c/EventHandlingScope_1.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-8424976438753766752</id><published>2007-12-27T16:22:00.000-05:00</published><updated>2007-12-28T11:23:34.353-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><title type='text'>WSS Content Type Was Not Updated</title><content type='html'>I tried to update a content type in WSS, but the system was still using the older version of content type somehow. After two-day frustration, I found out why :(&lt;br /&gt;&lt;br /&gt;Here was what happened in the beginning: I created a simple content type like below:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&amp;lt;ContentType ID="0x01080100B7336179CFFE43e59B86E241C767010E" Name="GradingTask" Group="Grading" Description="Grading Task" Version="0" Hidden="FALSE"&amp;gt;&lt;br /&gt;  &amp;lt;/ContentType&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The content type worked perfectly and I added several items of GradingTask type to a list. Then I thought: How about adding custom Edit/Display pages? So I added these lines to the configuration:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;    &amp;lt;XmlDocuments&amp;gt;&lt;br /&gt;      &amp;lt;XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url"&amp;gt;&lt;br /&gt;        &amp;lt;FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url"&amp;gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);font-size:85%;" &gt;&amp;lt;Edit&amp;gt;_layouts/Grades/GradesTaskEditForm.aspx&amp;lt;/Edit&amp;gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;          &lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);font-size:85%;" &gt;&amp;lt;Display&amp;gt;_layouts/Grades/GradesTaskEditForm.aspx&amp;lt;/Display&amp;gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;        &amp;lt;/FormUrls&amp;gt;&lt;br /&gt;      &amp;lt;/XmlDocument&amp;gt;&lt;br /&gt;    &amp;lt;/XmlDocuments&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After I installed the updated content type and tried to edit a task, WSS kept showing me the default EditForm.aspx page, not the GradesTaskEditForm.aspx. Then I tried to deactivate and uninstall the content type for many times, but WSS still used the default page.&lt;br /&gt;&lt;br /&gt;Finally, I saw a line in the "Real World SharePoint 2007" book: When you use Feature to install a new version of Content Type, WSS does not support cascading update if inherited content type is used somewhere. (No quote)&lt;br /&gt;&lt;br /&gt;Oh ... That is the reason why I failed to overwrite the old content type definition -- WSS kept GradingTask's meta data for the list even after the Feature was uninstalled. &lt;br /&gt;&lt;br /&gt;So I deleted all items of that GradingTask type, removed workflow setting, detached the content type from the list, deactivated/uninstalled the feature, deleted the list and then reinstalled/activated the feature, ... ... finally my lovely custom Edit page showed up :)&lt;br /&gt;&lt;br /&gt;According to the book, to support cascading update I need write code using WSS object model API to force cascading update ... I would try that later.&lt;br /&gt;&lt;br /&gt;[Updated 12/28/2007] I saw &lt;a href="http://soerennielsen.wordpress.com/2007/09/11/propagate-site-content-types-to-list-content-types/"&gt;this great article&lt;/a&gt; this morning to deal with the mess of Content Type inheritance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-8424976438753766752?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/8424976438753766752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=8424976438753766752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8424976438753766752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8424976438753766752'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/12/wss-content-type-was-not-updated.html' title='WSS Content Type Was Not Updated'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-8682088493818386646</id><published>2007-12-17T17:00:00.000-05:00</published><updated>2007-12-17T17:08:34.551-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><category scheme='http://www.blogger.com/atom/ns#' term='Office'/><title type='text'>Can I use SharePoint Workflow on SPGridView?</title><content type='html'>Nowadays, it is quite easy to find articles about how beautiful it is to use Microsoft SharePoint 2007 Workflow and InfoPath to manage Documents or List. &lt;br /&gt;&lt;br /&gt;But I am too poor to buy MOSS 2007 and InfoPath, is it possible to use WSS 3.0 Workflow frame to manage normal business objects (e.g. purchase orders, law suit cases) in an ASP.NET SPGridView on a WSS 3.0 site? Or to say, can I build a WSS Workflow and related ASP.NET pages (Workflow Association, Instatiation, Modification, and Task Edit pages) in Visual Studio, then use that workflow for each item of an ASP.NET SPGridView and modify data stored in a standalone database (not WSS Content database)? &lt;br /&gt;&lt;br /&gt;From my current understanding, the answer is: No, because SharePoint Workflow processes SPListItem, not item of SPGridView; and of course, you are not supposed to create task from your code because the task is of SPWorkflowTask type that can only be created from SPWorkflow.&lt;br /&gt;&lt;br /&gt;Ok ... fine. How about creating a SharePoint List to hold my business objects but I need save my business objects in a separate database?&lt;br /&gt;&lt;br /&gt;Well ... To use SharePoint List, you have to create list columns inside SharePoint Content database, not in other databases.  &lt;br /&gt;&lt;br /&gt;&amp;*%*^%%^$&lt;br /&gt;&lt;br /&gt;So from my current understanding, if I want to use WSS 3.0 workflow framework for my own business objects in a standalone database (S_DB), I have to create a List and several columns (for display and search purposes) in WSS site. Those columns are duplicated because they are already defined in database S_DB. &lt;br /&gt;&lt;br /&gt;When user starts workflow on the list item, the workflow (Instatiation) ASP.NET page will use ADO.NET code to load other fields from database S_DB. Then the ASP.NET page should save updated data back to S_DB, and at the same time save the data of the List columns to WSS Content database too.&lt;br /&gt;&lt;br /&gt;Is there a better way to avoid data duplication in WSS Content database and the other standalone database?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-8682088493818386646?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/8682088493818386646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=8682088493818386646' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8682088493818386646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8682088493818386646'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/12/can-i-use-sharepoint-workflow-on.html' title='Can I use SharePoint Workflow on SPGridView?'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-3578918741433197355</id><published>2007-12-17T15:56:00.000-05:00</published><updated>2007-12-17T16:09:58.736-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>Convert Access database to SQL Server 2005</title><content type='html'>In one of my projects, I need analyze data in an Access application. Frankly speaking, that is the best Access application I have seen so far: with many front-end Access forms, users can input data to the back-end single Access database.&lt;br /&gt;&lt;br /&gt;But Access is not designed for client-server mode anyway. A lock file is needed to only allow one user to lock a table at one time. Sometimes, users have to wait for minutes for others to finish a simple data update operation.&lt;br /&gt;&lt;br /&gt;For me, I am not a fan of Access, although I was amazed by how that Access application worked. So I decide to convert to SQL Server database.&lt;br /&gt;&lt;br /&gt;But how? Although SQL Server Integration Service (SSIS) can import data from Access, it is hard to maintain database settings (e.g. foreign-key relationship, etc). Today, I found &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=D842F8B4-C914-4AC7-B2F3-D25FFF4E24FB&amp;displaylang=en"&gt;SQL Server Migration Assistant for Access&lt;/a&gt; from Microsoft. Now my life is easier :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-3578918741433197355?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/3578918741433197355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=3578918741433197355' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3578918741433197355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3578918741433197355'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/12/convert-access-database-to-sql-server.html' title='Convert Access database to SQL Server 2005'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-8919180986317485875</id><published>2007-08-07T14:02:00.000-04:00</published><updated>2007-08-07T14:46:27.394-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Why "using" is bad for your WCF service host</title><content type='html'>I scratched my head this morning for a WCF service host program. It threw a very generic exception like this:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;“The communication object, System.ServiceModel.ServiceHost, cannot be used for communication because it is in the Faulted state.”&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The exception above had no any useful information about where the real problem was. The logic of my program was simple:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using(ServiceHost host = new ServiceHost(&lt;br /&gt;    typeof(MyService), new Uri("http://localhost:8080/MyService"))&lt;br /&gt;{&lt;br /&gt;    host.Open();&lt;br /&gt;    ... ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;When I looked inside Output of VS 2005, I saw this log information:&lt;br /&gt;&lt;br /&gt;'System.ServiceModel.AddressAlreadyInUseException'&lt;br /&gt;&lt;br /&gt;But why WCF did not give me that exception directly? Finally, this blog explains the reason: &lt;a href="http://blogs.msdn.com/salvapatuel/archive/2007/04/25/why-using-is-bad-for-your-wcf-service-host.aspx"&gt;Why "using" is bad for your WCF service host&lt;/a&gt;.&lt;br /&gt;------------------------------------------&lt;br /&gt;&lt;em&gt;&lt;pre&gt;ServiceHost Host = null;&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;       Host = new ServiceHost(MySingletonService);&lt;br /&gt;       Host.Open();&lt;br /&gt;       Console.ReadKey();&lt;br /&gt;       Host.Close();&lt;br /&gt;}&lt;br /&gt;finally&lt;br /&gt;{&lt;br /&gt;       if (Host != null)&lt;br /&gt;              ((IDisposable)Host).Dispose();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The configuration exception is thrown by the “Host.Open()” line, the code jumps into the finally block and tries to dispose the host. Here the host is not null but it is in a faulty state, this means that it cannot be disposed and this raises the second exception that you usually see on your application.&lt;br /&gt;&lt;br /&gt;The lesson learn is “do not use ‘using’ to host your WCF service”.&lt;/em&gt;&lt;br /&gt;------------------------------------------&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-8919180986317485875?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/8919180986317485875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=8919180986317485875' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8919180986317485875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/8919180986317485875'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/08/why-using-is-bad-for-your-wcf-service.html' title='Why &quot;using&quot; is bad for your WCF service host'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-5275225418517786488</id><published>2007-07-24T16:01:00.001-04:00</published><updated>2010-02-04T12:42:10.066-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Taiji'/><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>Traditional Chinese medicine to cure "incurable" diseases</title><content type='html'>I did not read technical books for weeks after I finished my project (which is rare for me), because I was reading/studying a more important thing for our daily life: traditional Chinese medicine, that can even cure some so-called "incurable" diseases, such as cancers, or AIDS!&lt;br /&gt;&lt;br /&gt;Frankly speaking, I had been disappointed by Chinese doctors for a long long time since I was a child. My previous impression was Chinese medicine/method were too slow for illness, until recently I began to know several real Chinese doctors and their treatments. &lt;br /&gt;&lt;br /&gt;One doctor is &lt;a href="http://www.hantang.com/"&gt;Mr. Ni Haisha&lt;/a&gt; (Please don't be cheated by his English site for Acupuncture, that is only because USA has no license for Chinese medicine yet). His Chinese site has far more great information about why/how about cancers than his &lt;a href="http://www.hantang.com/english/en_Articles/researchstudy.htm"&gt;English site&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Chinese medicine takes our body as a whole system. For example, the root reason for the &lt;a href="http://www.hantang.com/english/en_Articles/breastpro-5.htm"&gt;breast cancer&lt;/a&gt; is because heart and small intestine are weak. But Western medicine takes our body as separate items. That is the reason why Western medicine does not work.&lt;br /&gt;&lt;br /&gt;If Chinese medicine is so good, but why the medicine from many Chinese doctors is not effective, and even many Chinese doctors take western medicine by themselves for illness? The reasons are quite complex. Basically, Chinese medicine is like "art", not many good doctors exist; many Chinese doctors learned in a wrong way; Chinese government admired western technology too much and ignored real jewels/wisdom in the long Chinese history ...&lt;br /&gt;&lt;br /&gt;How to find a good doctor? If your feet get warm after you take Chinese medicine, then that doctor is a good doctor; otherwise, if you still feel cold in your feet, and your symptoms still exist, then that doctor is likely a fake Chinese doctor. &lt;br /&gt;&lt;br /&gt;Currently, I know two Chinese doctors are good: &lt;a href="http://www.hantang.com/english/en_index.html"&gt;Mr. Ni&lt;/a&gt; and &lt;a href="http://www.yuanji.org/contact_us.htm"&gt;Mr. Huo&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-5275225418517786488?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/5275225418517786488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=5275225418517786488' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5275225418517786488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5275225418517786488'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/07/traditional-chinese-medicine-to-cure.html' title='Traditional Chinese medicine to cure &quot;incurable&quot; diseases'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-6484026942810747226</id><published>2007-07-24T15:44:00.000-04:00</published><updated>2007-07-24T15:59:32.013-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'># in URL</title><content type='html'>It may be obvious to many people: if # is included in URL, it refers to a relative location of current HTML page in browser. For example, URL "http://somewhere.com/home.htm#section1" refers to ID "section1" on "home.htm" page. So what's the point to mention again here?&lt;br /&gt;&lt;br /&gt;The interesting thing happens when the URL is used between ASP.NET web services: The IIS server side cannot get the whole URL if a client sends URL with #. Basically, the ASP.NET web service can only get the front part of URL. Everything behind # will not be available to web service.&lt;br /&gt;&lt;br /&gt;So if web service client wants to send parameter ("#1", "#2", or "#3") to web service, sorry, the service side cannot see that parameter.&lt;br /&gt;&lt;br /&gt;A bug in my recent project was related with this issue: a telephony system sent dynamic URL to web services, sometimes with # in the URL.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-6484026942810747226?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/6484026942810747226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=6484026942810747226' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/6484026942810747226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/6484026942810747226'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/07/in-url.html' title='# in URL'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-7173519989750686317</id><published>2007-06-15T13:56:00.000-04:00</published><updated>2007-06-15T14:22:49.528-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Crystal Report generates PDF in different fonts on different servers</title><content type='html'>We were satisfied with Crystal Report (CR) to generate PDF on the fly until we put CR templates on production servers. &lt;br /&gt;&lt;br /&gt;The CR templates were tested on DEV and QA servers without any problem. But when the templates were put onto production box, we were amazed how messy the generated PDF looked like: the font size were mysteriously changed and paragraphs overlapped! @^@&lt;br /&gt;&lt;br /&gt;I searched for reasons on Internet for hours, until I found one possible answer &lt;a href="http://diamond.businessobjects.com/node/2905"&gt;here&lt;/a&gt;: &lt;span style="font-style:italic;"&gt;Typically when you are seeing page formatting issues on different machines, it could be because of printer drivers (or lack of). The reporting engine relies on the printer driver configured on the machine to provide information so that a page can be properly rendered. If you designed the report on your dev machine which is using PrinterA and then deploy to another machine using PrinterB, the formatting could be off. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My program was a .NET web service to create PDF document using ExportToDisk not PrintToPrinter:&lt;br /&gt;&lt;pre&gt;oDocument.ExportToDisk(&lt;br /&gt;     ExportFormatType.PortableDocFormat, sOutputFile);&lt;/pre&gt;&lt;br /&gt;so I wondered if the printer was the real problem. After I was told the production server pointed to the exact same printer as QA server, I reluctantly asked IT to check version of printer driver on both servers.&lt;br /&gt;&lt;br /&gt;Then ... IT told me that the servers had different versions of printer driver even they pointed to same printer. After IT installed the same latest drivers on servers, the formating issue was resolved. :)&lt;br /&gt;&lt;br /&gt;Although we had to postpone production delivery, it's good to know some software use printer driver to arrange layout internally.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-7173519989750686317?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/7173519989750686317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=7173519989750686317' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7173519989750686317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7173519989750686317'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/06/crystal-report-generates-pdf-in.html' title='Crystal Report generates PDF in different fonts on different servers'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-726923590289851531</id><published>2007-06-04T12:31:00.000-04:00</published><updated>2008-11-15T03:18:08.448-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='Biztalk'/><title type='text'>Zero to Biztalk Weekend</title><content type='html'>In the wonderful "Zero to Biztalk Weekend", Biztalk expert Geoff Snowman gave us two-day FREE hands-on labs and demos about Biztalk 2006 (and R2)! The hands-on labs were well designed and the lab document was in great details. &lt;br /&gt;&lt;br /&gt;Biztalk is a useful product to integrate systems together. From concept, it receives messages from Receive Adapter/Port, processes messages in Orchestration (optional), and sends out messages using Send Adapter/Port. Biztalk can run long-running transactions, which is very important for real world business.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_bVjNlhxO13c/RmQ_tpGkQtI/AAAAAAAAAB8/OoKOB1GkRVY/s1600-h/BTS_Messaging.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_bVjNlhxO13c/RmQ_tpGkQtI/AAAAAAAAAB8/OoKOB1GkRVY/s320/BTS_Messaging.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5072249133686080210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Below are the agenda and my comments for the labs:&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Saturday (06/02/2007)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   1. Architecture and Content-Based Routing: Deciding Where to Send a Message&lt;br /&gt; &lt;br /&gt; This hello-world type XCopy lab uses File adapter to receive and send files without transformation. This is a good introduction of Biztalk adapter concept.&lt;br /&gt; &lt;br /&gt;   2. The BizTalk Mapper: Transforming Between Message Formats&lt;br /&gt;   &lt;br /&gt; Biztalk uses XML intenally to represent messages. When Biztalk integrates multiple systems, it is necessary to transform different data schemas into one internal schema; after business process, Biztalk will transform internal XML to according external schema.&lt;br /&gt; &lt;br /&gt; But how to deal with non-XML input, such as flat file? Well, that is a topic in the second-day lab.&lt;br /&gt;   &lt;br /&gt;   3. The SQL and FTP Adapters: Sending Messages to Databases and IIS&lt;br /&gt;   &lt;br /&gt; FTP adapter has the same logic with normal FTP client software, which is easy to use.&lt;br /&gt;   &lt;br /&gt; SQL adapter is a little complex: to map Biztalk XML schema to database table or stored procedure parameters. Fortunately there is a wizard to generate the interesting SQL schema.&lt;br /&gt;   &lt;br /&gt;   4. Creating a Simple Business Process. Publishing a Business Process as a Web Service. Using the SOAP Adapter&lt;br /&gt;   &lt;br /&gt; Orchestration with complex workflow can be published as a normal web service. Unlike using File adapter where Biztalk checks file system periodically for new file, Web Service request can go directly into Message Box without waiting for Biztalk polling. I believe Biztalk server uses similar machenism of SQL Server Notification Service to notify an Orchestration a request is coming.&lt;br /&gt;   &lt;br /&gt;   5. Correlation: Which Instance of My Business Process Sees My Incoming Message?&lt;br /&gt;   &lt;br /&gt; Correlation has been one of exciting build-in features of Biztalk for a long time. Correlation is normally used to match responses with proper original requests sent out by Orchestration. You do not need write code for correlation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Sunday (06/03/2007)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   1. The Flat File Wizard and the Pipeline Designer: Dealing with Text Files.&lt;br /&gt;   &lt;br /&gt; Biztalk 2006 has a new Wizard to convert Flat file into XML. The wizard parse a sample flat file data to let user select delimiter and generate XML schema. The wizard is easy to use.&lt;br /&gt;   &lt;br /&gt; But how about binary file? Is there a wizard to parse and generate XML schema? No, you have to write your own pipeline component to parse binary format.&lt;br /&gt;   &lt;br /&gt;   2. Integrating with SharePoint and InfoPath&lt;br /&gt;   &lt;br /&gt; Biztalk has Human Workflow solution. Its name sounds good, but remember: Do not use it! The reason is we have SharePoint 2007 with built-in workflow feature. SharePoint and InfoPath are good tools for people to approve/decline messages, and Biztalk can communicate with SharePoint database.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bVjNlhxO13c/RmQ_i5GkQsI/AAAAAAAAAB0/woYmHULHx9E/s1600-h/BTS_MOSS.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_bVjNlhxO13c/RmQ_i5GkQsI/AAAAAAAAAB0/woYmHULHx9E/s320/BTS_MOSS.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5072248949002486466" /&gt;&lt;/a&gt;&lt;br /&gt;   &lt;br /&gt;   3. The Business Rules Engine: Separating the Business Logic from the Application&lt;br /&gt;   &lt;br /&gt; Biztalk is not only used for we developers, of course. Business people has a tool to modify business rules (e.g. change pricing rate, change approve/decline rules). &lt;br /&gt;   &lt;br /&gt;   4. Business Activity Monitoring: Tracking the Business Process (Demo)&lt;br /&gt; &lt;br /&gt; BAM is valuable to business people to track activities in their own vocabulary. I am not so sure if it is built on SQL Server Reporting Service or not, but it looks similar.&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;Overall, the two-day training is very good to know architecture of Biztalk and have some hand-on experience. With time limit, it is hard to know the internal of Biztalk in only two days. I am waiting for level 200 or 300 training in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-726923590289851531?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/726923590289851531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=726923590289851531' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/726923590289851531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/726923590289851531'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/06/zero-to-biztalk-weekend.html' title='Zero to Biztalk Weekend'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_bVjNlhxO13c/RmQ_tpGkQtI/AAAAAAAAAB8/OoKOB1GkRVY/s72-c/BTS_Messaging.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-7891411562664240927</id><published>2007-04-11T10:37:00.000-04:00</published><updated>2008-11-15T03:18:08.664-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>To remove “Is Identity” setting in SQL Server: Not simple</title><content type='html'>Yesterday I found a seems-like-simple SQL problem: It is a simple task inside SQL Server Enterprise Manager (Management Studio), but there is no simple single SQL statement to set “Is Identity” to “no” for a table column. Because the setting is not a constraint, “alter table” statement does not work.&lt;br /&gt;&lt;br /&gt;It turns out I have to create a same temporary column, copy all data to that new column, remove the original column, and rename the temporary column back to that original name. Another way is to create a temporary table without setting "Is Identity" and copy all data ... Oh my, such a “simple” work!&lt;br /&gt;&lt;br /&gt;But fortunately there is a tip available to generate SQL script for database schema change: In SQL Server Enterprise Manager, when you change table schema, you can let Enterprise Manager generate the schema change script for you. The most left button of this tool bar is used to “Generate change script”:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bVjNlhxO13c/RhzzdDIxU-I/AAAAAAAAABs/sd2_HF-c41A/s1600-h/GenerateSQLScript.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_bVjNlhxO13c/RhzzdDIxU-I/AAAAAAAAABs/sd2_HF-c41A/s320/GenerateSQLScript.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5052180562386703330" /&gt;&lt;/a&gt;&lt;br /&gt;Yesterday, I used it to generate a complex script to remove “Identity” setting for a column:&lt;br /&gt;&lt;pre&gt;-- To remove Identity setting of the Id column&lt;br /&gt;BEGIN TRANSACTION&lt;br /&gt;SET QUOTED_IDENTIFIER ON&lt;br /&gt;SET ARITHABORT ON&lt;br /&gt;SET NUMERIC_ROUNDABORT OFF&lt;br /&gt;SET CONCAT_NULL_YIELDS_NULL ON&lt;br /&gt;SET ANSI_NULLS ON&lt;br /&gt;SET ANSI_PADDING ON&lt;br /&gt;SET ANSI_WARNINGS ON&lt;br /&gt;COMMIT&lt;br /&gt;BEGIN TRANSACTION&lt;br /&gt;GO&lt;br /&gt;ALTER TABLE dbo.partner_attribute_name&lt;br /&gt;  DROP CONSTRAINT DF_partner_attribute_name_last_update_date&lt;br /&gt;GO&lt;br /&gt;ALTER TABLE dbo.partner_attribute_name&lt;br /&gt;  DROP CONSTRAINT DF_partner_attribute_name_creation_date&lt;br /&gt;GO&lt;br /&gt;-- Create a temp table&lt;br /&gt;CREATE TABLE dbo.Tmp_partner_attribute_name&lt;br /&gt; (&lt;br /&gt; partner_attribute_name_id int NOT NULL,&lt;br /&gt; attribute_name varchar(50) NOT NULL,&lt;br /&gt; description varchar(200) NOT NULL,&lt;br /&gt; last_update_date datetime NOT NULL,&lt;br /&gt; creation_date datetime NOT NULL&lt;br /&gt; )  ON [PRIMARY]&lt;br /&gt;GO&lt;br /&gt;ALTER TABLE dbo.Tmp_partner_attribute_name ADD CONSTRAINT&lt;br /&gt;  DF_partner_attribute_name_last_update_date &lt;br /&gt;  DEFAULT (getdate()) FOR last_update_date&lt;br /&gt;GO&lt;br /&gt;ALTER TABLE dbo.Tmp_partner_attribute_name ADD CONSTRAINT&lt;br /&gt;  DF_partner_attribute_name_creation_date &lt;br /&gt;  DEFAULT (getdate()) FOR creation_date&lt;br /&gt;GO&lt;br /&gt;-- Copy all data to the temp table&lt;br /&gt;IF EXISTS(SELECT * FROM dbo.partner_attribute_name)&lt;br /&gt;  EXEC('INSERT INTO dbo.Tmp_partner_attribute_name&lt;br /&gt;   (partner_attribute_name_id, attribute_name&lt;br /&gt;    , description, last_update_date, creation_date)&lt;br /&gt;    SELECT partner_attribute_name_id&lt;br /&gt;     , attribute_name, description&lt;br /&gt;     , last_update_date, creation_date &lt;br /&gt;    FROM dbo.partner_attribute_name &lt;br /&gt;    WITH (HOLDLOCK TABLOCKX)')&lt;br /&gt;GO&lt;br /&gt;DROP TABLE dbo.partner_attribute_name&lt;br /&gt;GO&lt;br /&gt;EXECUTE sp_rename N'dbo.Tmp_partner_attribute_name'&lt;br /&gt;    , N'partner_attribute_name', 'OBJECT' &lt;br /&gt;GO&lt;br /&gt;ALTER TABLE dbo.partner_attribute_name ADD CONSTRAINT&lt;br /&gt;    PK_partner_attribute_name PRIMARY KEY CLUSTERED &lt;br /&gt;    (&lt;br /&gt;        partner_attribute_name_id&lt;br /&gt;    ) ON [PRIMARY]&lt;br /&gt;GO&lt;br /&gt;COMMIT&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Note: You should generate the script BEFORE you save the changes in EM. Otherwise, that button will be disabled.&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-7891411562664240927?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/7891411562664240927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=7891411562664240927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7891411562664240927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7891411562664240927'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/04/to-remove-is-identity-setting-in-sql.html' title='To remove “Is Identity” setting in SQL Server: Not simple'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_bVjNlhxO13c/RhzzdDIxU-I/AAAAAAAAABs/sd2_HF-c41A/s72-c/GenerateSQLScript.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-3262126580549469467</id><published>2007-04-05T11:49:00.000-04:00</published><updated>2007-04-05T11:51:29.397-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>A small compiler - Wilco Syntax Highlighting</title><content type='html'>Although I am quite busy these days for my projects at hand, I still try to find time to do what I really want: to dig into compiler, operating system, and CLR framework.&lt;br /&gt;&lt;br /&gt;Yesterday, I spent hours to analyze a popular syntax highlighter tool - &lt;a href="http://www.wilcob.com/wilco/Toolbox/SyntaxHighlighter.aspx"&gt;Wilco SyntaxHighter&lt;/a&gt;, because it is a small compiler to some degree. :)&lt;br /&gt;&lt;br /&gt;The highlighter parses string source (the code to be highlighted) to scan tokens (comment, string, key word). Each token includes position/length information in the string source and related with highlighter style data. Then the parser reads the source again to merge those parsed tokens. The string segment of the token will be updated with style data. Other string segment will leave as-is.&lt;br /&gt;&lt;br /&gt;The good feature of that parser is to build a scanner chain. For example, to parse C# code, these scanner will be used: CommentBlockScanner (/* ... */) -- CommentLineScanner (//) -- StringBlockScanner (@) -- StringLineScanner ("") -- WordScanner. When the current and following characters match CommentBlockScanner, the CommentBlockScanner will continue to read characters to the end of the comment block and take that block as a Comment token; if the current character does not match CommentBlockScanner, then it may match the next scanner in the scanner chain ... If the character does not match any scanner, then it does not belong to a token and should be ignored. &lt;br /&gt;&lt;br /&gt;For different type of language (e.g. Java, CSS, etc), we can build and use different scanner chain. But the basic parsing logic is still same.&lt;br /&gt;&lt;br /&gt;The concept of Compiler is very useful when generating code dynamically. When the theory of "Software Factory" becomes real, code generation tool will be the fundamental in the system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-3262126580549469467?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/3262126580549469467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=3262126580549469467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3262126580549469467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3262126580549469467'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/04/small-compiler-wilco-syntax.html' title='A small compiler - Wilco Syntax Highlighting'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-424966894316807493</id><published>2007-04-05T11:02:00.000-04:00</published><updated>2007-04-05T13:28:37.423-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AJAX'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>MS AJAX UpdatePanel throws Sys.WebForms.PageRequestManagerParserErrorException</title><content type='html'>I wrote ASP.NET code to call a service to generate and download a PDF file. At first, I tried to use AJAX UpdatePanel in the ASP.NET code to show progress because the service call may take long time. When the service call returned, I wanted to show the PDF file directly in browser on the same ASP.NET page:&lt;br /&gt;&lt;PRE&gt;  &lt;span style="color: Green; font-family: Courier New; font-size: 11px;"&gt;// Stream PDF kit to client&lt;br /&gt;&lt;/span&gt;  Byte[] buffer &lt;span style="color: Red; font-family: Courier New; font-size: 11px; "&gt;=&lt;/span&gt; File.ReadAllBytes(filePath);&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;base&lt;/span&gt;.Response.Clear();&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;base&lt;/span&gt;.Response.ContentType &lt;span style="color: Red; font-family: Courier New; font-size: 11px; "&gt;=&lt;/span&gt; &lt;span style="color: #666666; font-family: Courier New; font-size: 11px;"&gt;"application/pdf"&lt;/span&gt;;&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;int&lt;/span&gt; length &lt;span style="color: Red; font-family: Courier New; font-size: 11px; "&gt;=&lt;/span&gt; buffer.Length;&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;base&lt;/span&gt;.Response.AddHeader(&lt;span style="color: #666666; font-family: Courier New; font-size: 11px;"&gt;"Accept-Header"&lt;/span&gt;, length.ToString());&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;base&lt;/span&gt;.Response.AddHeader(&lt;span style="color: #666666; font-family: Courier New; font-size: 11px;"&gt;"Content-Length"&lt;/span&gt;, length.ToString());&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;base&lt;/span&gt;.Response.OutputStream.Write(buffer, 0, buffer.Length);&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;base&lt;/span&gt;.Response.Flush();&lt;br /&gt;  &lt;span style="color: Blue; font-family: Courier New; font-size: 11px; "&gt;base&lt;/span&gt;.Response.End();&lt;br /&gt;&lt;/PRE&gt;&lt;br /&gt;But I saw this exception message:&lt;br /&gt;&lt;br /&gt;Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed ...&lt;br /&gt;&lt;br /&gt;Then I realized the UpdatePanel JavaScript tried to parse the returned data for the original web page, but it received strange PDF stream instead. I found the explanation &lt;a href="http://weblogs.asp.net/leftslipper/archive/2007/02/26/sys-webforms-pagerequestmanagerparsererrorexception-what-it-is-and-how-to-avoid-it.aspx"&gt;here&lt;/a&gt;: &lt;br /&gt;&lt;br /&gt;&lt;i&gt;The UpdatePanel control uses asynchronous postbacks to control which parts of the page get rendered. It does this using a whole bunch of JavaScript on the client and a whole bunch of C# on the server. Asynchronous postbacks are exactly the same as regular postbacks except for one important thing: the rendering. Asynchronous postbacks go through the same life cycles events as regular pages (this is a question I get asked often). Only at the render phase do things get different. We capture the rendering of only the UpdatePanels that we care about and send it down to the client using a special format. In addition, we send out some other pieces of information, such as the page title, hidden form values, the form action URL, and lists of scripts.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;It turned out that I should using Response.Redirect() to another page to show the PDF file in browser. To avoid the same exception, there is no AJAX code in the second page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-424966894316807493?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/424966894316807493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=424966894316807493' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/424966894316807493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/424966894316807493'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/04/ms-ajax-updatepanel-throws.html' title='MS AJAX UpdatePanel throws Sys.WebForms.PageRequestManagerParserErrorException'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-5070963223256699563</id><published>2007-03-21T10:17:00.000-04:00</published><updated>2007-03-21T10:30:21.610-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>A missing feature of WF</title><content type='html'>Microsoft Workflow Foundation (WF) is designed to build a kind of Domain Specific Language. You can take WF as a higher level programming language. For example, it has "while" and "if" statements (activities). All the statements run sequentially.&lt;br /&gt;&lt;br /&gt;At this time, WF is good for back end process, but not for (web) user interface. Why? Because WF does not support "Back" button. Let's suppose a web application using WF to control page flow. It is very common for user to input data across pages and want to go "back" to previous pages to change data. WF does not provide built-in mechanism to do that.&lt;br /&gt;&lt;br /&gt;How to implement "Back" logic in WF? WF needs a stack to save states for previous activities. When user clicks "Back" button, WF should pop up previous state from stack and continue the "previous" work.&lt;br /&gt;&lt;br /&gt;I hope the new version of ASP.NET integrated with WF can have that "Back" button feature.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-5070963223256699563?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/5070963223256699563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=5070963223256699563' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5070963223256699563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/5070963223256699563'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/03/missing-feature-of-wf.html' title='A missing feature of WF'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-1083155724404122117</id><published>2007-03-05T16:18:00.000-05:00</published><updated>2007-03-05T16:33:46.485-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Crystal Report .NET is lazy</title><content type='html'>Crystal Report .NET can bind .NET object to its report template, which I took for granted for a long time until I really get my hands dirty these days. &lt;br /&gt;&lt;br /&gt;The question is: could you bind composited object in Crystal Report .NET? For example, an Employee class can be like this:&lt;pre&gt;&lt;br /&gt;public class Employee&lt;br /&gt;{&lt;br /&gt;    public string    m_name;&lt;br /&gt;    public Address    m_address;&lt;br /&gt;    public Salary   m_salary;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Address and Salary are also classes.&lt;br /&gt;&lt;br /&gt;How can I bind an Employee object to Crystal Report to show detailed Address and Salary information? It turns out Crystal Report .NET can only access the top level properties of an object (only m_name in this case)! Crystal Report .NET is too lazy to dig into the object hierarchy.&lt;br /&gt;&lt;br /&gt;Ugly solution? You should create a flat class including all properties of all children classes! A mapping method to fill data to the flat class is needed of course.&lt;br /&gt;&lt;br /&gt;In my current project, I have a class that is composited with many other child classes. If I make all fields flat in one class, there will be more than one hundred properties.&lt;br /&gt;&lt;br /&gt;Except that I have to spend days to create flat classes, Crystal Report also gives me a big task from now on: to keep the flat classes synchronized with those hierarchical classes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-1083155724404122117?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/1083155724404122117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=1083155724404122117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/1083155724404122117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/1083155724404122117'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/03/crystal-report-net-is-lazy.html' title='Crystal Report .NET is lazy'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-2901084194569053290</id><published>2007-02-22T09:11:00.000-05:00</published><updated>2008-11-15T03:18:08.969-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Taiji'/><title type='text'>Beautiful Taiji performance in 2007 Chinese New Year gala</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bVjNlhxO13c/Rd2sDvSqxFI/AAAAAAAAABI/wqkj5NmUw_g/s1600-h/taiji2007.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_bVjNlhxO13c/Rd2sDvSqxFI/AAAAAAAAABI/wqkj5NmUw_g/s320/taiji2007.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5034369138704434258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Chinese New Year gala has been a "traditional" program for more than 1 billion people  for about 20 years. I like martial art programs every year. This year, the martial art program is so beautiful that lots of young Chinese want to learn Taiji after watching the performance.&lt;br /&gt;&lt;br /&gt;Eight national and international Taiji champions showed their GongFu. This is the international champion Zhou Bin:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_bVjNlhxO13c/Rd2sK_SqxGI/AAAAAAAAABQ/8znjkCyxvYE/s1600-h/taiji2007_2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_bVjNlhxO13c/Rd2sK_SqxGI/AAAAAAAAABQ/8znjkCyxvYE/s320/taiji2007_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5034369263258485858" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is the link for the Taiji (It looks like Chen-style Taiji) and dance part of 2007 Chinese New Year gala:&lt;br /&gt;&lt;br /&gt;http://www.youtube.com/watch?v=6hpYtc0BLZ8&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-2901084194569053290?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/2901084194569053290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=2901084194569053290' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/2901084194569053290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/2901084194569053290'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/02/beautiful-taiji-performance-in-2007.html' title='Beautiful Taiji performance in 2007 Chinese New Year gala'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_bVjNlhxO13c/Rd2sDvSqxFI/AAAAAAAAABI/wqkj5NmUw_g/s72-c/taiji2007.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-6740430372781739518</id><published>2007-01-24T11:46:00.000-05:00</published><updated>2007-01-24T11:48:17.164-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>WhileActivity and ActivityExecutionContext in WF</title><content type='html'>WhileActivity is a special activity in WF when ActivityExecutionContext (AEC) is concerned, because it creates a new AEC for each iteration. &lt;br /&gt;&lt;br /&gt;Why? You can know the reason from common programming languages. For example, the below C# while statement adds/removes local variables from stack for each iteration:&lt;br /&gt;&lt;pre&gt;while (conditionIsMet)&lt;br /&gt;{&lt;br /&gt; string output = DateTime.Now.ToString();&lt;br /&gt; int count = 0;&lt;br /&gt; ......&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;WF WhileActivity has similar logic for each iteration: to create a new AEC based on the template activity (e.g. the SequenceActivity inside the WhileActivity).&lt;br /&gt;&lt;br /&gt;Will the new AEC be destroyed at the end of each iteration? You may think "Of course! This is an obvious question". But the answer is "yes or no".&lt;br /&gt;&lt;br /&gt;The answer is yes for normal cases without the need for compensation. There will be only one new AEC in memory for the iterations.&lt;br /&gt;&lt;br /&gt;But the answer is no when compensation is needed. If a CompensatableActivity is defined inside the WhileActivity and when an exception occurrs in one iteration, all the previous iterations will be compensated. That means all previous AEC's can not be destroyed after each iteration. They have to be in memory for compensation purpose.&lt;br /&gt;&lt;br /&gt;According to &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1139519&amp;SiteID=1"&gt;Krishnan&lt;/a&gt;:"The runtime will clean up execution contexts after each WhileActivity iteration. But only if you don't have an ICompensatableActivity inside (if you do, the EC's will stay in memory until the next persistence point.)"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-6740430372781739518?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/6740430372781739518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=6740430372781739518' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/6740430372781739518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/6740430372781739518'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/01/whileactivity-and-activityexecutioncont.html' title='WhileActivity and ActivityExecutionContext in WF'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-2060381212852466849</id><published>2007-01-11T14:22:00.000-05:00</published><updated>2007-01-11T15:00:32.961-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>XmlSerializer may cause memory leak</title><content type='html'>&lt;a href="http://junmeng.blogspot.com/2006/09/xmlserializersdll.html"&gt;In my previous post&lt;/a&gt;, I mentioned XmlSerializer.dll is needed to serialize/deserialize types during web service call. But I did not know a potential memory leak problem until today from &lt;a href="http://msdn.microsoft.com/msdnmag/issues/07/01/ManagedLeaks/default.aspx"&gt;an excellent MSDN article&lt;/a&gt;: Do not use the overload of XmlSerializer constructor that takes the XML root element name as its second parameter!&lt;br /&gt;&lt;br /&gt;As you may know, once a .NET assembly is loaded into memory, it will not be unloaded until the hosting AppDomain is unloaded. XmlSerializer constructor generates a temporary assembly for the type to be serialized using reflection. Because the code generation is expensive, the assembly is cached in memory on a per-type basis.&lt;br /&gt;&lt;br /&gt;For example, the following code will create a cached assembly for type Employee:&lt;br /&gt;&lt;pre&gt;XmlSerializer serializer = new XmlSerializer(typeof(Employee));&lt;/pre&gt;&lt;br /&gt;Whenever an Employee object is to be serialized, the cached assembly will be used.&lt;br /&gt;&lt;br /&gt;But sometimes, we may want to change XML root name in the serialized XML message in a web service. An option is to call an overloaded constructor with XML root name as a parameter:&lt;br /&gt;&lt;pre&gt;XmlSerializer serializer = new XmlSerializer(typeof(Employee), &lt;br /&gt;new XmlRootAttribute("Manager"));&lt;/pre&gt;&lt;br /&gt;Because the root name parameter is supposed to be dynamic, XmlSerializer will not cache the generated temporary assembly. It will generate a new assembly every time you create a new XmlSerializer with that parameter, and the generated assembly will stay in memory unless AppDomain is unloaded. So more and more generated assembly will stay in memory -- memory is being leaked!&lt;br /&gt;&lt;br /&gt;If the root name is static, you can use XmlRootAttribute on the class to change root name of the serialized type; if the root name is dramatically dynamic, there is no easy way to solve the leak problem yet ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-2060381212852466849?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/2060381212852466849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=2060381212852466849' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/2060381212852466849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/2060381212852466849'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/01/xmlserializer-may-cause-memory-leak.html' title='XmlSerializer may cause memory leak'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-4163779524421088778</id><published>2007-01-10T16:10:00.000-05:00</published><updated>2008-11-15T03:18:09.163-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>That so-called security feature is still in IE 7 ?!</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_bVjNlhxO13c/RaVWf3okXsI/AAAAAAAAAA8/X3EOnXG3oik/s1600-h/IE_securityInfo.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_bVjNlhxO13c/RaVWf3okXsI/AAAAAAAAAA8/X3EOnXG3oik/s400/IE_securityInfo.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5018512465284325058" /&gt;&lt;/a&gt;&lt;br /&gt;I believe you saw this warning window for many times when using IE. The reason is the web page of HTTPS URL includes both secure (HTTPS) and nonsecure (HTTP) content. When you view page source, you can see there is image, CSS source, JavaScript src, or other content that begins with "http://", not "https://". &lt;br /&gt;&lt;br /&gt;I do not know the reason why IE team still keep this "feature" in IE 7: &lt;br /&gt;&lt;br /&gt;1) Why should developer put HTTPS for a common image in web page? A common image should be fetched using HTTP directly because it is also shared by other nonsecure site&lt;br /&gt;2) If I embed google map in a secure site, why should I use HTTPS for google content?&lt;br /&gt;&lt;br /&gt;Although developers can write code to map URL from HTTPS to HTTP on web server to solve the problem, although users can change IE security options to enable "Display mixed content", one thing is for sure: This feature of IE is useless and annoying.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-4163779524421088778?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/4163779524421088778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=4163779524421088778' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/4163779524421088778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/4163779524421088778'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2007/01/that-so-called-security-feature-is.html' title='That so-called security feature is still in IE 7 ?!'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bVjNlhxO13c/RaVWf3okXsI/AAAAAAAAAA8/X3EOnXG3oik/s72-c/IE_securityInfo.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-1774376987797572312</id><published>2006-12-21T09:03:00.000-05:00</published><updated>2008-11-15T03:18:09.265-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Office'/><title type='text'>A good feature of InfoPath 2007</title><content type='html'>Last night, I attended MS meeting of "Overview of new Portal features in Microsoft Office SharePoint Server 2007". Although the workflow feature for document management sounds good to me, I have deep impression about a good feature of InfoPath 2007: One form everywhere!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_bVjNlhxO13c/RYqXHR_ZJbI/AAAAAAAAAAY/5TqDlHHV9Xs/s1600-h/InfoPath2007.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_bVjNlhxO13c/RYqXHR_ZJbI/AAAAAAAAAAY/5TqDlHHV9Xs/s320/InfoPath2007.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5010983686747268530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Basically, you can design a form to deploy only once. If a user has InfoPath installed on his/her machine, the user will download and fill the form locally (smart-client version); if the user does not have InfoPath installed, he/she can use popular web browser to fill the form (browser version, slightly different from smart-client version); the user can even see the form on a mobile device. &lt;br /&gt;&lt;br /&gt;"One form" makes development and business process much easier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-1774376987797572312?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/1774376987797572312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=1774376987797572312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/1774376987797572312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/1774376987797572312'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/12/good-feature-of-infopath-2007.html' title='A good feature of InfoPath 2007'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bVjNlhxO13c/RYqXHR_ZJbI/AAAAAAAAAAY/5TqDlHHV9Xs/s72-c/InfoPath2007.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-3049584273319651275</id><published>2006-12-14T17:26:00.000-05:00</published><updated>2008-11-15T03:18:09.429-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>Something big - Windows Workflow Foundation (WF) and ...</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bVjNlhxO13c/RYHQ8hFoPOI/AAAAAAAAAAM/TqoKi53g9Cs/s1600-h/wf.gif"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_bVjNlhxO13c/RYHQ8hFoPOI/AAAAAAAAAAM/TqoKi53g9Cs/s320/wf.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5008513998705409250" /&gt;&lt;/a&gt;&lt;br /&gt;"Something big is about to happen ..." is the very first statement of the excellent book &lt;a href="http://www.bookpool.com/sm/0321399838"&gt;"Essential Windows Workflow Foundation"&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;The book convinced me that WF will change our programming world by enabling domain specific language: Programmers can build domain specific WF Activities, then business people can build system using those WF Activities directly! -- That will be a really BIG thing!&lt;br /&gt;&lt;br /&gt;Another BIG thing I realize will be: big monitor! Our current monitor is not designed to show workflow. Take a brief look at a workflow diagram, you will know my meaning. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-3049584273319651275?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/3049584273319651275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=3049584273319651275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3049584273319651275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/3049584273319651275'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/12/something-big-windows-workflow.html' title='Something big - Windows Workflow Foundation (WF) and ...'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_bVjNlhxO13c/RYHQ8hFoPOI/AAAAAAAAAAM/TqoKi53g9Cs/s72-c/wf.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-7856203738003350958</id><published>2006-12-14T16:54:00.000-05:00</published><updated>2007-04-05T13:30:40.186-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><title type='text'>SOA Messaging or bridge table?</title><content type='html'>Nowadays, when we integrate different systems together inside a company, Service Oriented Architecture (SOA) is the first choice.&lt;br /&gt;&lt;br /&gt;But is it a really good choice? SOA is based on messaging to transfer request and response. Messaging gives us decoupling advantage, but also unreliability.&lt;br /&gt;&lt;br /&gt;Let's suppose one case: System A sends message to System B for data update. What will happen if the message is lost for some reason (out of buffer, system failure,  etc.)? Should we build shake-hand protocol between A and B to make sure the message is successfully delivered?&lt;br /&gt;&lt;br /&gt;How about the old way -- to use a bridge table in a shared database? System A can add a new record into the bridge table for data update; System B can query the bridge table periodically (or to use database notificatione, like SQL Server 2005) to get the update. In this way, we can guarantee the update "message" is delivered from A to B.&lt;br /&gt;&lt;br /&gt;If you think there is delay for this solution, SOA messaging also has delay. We can adjust query period for performance issues.&lt;br /&gt;&lt;br /&gt;I am not saying SOA is bad. I just want to say when you integrate systems, old way may be a better choice than SOA.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-7856203738003350958?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/7856203738003350958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=7856203738003350958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7856203738003350958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/7856203738003350958'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/12/soa-messaging-or-bridge-table.html' title='SOA Messaging or bridge table?'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-116595326006532980</id><published>2006-12-12T14:41:00.000-05:00</published><updated>2006-12-12T14:54:20.123-05:00</updated><title type='text'>How to break a connection in LinkedIn</title><content type='html'>I invited several friends to my &lt;a href="http://www.linkedin.com"&gt;linkedin&lt;/a&gt; account. I will invite more later, because it is an easy way to find old friends to keep in touch.&lt;br /&gt;&lt;br /&gt;But it is hard to delete a person from my connection list: I did not find any button to break a connection. (This sounds like I hate somebody, no, I only do not want to keep many names that I can not remember well.)&lt;br /&gt;&lt;br /&gt;Finally, I got this link somewhere:&lt;br /&gt;&lt;br /&gt;http://www.linkedin.com/connections?displayBreakConnections=&lt;br /&gt;&lt;br /&gt;Hopefully, when I delete a person from my connections, he/she would not receive an email like "Jun hates you! He does not want to see you any more!" :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-116595326006532980?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/116595326006532980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=116595326006532980' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116595326006532980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116595326006532980'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/12/how-to-break-connection-in-linkedin.html' title='How to break a connection in LinkedIn'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-116300708012290872</id><published>2006-11-08T12:26:00.000-05:00</published><updated>2007-04-05T13:31:30.554-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>Column Data Encryption in SQL 2005</title><content type='html'>How to encrypt Social Security Number or Credit Card Number in SQL database? We can not use one-way hash, which can be used to verify password in some solutions. For SSN, we should be able to decrypt the data when needed.&lt;br /&gt;&lt;br /&gt;To speed up process, we should use symmetric key – same key for encryption and decryption. When we add a new record, the key is used to encrypt the data before the record is physically added into data table; when we get the record, the same key is used to decrypt the data before it is returned to client program.&lt;br /&gt;&lt;br /&gt;Here are the questions: &lt;br /&gt;&lt;br /&gt;1. Where do you save the symmetric key? It is not a good idea to include plain text key in every related SQL statements or stored procedures – it is too easy to hack and too complex to change key! &lt;br /&gt;&lt;br /&gt;Ok, I can put the symmetric key (key1) into a central table in SQL server database. To avoid hacking, I also encrypt key1 using another symmetric key (key2) – good :) But where should I put key2 then? The problem to save key2 is very similar to the initial problem to save key1. &lt;br /&gt;&lt;br /&gt;2. When the encryption key is changed for security reason, we should decrypt the old data using the old key and then to encrypt all data using the new encryption key. Do we need track which column in which table is encrypted using which key? What will happen if somehow we forget to keep the tracking up-to-date?&lt;br /&gt;&lt;br /&gt;Fortunately, SQL Server 2005 builds the encryption feature for us. :)&lt;br /&gt;&lt;br /&gt;For question #1, SQL Server uses multiple levels of keys: &lt;br /&gt;&lt;br /&gt;Symmetric key --encrypted by--&gt; Database Master Key or certificate --encrypted by--&gt; SQL Server Service Master Key --encrypted by--&gt; Windows DPAPI and the service account credential or the machine key.&lt;br /&gt;&lt;br /&gt;The benefit of multiple level keys is that you do not need to provide any password to decrypt a key. SQL Server can decrypt the key by itself. What you need is to use symmetric key name in your code.&lt;br /&gt;&lt;br /&gt;Below is a sample from http://msdn2.microsoft.com/en-us/library/ms179331.aspx:&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;&lt;br /&gt;USE AdventureWorks;&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;--If there is no master key, create one now. &lt;br /&gt;IF NOT EXISTS &lt;br /&gt;    (SELECT * FROM sys.symmetric_keys WHERE symmetric_key_id = 101)&lt;br /&gt;    CREATE MASTER KEY ENCRYPTION BY &lt;br /&gt;    PASSWORD = '23987hxJKL969#ghf0%94467GRkjg5k3fd117r$$#1946kcj$n44nhdlj'&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;CREATE CERTIFICATE HumanResources037&lt;br /&gt;   WITH SUBJECT = 'Employee Social Security Numbers';&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;CREATE SYMMETRIC KEY SSN_Key_01&lt;br /&gt;    WITH ALGORITHM = AES_256&lt;br /&gt;    ENCRYPTION BY CERTIFICATE HumanResources037;&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;USE [AdventureWorks];&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;-- Create a column in which to store the encrypted data.&lt;br /&gt;ALTER TABLE HumanResources.Employee&lt;br /&gt;    ADD EncryptedNationalIDNumber varbinary(128); &lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;-- Open the symmetric key with which to encrypt the data.&lt;br /&gt;OPEN SYMMETRIC KEY SSN_Key_01&lt;br /&gt;   DECRYPTION BY CERTIFICATE HumanResources037;&lt;br /&gt;&lt;br /&gt;-- Encrypt the value in column NationalIDNumber with symmetric &lt;br /&gt;-- key SSN_Key_01. Save the result in column EncryptedNationalIDNumber.&lt;br /&gt;UPDATE HumanResources.Employee&lt;br /&gt;SET EncryptedNationalIDNumber = EncryptByKey(Key_GUID('SSN_Key_01'), NationalIDNumber);&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;-- Verify the encryption.&lt;br /&gt;-- First, open the symmetric key with which to decrypt the data.&lt;br /&gt;OPEN SYMMETRIC KEY SSN_Key_01&lt;br /&gt;   DECRYPTION BY CERTIFICATE HumanResources037;&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;-- Now list the original ID, the encrypted ID, and the &lt;br /&gt;-- decrypted ciphertext. If the decryption worked, the original&lt;br /&gt;-- and the decrypted ID will match.&lt;br /&gt;SELECT NationalIDNumber, EncryptedNationalIDNumber &lt;br /&gt;    AS 'Encrypted ID Number',&lt;br /&gt;    CONVERT(nvarchar, DecryptByKey(EncryptedNationalIDNumber)) &lt;br /&gt;    AS 'Decrypted ID Number'&lt;br /&gt;    FROM HumanResources.Employee;&lt;br /&gt;GO&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;To support server cluster, you can export Service Master Key, Database Master Key, symmetric key and certificate to another server. &lt;br /&gt;&lt;br /&gt;For question #2, when a key is to be changed, you should use SQL command to change or recreate a key, so that SQL Server can decrypt old data and encrypt data using the new key automatically.&lt;br /&gt;&lt;br /&gt;The encrypted data begins with symmetric key GUID. You can define several symmetric keys to encrypt different data columns. SQL Server can get proper key using the GUID part.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-116300708012290872?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/116300708012290872/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=116300708012290872' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116300708012290872'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116300708012290872'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/11/column-data-encryption-in-sql-2005.html' title='Column Data Encryption in SQL 2005'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-116230938795184197</id><published>2006-10-31T10:15:00.000-05:00</published><updated>2006-10-31T10:43:07.966-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Using iText to build PDF on the fly</title><content type='html'>Although there are many solutions (such as XML-FOP) to generate PDF on the fly, iText is a good choice to read PDF template and bind data dynamically.&lt;br /&gt;&lt;br /&gt;1) For PDF form where data fields have fixed length, it is quite easy to use iText (I use C# version iTextSharp here) to bind data to PDF Text Field:&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;&lt;br /&gt;// Read PDF template&lt;br /&gt;iTextSharp.text.pdf.PdfReader pdfRd = new iTextSharp.text.pdf.PdfReader(Server.MapPath("~/SampleJS.pdf"));&lt;br /&gt;iTextSharp.text.pdf.PdfStamper stamp = new iTextSharp.text.pdf.PdfStamper(pdfRd, outputStream);&lt;br /&gt;&lt;br /&gt;// Set form Text Fields&lt;br /&gt;iTextSharp.text.pdf.AcroFields fields = stamp.AcroFields;&lt;br /&gt;fields.SetField("formText", value);&lt;br /&gt;&lt;br /&gt;// Close stamp&lt;br /&gt;stamp.Close();&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;2) For free text data, you cannot put PDF Text Field to show data. For example, if you want to bind data to this template:&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;"Welcome to «Institution»! Please send mail to «Person» before «Date»"&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;You cannot use PDF Text Field because Text Field has fixed length. If «Institution» value is short, there will be extra blank space in the statement.&lt;br /&gt;&lt;br /&gt;So what can you do? You can put the template statement into one Text Field with “Read Only” permission. Then you can replace the string with data like below:&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;&lt;br /&gt;// Get Text Fields from PDF file&lt;br /&gt;iTextSharp.text.pdf.AcroFields fields = stamp.AcroFields;&lt;br /&gt;&lt;br /&gt;// Get template&lt;br /&gt;string formText = fields.GetField("formText");&lt;br /&gt;&lt;br /&gt;// Replace template with data&lt;br /&gt;formText = formText.Replace("«Institution»", txtInstitution);&lt;br /&gt;formText = formText.Replace("«Person»", txtPerson);&lt;br /&gt;formText = formText.Replace("«Date»", date);&lt;br /&gt;&lt;br /&gt;// Set back the Text Field&lt;br /&gt;fields.SetField("formText", formText);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;3) How to insert image? PDF Text Field can be a placeholder for image. For example, to add a logo image to a placeholder:&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;&lt;br /&gt;// Get content to make changes&lt;br /&gt;PdfContentByte overContent = stamp.GetOverContent(1);&lt;br /&gt;&lt;br /&gt;// Get logo image&lt;br /&gt;iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance(Server.MapPath("~/logo.jpg"));&lt;br /&gt;&lt;br /&gt;// Get logo placeholder position&lt;br /&gt;float[] logoArea = fields.GetFieldPositions("Logo");&lt;br /&gt;&lt;br /&gt;// Get logo rectangle&lt;br /&gt;iTextSharp.text.Rectangle logoRect = new Rectangle(logoArea[1], logoArea[2], logoArea[3], logoArea[4]);&lt;br /&gt;&lt;br /&gt;// Set logo position in the placeholder (right alignment)&lt;br /&gt;logo.ScaleToFit(logoRect.Width, logoRect.Height);&lt;br /&gt;logo.SetAbsolutePosition(logoArea[3] - logo.ScaledWidth + (logoRect.Width - logo.ScaledWidth) / 2, logoArea[2] + (logoRect.Height - logo.ScaledHeight) / 2);&lt;br /&gt;&lt;br /&gt;// Add image&lt;br /&gt;overContent.AddImage(logo);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;4) How to add a barcode? Barcode is similar to image:&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;&lt;br /&gt;// Get content to make changes&lt;br /&gt;PdfContentByte overContent = stamp.GetOverContent(1);&lt;br /&gt;&lt;br /&gt;// Create a barcode&lt;br /&gt;Barcode39 code39 = new Barcode39();&lt;br /&gt;// Assign barcode value&lt;br /&gt;code39.Code = barcodeValue;&lt;br /&gt;code39.StartStopText = false;&lt;br /&gt;&lt;br /&gt;// Create image from the barcode&lt;br /&gt;iTextSharp.text.Image image39 = code39.CreateImageWithBarcode(overContent, null, null);&lt;br /&gt;&lt;br /&gt;// Get barcode image placeholder&lt;br /&gt;float[] barcodeArea = fields.GetFieldPositions("AppIDBarCode");&lt;br /&gt;iTextSharp.text.Rectangle rect = new Rectangle(barcodeArea[1], barcodeArea[2], barcodeArea[3], barcodeArea[4]);&lt;br /&gt;image39.ScaleToFit(rect.Width, rect.Height);&lt;br /&gt;image39.SetAbsolutePosition(barcodeArea[1] + (rect.Width - image39.ScaledWidth) / 2, barcodeArea[2] + (rect.Height - image39.ScaledHeight) / 2);&lt;br /&gt;&lt;br /&gt;// Add barcode image&lt;br /&gt;overContent.AddImage(image39);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;I still have several issues to solve, such as how to put rich text into Text Field. But for now, I have a good start for PDF generation. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-116230938795184197?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/116230938795184197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=116230938795184197' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116230938795184197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116230938795184197'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/10/using-itext-to-build-pdf-on-fly.html' title='Using iText to build PDF on the fly'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-116136821449434199</id><published>2006-10-20T13:17:00.001-04:00</published><updated>2006-12-14T17:25:49.237-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Taiji'/><title type='text'>Relax with Taiji -- for programmers like me</title><content type='html'>I went to doctor's office this morning and saw a poster to prevent heart disease. It says right things like low-fat diet, no smoking, no alcohol, and regular exercise (with a gym picture). But one important point is missed -- Relax. :)&lt;br /&gt;&lt;br /&gt;Everybody has experience of blood pressure difference when he/she is in anger and in sleep. Emotion is a big factor for health, so calm your body and mind down, and relax...&lt;br /&gt;&lt;br /&gt;Who does not know how to relax?! "I can lie down on sofa and watch TV" ... Is that a good way to relax after sitting in front of computer for a whole day?&lt;br /&gt;&lt;br /&gt;One old phrase says "People's leg gets old first". I am not so old, but my sensitive body is verifying it: After a whole day tiring computer work and when I use eyes to look at computer or TV at night, sometimes I even feel my eyes poll energy from feet to upper body! Our brain and eyes are consuming most of our energy everyday.&lt;br /&gt;&lt;br /&gt;So to get heath back, we should:&lt;br /&gt;&lt;br /&gt;1) Calm down eyes (no computer or TV) and mind (no work at home)&lt;br /&gt;2) Exercise in slow motion to build energy&lt;br /&gt;3) Let energy go down to get legs stronger&lt;br /&gt;&lt;br /&gt;Those are some important values of Taiji to programmers.&lt;br /&gt;&lt;br /&gt;If you have no chance to learn Taiji with a good teacher, you can relax by yourself: Stand still and calm your body down (for half an hour). You should feel your feet are heavy and your upper body is light -- that is also Taiji. :) Your feet are heavy because your body is relaxed and energy goes down. Gradually, your feet and legs will become stronger and healthier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-116136821449434199?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/116136821449434199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=116136821449434199' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116136821449434199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116136821449434199'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/10/relax-with-taiji-for-programmers-like_20.html' title='Relax with Taiji -- for programmers like me'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-116135902976257992</id><published>2006-10-20T10:55:00.000-04:00</published><updated>2006-10-20T11:50:03.743-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>To Generate PDF on the fly</title><content type='html'>PDF is a standard format for B2B or B2C process these days. I think you may have tried to download bank statement in PDF format. On web sites, the PDF documents are generated on demand. They are not generated and saved somewhere ahead.&lt;br /&gt;&lt;br /&gt;I am doing research on how to generate PDF on the fly. I tried some products on market, but I have not found any software that can do the job for me.&lt;br /&gt;&lt;br /&gt;This is my requirement: I have some Word template documents with merge fields that can be used to bind database data to generate real documents.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I already have a back-end system to generate those Word documents and convert to PDF format to print&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The front-end system also wants to generate PDF documents on the fly when user clicks a "Get PDF" button on web page&lt;/li&gt;&lt;/ul&gt;It is too slow to convert Word document to PDF format. For some relatively large document, it may take minutes to finish. This process can be used in back-end system asynchronously, but it is not for web site.&lt;br /&gt;&lt;br /&gt;For web site, I have to use PDF forms with form fields to bind database data. I can use PDF editor software to add form fields. But if I create both Word templates and PDF forms, it is hard to maintain both versions.&lt;br /&gt;&lt;br /&gt;Is there a software to convert Word templates to PDF forms and to convert Word merge fields to PDF form fields? I tried Adlib, Adobe, ActivePDf, even OpenOffice. Unfortunately, none of them can do merge field conversion.&lt;br /&gt;&lt;br /&gt;Why did we use Word template in the beginning? Because Word is better than PDF editor in formatting, and also people are familiar with Word than PDf editor too.&lt;br /&gt;&lt;br /&gt;So, it seems I have to create and maintain both Word template (for back-end system) and PDF form (for front-end system) versions. :(&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-116135902976257992?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/116135902976257992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=116135902976257992' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116135902976257992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/116135902976257992'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/10/to-generate-pdf-on-fly.html' title='To Generate PDF on the fly'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115954095364140728</id><published>2006-09-29T10:09:00.000-04:00</published><updated>2006-09-29T10:45:32.263-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>Biztalk Server 2006 and Windows Workflow Foundation: Better Together</title><content type='html'>This is a short note from last night's &lt;a href="http://groups.msn.com/micsug"&gt;MICUG meeting&lt;/a&gt; about Biztalk and WF.&lt;br /&gt;&lt;br /&gt;A typical system is like below:&lt;pre&gt;&lt;br /&gt;  Customers -- Processes -- Services -- Data Library -- Database&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It is relatively easy to create Database, Data Library, Service programs, and Business Process Programs. &lt;br /&gt;&lt;br /&gt;Developer can use&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Biztalk to model business process across heterogeneous applications&lt;/li&gt;&lt;li&gt;Windows Workflow Foundation (WF) to model business processes involving human intervention&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;But:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How should I manage or control the state of a business process involving systems and people?&lt;/li&gt;&lt;li&gt;How do I allow business users to modify the business process on demand?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Biztalk 2006 does not allow to modify process on demand. Business users have to ask developer to change, compile and deploy new orchestration assembly. But WF allows to change or create workflow on demand. &lt;br /&gt;&lt;br /&gt;Biztalk is not designed for user intervention either, while WF has sequential and stateful workflow to support user intervention.&lt;br /&gt;&lt;br /&gt;So we can combine Biztalk and WF together to make everybody happy in two ways:&lt;br /&gt;1. WF accesses Biztalk&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/WF_Biztalk.0.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/7748/2306/320/WF_Biztalk.0.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;This is a common design. WF deals with user interaction to fill in forms, then WF sends request to Biztalk to complete process across other systems.&lt;br /&gt;&lt;br /&gt;2. Biztalk accesses WF services&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/Biztalk_WF.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/7748/2306/320/Biztalk_WF.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;In this design, Biztalk sends Web Service request to WF service for business users intervention. Also business users can access WF program to get Biztalk statistics through Biztalk BAM.&lt;br /&gt;&lt;br /&gt;Although Biztalk R2 will build WF engine inside, the above two kinds of integration will still be reasonable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115954095364140728?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115954095364140728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115954095364140728' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115954095364140728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115954095364140728'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/09/biztalk-server-2006-and-windows.html' title='Biztalk Server 2006 and Windows Workflow Foundation: Better Together'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115938335751131912</id><published>2006-09-27T14:25:00.000-04:00</published><updated>2006-09-27T14:55:57.526-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><title type='text'>A difference between OO method call and web service method call</title><content type='html'>Nowadays, .NET framework is making web service call similar to local method call to developers. There is no much learning curve to write integrated/distributed software using web service. &lt;br /&gt;&lt;br /&gt;Traditionally when we develop OO software, we can define base class in API and call that API by passing subclass object. The benefit of this design is that we can use a single API to process multiple subclasses, which is easy and reasonable.&lt;br /&gt;&lt;br /&gt;How about the API for Web Service method then? Can we follow the same style (ie. passing subclass object to the API) to define base class in API? &lt;br /&gt;&lt;br /&gt;Unfortunately, no!&lt;br /&gt;&lt;br /&gt;For example: There is a web method HelloWorld() like below&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    public class BaseClass&lt;br /&gt;    {&lt;br /&gt;        public string Name = "Base Class";&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public class SubClass : BaseClass&lt;br /&gt;    {&lt;br /&gt;        public string Type = "Sub class";&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [WebMethod]&lt;br /&gt;    public string HelloWorld(BaseClass oClass)&lt;br /&gt;    {&lt;br /&gt;        return "Hello " + oClass.Name;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;1. If client gets web service definition through WSDL, it cannot get definition of SubClass. So it has no way to create a SubClass object to call HelloWorld()&lt;br /&gt;&lt;br /&gt;2. If client shares BaseClass and SubClass library with web service, then the client can create a SubClass object (oSubClass). But the client can not call HelloWorld(oSubClass) that generated by WSDL either, because WSDL does not have any information for SubClass, not to mention the relationship between SubClass and BaseClass&lt;br /&gt;&lt;br /&gt;3. If client shares BaseClass and SubClass library with web service, and call System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke() directly:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    Invoke("HelloClass", new object[] {oSubClass});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That still can not work: XmlSerializer will throw exception because we are passing an incompatible object.&lt;br /&gt;&lt;br /&gt;So when we design the interface of web service, we have to define APIs separately for each kind of subclass!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115938335751131912?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115938335751131912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115938335751131912' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115938335751131912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115938335751131912'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/09/difference-between-oo-method-call-and.html' title='A difference between OO method call and web service method call'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115834640959586603</id><published>2006-09-15T14:34:00.000-04:00</published><updated>2006-10-05T12:35:10.400-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>ASP.NET TreeView shows old datasource</title><content type='html'>I do not know what's wrong in my code: The TreeView always shows the old data source, although I assign a new data source to it.&lt;br /&gt;&lt;br /&gt;My purpose: To show XML in a tree view. Each leaf element is in "element_name = element_value" format:&lt;pre&gt;&lt;br /&gt;name&lt;br /&gt; |&lt;br /&gt; +-- first = F1&lt;br /&gt; |&lt;br /&gt; +-- last = L1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here is a sample code:&lt;br /&gt;&lt;br /&gt;Add a TreeView control to Default.aspx:&lt;pre&gt;&lt;br /&gt;&amp;lt;asp:TreeView ID="xmlTreeView" runat="server"&lt;br /&gt;OnTreeNodeDataBound="XmlTreeView_OnTreeNodeDataBound"&lt;br /&gt;ShowLines="True" EnableViewState="False"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In code behind:&lt;div style="overflow: auto; width: auto;"&gt;&lt;pre&gt;&lt;br /&gt;public partial class _Default : System.Web.UI.Page&lt;br /&gt;{&lt;br /&gt;  List&amp;lt;string&amp;gt; xmlStrList = new List&amp;lt;string&amp;gt;();&lt;br /&gt;&lt;br /&gt;  protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;  {&lt;br /&gt;      // Initiate XML data&lt;br /&gt;      xmlStrList.Add("&amp;lt;name&amp;gt;&amp;lt;first&amp;gt;F1&amp;lt;/first&amp;gt;&amp;lt;last&amp;gt;L1&amp;lt;/last&amp;gt;&amp;lt;/name&amp;gt;");&lt;br /&gt;      xmlStrList.Add("&amp;lt;name&amp;gt;&amp;lt;first&amp;gt;F2&amp;lt;/first&amp;gt;&amp;lt;last&amp;gt;L2&amp;lt;/last&amp;gt;&amp;lt;/name&amp;gt;");&lt;br /&gt;      xmlStrList.Add("&amp;lt;name&amp;gt;&amp;lt;first&amp;gt;F3&amp;lt;/first&amp;gt;&amp;lt;last&amp;gt;L3&amp;lt;/last&amp;gt;&amp;lt;/name&amp;gt;");&lt;br /&gt;      xmlStrList.Add("&amp;lt;name&amp;gt;&amp;lt;first&amp;gt;F4&amp;lt;/first&amp;gt;&amp;lt;last&amp;gt;L4&amp;lt;/last&amp;gt;&amp;lt;/name&amp;gt;");&lt;br /&gt;&lt;br /&gt;      // Get random XML string&lt;br /&gt;      int i = DateTime.Now.Second % xmlStrList.Count;&lt;br /&gt;&lt;br /&gt;      // Create XmlDataSource&lt;br /&gt;      XmlDataSource dataSource = new XmlDataSource();&lt;br /&gt;      dataSource.Data = xmlStrList[i];&lt;br /&gt;&lt;br /&gt;      // Bind XMLDataSource to tree view&lt;br /&gt;      xmlTreeView.DataSource = dataSource;&lt;br /&gt;      xmlTreeView.DataBind();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // To show leaf element in "element_name = element_value" format&lt;br /&gt;  protected virtual void XmlTreeView_OnTreeNodeDataBound(Object sender, TreeNodeEventArgs e)&lt;br /&gt;  {&lt;br /&gt;      if (e.Node.DataItem is XmlElement)&lt;br /&gt;      {&lt;br /&gt;          XmlElement element = (XmlElement)e.Node.DataItem;&lt;br /&gt;          if (!element.FirstChild.HasChildNodes)&lt;br /&gt;          {&lt;br /&gt;              e.Node.Text = e.Node.Text + " = " + element.InnerText;&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Everytime when I refresh the page, I get different XML string data source, but I see the SAME tree view data in browser! --- That is weird ...&lt;br /&gt;&lt;br /&gt;I don't know why?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;[Update]&lt;/span&gt; Copied from &lt;a href="http://forums.asp.net/thread/1416907.aspx"&gt;asp.net forum&lt;/a&gt;:&lt;br /&gt;------------------------------------&lt;br /&gt;&lt;span style="font-style:italic;"&gt;This looks like a bug in the XmlDataSource control where modifying the Data property does not invalidate the cache. Setting EnableCaching=false is the workaround to use here.&lt;br /&gt;&lt;br /&gt;Thanks,&lt;br /&gt;&lt;br /&gt;Eilon&lt;br /&gt;------------------------------------&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115834640959586603?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115834640959586603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115834640959586603' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115834640959586603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115834640959586603'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/09/aspnet-treeview-shows-old-datasource.html' title='ASP.NET TreeView shows old datasource'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115808211691640086</id><published>2006-09-12T13:22:00.000-04:00</published><updated>2006-09-12T13:30:00.703-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>XmlSerializers.dll?</title><content type='html'>After I generated web service proxy using WSDL file and ran my web service client, I noticed this log:"Resolver failed to load assembly 'myAssembly.XmlSerializers.dll'". What is that?&lt;br /&gt;&lt;br /&gt;I did not use any XmlSerializers DLL reference, or even did not know its existence until I saw &lt;a href="http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx"&gt;XML Serializer Generator Tool&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;The XML Serializer Generator creates an XML serialization assembly for types in a specified assembly in order to improve the startup performance of a XmlSerializer when it serializes or deserializes objects of the specified types.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Anyway, I added this line to "Post-build event" in Visual Studio project to generate myAssembly.XmlSerializers.dll dynamically:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sgen" "$(TargetPath)"&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115808211691640086?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115808211691640086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115808211691640086' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115808211691640086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115808211691640086'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/09/xmlserializersdll.html' title='XmlSerializers.dll?'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115757335363579669</id><published>2006-09-06T15:54:00.000-04:00</published><updated>2006-09-06T16:09:13.656-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>propertySpecified in XML Serialization</title><content type='html'>What will be saved when an object of SomeDate class is serialized?&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class SomeDate&lt;br /&gt;{&lt;br /&gt;    private short yearField;&lt;br /&gt;    private bool yearFieldSpecified;&lt;br /&gt;&lt;br /&gt;    public short Year&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            return this.yearField;&lt;br /&gt;        }&lt;br /&gt;        set&lt;br /&gt;        {&lt;br /&gt;            this.yearField = value;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [System.Xml.Serialization.XmlIgnoreAttribute()]&lt;br /&gt;    public bool YearSpecified&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            return this.yearFieldSpecified;&lt;br /&gt;        }&lt;br /&gt;        set&lt;br /&gt;        {&lt;br /&gt;            this.yearFieldSpecified = value;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The serialization code is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private static void InitializeDateFile()&lt;br /&gt;{&lt;br /&gt;    SomeDate oDate = new SomeDate();&lt;br /&gt;    oDate.Year = 1910;&lt;br /&gt;    oDate.YearSpecified = true;&lt;br /&gt;&lt;br /&gt;    XmlSerializer xmlSer = &lt;br /&gt;           new XmlSerializer(typeof(SomeDate));&lt;br /&gt;    XmlTextWriter writer = &lt;br /&gt;           new XmlTextWriter(@"SomeDate.xml", &lt;br /&gt;                   Encoding.Default);&lt;br /&gt;    writer.Formatting = Formatting.Indented;&lt;br /&gt;    xmlSer.Serialize(writer, oDate);&lt;br /&gt;    writer.Close();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With &lt;span style="font-style: italic;"&gt;oDate.YearSpecified = true;&lt;/span&gt;, the output is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;SomeDate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xmlns:xsd="http://www.w3.org/2001/XMLSchema"&amp;gt;&lt;br /&gt;  &amp;lt;Year&amp;gt;1910&amp;lt;/Year&amp;gt;&lt;br /&gt;&amp;lt;/SomeDate&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But without &lt;span style="font-style: italic;"&gt;oDate.YearSpecified = true;&lt;/span&gt;, the output becomes:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;SomeDate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" &lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Where is Year element?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemXmlSerializationXmlIgnoreAttributeClassTopic.asp"&gt;Here&lt;/a&gt; I found the reason: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;The XML Schema Definition Tool (Xsd.exe) occasionally generates the XmlIgnoreAttribute when creating classes from a schema file (.xsd). This behavior occurs because value types cannot be set to a null reference (Nothing in Visual Basic), but all XML data types can be. Therefore, the tool creates two fields when it encounters an XML type that maps to a value type: one to hold the value, and another, special field that takes the form of fieldnameSpecified, where the fieldname is replaced by the name of the field or property. Notice, however, that this special field is generated only when the schema specifies that the element need not occur (minOccurs = "0") and that the element has no default value. The XmlSerializer sets and checks this special field to determine whether a value has been set for the field or property. Because the special field must not be serialized, the tool applies the XmlIgnoreAttribute to it.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115757335363579669?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115757335363579669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115757335363579669' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115757335363579669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115757335363579669'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/09/propertyspecified-in-xml-serialization.html' title='propertySpecified in XML Serialization'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115729082417122876</id><published>2006-09-03T09:21:00.000-04:00</published><updated>2006-09-03T09:40:24.243-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Taiji'/><title type='text'>Good Videos (Taiji)</title><content type='html'>Although I have practiced Chen-style Taiji for several years, I did not learn Taiji Push-Hand.&lt;br /&gt;&lt;br /&gt;From last month, I began to learn Push-Hand with Yang-style Taiji teachers. Their teaching also changed my feeling that Yang-style Taiji is eaiser than Chen-style. With good teachers around, I am confident that I can improve my health and Taiji skills from now on. :)&lt;br /&gt;&lt;br /&gt;There are some good videos about Chen-style and Yang-style Taiji &lt;a href="http://www.youtube.com/profile?user=taichitsao"&gt;here&lt;/a&gt;. I save the link in this post for my later reference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115729082417122876?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115729082417122876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115729082417122876' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115729082417122876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115729082417122876'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/09/good-videos-taiji.html' title='Good Videos (Taiji)'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115616944322584659</id><published>2006-08-21T10:06:00.000-04:00</published><updated>2006-08-21T10:10:43.253-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>DateTime serialization in .NET 1.1 and 2.0</title><content type='html'>When a system is running in different time zones, we need pay attention to DateTime field, because .NET 2.0 web service is not compatible with .NET 1.1 web service in design for DateTime field.&lt;br /&gt;&lt;br /&gt;.NET 2.0 DateTime uses two-bit flag to indicate time zone: Local, UTC, or unspecified (default)..NET 1.1 does not use that flag.&lt;br /&gt;&lt;br /&gt;.NET 2.0 serializes DateTime with time zone information for “Local” and “UTC” DateTime object. There is no time zone for “Unspecified” DateTime object. By default, .NET program uses “Unspecified” DateTime value as local time. In distributed system across time zones, this may bring troubles.&lt;br /&gt;&lt;br /&gt;.NET 1.1 always serializes DateTime with time zone. &lt;br /&gt;&lt;br /&gt;Below is an example tested in our project:&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class DateTimeSample &lt;br /&gt;{ &lt;br /&gt; private System.DateTime m_dtDateTime = &lt;br /&gt;  DateTime.Parse("08/10/1971"); &lt;br /&gt;&lt;br /&gt; public System.DateTime LocalTime &lt;br /&gt; { &lt;br /&gt;  get &lt;br /&gt;  { &lt;br /&gt;   return m_dtDateTime.ToLocalTime(); &lt;br /&gt;  } &lt;br /&gt; } &lt;br /&gt;&lt;br /&gt; public System.DateTime Default &lt;br /&gt; { &lt;br /&gt;  get &lt;br /&gt;  { &lt;br /&gt;   return m_dtDateTime; &lt;br /&gt;  } &lt;br /&gt; } &lt;br /&gt;&lt;br /&gt; public System.DateTime UniversalTime &lt;br /&gt; { &lt;br /&gt;  get &lt;br /&gt;  { &lt;br /&gt;   return m_dtDateTime.ToUniversalTime(); &lt;br /&gt;  } &lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;.Net 1.1 serialization: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-16"?&amp;gt; &lt;br /&gt;&amp;lt;DateTimeSample xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt; &lt;br /&gt;    &amp;lt;LocalTime&amp;gt;1971-08-10T20:00:00.0000000-04:00&amp;lt;/LocalTime&amp;gt; &lt;br /&gt;    &amp;lt;Default&amp;gt;1971-08-11T00:00:00.0000000-04:00&amp;lt;/Default&amp;gt; &lt;br /&gt;    &amp;lt;UniversalTime&amp;gt;1971-08-11T04:00:00.0000000-04:00&amp;lt;/UniversalTime&amp;gt; &lt;br /&gt;&amp;lt;/DateTimeSample&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;.Net 2.0 serialization: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-16"?&amp;gt; &lt;br /&gt;&amp;lt;DateTimeSample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xmlns:xsd="http://www.w3.org/2001/XMLSchema"&amp;gt; &lt;br /&gt;    &amp;lt;LocalTime&gt;1971-08-10T20:00:00-04:00&amp;lt;/LocalTime&amp;gt; &lt;br /&gt;    &amp;lt;Default&gt;1971-08-11T00:00:00&amp;lt;/Default&amp;gt; &lt;br /&gt;    &amp;lt;UniversalTime&gt;1971-08-11T04:00:00Z&amp;lt;/UniversalTime&amp;gt; &lt;br /&gt;&amp;lt;/DateTimeSample&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115616944322584659?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115616944322584659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115616944322584659' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115616944322584659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115616944322584659'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/08/datetime-serialization-in-net-11-and.html' title='DateTime serialization in .NET 1.1 and 2.0'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115582612464029951</id><published>2006-08-17T10:46:00.000-04:00</published><updated>2006-08-17T10:48:44.653-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>When a system becomes distributed …</title><content type='html'>When we build a system, normally we design a simple framework at first. Then we will add more features to it. When the system is growing bigger and distributed, you will find some weird and interesting bugs.&lt;br /&gt;&lt;br /&gt;One example is about date time. When a system was designed at the beginning, the developers decided to use local time to save all the time fields, including “date of birth”. When the program was running locally, there was no problem. But when a call center using Windows Forms application became part of the system, a weird bug arose: some clients’ date of birth had one day difference between sub systems (e.g. 08/18/1966 in one database, but 08/19/1966 in another database). Because of wrong DOB, the clients could not pass credit check.&lt;br /&gt;&lt;br /&gt;I spent the whole afternoon and evening yesterday to check code and logs, but I didn’t find any reason. Then before I went bed last night, suddenly I realized the bug was caused by time zone difference in computers.&lt;br /&gt;&lt;br /&gt;For example, the business layer server is in “-5” time zone, but a Call Center agent’s computer is set to time zone “-4”.  When the agent inputs DOB “08/18/1966”, the Call Center Windows Forms program will pass that date (“08/18/1966 00:00:00”) in local time format to business layer server. Because of time zone difference, the server will receive “08/17/1966 23:00:00” instead – one day difference occurs.&lt;br /&gt;&lt;br /&gt;Some computers may have random time zone settings. The DOB field becomes messy.&lt;br /&gt;&lt;br /&gt;A quick, temporary, logically (not physically) simple solution: to make all machines in same time zone. For the long term solution, the system should change to use UTC, not local time. That will require longer time to change database and code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115582612464029951?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115582612464029951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115582612464029951' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115582612464029951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115582612464029951'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/08/when-system-becomes-distributed.html' title='When a system becomes distributed …'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115465153262713697</id><published>2006-08-03T20:27:00.000-04:00</published><updated>2006-08-03T20:33:49.960-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>State Machine Workflow: Screencast</title><content type='html'>Although there are many webcasts or articles about MS Workflow Foundation, it is hard to find good stuff about state machine workflow. So when I found &lt;a href="http://dotnetaddict.dotnetdevelopersjournal.com/stateworkflow_screencast.htm"&gt;this good introduction of state machine workflow&lt;/a&gt;, I was quite happy to watch it several times. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115465153262713697?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115465153262713697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115465153262713697' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115465153262713697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115465153262713697'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/08/state-machine-workflow-screencast.html' title='State Machine Workflow: Screencast'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115444239542685346</id><published>2006-08-01T10:22:00.000-04:00</published><updated>2006-08-01T12:25:08.336-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Load Balancer and System.Net Connection Management</title><content type='html'>When you make first HttpWebRequest from you application to access a web site or web service, you will use this code:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;WebRequest request = WebRequest.Create(url);&lt;br /&gt;WebResponse response = request.GetResponse();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The process of creating a connection with remote application is complex. In order to improve connection speed for later web requests, .NET framework creates a connection pool for each URL. When a web response comes back, the connection is still available for other web requests with the same URL.&lt;br /&gt;&lt;br /&gt;By default, the connection’s KeepAlive attribute is true. But the connection can not stay forever, of course. In .NET 2.0, you can define MaxIdleTime -- when the connection has been idle for more than MaxIdleTime, the connection will be closed by framework.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/LoadBalancer.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://photos1.blogger.com/blogger/7748/2306/320/LoadBalancer.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The logic looks good so far. But when a load balancer is involved, a problem may arise. Load balancer directs a request to a Web service and creates connection for the request. If the connection is idle for a period, the load balancer will break the connection without sending notification out.&lt;br /&gt;&lt;br /&gt;Let’s suppose the load balancer breaks idle connection after 90 seconds. But on application server side, .NET connection pool keeps idle connection for 100 seconds (by default). When a new web request is sent at this point, an HTTP transport exception will be thrown.&lt;br /&gt;&lt;br /&gt;So it is important to make sure the connection timeout settings. After contacting system administrator for load balancer setting, developer can set MaxIdleTime for the connection:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt; request.ServicePoint.MaxIdleTime = maxIdleTimeValue;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Please make sure the .NET connection MaxIdleTime must be smaller than the load balancer's max connection idle setting. In this way, .NET framework will create a new connection when the connection has been broken by load balancer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115444239542685346?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115444239542685346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115444239542685346' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115444239542685346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115444239542685346'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/08/load-balancer-and-systemnet-connection.html' title='Load Balancer and System.Net Connection Management'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115220102069542312</id><published>2006-07-06T11:26:00.000-04:00</published><updated>2006-07-06T11:59:11.583-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><title type='text'>Service Factory</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/ServiceFactory.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://photos1.blogger.com/blogger/7748/2306/320/ServiceFactory.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Patterns &amp; Practices group is making &lt;a href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=6fde9247-53a8-4879-853d-500cd2d97a83"&gt;Service Factory&lt;/a&gt; to ease Service-Oriented programming in Visual Studio. &lt;a href="http://blogs.msdn.com/donsmith/default.aspx"&gt;Don Smith&lt;/a&gt; had an excellent &lt;a href="http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032300719&amp;amp;Culture=en-US"&gt;webcast&lt;/a&gt; to demonstrate how to use Service Factory Visual Studio extension to develop ASMX and WCF solutions.&lt;br /&gt;&lt;br /&gt;The Service Factory allows developer to write contract-first services easier (instead of current implementation-first development). Don Smith showed how to use XSD file to generate data contract classes and how to define service contract to generate web service classes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115220102069542312?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115220102069542312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115220102069542312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115220102069542312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115220102069542312'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/07/service-factory.html' title='Service Factory'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115167499065087692</id><published>2006-06-30T09:17:00.000-04:00</published><updated>2006-06-30T09:47:15.013-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>.NET Guidance Explorer</title><content type='html'>Although I have disks about .NET patterns &amp; practices, a desktop &lt;a href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=bb9aecfe-56ba-4ca9-8127-44e551b90962"&gt;Guidance Explorer&lt;/a&gt; is quite handy:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/GuidanceExplorer.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 292px; height: 202px;" src="http://photos1.blogger.com/blogger/7748/2306/320/GuidanceExplorer.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The only problem is that the explorer does not include enough topics at this point. The developing group is adding and releasing more content nearly weekly.&lt;br /&gt;&lt;br /&gt;Is there an auto update feature in the explorer? Unfortunately, no.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115167499065087692?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115167499065087692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115167499065087692' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115167499065087692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115167499065087692'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/net-guidance-explorer.html' title='.NET Guidance Explorer'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115108204634899661</id><published>2006-06-23T12:55:00.000-04:00</published><updated>2006-06-26T09:18:46.300-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Using I/O Completion Port (IOCP) to implement our own thread pool</title><content type='html'>Here I talk about another old but important technology for .NET server application.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Before we discuss thread pool, a concept should be clear: You can generate as many threads as you want in .NET code, but the default thread pool has at most 25 threads.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For a server application, it is normally necessary to use thread pool to leverage client requests, even on a single CPU computer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Thread pool background knowledge&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/03/06/NET/default.aspx"&gt;Creating thread is expensive&lt;/a&gt;: To create a thread, a kernel object is allocated and initialized, the thread's stack memory is allocated and initialized, and Windows sends every DLL in the process a DLL_THREAD_ATTACH notification, causing pages from disk to be faulted into memory so that code can execute. When a thread dies, every DLL is sent a DLL_THREAD_DETACH notification, the thread's stack memory is freed, and the kernel object is freed (if its usage count goes to 0).&lt;br /&gt;&lt;br /&gt;Thread pool keeps some idle threads in suspended state to save time. At first, there is no thread in the thread pool. When the first request comes, a thread is created to process the request. If the request process takes long time (such as accessing web service), the thread enters sleeping mode at a certain time, the thread pool can create another thread to serve queued requests. When web service response comes back, the sleeping thread is woken up to continue the process. After the request is processed, the thread does not simply die, but serves other requests.&lt;br /&gt;&lt;br /&gt;If we do not use thread pool, we will end up using one single thread to serve all client requests sequentially (for long-running request, the performance is terrible); or we create/destroy a thread for each client request, which is time consuming for large amount of requests.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Why do we need our own thread pool&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;By default, there are 25 threads in the thread pool for a .NET application. Normally, the .NET thread pool is OK if there are not many services running in the application and each request process is short. But if the application have many tasks to do (with several back ground threads, scheduler, many long-running requests), it is necessary to build our own thread pool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. How to build thread pool&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Windows Server I/O Completion Port (IOCP) is a kernel queue that can be used for thread pool. The basic idea is to allocate a number of threads to wait on the queue. A request on the queue includes request data address that is supposed to indicate delegate value, so that the thread can run the delegated method.&lt;br /&gt;&lt;br /&gt;You can read more about IOCP thread pool implementation in C# from &lt;a href="http://www.devarticles.com/c/a/C-Sharp/IOCP-Thread-Pooling-in-C-sharp-Part-I/"&gt;Part I&lt;/a&gt; and &lt;a href="http://www.devarticles.com/c/a/C-Sharp/IOCP-Thread-Pooling-in-C-sharp-Part-II/"&gt;Part II&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The problem of the article is that the author did not show how to get the request data. You should use Target property of GCHandle to get the real .NET data back.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115108204634899661?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115108204634899661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115108204634899661' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115108204634899661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115108204634899661'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/using-io-completion-port-iocp-to.html' title='Using I/O Completion Port (IOCP) to implement our own thread pool'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115106887806300467</id><published>2006-06-23T09:07:00.000-04:00</published><updated>2006-06-23T09:22:31.323-04:00</updated><title type='text'>Microsoft Identity Integration Server</title><content type='html'>Last night, I attended &lt;a href="http://groups.msn.com/micsug"&gt;MICSUG&lt;/a&gt; user group meeting. The topic of the meeting was about Microsoft Identity Integration Server (MIIS) to integrate user identities from different data sources. MIIS is a good server for a big company where some legacy systems or departments want to share user identity.&lt;br /&gt;&lt;br /&gt;The picture below is an example of MIIS use case. MIIS developer can define attribute mapping for data sources (SQL server, flat file, Active Directory, etc) to import/export identity data.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/MIIS.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/blogger/7748/2306/320/MIIS.jpg" alt="" border="0" /&gt;&lt;/a&gt;The current version has limited ability to manage password though. It is understandable that many systems use hash code to store password, so that MIIS can not get original password out. MS is developing password management in next version.&lt;br /&gt;&lt;br /&gt;The next version of MIIS can also support Extranet for B2B/B2C identity integration. InfoCard (CardSpaces) will also be supported. It sounds like MIIS will become a good middleware for a big company.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115106887806300467?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115106887806300467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115106887806300467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115106887806300467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115106887806300467'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/microsoft-identity-integration-server.html' title='Microsoft Identity Integration Server'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115091657823795624</id><published>2006-06-21T14:27:00.000-04:00</published><updated>2006-06-21T15:02:58.260-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Web Service Host Application Implementation</title><content type='html'>I have been curious for a long time about how Web Service host application is implemented. After I build .NET web service assembly, how can Web Service host application receive request and call the correct method?&lt;br /&gt;&lt;br /&gt;From the research I did on Web Service topics these days, I have a concrete idea about how to implement a Web Service host environment. How does ASP.NET platform process Web Service request is beyond my current ability. Here I only talk about the main steps for a normal Web Service host application to process Web Service request.&lt;br /&gt;&lt;br /&gt;Reflection is the key for Web Service host application to work.&lt;br /&gt;&lt;br /&gt;1. We define a Web Service class and Web Methods by using according attributes. When we deploy the assembly to the host application, the application uses reflection to load the assembly and initialize properties using those attributes:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Assembly assem = Assembly.LoadFrom(assemblyPath);&lt;br /&gt;foreach (Type t in assem.GetExportedTypes())&lt;br /&gt;{&lt;br /&gt;  foreach (MethodInfo info in&lt;br /&gt;    t.GetMethods(BindingFlags.Public | BingFlags.Instance)&lt;br /&gt;  {&lt;br /&gt;   if (info.IsDefined(typeof(WebMethodAttribute), false))&lt;br /&gt;   {&lt;br /&gt;    // Set according properties&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Reflection is also used here to generate WSDL file by going through WebMethodAttribute.&lt;br /&gt;2. When a SOAP request comes, the host application parses the SOAP packet to get class name, method name and parameter list.&lt;br /&gt;3. The host application allocates an instance using the class name, either from instance pool or using a singleton&lt;br /&gt;4. The host application finds the method by using method name and calls the method:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;MethodInfo info = type.GetMethod(methodName);&lt;br /&gt;object result = info.Invoke(instance, parameters[]);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;5. Return the object in SOAP packet if there is no error; otherwise, return exception&lt;br /&gt;&lt;br /&gt;The steps above are my simplest design of a Web Service host. I will consider WSE later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115091657823795624?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115091657823795624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115091657823795624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115091657823795624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115091657823795624'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/web-service-host-application.html' title='Web Service Host Application Implementation'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115089947243964970</id><published>2006-06-21T09:47:00.000-04:00</published><updated>2006-06-21T10:22:36.063-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Dynamic Code Compilation</title><content type='html'>Maybe you already know this old technology -- dynamic code compilation, but I didn't touch it until today.&lt;br /&gt;&lt;br /&gt;Suppose we put code on production box, later we need trace a bug in production environment. Of course there is no Visual Studio installed on production box. How can we do? Sometimes it is too complex to build a testing project and upload to production box. What about building a generic editor with code compilation capability, so that we can put testing code in it and compile the source code dynamically without complex command line typing?&lt;br /&gt;&lt;br /&gt;Another example is Application Server. It is a good feature to compile testing code inside the server environment for module's stress test.&lt;br /&gt;&lt;br /&gt;Inside the editor, we can define our own format for DLL references. For example:&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(0, 102, 0);"&gt;&lt;br /&gt;//@ref "DLL file name"&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The editor compiles source code in these steps:&lt;ol&gt;&lt;li&gt; Create an instance of CodeDomProvider &lt;span style="color: rgb(153, 0, 0);"&gt;CSharpCodeProvider&lt;/span&gt; (&lt;span style="color: rgb(153, 0, 0);"&gt;VBCodeProvider&lt;/span&gt; for Visual Basic)&lt;/li&gt;&lt;li&gt; Provide &lt;code&gt;CompilerParameters&lt;/code&gt; for compiler options, such as adding DLL references&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Compile source code using &lt;code&gt;CompileAssemblyFromSource&lt;/code&gt; method of the CodeDomProvider&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Check &lt;code&gt;CompilerResults&lt;br /&gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt; Execute generated application if there were no errors&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115089947243964970?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115089947243964970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115089947243964970' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115089947243964970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115089947243964970'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/dynamic-code-compilation.html' title='Dynamic Code Compilation'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115038723225740406</id><published>2006-06-15T11:48:00.000-04:00</published><updated>2006-06-15T13:15:02.276-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>SoapHttpClientProtocol and XMLSerializer</title><content type='html'>I took it for granted that because .NET web service client sends SOAP request to invoke web service method, the client side should use SoapFormatter to serialize SOAP request parameters. Today I know I was wrong.&lt;br /&gt;&lt;br /&gt;Actually the client side uses XMLSerializer (instead of SOAPFormatter) to serialize SOAP request content.&lt;br /&gt;&lt;br /&gt;Why? Because SOAPFormatter (or BinaryFormatter) serializes all public, private data members and even methods to a stream, while XMLSerializer only serializes public data members. Web service is supposed to integrate separate applications in different platform (.Net, or Java, etc.), so it does not make sense to send private members and methods to the other side.&lt;br /&gt;&lt;br /&gt;If you want to send the whole object to the other side, you should use .NET remoting where you can make use of SOAPFormatter or BinaryFormatter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115038723225740406?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115038723225740406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115038723225740406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115038723225740406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115038723225740406'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/soaphttpclientprotocol-and.html' title='SoapHttpClientProtocol and XMLSerializer'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-115004128377391762</id><published>2006-06-11T10:45:00.000-04:00</published><updated>2006-06-11T15:32:37.786-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>What I learned in Mid-Atlantic Code Camp in Reston</title><content type='html'>Yesterday I attended &lt;a href="http://www.madcodecamp.com/"&gt;.NET Code Camp&lt;/a&gt; in Reston, VA. Before I went there, I had wondered how well it would be, because many good speakers went to TechEd 2006 in Boston. If this code camp had been scheduled days ahead of TechEd, maybe some TechEd speakers would attend the code camp to practice their topics. "Anyway, I will go there to have a look on this beautiful Saturday", so I went there in the morning.&lt;br /&gt;&lt;br /&gt;According to the session schedule, some good speakers were not there of course, but I did find several good speakers on the list! :)&lt;br /&gt;&lt;br /&gt;The schedule included five tracks: Web track, Data track, Smart Client track, Miscellaneous track, and Security track. There were no much stuff on WinFX (.NET 3.0). Below are the sessions I attended:&lt;br /&gt;&lt;br /&gt;1) "Enterprise Library and Data Security": Gary Blatt was still humorous. It's pleasure to listen to his speech. He did not talk about Enterprise Library 2.0 though.&lt;br /&gt;&lt;br /&gt;2) "Secure Click Once Smart Client Deployment": MS Regional Director - Brian Noyes' speech was full of exciting technology to me! :) He showed his broad knowledge on .NET platform. Actually, it was the first time for me to see a real "Click Once" (or Click Twice) deployment.&lt;br /&gt;&lt;br /&gt;In his speech, Brian showed deployment and application manifest files for an assembly. Whenever an assembly is deployed, new manifest files will include hash code for its XML content, and application manifest file also includes hash code for DLL files. In this way, it is quite difficult for hackers to replace DLL files or to change manifest content.&lt;br /&gt;&lt;br /&gt;On user side, Smart Client application runs code according to deployment server URL, so that user can run applications side-by-side deployed from QA server and production server.&lt;br /&gt;&lt;br /&gt;It is impossible for me to write down all what I learned from this session. I will wait for his coming MSDN Online article about Secure Click Once Deployment.&lt;br /&gt;&lt;br /&gt;3) "Refactoring: Why? When? How?": C# MVP Jonathan Cogley is also one of my favorite speakers (I attended two of his sessions :&gt;). He did not prepare PowerPoint slides. What he did was to show in Visual Studio how to make existing code better for maintenace and performance purposes using refactoring techniques (Rename, Extract Method, Move Method, Introducing Explaining Variable, etc.) and tools (e.g. ReSharper, NUnit). To see a smart guy changing code step by step is really a good learning experience! :)&lt;br /&gt;&lt;br /&gt;4) "Web Applications Security: Greatest Hits": Jonathan Cogley demonstrated SQL Injection and Cross-Site Script Attack in ASP.NET application, and how to change code to avoid attacks. Some concepts were not new to me, but I still got some good hints.&lt;br /&gt;&lt;br /&gt;For example, we may separate input pages with HTML editor from other input pages. HTML editor accepts Java Script in the textbox, so we should disable Request Validation for that page. For other input pages, we should enable ASP.net Request Validation to avoid script attack.&lt;br /&gt;&lt;br /&gt;5) "SQL Server Integration Services with Team Systems": Andy Leonard had planned to show Team system, but unfortunately his VPC died at that time. Instead, he showed us more exciting SSIS feathers. What surprised me in SSIS was its step-by-step debug capability inside Visual Studio.&lt;br /&gt;&lt;br /&gt;Andy mentioned that DBA should be involved in Software Development Life Cycle to make system better. I totally agree with him. Nowadays, many systems are designed without DBA, Tester, even Developers being involved --- How can they develop the system without misunderstanding?&lt;br /&gt;&lt;br /&gt;6) "Building Ajax Style Applications using ASP.NET 2.0 and Atlas": MS Regional Director Vishwas Lele showed some cool features of Atlas. He made it clear that Atlas does not use ASP.NET 2.0 Callback feature, it uses a special HTTP Handler to process JSON request directly without going through the whole ASP.NET page cycle.&lt;br /&gt;&lt;br /&gt;Overall, although I did not see topics about latest .NET 3.0, I still learned a lot from this code camp and went back home happily! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-115004128377391762?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/115004128377391762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=115004128377391762' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115004128377391762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/115004128377391762'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/what-i-learned-in-mid-atlantic-code.html' title='What I learned in Mid-Atlantic Code Camp in Reston'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114986104607433055</id><published>2006-06-09T09:10:00.000-04:00</published><updated>2006-06-10T00:47:44.010-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>.NET Application Server</title><content type='html'>"Application Server" has been a common buzz word in Java world for many years. J2EE Application Server hosts Java applications and provide environment for deployment, configuration, transaction, logging, session management, instance management, reporting, exception handling, load balancing etc. What application developer cares is mainly the application's business logic.&lt;br /&gt;&lt;br /&gt;Application Server in Java world makes perfect sense, because Java runs on different operating systems. It is necessary to build a common environment to hold applications.&lt;br /&gt;&lt;br /&gt;But in .NET world, "Application Server" is not well-known. We do not need Application Server in .NET, right? Yes or no. &lt;br /&gt;&lt;br /&gt;Yes. The main reason is that .NET is built upon Windows system, so that .NET can use features provided by Windows System (e.g. Transaction, Logging) directly. &lt;br /&gt;&lt;br /&gt;No. We still need an integrated environment for Enterprise software. That is the reason why &lt;a href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=295a464a-6072-4e25-94e2-91be63527327"&gt;MS Enterprise Library&lt;/a&gt; exists. But to set up and use that library is still complex for a normal developer. Compared with Java Application Server environment, .NET framework is not an integrated product for developers and project managers. The only one Application Server I know is &lt;a href="http://interactivesoftworks.com/Products/Application_Infrastructure/index.htm"&gt;Interactive Server&lt;/a&gt;. From my research on that product these days, it has some limitations.&lt;br /&gt;&lt;br /&gt;So, can we make an application server product to hold various .NET applications? Technically yes, although not easy. Maybe MS will build application server later. I heard a rumor that IIS 7 is a kind of Application Server, but I doubt. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114986104607433055?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114986104607433055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114986104607433055' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114986104607433055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114986104607433055'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/net-application-server.html' title='.NET Application Server'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114985839567278925</id><published>2006-06-09T08:52:00.000-04:00</published><updated>2006-06-09T09:06:35.683-04:00</updated><title type='text'>Social Engineering, the USB Way</title><content type='html'>The article &lt;a href="http://www.darkreading.com/document.asp?doc_id=95556&amp;amp;WT.svl=column1_1"&gt;"Social Engineering, the USB Way"&lt;/a&gt; amused and scared me a lot: When a credit union’s employees happened to find USB keys (with Trojans software), they were so happy to pick up and plug into company computers --- Everybody likes free stuff! :) The Trojans software ran secretly on those computers and sent emails to hackers with users’ important data --- It is so easy to hack a system!&lt;br /&gt;&lt;br /&gt;From that story and discussions, I realized two important security problems people ignore:&lt;br /&gt;&lt;br /&gt;1) Most people use Administrator account for daily work.&lt;br /&gt;&lt;br /&gt;For a financial company with customer SSN, birth date, and address in database, it is quite important to train employees to use non-admin account to avoid virus and Trojans software to some degree. However, in reality, many people (even IT people!) in financial company still do not feel that danger. They love the convenience of Administrator account!&lt;br /&gt;&lt;br /&gt;2) Auto-Run feature may run malicious software automatically&lt;br /&gt;&lt;br /&gt;Auto-Run feature is useful to play music CDs (not from Sony!), but if hackers use that feature to install virus or Trojans software, it will become a nightmare to users.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114985839567278925?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114985839567278925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114985839567278925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114985839567278925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114985839567278925'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/06/social-engineering-usb-way.html' title='Social Engineering, the USB Way'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114847682854300812</id><published>2006-05-24T09:19:00.000-04:00</published><updated>2006-12-28T15:39:41.473-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Great .NET posters</title><content type='html'>[Change note: The URL of those .NET posters has been changed]&lt;br /&gt;&lt;br /&gt;"Barone, Budge &amp; Dominick" has a great collection of posters relating to.NET technology. You can find the first page &lt;a href="http://www.drp.co.za/Media/Posters/PostersPDF/tabid/62/Default.aspx"&gt;Here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114847682854300812?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114847682854300812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114847682854300812' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114847682854300812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114847682854300812'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/05/great-net-posters.html' title='Great .NET posters'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114779455868807613</id><published>2006-05-16T11:34:00.000-04:00</published><updated>2006-05-16T11:52:55.193-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><title type='text'>.NET web service tips</title><content type='html'>Here are list of tips for .NET web service development. I put here so that I need not google to find them later. :)&lt;br /&gt;&lt;br /&gt;1) Generate  web service interface so that we can separate implementation from WSDL. When WSDL is changed someday, we will not lose our implemenation code:&lt;br /&gt;&lt;pre&gt;wsdl.exe /si ServerInterfaceSample.wsdl&lt;/pre&gt;&lt;br /&gt;2) Web service can use ASP.NET session state. To enable ASP.NET session state, set WebMethod.EnableSession = True. On the client you must also create a new instance of System.Net.CookieContainer. Note that to persist data for the entire application, neither step is required.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Client code:&lt;/b&gt;&lt;div style="overflow:auto; width:auto"&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;//On the client you must add the following code (for session state only):&lt;br /&gt;serviceName.CookieContainer = new System.Net.CookieContainer();&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Server code:&lt;/b&gt;&lt;br /&gt;&lt;div style="overflow:auto; width:auto"&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; //Setting EnableSession to true allows state to be persisted per Session&lt;br /&gt;[WebMethod(EnableSession=true)]&lt;br /&gt;public String UpdateSessionHitCounter() {&lt;br /&gt;   //update the session "HitCounter" here&lt;br /&gt;   return Session["HitCounter"].ToString();&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;3) Asynchronous call to web service:&lt;br /&gt;Use the event-based model to asynchronously call your Web services.&lt;br /&gt;&lt;div style="overflow:auto; width:auto"&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;   //First implement the HelloWorldCompleted method using the following signature:&lt;br /&gt;  //public void HelloWorldCompleted(object sender, HelloWorldCompletedEventArgs args)&lt;br /&gt; &lt;br /&gt;  //Create the Web service&lt;br /&gt;  HelloWorldWaitService service = new HelloWorldWaitService();&lt;br /&gt;  //Add our callback function to the event handler&lt;br /&gt;  service.HelloWorldCompleted += this.HelloWorldCompleted;&lt;br /&gt;  //Call the Web service asynchronously&lt;br /&gt;  service.HelloWorldAsync("first call");&lt;br /&gt;  //when the Web service call returns the HelloWorldCompleted method will be called&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114779455868807613?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114779455868807613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114779455868807613' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114779455868807613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114779455868807613'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/05/net-web-service-tips.html' title='.NET web service tips'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114685242359482484</id><published>2006-05-05T13:36:00.000-04:00</published><updated>2007-04-05T13:32:17.729-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>Optimistic Concurrency Control using RowVersion in Sql 2005 and C#</title><content type='html'>To use optimistic concurrency control, one option is to add a RowVersion (kind of timeStamp) column in Sql 2005 table. Its value will be modified automatically by Sql server whenever the row is updated.&lt;br /&gt;&lt;pre&gt;alter table dbo.authors add LastRowVersion RowVersion&lt;/pre&gt;&lt;br /&gt;The type of the newly added column is "TimeStamp" in Sql 2005, but its value has no relationship with time at all. The RowVersion column only uses the same structure of TimeStamp to save version number (8 bytes).&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-weight: bold;"&gt;process of optimistic concurrency control&lt;/span&gt; using RowVersion column is like below: When user A gets a record and tried to edit, the RowVersion value is also got to A's program. Another user B also gets the same record to edit, but B saves his/her content before A saves. Now the record's LastRowVersion is changed. When A tries to save content into the record, the save process should compare the previously fetched LastRowVersion with the latest value in the database. If the two values do not match, user A should get error message like "Another user has saved the content in front of you. Your content cannot be saved", blah blah.&lt;br /&gt;&lt;br /&gt;Now, let's see how to deal with &lt;span style="font-weight: bold;"&gt;the RowVersion column in ASP.NET/C# code&lt;/span&gt;. In data access layer, we still use SqlDbType.Timestamp for RowVersion to transfer value between our code and Sql Server. But in other layers, we should use byte[] array.&lt;br /&gt;&lt;br /&gt;When the ASP.NET page gets the data from business layer, the RowVersion value can be saved in ViewState:&lt;br /&gt;&lt;pre&gt;ViewState["RowVersion"] =&lt;br /&gt;Convert.ToBase64String(bo.LastRowVersion);&lt;/pre&gt;&lt;br /&gt;When user clicks "Save" button in edit page to save changes, we can get the old RowVersion from ViewState in postback:&lt;br /&gt;&lt;pre&gt;byte[] rowVersion =&lt;br /&gt;Convert.FromBase64String(ViewState["RowVersion"] as string);&lt;/pre&gt;&lt;br /&gt;Then we can pass the rowVersion variable with the new content to data access layer for concurrency check as mentioned above.&lt;br /&gt;&lt;br /&gt;In some applications, ViewState may be disabled. In this case, we can save the value in ControlState, which needs several more lines of code than using ViewState.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114685242359482484?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114685242359482484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114685242359482484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114685242359482484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114685242359482484'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/05/optimistic-concurrency-control-using.html' title='Optimistic Concurrency Control using RowVersion in Sql 2005 and C#'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114675432354416416</id><published>2006-05-04T10:40:00.000-04:00</published><updated>2006-05-04T10:52:03.556-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Mix'06 sessions are online now :)</title><content type='html'>Luckily I attended Microsoft &lt;a href="http://www.mix06.com/"&gt;Mix'06&lt;/a&gt; conference in Las Vegas in March, 2006. As the conference included various topics covering web design, web development, smart client application, next generation of OS and browser, so the conference was named Mix (mixture).&lt;br /&gt;&lt;br /&gt;I was quite impressed by the demos of Windows Presentation Foundation, Windows Presentation Foundation Everywhere, and Atlas. I think other sessions must be also interesting, such as "building your own search engine", but I couldn't attend those meetings at that time.&lt;br /&gt;&lt;br /&gt;But now, I can watch all those sessions &lt;a href="http://sessions.mix06.com/"&gt;online&lt;/a&gt; :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114675432354416416?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114675432354416416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114675432354416416' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114675432354416416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114675432354416416'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/05/mix06-sessions-are-online-now.html' title='Mix&apos;06 sessions are online now :)'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114644922899070027</id><published>2006-04-30T22:04:00.000-04:00</published><updated>2006-04-30T23:35:21.593-04:00</updated><title type='text'>Management and Engineers</title><content type='html'>I saw this article from &lt;a href="http://codebetter.com/blogs/sahil.malik/archive/2006/04/30/143728.aspx"&gt;Sahil Malik's blog&lt;/a&gt;. It is quite what I am feeling for current IT industry.&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;A man in a hot air balloon realized he was lost. He reduced altitude and spotted a woman below. He descended a bit more and shouted, "Excuse me, can you help me? I promised a friend I would meet him an hour ago, but I don't know where I am."&lt;br /&gt;&lt;br /&gt;The woman below replied, "You are in a hot air balloon hovering approximately  30 feet above the ground.  You are between 40 and 41 degrees north latitude and between 59 and  60 degrees west longitude."&lt;br /&gt;&lt;br /&gt;"You must be an engineer," said the balloonist.&lt;br /&gt;&lt;br /&gt;"I am," replied the woman, "How did you know?"&lt;br /&gt;&lt;br /&gt;"Well," answered the balloonist, "everything you told me is, technically correct, but I have no idea what to make of your information, and the fact  is I am still lost. Frankly, you've not been much help so far."&lt;br /&gt;&lt;br /&gt;The woman below responded, "You must be in Management."&lt;br /&gt;&lt;br /&gt;"I am," replied the balloonist, "but how did you know?"&lt;br /&gt;&lt;br /&gt;"Well," said the woman, "you don't know where you are or where you are going. You have risen to where you are due to a large quantity of hot air. You made a promise, which you have no idea how to keep, and you expect  people  beneath you to solve your problems. The fact is you are in exactly the same  position you were in before we met, but now, somehow, it's my fault."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114644922899070027?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114644922899070027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114644922899070027' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114644922899070027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114644922899070027'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/management-and-engineers.html' title='Management and Engineers'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114622827830766391</id><published>2006-04-28T08:28:00.000-04:00</published><updated>2006-04-28T08:44:38.320-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><title type='text'>Middle-Ware is in the Middle</title><content type='html'>I attended the "&lt;a href="http://groups.msn.com/MICSUG"&gt;Capital Area Microsoft Integration and Connected Systems User Group&lt;/a&gt;" last night. It had good topics about lessons learned from Biztalk integration projects.&lt;br /&gt;&lt;br /&gt;One of the lessons I feel important is to really know "Middle-Ware is in the Middle", which means whenever there is something wrong with the operation of an integrated system, normally either developers or clients will complain:"Middle-Ware is not working properly". But in fact, most of the cases are not because of the Middle-Ware, but the end-point applications.&lt;br /&gt;&lt;br /&gt;To protect from the easy blame from other people, tracking and reporting are the life-savers: Keep all detailed tracking and reporting information to indicate where the real problem is, e.g. the schema of the source data has been arbitrarily changed.&lt;br /&gt;&lt;br /&gt;We needn't work on really big project to create/use Middle-Ware. Even for small project, we will write middle-ware program occasionally. For example, we may write either Windows Service to collect data or Web Service to process data. For end user, they are back end Middle-Ware. It is important to keep event log for each process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114622827830766391?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114622827830766391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114622827830766391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114622827830766391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114622827830766391'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/middle-ware-is-in-middle.html' title='Middle-Ware is in the Middle'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114607722725132767</id><published>2006-04-26T13:44:00.000-04:00</published><updated>2007-06-04T13:27:25.902-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='Biztalk'/><title type='text'>Service-Oriented Architecture and Biztalk Server</title><content type='html'>When people talk about Service-Oriented Architecture (SOA), they talk more details about how to write Web Services. Actually, SOA is more than web services. For developer, SOA means contract-first development for a distributed system to support interoperability between applications.&lt;br /&gt;&lt;br /&gt;As Biztalk Server 2006 is released, let's look at its architecture for an example of SOA.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/biztalk_arch.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/7748/2306/320/biztalk_arch.jpg" border="0" alt="Biztalk messaging architecture" /&gt;&lt;/a&gt;&lt;br /&gt;Biztalk server includes four parts: Receive Port, Message Box, Orchestration, and Send Port. Receive Port uses protocol (FTP, SOAP, etc.) specific Adpater to receive file or message, then persists the (transformed) message into Message Box. Message Box activates according Orchestration or Send Port based on subscription of the message type. Orchestration is a process workflow to do some work based on incoming message, then Orchestration may persist a new message in Message Box. Message Box activates according Send Port to send the new message out.&lt;br /&gt;&lt;br /&gt;From the architecture, we can know that Biztalk server is in message-based. Its main function is to receive a message, and to send message after doing some work. You can also take Biztalk as a message processing service.&lt;br /&gt;&lt;br /&gt;For development, Biztalk developers typically start by modeling the messages using XML schema. Developers then promote several message properties for routing purposes. Then Developers configure Orchtestration or Send Ports to subscribe the messages matching those promoted properties. The orchestration developed also deals with XML schema to process message. From these steps, you can see it is a contract-first development. &lt;br /&gt;&lt;br /&gt;Biztalk application is also autonomous. Biztalk does not care about the implementation details of other connected applications. It only cares the messages received/sent using the predefined XML schema.&lt;br /&gt;&lt;br /&gt;Until now, you can say Biztalk is a good example of Service-Oriented application. Is it a web service? No, although you can optionally publish an orchestration as a web service.&lt;br /&gt;&lt;br /&gt;Biztalk architecture allows flexibility to connect to nearly any kind of legacy applications by using different Adapter in receive/send port. Let's take receive port as an example:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/biztalk_recvPort.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/7748/2306/320/biztalk_recvPort.jpg" border="0" alt="Biztalk receive port" /&gt;&lt;/a&gt; &lt;br /&gt;The receive port uses protocol-specific Adpater to receive original message and add other context information to build an internal message, then the pipeline can decode the message, the last step in receive port is XML schema mapping to transform the original message into another format that Orchestration knows. &lt;br /&gt;&lt;br /&gt;Developers can use many kinds of Adapter to receive/send message, e.g. using MSMQ, SOAP, even Windows Communication Foundation Adapter. This architecture allows to integrate various applications without modifying those applications' code.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wrap-Up&lt;/b&gt;&lt;br /&gt;Biztalk is a good example of Service-Oriented Architecture application. The architecture uses contract-first development and allows potential extension.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114607722725132767?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114607722725132767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114607722725132767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114607722725132767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114607722725132767'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/service-oriented-architecture-and.html' title='Service-Oriented Architecture and Biztalk Server'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114606117556898868</id><published>2006-04-26T09:44:00.000-04:00</published><updated>2006-04-26T15:00:12.106-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><title type='text'>Contract-First Web Service development</title><content type='html'>Although we normally define interface (contract) between client and server in distributed environment before we really write logic code, Visual Studio does not provide this Contract-First mechanism for Web Service application development.&lt;br /&gt;&lt;br /&gt;What VS provides is implementation-first: Developer writes web methods first, then VS generates WSDL (contract) to allow client developer to implement web service client.&lt;br /&gt;&lt;br /&gt;The advantage of implementation-first approach is that it is quite easy to develop a web service. Developer need not write complicated WSDL file manually. When web service client accesses the web service, .NET framework will reflect web methods in web service code and generate WSDL dynamically.&lt;br /&gt;&lt;br /&gt;The disadvantages of implementation-first approach are:&lt;ul&gt;&lt;li&gt; Web service developer can change web method easily, which may change the generated WSDL accidentally or without enough warning. This will break the contract between web service and client. &lt;/li&gt;&lt;br /&gt;&lt;li&gt; Web service developer may ignore the compatibility of generated WSDL to include complex object type, like DataSet. This will make Java client difficult to get result because DataSet is only used in .NET framework, not Java framework.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So, how can we use current tools to develop web service? Actually, we can use implementation-first approach in the beginning:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; We can write web methods in Visual Studio without put logic code inside. Then we can let VS generate the complex WSDL for us.&lt;/li&gt;&lt;br /&gt;&lt;li&gt; We examine the WSDL to make sure it does not include .NET specific data types. We may add more parameters to it. &lt;/li&gt;&lt;br /&gt;&lt;li&gt; If we changed the WSDL, we can re-generate web service code using "wsdl.exe /server &amp;lt;WebService WSDL file&amp;gt;"&lt;/li&gt;&lt;br /&gt;&lt;li&gt; When the contract need modification, we should explicitly update the WSDL file and re-generate web service code. We cannot modify web method code directly. This step may overwrite original code, so it is a good idea to separate implementation code into another file&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/interoperability_wp-fig3.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/7748/2306/320/interoperability_wp-fig3.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If we follows the steps above, we should be able to keep interoperability between web service and client.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114606117556898868?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114606117556898868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114606117556898868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114606117556898868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114606117556898868'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/contract-first-web-service-development.html' title='Contract-First Web Service development'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114592768468048273</id><published>2006-04-24T20:31:00.000-04:00</published><updated>2007-04-05T13:33:43.929-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='WF'/><title type='text'>Windows Workflow Foundation (WF) and ASP.NET</title><content type='html'>Windows Workflow Foundation (WF) is an exciting addition to .NET development framework, which makes developing enterprise Workflow application easier -- You need not worry about maintaining states for each activity inside WF. As most of the enterprise applications are web-based, I am more curious how WF can integrate with ASP.NET framework.&lt;br /&gt;&lt;br /&gt;Let's take a brief look at how WF and ASP.NET work separately.&lt;br /&gt;&lt;br /&gt;WF: WF runtime creates a WF instance that is defined by developer using workflow designer or XOML (a XAML configuration file). Then the instance is started to process passed-in parameters (for sequential workflow) or wait for an event to trigger a series of activities (for state machine workflow). To avoid blocking front-end application, by default the WF instance runs asynchronously using another thread. When WF instance is idle (e.g. while waiting for human intervention), the instance is serialized and saved in database. Later, when certain event happens, the instance will be deserialized and continue to process from former state. A sample of WF code is like below:&lt;div style="overflow:auto; width:auto"&gt;&lt;br /&gt;&lt;pre&gt;// Get a reference to the Workflow runtime&lt;br /&gt;WorkflowRuntime wr = WorkflowWebRequestContext.Current.WorkflowRuntime;&lt;br /&gt;&lt;br /&gt;// Attach to the WorkflowCompleted event&lt;br /&gt;wr.WorkflowCompleted += new EventHandler&amp;lt;workflowcompletedeventargs&amp;gt;(CallbackMethodWhenCompleted);&lt;br /&gt;&lt;br /&gt;// Create workflow instance&lt;br /&gt;WorkflowInstance workflowInstance = wr.CreateWorkflow(typeof(Samples.HelloWorkflow), parameters);&lt;br /&gt;&lt;br /&gt;// Start the workflow instance&lt;br /&gt;workflowInstance.Start();&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;ASP.NET: ASP.NET runs synchronously for each request. There is no relationship between each request. After the request is processed, a response will be returned.&lt;br /&gt;&lt;br /&gt;1) The synchronous ASP.NET and asynchronous WF makes integration a little bit complex. If ASP.NET code call WF runtime to create an instance to run without special configuration, ASP.NET code will return directly without waiting for the WF instance to finish -- This is not what we want.&lt;br /&gt;&lt;br /&gt;2) When a new request comes, ASP.NET cannot create a new WF runtime. Because WF runtime cannot be loaded more than once in the same AppDomain.&lt;br /&gt;&lt;br /&gt;To solve the first problem, uses the &amp;lt;workflowruntime&amp;gt; configuration section in the configuration file to store information to include WorkFlowPersistenceService and WorkFlowSchedulerService. The former service automatically persists the workflow instance to the specified database as soon as the workflow becomes idle. The second service ensure that the ASP.NET thread in charge of executing the current request waits until the workflow is completed, in another word, the service guarantees that the execution of the workflow is synchronous and that the Start() method returns only when the workflow has ended or is idle.&lt;br /&gt;&lt;br /&gt;For example, the configuration part can be like below:&lt;br /&gt;&lt;div style="overflow:auto; width:auto"&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;WorkflowRuntime Name="WorkflowServiceContainer"&amp;gt;&lt;br /&gt;    &amp;lt;Services&amp;gt;&lt;br /&gt;      &amp;lt;add type=&lt;br /&gt;        "System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService,&lt;br /&gt;         System.Workflow.Runtime, ..." /&amp;gt;&lt;br /&gt;      &amp;lt;add type=&lt;br /&gt;        "System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, &lt;br /&gt;         System.Workflow.Runtime, ..." /&amp;gt;&lt;br /&gt;    &amp;lt;/Services&amp;gt;&lt;br /&gt;  &amp;lt;/WorkflowRuntime&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;To solve the second problem, WF provides WorkflowWebRequestContext to provide unique runtime instance in an AppDomain (see above code example).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114592768468048273?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114592768468048273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114592768468048273' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114592768468048273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114592768468048273'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/windows-workflow-foundation-wf-and.html' title='Windows Workflow Foundation (WF) and ASP.NET'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114549473269656097</id><published>2006-04-19T20:44:00.000-04:00</published><updated>2007-04-05T13:32:17.730-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Database'/><title type='text'>CTE in SQL Server 2005</title><content type='html'>CTE (common table expression) is a good feature in SQL Server 2005 to make recursive logic easier. But the implementation of SQL Server 2005 has limitation. Let's look at an example as below to get directory tree:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;DECLARE @DirID int&lt;br /&gt;SET @DirID = 11;&lt;br /&gt;&lt;br /&gt;WITH cte_subDir (dirID, dirName, parentDirID)&lt;br /&gt;AS&lt;br /&gt;(&lt;br /&gt;SELECT dirID, dirName, parentDirID&lt;br /&gt;FROM DirTable&lt;br /&gt;WHERE dirID = @DirID&lt;br /&gt;&lt;br /&gt;UNION ALL&lt;br /&gt;&lt;br /&gt;SELECT dirID, dirName, parentDirID&lt;br /&gt;FROM DirTable&lt;br /&gt;INNER JOIN cte_subDir&lt;br /&gt;  ON DirTable.parentDirID = cte_subDir.DirID&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;IF @DirID &gt; 10&lt;br /&gt;DELETE FROM DirTable&lt;br /&gt;WHERE dirID IN (&lt;span style="color: rgb(51, 51, 255);"&gt;SELECT dirID FROM cte_subDir&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;When I ran the script, I got this error:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Msg 156, Level 15, State 1, Line 18&lt;br /&gt;Incorrect syntax near the keyword 'IF'.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It took me about one hour that I realized CTE With statement cannot be followed by IF statement. It can be followed by SELECT statement though.&lt;br /&gt;&lt;br /&gt;To make the above logic, I have to create a temporary table using&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT * INTO #tempTable FROM cte_subDir&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then, I can use #tempTable for the remaining logic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114549473269656097?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114549473269656097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114549473269656097' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114549473269656097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114549473269656097'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/cte-in-sql-server-2005.html' title='CTE in SQL Server 2005'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114530655307245854</id><published>2006-04-17T16:22:00.000-04:00</published><updated>2006-04-17T16:47:05.290-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>SelectedDate of ASP.NET Calendar control</title><content type='html'>During years of ASP.NET development, sometimes I find I ignored important page lifecycle even I used some features frequently.&lt;br /&gt;&lt;br /&gt;Here is an example of Calendar control. I put the Calendar control dynamically into one page, and put data binding logic for the selected date in Page_Load() like below:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected new void Page_Load(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt; // Call base method&lt;br /&gt; base.Page_Load(sender, e);&lt;br /&gt;&lt;br /&gt; // Get selected date&lt;br /&gt; DateTime selectedDate = wsCalendar.SelectedDate;&lt;br /&gt;&lt;br /&gt; // Bind data&lt;br /&gt; BindEventList(selectedDate);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When I ran the program and check the selectedDate variable, you know what? On the first time postback, the value of selectedDate was 1/1/0001 while I had selected 4/17. On the second time of postback, the value of selectedDate was 4/17, instead of the latest selected date 4/20: I got the selected date of the last time, not the current one!&lt;br /&gt;&lt;br /&gt;That result amused me for a while until I realized I made this mistake: I should get the selectedDate in &lt;span style="color:blue;"&gt;&lt;b&gt;Selectionchanged&lt;/b&gt;&lt;/span&gt; event. During Page_Load(), the real selectedDate has not been updated yet although part of postBack logic was already executed before load event.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;protected void DateChanged(object s, EventArgs e)&lt;br /&gt;{&lt;br /&gt; // I can get the real selected date now&lt;br /&gt; DateTime selectedDate = wsCalendar.SelectedDate;&lt;br /&gt;&lt;br /&gt; // Bind data&lt;br /&gt; BindEventList(selectedDate);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114530655307245854?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114530655307245854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114530655307245854' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114530655307245854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114530655307245854'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/selecteddate-of-aspnet-calendar.html' title='SelectedDate of ASP.NET Calendar control'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114494161208240270</id><published>2006-04-13T10:52:00.000-04:00</published><updated>2006-04-13T11:36:59.756-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>Try/Catch internal</title><content type='html'>I was curious how to implement Try/Catch statement in compiler. When an exception occurs in methodChild(), how can OS know which part of code to catch that exception? If methodChild() does not catch the exception, the methodParent() (calling methodChild()) should catch the exception. If methodParent() does not catch, the exception should be handled by parent method of methodParent(), and so on ... But how can this catching process be implemented?&lt;br /&gt;&lt;br /&gt;Today, several articles (e.g. &lt;a href="http://blogs.msdn.com/freik/archive/2005/03/17/398200.aspx"&gt;Calling Conventions&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx"&gt;X64 Primer&lt;/a&gt;) let me understand what is going on under the hood.&lt;br /&gt;&lt;br /&gt;In Win32, compiler generates special instructions for Try/Catch statement. Every     function that needs attention due to an exception must add an element     to a thread-global linked list upon entry, and remove it upon exit. Each element in the linked list contains a function pointer to call in the event of an exception, and then     some data that said function will consume.  When an exception is thrown, OS will walk through the linked list to find a function to process the exception properly.&lt;br /&gt;&lt;br /&gt;The linked list structure of Win32 is not efficient. In addition,     the linked list actually resides on the stack, thus there is a function pointer (to remove element upon exit?) sitting     right below the return address on your stack -- Buffer overruns.&lt;p&gt;In contrast to the Win32 exception handling, Win64 executable contains a runtime function table. Each function table entry contains both the starting and ending address for the function, as well as the location of a rich set of data about exception-handling code in the function and the function's stack frame layout.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;When an exception occurs, the OS walks the regular thread stack to search the runtime function table in that module, locates the appropriate runtime function entry, and makes the appropriate exception-processing decisions from that data.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114494161208240270?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114494161208240270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114494161208240270' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114494161208240270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114494161208240270'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/trycatch-internal.html' title='Try/Catch internal'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114484502799128413</id><published>2006-04-12T08:26:00.000-04:00</published><updated>2006-04-12T14:55:41.926-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>ASP.NET 2.0 Master Page article</title><content type='html'>Scott's article style is informative and  inspiring. Here is &lt;a href="http://odetocode.com/Articles/450.aspx"&gt;an article about ASP.NET 2.0 Master page tricks and tips&lt;/a&gt;. Enjoy :)&lt;br /&gt;&lt;br /&gt;In this article, Scott makes the masterpage process clear: Master page replaces the content page's children to itself, then the master page looks for Content control in the controls formerly associated with the content page. When the master page finds a Content control that matches its ContentPlaceHolder, it moves the controls inside the Content control into the matching ContentPlaceHolder. This process happens after the content page's PreInit event, but before the content page's Init event.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note: At this time, the Content control itself does not exist in content page's DOM tree any more, which means you cannot use ContentControl.FindControl("ctl") .&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the article, Scott gives good suggestion for interaction between mater page and content page. Basic idea is not to bundle mater page and content page too tightly. It is better to use a separate event, and let the two pages subscribe to the event.&lt;br /&gt;&lt;br /&gt;There are also several other useful tips. I believe I will refer to that article later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114484502799128413?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114484502799128413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114484502799128413' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114484502799128413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114484502799128413'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/aspnet-20-master-page-article.html' title='ASP.NET 2.0 Master Page article'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114480890067728414</id><published>2006-04-11T22:18:00.000-04:00</published><updated>2006-04-11T22:28:20.686-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>WPF/E architecture</title><content type='html'>WPF/E (Windows Presentation Foundation Everywhere) has subset feature of WPF. It can dynamically arrange document layout, show 2D, subpixel text, etc.&lt;br /&gt;&lt;br /&gt;The good thing about WPF/E is it is cross browser and cross OS framework.&lt;br /&gt;&lt;br /&gt;The not so good things are:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;Cannot support 3D&lt;/li&gt;   &lt;li&gt;Need plugin to browser to show content&lt;/li&gt; &lt;/ul&gt; Below shows the architecture of WPF/E:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/7748/2306/1600/WPFE.0.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/7748/2306/320/WPFE.0.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114480890067728414?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114480890067728414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114480890067728414' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114480890067728414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114480890067728414'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/wpfe-architecture.html' title='WPF/E architecture'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114478238479814924</id><published>2006-04-11T14:44:00.000-04:00</published><updated>2006-04-11T15:07:53.776-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>508 Compliant issue in web development</title><content type='html'>As I am building websites in a government department, it is quite common to hear "Is this site &lt;a href="http://www.section508.gov/"&gt;508 compliant&lt;/a&gt;"? Most people in corporate do not know what 508 is about, but in government, 508 makes developers pulling their hair every day.&lt;br /&gt;&lt;br /&gt;508 compliance is to let disabled people view websites and low end browser (e.g. text-only browser) display content correctly. If a page displays image, that image must have alternative text to show text information about that image. So disabled user can use screen reader to "view" the page.&lt;br /&gt;&lt;br /&gt;But 508 does not mention JavaScript. So can we use JavaScript in web pages? Some people would say No! Why? Because if user disables JavaScript in browser, the web site is not workable for him/her anymore, which means it is not a 508 compliant site. So to make a workable 508-compliant, we have to develop web pages without any JavaScript involved. Of course, we can add JavaScript to make pages look nicer, but without JavaScript, the web pages must also work.&lt;br /&gt;&lt;br /&gt;For a web site only displaying content most of the time, it is ok without JavaScript. But for a web application (like Intranet), without JavaScript means driving a car that has no engine. How can you make an Intranet interactive only by using URL parameters and hidden fields? Not to mention good user experience of AJAX that definitely needs JavaScript.&lt;br /&gt;&lt;br /&gt;508 was made a decade ago when Internet was supposed to display content, not for interaction. Nowadays, 99% of people will not use text-base browser. 508 seems out-of-date now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114478238479814924?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114478238479814924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114478238479814924' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114478238479814924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114478238479814924'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/508-compliant-issue-in-web-development.html' title='508 Compliant issue in web development'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114478078012840363</id><published>2006-04-11T14:26:00.000-04:00</published><updated>2006-04-11T15:08:05.193-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>WPF and WPF/E</title><content type='html'>WPF (Windows Presentation Foundation) is a MS .NET framework to build desktop/browser application. As the name indicates, WPF is to display content in interactive manner, like 2D, 3D, audio, video, etc. Normally, WPF application can be compiled in desktop or browser mode without much code change: because WPF browser application uses XAML (not HTML) to display content.&lt;br /&gt;&lt;br /&gt;WPF is based on DirectX. So if you want to write a high-performance application (e.g. 3D game), you had better use DirectX, not WPF. For other cases, WPF will be your choice for next generation Windows development.&lt;br /&gt;&lt;br /&gt;The advantage of WPF is that application can take advantage of user's computer resource (memory, CPU, harddisk, etc), and easy to deploy without installation. The latter is the biggest reason why web sites are so popular.&lt;br /&gt;&lt;br /&gt;The disadvantage of WPF is it requires .NET 2.0 and WinFX platform on user's computer. So it is limited on Windows machine.&lt;br /&gt;&lt;br /&gt;To solve that problem, MS is developing WPF/E (everywhere). It has subset features of WPF (without 3D support), but it can run in IE, Safari, or Firefox. It also uses XAML for content layout.&lt;br /&gt;&lt;br /&gt;WPF/E need a small plugin inside browser to run application. WPF/E application includes XAML and .NET (C#, VB.NET) compiled library (IL). For this reason, WPF/E runtime includes a simplified version of .NET framework (~200KB)&lt;br /&gt;&lt;br /&gt;WPF/E is much better than Flash in both feature and development.&lt;br /&gt;&lt;br /&gt;Hopefully, we can try those technology this year :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114478078012840363?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114478078012840363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114478078012840363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114478078012840363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114478078012840363'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/wpf-and-wpfe.html' title='WPF and WPF/E'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114468659608781268</id><published>2006-04-10T12:18:00.000-04:00</published><updated>2006-04-10T12:29:56.100-04:00</updated><title type='text'>Dragon CPU makes computer industry interesting</title><content type='html'>These days, &lt;a href="http://english.cas.cn/Eng2003/news/detailnewsb.asp?infoNo=25459"&gt;Dragon CPU&lt;/a&gt; (also named GodSon chip)  has been a hot topic in IT websites. The performance of the CPU is similar to lower-level Pentium 4. It is a 64-bit CPU with 95% MIPS compatible instruction set. In 03/2006, a ~$180 Godson II computer running Linux called &lt;a href="http://en.wikipedia.org/wiki/Longmeng" title="Longmeng"&gt;Longmeng&lt;/a&gt; (Dragon Dream) was announced.&lt;br /&gt;&lt;br /&gt;With the low price and high performance, that CPU may threaten WinTel: Just like somebody said, M$ does not care Linux, but care Linux + cheap computer!&lt;br /&gt;&lt;br /&gt;The IT world will change soon. Let's wait and see ... ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114468659608781268?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114468659608781268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114468659608781268' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114468659608781268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114468659608781268'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/04/dragon-cpu-makes-computer-industry.html' title='Dragon CPU makes computer industry interesting'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114088131550215596</id><published>2006-02-25T10:19:00.000-05:00</published><updated>2006-02-25T10:32:52.136-05:00</updated><title type='text'>labeling of insect-derived red food dye</title><content type='html'>Until today, I didn't know that some "artificial colors" in our food product are from insects (&lt;a href="http://www.foodqualitynews.com/news/ng.asp?n=65603-cochineal-carmine-color"&gt;here&lt;/a&gt;). I thought I was careful enough to avoid food with animal stuff inside, but now I think I had better be a farmer to get pure vegetarian food.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"Derived from the ground bodies of female cochineal beetles, the colorings are currently used in a variety of ice creams, yogurts, fruit drinks, alcoholic drinks and candy products, to which they bring a characteristic pink, red or purple color."&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;" class="verdana11000000"&gt;Currently the FDA only requires that the ingredient is labeled as a ‘color added' or ‘artificial color'"&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;i&gt;"Why not use a word that people can understand?” &lt;/i&gt;said CSPI director Michael Jacobson. &lt;i&gt;”Sending people scurrying to the dictionary or to Google to figure out what ‘carmine' or ‘cochineal' means is just plain sneaky. Call these coloring what they are – insect-based.” &lt;/i&gt; &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114088131550215596?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114088131550215596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114088131550215596' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114088131550215596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114088131550215596'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/02/labeling-of-insect-derived-red-food.html' title='labeling of insect-derived red food dye'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114070514035131401</id><published>2006-02-23T09:31:00.000-05:00</published><updated>2006-02-23T11:29:52.800-05:00</updated><title type='text'>Alternative Living</title><content type='html'>It seems like vegetarian is a good choice for us and for animals:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/7748/2306/1600/AL.0.jpg"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/7748/2306/320/AL.0.jpg" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114070514035131401?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114070514035131401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114070514035131401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114070514035131401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114070514035131401'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/02/alternative-living.html' title='Alternative Living'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114061908111987759</id><published>2006-02-22T09:04:00.000-05:00</published><updated>2006-04-11T22:40:03.313-04:00</updated><title type='text'>Health Studies in Confusion</title><content type='html'>According to the so-called 8-year study: low-fat diets do not benefit cancer significantly (&lt;a href="http://www.washingtonpost.com/wp-dyn/content/article/2006/02/07/AR2006020701681.html"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;When I first saw that result, I doubted my own vegetarian habit: Is it a really healthy to be a vegetarian? I can tell from my years of vegetarian experience that it does not give me much more energy, but compared with when I ate meat and eggs, my health is not getting worse at least. I am getting old as well. It is difficult to tell if vegetarian really improved my health. But from theory, it should be a good eating habit.&lt;br /&gt;&lt;br /&gt;Then I read several articles about that study in the coming days. It turns out that study was based on out-of-date hypothesis. It even did not distinguish lard or olive oil!&lt;br /&gt;&lt;br /&gt;They spent more than 400 million dollars for that nonsense study.&lt;br /&gt;&lt;br /&gt;I will not take those kind of study for granted any more. I will keep my diet because I prove it works for me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114061908111987759?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114061908111987759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114061908111987759' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114061908111987759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114061908111987759'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/02/health-studies-in-confusion.html' title='Health Studies in Confusion'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114038468201292411</id><published>2006-02-19T16:05:00.000-05:00</published><updated>2006-02-19T22:49:35.193-05:00</updated><title type='text'>Unhealthy lifestyle</title><content type='html'>During the past dozen years of work as a software engineer, I met many computer guys who do not look like in their age. They are either too fat, or too weak. The reason is obvious: we sit in front of computer for years without necessary exercise, and even worse, many of us like to eat something during coding.&lt;br /&gt;&lt;br /&gt;I am quite sad with this lifestyle although I love computer and already get used to programming life. I wanted to find a way to improve health without interrupting work. Here are what I found useful to me at least:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Stand up and keep knees bent a little bit for several minutes every hour. You can talk with coworkers or design a solution to solve a problem at the same time. Human being gets older from her/his legs, so it is very important to strengthen our legs&lt;/li&gt;&lt;li&gt;Practice TaiJi or QiGong to build energy. Healthy does not necessarily mean big muscle. We needn't go to expensive gym to keep us healthy. Simple QiGong can work perfectly for our body and our mind. For Taiji, I recommend Chen-Style TaiJi that is not so slow.&lt;/li&gt;&lt;li&gt;Eat more vegetable and fruit. Saturated fat is not good for our body.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;What else?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114038468201292411?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114038468201292411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114038468201292411' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114038468201292411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114038468201292411'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/02/unhealthy-lifestyle.html' title='Unhealthy lifestyle'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-22643768.post-114038013798532110</id><published>2006-02-19T15:08:00.000-05:00</published><updated>2006-04-22T17:16:02.070-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General .NET'/><title type='text'>The 'using' statement in .Net 2.0</title><content type='html'>The 'using' statement in .Net 2.0 is to dispose an object implicitly when the code block is finished. The compiler translates 'using' statement to try...finally statement and call the object's dispose() function.&lt;br /&gt;&lt;br /&gt;Suppose that we have this using statement:&lt;pre&gt;&lt;br /&gt;using (obj)&lt;br /&gt;{&lt;br /&gt; obj.DoSomething();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;From concept, the compiler translates that block into code like below:&lt;pre&gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt; obj.DoSomething();&lt;br /&gt;}&lt;br /&gt;finally&lt;br /&gt;{&lt;br /&gt; if (obj != null)&lt;br /&gt; {&lt;br /&gt;   obj.Dispose();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;But when obj is not an IDisposable object, that using statement can not be compiled. For example, ITestInterface has one method DoSomething(). TestClass is an implementation class for ITestInterface and IDisposable, the code below can not be compiled:&lt;pre&gt;&lt;br /&gt;public class Program&lt;br /&gt;{&lt;br /&gt;  static void Main(string [] args)&lt;br /&gt;  {&lt;br /&gt;      ITestInterface obj = new TestClass();&lt;br /&gt;      using (obj)&lt;br /&gt;      {&lt;br /&gt;          obj.DoSomething();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;To make it work, we should add "as IDisposable":&lt;pre&gt;&lt;br /&gt;using (obj as IDisposable)&lt;br /&gt;{&lt;br /&gt; obj.DoSomething();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The logic is same as:&lt;pre&gt;&lt;br /&gt;using (IDisposable obj2 = (obj as IDisposable))&lt;br /&gt;{&lt;br /&gt; obj.DoSomething();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/22643768-114038013798532110?l=junmeng.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://junmeng.blogspot.com/feeds/114038013798532110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=22643768&amp;postID=114038013798532110' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114038013798532110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/22643768/posts/default/114038013798532110'/><link rel='alternate' type='text/html' href='http://junmeng.blogspot.com/2006/02/using-statement-in-net-20.html' title='The &apos;using&apos; statement in .Net 2.0'/><author><name>Jun Meng</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://photos1.blogger.com/blogger/8190/2692/1600/BruceLee.jpg'/></author><thr:total>0</thr:total></entry></feed>
