tag:blogger.com,1999:blog-226437682024-03-05T10:11:55.881-05:00Jun Meng's blogTechnology about computer and ... our bodyUnknownnoreply@blogger.comBlogger80125tag:blogger.com,1999:blog-22643768.post-45678353219007864772013-11-09T22:42:00.002-05:002013-11-09T22:46:06.424-05:00Teach kids to love, not to kill!<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">Below explains why Jimmy Kimmel has a big evil in his heart.</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">----------------------------------------------------------</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">What a Journey</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">Chunyan Li, Ph.D.</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">11/8/2013</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">Dear all,</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">How long does it take us to get here today? One hour? Two hours? For me, it is 20 years! 20 years ago I arrived at this land of the free, full of ideals, perhaps from listening too much to radio Voice of America. 20 years later my sons join me to protest against ABC's spreading of racial hatred and violence. What is wrong with this picture?</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">I ask my teenage son whether we should just treat "killing Chinese" as a joke. He said this demonstrates what the society and media had been feeding our young kids. My heart sank. Is America moving forward or backward?</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">Now I ask again: How long does it take us to get here? I don't know about you, but the last 20 days seem longer than my 20 years. Those of us who stand here today must have been reading, writing, arguing, and agonizing over confusing pieces of reports and commentaries. And we ask ourselves, are we being unreasonable? Is our English that bad that we don't know what an apology is? </span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">On 10/28, the night of our first protest, Mr. Kimmel said, "today is a weird day...I am sorry if I offended anyone." I ask ABC, who is the weird one? Who truly apologizes if he doesn't even say sorry for what? Sorry to whom? To the Chinese whose sense of tranquility is forever disturbed? To our kids whom we try so hard to shield from pain and harm? To the schools that teach kids the spirit of Dr. Martin Luther King? ABC, do you call that an apology? </span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">In a letter to 80-20, ABC still claims it only entertains. Why is joking about killing Chinese so entertaining? Is it because we are always so nice? My friend's sweet 11-year old wants to write on his poster, "do not take advantage of us." I first didn't understand, then found out he meant "don't take advantage of us because we are nice." That broke my heart!!! ABC and Mr. Kimmel, we hold you accountable for taking away our children's precious sense of security. And we hold you accountable for sowing the seeds of hatred in other children's minds.</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">On 10/29, Mr. Kimmel even resorted to the ridiculous notion of cultural difference. I ask him, what cultural difference do you mean? A culture of hard work, respect, harmony versus a culture of violence and racial hatred? Then I admit there is an unbridgeable difference between Kimmel and us. We know what's right, what's wrong. And we know what humor is too! Yet we have no tolerance of your malicious joke, subsequent insult on air, then the absurd reference to culture. This only proves Mr. Kimmel you are unfit to be a public figure. </span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">ABC, stop blaming cultural differences for your own mistakes! Except for Native Americans, all are immigrants with unique traits. Yet we share the basic value of human dignity. Stop magnifying the differences in skin colors, or accents!</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">I ask a third time, how long does it take us to get here? Our friends started telling us there is another written apology somewhere. Who in real life is given so many third chances? Yet I ponder, are we asking too much? I discovered to my dismay that in that written letter, Mr. Kimmel is still hiding behind the 6-year old. Come on Mr. Kimmel, you think our anger is on a 6-year old? Our anger is on your malicious question "Should we allow the Chinese to live?" Our anger is on your subsequent arrogant ridicule. Our rage is on ABC for not letting the public know the truth of these so called apologies. </span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">America is the home of the brave. ABC, show our kids you have the courage of admitting wrong doing, show our kids you have the guts to take responsibility by dismissing Mr. Kimmel. Show us you have the resolve to institute procedures to prevent future incidences. ABC, do NOT hide behind a 6-year old! Show us what a major network can do to right its wrong!</span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">Twenty years, twenty days. Life, liberty and the pursuit of happiness. Who doesn't want to be happy? But without life, what is liberty? Without liberty, what is happiness? Let's join hands in our pursuit of human dignity. </span></span><br />
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="font-family: Geneva, Arial, Helvetica, sans-serif;"><span style="font-size: 14px; line-height: 22px;">Teach kids to love, not to kill!</span></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-6127528679512675482013-07-10T14:46:00.002-04:002013-07-10T14:49:23.072-04:00jQuery UI Dialog and ASP.NET PostBackI am replacing <a href="http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/ModalPopup/ModalPopup.aspx">MS ModalPopup</a> with <a href="http://jqueryui.com/dialog/">jQuery UI Dialog</a> in my ASP.NET projects recently. It seemed easy in the beginning, but it turned out I had to search solutions on Internet.<br />
<br />
Let me use a sample to explain what should be done to make jQuery Dialog work in ASP.NET page. The web page has input fields (Name and Address) and buttons (Save and Clone):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJoI0IDet3jPiYa9jGF758OmhklRbRMOVkEU-Dk6I1YBILmQSiRn3Lb-xIf-4tKwkfpLsFuQtxiSzpbVKbFp4RoszFOvC81YINmnn3lM9Ln6jtf7UdX310zSeGn_txygJeoovtag/s1600/defaultPage.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJoI0IDet3jPiYa9jGF758OmhklRbRMOVkEU-Dk6I1YBILmQSiRn3Lb-xIf-4tKwkfpLsFuQtxiSzpbVKbFp4RoszFOvC81YINmnn3lM9Ln6jtf7UdX310zSeGn_txygJeoovtag/s1600/defaultPage.PNG" /></a></div>
<br />
All the fields and buttons are inside an UpdatePanel. When Clone button is clicked, a Dialog will be displayed:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi7sOsCb2jLru0mMffCWR5RiZ-frLT0eFFYW3fpanQ8IQW-4wtokKBet78IMk_BgYXm4MTJFm7yIhMyJS11FWJtjMjFeFqHv_VQpxXDZQyKmlSZlp0JV8-Nin8DcFY4fPyDmUCKg/s1600/popup1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi7sOsCb2jLru0mMffCWR5RiZ-frLT0eFFYW3fpanQ8IQW-4wtokKBet78IMk_BgYXm4MTJFm7yIhMyJS11FWJtjMjFeFqHv_VQpxXDZQyKmlSZlp0JV8-Nin8DcFY4fPyDmUCKg/s1600/popup1.PNG" /></a></div>
<br />
The Submit button is supposed to postback user's selection.<br />
<br />
The JavaScript is like below:<br />
<br />
<pre> $(function () {
CreateCloneDialog();
});
function CreateCloneDialog() {
// Clone dialog
$('#pnlSectionsToClone').dialog(</pre>
<pre> { autoOpen: false,
modal: true,
width: 'auto',
height: 'auto',
resizable: false
});
}
function DisplayCloneDialog() {
// Open the dialog
$('#pnlSectionsToClone').dialog('open');
}
</pre>
<br />
The pnlSectionsToClone is the content panel of the Dialog. When Clone button is clicked, function DisplayCloneDialog() will be called. Everything seems simple so far. But the page had these problems:<br />
<br />
1. When the page is loaded and Clone button is clicked, the Dialog is displayed with no problem. But once the Save button is clicked, the Clone button will throw this exception (in Firefox) and no Dialog is displayed:<br />
<br />
<i><span class="objectBox objectBox-errorMessage hasBreakSwitch " role="presentation"><span class="errorMessage ">Error: cannot call methods on dialog prior to initialization; attempted to call method 'open'</span></span></i><br />
<br />
The reason of the exception is: after Save button is clicked, the UpdatePanel receives HTTP response and updates DOM in browser. The Dialog object in CreateCloneDialog() is removed from DOM at this time. The following 'open' will fail.<br />
<br />
The solution for this issue is to call CreateCloneDialog() after each postback:<br />
<br />
<pre> $(function () {
CreateCloneDialog();
Sys.WebForms.PageRequestManager.getInstance()</pre>
<pre> .add_endRequest(CreateCloneDialog);
});
</pre>
<br />
2. When the Dialog is displayed, the Submit button does NOT postback.<br />
<br />
The reason for this issue is: the dialog object is added to the Document in DOM, not inside Form tag. You can see that clearly in Firebug:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhda1WTzDIA0KW1u3vf6EWNM2n_8rrqYfP5OSCb5X3Qx8SwhQG9DsXovE_-RUmaO9rMnsFXVaGt1pMbtVvi6o6F7YGESVmAJhjmEL1DQ26dYPaI2J_3RfEDovha9Lc_GqbkTpB_6w/s1600/firebugDialog.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhda1WTzDIA0KW1u3vf6EWNM2n_8rrqYfP5OSCb5X3Qx8SwhQG9DsXovE_-RUmaO9rMnsFXVaGt1pMbtVvi6o6F7YGESVmAJhjmEL1DQ26dYPaI2J_3RfEDovha9Lc_GqbkTpB_6w/s1600/firebugDialog.PNG" /></a></div>
<br />
To move the dialog object into Form tag for postback, you need add one extra line of code to function CreateCloneDialog():<br />
<br />
<pre> function CreateCloneDialog() {
// Clone dialog
$('#pnlSectionsToClone').dialog(
{ autoOpen: false,
modal: true,
width: 'auto',
height: 'auto',
resizable: false
});
// Need add this line below, otherwise the buttons </pre>
<pre> // inside dialog will not postback
$("#pnlSectionsToClone").parent().appendTo(jQuery("form:first"));
}
</pre>
<br />
3. In Firefox or IE8+, the dialog layout looks OK; but in IE7 (yes, many people are still using IE7), the dialog title looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZoA5bxnc8Rs9iPEjCwz4-pGHcgtmj4pJA0M1y6g5Ee7X7j0U593zlUrhrpVPc8mB0bM-ySp3T_N4y53VwXj13fRPSo2cGzkn02gTgx0i5zZJRM5ZcOXz_vHWWAV3Am9OdX5hNYQ/s1600/popup2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZoA5bxnc8Rs9iPEjCwz4-pGHcgtmj4pJA0M1y6g5Ee7X7j0U593zlUrhrpVPc8mB0bM-ySp3T_N4y53VwXj13fRPSo2cGzkn02gTgx0i5zZJRM5ZcOXz_vHWWAV3Am9OdX5hNYQ/s1600/popup2.PNG" /></a></div>
<br />
<br />
This is because IE7 does not understand CSS style width:'auto'. To fix this issue, we need to manually assign width for the title when the dialog is created:<br />
<br />
<pre> function CreateCloneDialog() {
// Clone dialog
$('#pnlSectionsToClone').dialog({ autoOpen: false,
modal: true,
width: 'auto',
height: 'auto',
resizable: false,
open: function (event, ui) {
// fix for width:auto in IE7. If width is specified, </pre>
<pre> // the logic below is not needed.
var contentWidth = $(this).width();
$(this).parent().find('.ui-dialog-titlebar')</pre>
<pre> .each(function () {
$(this).width(contentWidth);
})
},
beforeClose: function (event, ui) {
//fix for width:auto in IE7
$(this).parent().css("width", "auto");
}
});
</pre>
<br />
Now the dialog looks OK in IE7:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBUAq_S71TtPtbA7ySgbzq0wSLsnUE19TGVv9JGz3mZimlZ7SGk0T8JfI_wZ5nAwKq_r0cQz_noKr-konljuzNM0KzHNYqNZtSu1E3CY27K1w1AIIJ7qH9JPWvpyGrCe9Kgf0Y6Q/s1600/popup3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBUAq_S71TtPtbA7ySgbzq0wSLsnUE19TGVv9JGz3mZimlZ7SGk0T8JfI_wZ5nAwKq_r0cQz_noKr-konljuzNM0KzHNYqNZtSu1E3CY27K1w1AIIJ7qH9JPWvpyGrCe9Kgf0Y6Q/s1600/popup3.PNG" /></a></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-39729859839444305222013-03-27T21:05:00.000-04:002013-03-27T22:44:48.544-04:00SQL Except statement with Order ByThe Except statement is easy to understand. For example, the result of "result set A Except result set B" is like below in grey: <br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8UKkQfi00VvY3OZ6nIRO-Mc_vIGp2_wb9-k8_b5A1ds79Ra8S1z_PzklPtKa5LeHchpno8M04aqeGCLHsUWrx6IW_vmh3RaDcoxtibsOZ-4S-Eakh9YVu0QFz77fjO25D016Ziw/s1600/Except.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="123" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8UKkQfi00VvY3OZ6nIRO-Mc_vIGp2_wb9-k8_b5A1ds79Ra8S1z_PzklPtKa5LeHchpno8M04aqeGCLHsUWrx6IW_vmh3RaDcoxtibsOZ-4S-Eakh9YVu0QFz77fjO25D016Ziw/s200/Except.png" width="200" /></a></div>
But thing will easily go wrong in SQL statement when you use Except and Order By.<br />
<br />
Take AdventureWorks database as an example here:<br />
<br />
1. Run the 1st statement and notice BusinessEntityID=66 is in the result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg454Wl87DpPSTaqp70IylOy1Cqh6xvmQ7THG79z0gqju5FwutxbLa349AaIPwsvmMmsh3prMVkUnRMnlUS9QCQsBi8dISE4eDJCX0IW6ATKGl-QztTRibqiRilgiC9VghJ8jlwHw/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg454Wl87DpPSTaqp70IylOy1Cqh6xvmQ7THG79z0gqju5FwutxbLa349AaIPwsvmMmsh3prMVkUnRMnlUS9QCQsBi8dISE4eDJCX0IW6ATKGl-QztTRibqiRilgiC9VghJ8jlwHw/s400/1.png" width="400" /></a></div>
2. Run the 2nd statement and notice BusinessEntityID=66 is also in the result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrNv-qDz0S7_NaaWmO0h0-bhO6Ud4Lo_aIQQ0-wLuCWe1J0dKG3K2qIi3PAyO2IcaD-InH9AwpCFt35ozkq8roo_70hzPvILO-RCU3r1lCgawHUuMNpW2Jx86rkaTFz1WYtOkKBQ/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrNv-qDz0S7_NaaWmO0h0-bhO6Ud4Lo_aIQQ0-wLuCWe1J0dKG3K2qIi3PAyO2IcaD-InH9AwpCFt35ozkq8roo_70hzPvILO-RCU3r1lCgawHUuMNpW2Jx86rkaTFz1WYtOkKBQ/s400/2.png" width="400" /></a></div>
<br />
3. How about combining those two SQL statements together with Except? From the concept, the record BusinessEntityID=66 should not be in the result, right? Let's take a look: <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimYkXS-EdhIiiTxf1G4Ii_UPF5NXEuD-b3gUQ0rcuteJkYtziIveI-T80rFMk6Z3Vy_RP6nUIfAZ0CDfEsHkwMK9A1vQxr5DmmxP-4BJUpZKNt0cduMcjtY5BG_Yzx7bqmFtaPDw/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="245" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimYkXS-EdhIiiTxf1G4Ii_UPF5NXEuD-b3gUQ0rcuteJkYtziIveI-T80rFMk6Z3Vy_RP6nUIfAZ0CDfEsHkwMK9A1vQxr5DmmxP-4BJUpZKNt0cduMcjtY5BG_Yzx7bqmFtaPDw/s400/3.png" width="400" /></a></div>
It is still there! Why?!<br />
<br />
The reason is: Order By actually belongs to the first Select statement, not the 2nd. <br />
<br />
This is the result set for the 2nd statement without Order By:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLdiHGsBOwK_K5uSmN5LK9cUrmjs40K5IiH1yIx0gJhjpXoyN0-BmMDie2WKUYW5oU_jWCkpKXprZFaR-GF3q2BEbqmoC4y7RqXXZzHFt4W7-ooXqLcgp9SQ7c1QB5Cag8KiClBA/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLdiHGsBOwK_K5uSmN5LK9cUrmjs40K5IiH1yIx0gJhjpXoyN0-BmMDie2WKUYW5oU_jWCkpKXprZFaR-GF3q2BEbqmoC4y7RqXXZzHFt4W7-ooXqLcgp9SQ7c1QB5Cag8KiClBA/s400/4.png" width="400" /></a></div>
<br />
The record BusinessEntityID=66 is NOT in the result. So the result of Except statement is actually correct.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-50985786627939439942010-02-04T12:22:00.003-05:002010-02-04T12:34:45.881-05:00Migrating ASP.NET applications to another Windows DomainYou 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.<br />
<br />
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 <a href="http://msdn.microsoft.com/en-us/library/ms178468%28VS.85%29.aspx">HttpModule</a> (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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN56skUqG0yD3RpyzhGy5chAWzqXUI7Pj9C24hfHabGHqIlhXUzoE8MBEJK68PUTLtlTzDePWAP5d2AukMhg5lCh3vTyLA74O3RDhS7SKvJuy5sK1JahcFhqqtEw-yGPUYv2tp2w/s1600-h/DomainMappingHttpModule.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN56skUqG0yD3RpyzhGy5chAWzqXUI7Pj9C24hfHabGHqIlhXUzoE8MBEJK68PUTLtlTzDePWAP5d2AukMhg5lCh3vTyLA74O3RDhS7SKvJuy5sK1JahcFhqqtEw-yGPUYv2tp2w/s320/DomainMappingHttpModule.PNG" /></a></div><br />
The main code logic for domain mapping HttpModule is as below:<br />
<br />
<div style="overflow: auto; width: auto;"><pre>// Get user's domain account
string strDomainUserAccount = HttpContext.Current.User.Identity.Name.ToUpper();
// Remove domain name from the account
string strUserAccount = strDomainUserAccount;
if (strDomainUserAccount.StartsWith("NewDomain\\")) {
strUserAccount = strUserAccount.Substring(10);
}
// Fetch cached user mappings
Dictionary<string, string> userMap = (Dictionary<string, string>)HttpRuntime.Cache(USER_CACHE_KEY);
if (userMap == null) {
// If no cache is available, reload the cache from database
// and try to get the item again
this.ReloadUserMap();
userMap = (Dictionary<string, string>)HttpRuntime.Cache(USER_CACHE_KEY);
if (userMap == null) {
// Throw exception here!!
return;
}
}
// Get user's NTUserName from the mapping in cache
// and create a new user for Http context
if (userMap.ContainsKey(strUserAccount)) {
string strNewAccount = userMap[strUserAccount];
if (!string.IsNullOrEmpty(strNewAccount)) {
// New Identity
string strAuthenticateType = HttpContext.Current.User.Identity.AuthenticationType;
System.Security.Principal.GenericIdentity newID =
new System.Security.Principal.GenericIdentity(strNewAccount, strAuthenticateType);
// Get cached roles in mapped domain.
// If no cache is available, get from AD and put into cache
string[] strRoles = this.GetDomainGroupsForUserFromCache[strNewAccount];
System.Security.Principal.GenericPrincipal newP =
new System.Security.Principal.GenericPrincipal(newID, strRoles);
HttpContext.Current.User = newP;
}
}
</pre></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-58213896993627948292010-02-03T14:55:00.006-05:002010-02-03T15:23:39.071-05:00FlowLayoutPanel for .NET Compact FrameworkIt 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. <br />
<br />
I found <a href="http://www.codeproject.com/KB/miscctrl/CSharpFlowLayoutPanel.aspx">an old article on CodeProject</a> about FlowLayoutPanel, but that code cannot work on CF because CF Panel does not have OnLayout event. Also the code logic has bugs too.<br />
<br />
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:<br />
<br />
<div style="overflow: auto; width: auto;"><pre>Protected Overloads Overrides Sub OnPaint(ByVal pEvent As PaintEventArgs)
Dim nextTop As Integer = 0, nextLeft As Integer = 0
Dim maxHeight As Integer = 0
Dim ParentWidth As Integer
If Me.Parent IsNot Nothing Then
ParentWidth = Me.Parent.Width
Else
ParentWidth = Me.Width
End If
' Modify control location for the layout
For Each myControl As Control In Me.Controls
' Ignore invisible controls
If myControl.Visible = False Then
Continue For
End If
If (nextLeft + myControl.Width) > ParentWidth Then
nextTop += maxHeight
nextLeft = 0
' Reset maxHeight
maxHeight = 0
End If
myControl.Top = nextTop
myControl.Left = nextLeft
If myControl.Height > maxHeight Then
maxHeight = myControl.Height
End If
nextLeft += myControl.Width
Next
Me.AutoScrollPosition = New System.Drawing.Point(0, 0)
MyBase.OnPaint(pEvent)
End Sub</pre></div><br />
Below is a sample using the logic above:<br />
<br />
<div style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMQ5YXmkIiqhhHhjg3eKui-86k-g5XzHHeyzQ5ZCk7UjPQstF0v1ZbH7il5sqEfVFg7pS6T_M79d8GnQrazbOTAXxF914fQvhksep8daJzPEP_QjPadFSSuLI9EFr6G475EZKmew/s1600-h/ShowPanel3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMQ5YXmkIiqhhHhjg3eKui-86k-g5XzHHeyzQ5ZCk7UjPQstF0v1ZbH7il5sqEfVFg7pS6T_M79d8GnQrazbOTAXxF914fQvhksep8daJzPEP_QjPadFSSuLI9EFr6G475EZKmew/s320/ShowPanel3.PNG" /></a></div><br />
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:<br />
<br />
<div style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQxKCekTsgSVWIWx7ALCG5StEtzjPMtyfOcASFl01dwEmgWP6qTZRTByjm4uy3B0ctMfFwdvSplCdUVpsmHbtHGmQokT9sGOJs21kD8Pgh8hcRb4Ap9WvmyO7khwSDNx6RxKJD9A/s1600-h/HidePanel3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQxKCekTsgSVWIWx7ALCG5StEtzjPMtyfOcASFl01dwEmgWP6qTZRTByjm4uy3B0ctMfFwdvSplCdUVpsmHbtHGmQokT9sGOJs21kD8Pgh8hcRb4Ap9WvmyO7khwSDNx6RxKJD9A/s320/HidePanel3.PNG" /></a></div><br />
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.<br />
<br />
The code for the button is like below:<br />
<br />
<div style="overflow: auto; width: auto;"><pre>Private Sub btnHide_Click(ByVal sender As Object, ByVal e As EventArgs)
If btnHide.Text = "Hide Panel 3" Then
Panel3.Visible = False
btnHide.Text = "Show Panel 3"
Else
Panel3.Visible = True
btnHide.Text = "Hide Panel 3"
End If
' Refresh the flow layout panel
Me.FlowLayoutPanel1.Invalidate()
End Sub
</pre></div><br />
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:<br />
<br />
'FlowLayoutPanel1<br />
'<br />
Me.FlowLayoutPanel1.Controls.Add(Me.Panel1)<br />
Me.FlowLayoutPanel1.Controls.Add(Me.Panel2)<br />
Me.FlowLayoutPanel1.Controls.Add(Me.Panel3)<br />
Me.FlowLayoutPanel1.Controls.Add(Me.Panel5)<br />
Me.FlowLayoutPanel1.Controls.Add(Me.Panel6)<br />
Me.FlowLayoutPanel1.Controls.Add(Me.Panel4)Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-22643768.post-15393495636070126362008-05-23T13:13:00.003-04:002008-05-23T13:29:58.631-04:00Set up Reporting Services in SharePoint Integration ModeI followed <a href="http://msdn.microsoft.com/en-us/library/bb677365.aspx">How to: Configure SharePoint Integration on Multiple Servers</a> step-by-step to configure SharePoint Integration on two servers. But on the step "Set server defaults" of "<a href="http://msdn.microsoft.com/en-us/library/bb326213.aspx">Configure the Report Server Integration Feature in SharePoint Central Administration</a>", I only saw this error:<br /><br /><em>An unexpected error occurred while connecting to the report server. Verify that the report server is available and configured for SharePoint integrated mode.</em><br /><br />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 <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1282744&SiteID=1">MSDN Forum</a>. As my environment did not allow me to use Kerberos, I tried to set up NTLM on both SharePoint server and Report server:<br /><br /><strong>cscript adsutil.vbs set w3svc/NTAuthenticationProviders "NTLM"</strong><br /><br />Then I was so happy to see the error disappeared! :)Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-22643768.post-76922669259066114442008-05-09T11:37:00.004-04:002008-11-15T03:18:07.174-05:00SSAS Permission for Least-Privilege User AccountWhen 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.<br /><br />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.<br /><br />When I tried to deploy an SSAS project, Visual Studio threw the error:<br /><br /><span style="font-style:italic;">Error -1055391738 : Either the '[domain]\[account]' user does not have permission to create a new object in '[machine]', or the object does not exist.</span><br /><br />So I went to SQL Server Management Studio and connected to SSAS, but I had no permission to create SSAS database manually:<br /><br /><span style="font-style:italic;">Either the '[domain]\[account]' user does not have permission to create a new object in '[machine]', or the object does not exist. (Microsoft.AnalysisServices)<br /></span><br /><br />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:<br /><ol><li>Run SQL Server Management Studio as Administrator account</li><li>Connect to the SSAS server</li><li>Right-click the SSAS server name and select Properties from the popup menu</li><li>Select Security to add account to server role</li></ol><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiZN7YyF4zt9EzUaV_7-WvtbOomZ59QHcmJVld-IFC6L2chdJunPl614_K53crdGCnAiqx0y4kesS5XXdRpG1Ke72VoS5V6pyo3CbnBYNshkzZ9QklCb6q1DciDhcUdhRUGkOvKw/s1600-h/SSAS_Security.PNG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiZN7YyF4zt9EzUaV_7-WvtbOomZ59QHcmJVld-IFC6L2chdJunPl614_K53crdGCnAiqx0y4kesS5XXdRpG1Ke72VoS5V6pyo3CbnBYNshkzZ9QklCb6q1DciDhcUdhRUGkOvKw/s400/SSAS_Security.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198407840086258626" /></a><br />Now, I can deploy SSAS project in Visual Studio without problem.Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-22643768.post-37194968335567841812008-05-08T15:50:00.005-04:002008-05-08T16:26:32.882-04:00SharePoint can not find user in its domainIt's quite weird that SharePoint (WSS 3.0) could not find any Active Directory user account from its own domain!<br /><br />According to its log, WSS complained it could not get trusted domains:<br /> <br /><div style="overflow: auto; width: auto;"><pre>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) <br />05/08/2008 10:09:18.72 Found 1 trusted forests ad.int.com. <br />05/08/2008 10:09:18.72 Found 0 trusted domains <br />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& rgResults) at Microsoft.SharePoint.Utilities.SPUserUtility.SearchAgainstAD(String input, SPActiveDirect... <br />05/08/2008 10:09:18.87* ...oryDomain domainController, SPPrincipalType scopes, SPUserCollection usersContainer, Int32 maxCount, String customQuery, String customFilter, TimeSpan searchTimeout, Boolean& reachMaxCount) at Microsoft.SharePoint.Utilities.SPActiveDirectoryPrincipalResolver.SearchPrincipals(String input, SPPrincipalType scopes, SPPrincipalSource sources, SPUserCollection usersContainer, Int32 maxCount, Boolean& reachMaxCount) at Microsoft.SharePoint.Utilities.SPUtility.SearchPrincipalFromResolvers(List`1 resolvers, String input, SPPrincipalType scopes, SPPrincipalSource sources, SPUserCollection usersContainer, Int32 maxCount, Boolean& reachMaxCount, Dictionary`2 usersDict). </pre></div><br /><br />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. <a href="http://technet.microsoft.com/en-us/library/cc263460.aspx">MSDN</a> 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.<br /><br />Finally, I had a try to add the WSS server's local domain using stsadm:<br /><br />stsadm -o setproperty -url http://localhost:82<br />-pn "peoplepicker-searchadforests" -pv "domain:ad.int.com"<br /><br />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! :)Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-22643768.post-82444940981981738472008-04-02T11:24:00.006-04:002008-05-08T16:24:00.101-04:00SharePoint XML Web Part and proxy settingXML 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 <a href="http://www.weather.com/services/xmloap.html">Weather.com XML Data Feed</a>. I followed these steps:<br /><ol><li>Registered to <a href="http://www.weather.com/services/xmloap.html">weather.com</a> to download the SDK (to use weather images)</li><li>Copied SDK images to TEMPLATE\Images\weather\</li><li>Added XML Web Part to WSS site and set URL to <pre>http://xoap.weather.com/weather/local/(zipcode)?cc=*&prod=xoap<br />&unit=e&par=null&key=(license key)</pre>[Update] Weather.com has changed the URL to <pre>http://xoap.weather.com/weather/local/[zipcode]?cc=*&dayf=5<br />&link=xoap&prod=xoap&par=[PartnerID]&key=[LicenseKey]</pre></li><li>Set up XSLT to display weather images</li></ol>But I got errors on different WSS machines:<br /><ol><li>"Cannot retrieve the URL specified in the XML Link property"</li><li>"The web part has timed out"</li></ol>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.<br /><br />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.<br /><br />After I added proxy settings in web.config, the problem was solved:<br /><pre><br /><!-- Proxy setting --><br /><system.net><br /> <defaultproxy useDefaultCredentials="true"><br /> <proxy usesystemdefault="false"<br /> proxyaddress="http://proxyServer:port"<br /> bypassonlocal="true"><br /> </proxy><br /> </defaultproxy><br /></system.net></pre>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-22643768.post-73644360653914718372008-02-15T09:57:00.003-05:002008-11-15T03:18:07.485-05:00ZoomItThis post is mainly for my own recall.<br /><br /><a href="http://rshelton.com/archive/2008/02/14/free-download-free-zoom-utility-for-windows.aspx">Robert Shelton</a> provides a link for the excellent <a href="http://technet.microsoft.com/en-us/sysinternals/bb897434.aspx"> screen zoom and annotation tool</a> for Windows. It is quite useful for presentation of course, but also useful to zoom in/out high resolution screen during normal work.<br /><br />I tried on my computer just now:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaiYxL-oHKWS45VJFk4HGV07J9taxyiClFY5o9MXBaIU5D5esoK7N2d2aqrHSxcWm5ICU3FDmPIThn-akr-r01flKCjlqCwTL32g4tAQkqiSHOvGruoYppDFgfmLR7XYosG9gLOA/s1600-h/ZoomIt.GIF"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaiYxL-oHKWS45VJFk4HGV07J9taxyiClFY5o9MXBaIU5D5esoK7N2d2aqrHSxcWm5ICU3FDmPIThn-akr-r01flKCjlqCwTL32g4tAQkqiSHOvGruoYppDFgfmLR7XYosG9gLOA/s400/ZoomIt.GIF" border="0" alt=""id="BLOGGER_PHOTO_ID_5167223562591497602" /></a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-29220741857797248202008-01-31T13:42:00.000-05:002008-01-31T14:00:54.558-05:00Reports cannot be deployed from VS 2005 to Reporting Services in WSS integration modeI 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. <br /><br />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 "<a href="http://msdn2.microsoft.com/en-us/library/bb326288.aspx">Deploying Reports, Models, and Shared Data Sources to a SharePoint Site</a>". 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.<br /><br />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."<br /><br />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.<br /><br />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.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-22643768.post-77569276847882070502008-01-15T14:36:00.000-05:002008-01-15T14:44:43.222-05:00Do not remove VS 2005 and install VS 2008 if ...Do not remove VS 2005 from your computer and install VS 2008 if:<br /><br />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!<br /><br />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.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-22643768.post-91052129051395635932007-12-31T15:23:00.000-05:002008-11-15T03:18:08.045-05:00WSS Workflow Modification FormIt 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?<br /><br />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.<br /><br />You can define Modification form in Feature file with the similar way for Instantiation form. But how about the workflow part?<br /><br />Instantiation form happens at the very beginning of a workflow, but Modification can happen anywhere in a scope. <br /><br />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.<br /><br />In Visual Studio, right-click the EventHandlingScope activity and select "view event handlers":<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxtvRKprulm7ZGdpgP82bR2Py92hVg8N2wWuyQ7CEjzoP8PRsTTSkswL2KYMqaUJoJTkjlnXyvFuuiSsvsRELCLYYINcs0w40HHbveFOZ-1fHt0JXX6VM1UI7To8mef2gimm1XSQ/s1600-h/EventHandlingScope_1.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxtvRKprulm7ZGdpgP82bR2Py92hVg8N2wWuyQ7CEjzoP8PRsTTSkswL2KYMqaUJoJTkjlnXyvFuuiSsvsRELCLYYINcs0w40HHbveFOZ-1fHt0JXX6VM1UI7To8mef2gimm1XSQ/s320/EventHandlingScope_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5150238492564648514" /></a><br /><br />Then you can add OnWorkflowModified and UpdateTask activities to the EventHandlersActivity:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWwR3kLWCTsdOGh08KByT73n9pnGsc5T2Mu5BgsUdyeE2vfaXEcQJkY0HYrtPr6KL1HxCOqmIZqy4Hqk40HeBNDvO6C-951MMnaUbhyphenhyphenF0qxfp3kDeG5M7e0lgiiadGqaCfd-Dn6Q/s1600-h/EventHandlingScope_2.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWwR3kLWCTsdOGh08KByT73n9pnGsc5T2Mu5BgsUdyeE2vfaXEcQJkY0HYrtPr6KL1HxCOqmIZqy4Hqk40HeBNDvO6C-951MMnaUbhyphenhyphenF0qxfp3kDeG5M7e0lgiiadGqaCfd-Dn6Q/s320/EventHandlingScope_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5150239068090266194" /></a><br /><br />The Modification activities have their own ContextData and CorrelationToken, because they are actually outside the normal workflow.<br /><br />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.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ4yBFWMoV2R9ivPgI8anATjvybCesaftqeutKjQht0rzWXtCJkihp8cQXKJ-SHa48yw5bP2lZMPH2M4Z0h3Ulfw8f9vcCAOvYIdJaPMPVF9TRx4zvJj9gK071pev5NER0srYD4Q/s1600-h/EventHandlingScope_3.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ4yBFWMoV2R9ivPgI8anATjvybCesaftqeutKjQht0rzWXtCJkihp8cQXKJ-SHa48yw5bP2lZMPH2M4Z0h3Ulfw8f9vcCAOvYIdJaPMPVF9TRx4zvJj9gK071pev5NER0srYD4Q/s320/EventHandlingScope_3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5150239897018954338" /></a>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-22643768.post-84249764387537667522007-12-27T16:22:00.000-05:002007-12-28T11:23:34.353-05:00WSS Content Type Was Not UpdatedI 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 :(<br /><br />Here was what happened in the beginning: I created a simple content type like below:<br /><br /><span style="font-size:85%;"><ContentType ID="0x01080100B7336179CFFE43e59B86E241C767010E" Name="GradingTask" Group="Grading" Description="Grading Task" Version="0" Hidden="FALSE"><br /> </ContentType></span><br /><br />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:<br /><br /><span style="font-size:85%;"> <XmlDocuments><br /> <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url"><br /> <FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url"><br /> </span><span style="color: rgb(255, 0, 0);font-size:85%;" ><Edit>_layouts/Grades/GradesTaskEditForm.aspx</Edit></span><span style="font-size:85%;"><br /> </span><span style="color: rgb(255, 0, 0);font-size:85%;" ><Display>_layouts/Grades/GradesTaskEditForm.aspx</Display></span><span style="font-size:85%;"><br /> </FormUrls><br /> </XmlDocument><br /> </XmlDocuments></span><br /><br />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.<br /><br />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)<br /><br />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. <br /><br />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 :)<br /><br />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.<br /><br />[Updated 12/28/2007] I saw <a href="http://soerennielsen.wordpress.com/2007/09/11/propagate-site-content-types-to-list-content-types/">this great article</a> this morning to deal with the mess of Content Type inheritance.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-22643768.post-86820884938183866462007-12-17T17:00:00.000-05:002007-12-17T17:08:34.551-05:00Can I use SharePoint Workflow on SPGridView?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. <br /><br />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)? <br /><br />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.<br /><br />Ok ... fine. How about creating a SharePoint List to hold my business objects but I need save my business objects in a separate database?<br /><br />Well ... To use SharePoint List, you have to create list columns inside SharePoint Content database, not in other databases. <br /><br />&*%*^%%^$<br /><br />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. <br /><br />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.<br /><br />Is there a better way to avoid data duplication in WSS Content database and the other standalone database?Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-22643768.post-35789187414331973552007-12-17T15:56:00.000-05:002007-12-17T16:09:58.736-05:00Convert Access database to SQL Server 2005In 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.<br /><br />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.<br /><br />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.<br /><br />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 <a href="http://www.microsoft.com/downloads/details.aspx?familyid=D842F8B4-C914-4AC7-B2F3-D25FFF4E24FB&displaylang=en">SQL Server Migration Assistant for Access</a> from Microsoft. Now my life is easier :)Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-89191809863174858752007-08-07T14:02:00.000-04:002007-08-07T14:46:27.394-04:00Why "using" is bad for your WCF service hostI scratched my head this morning for a WCF service host program. It threw a very generic exception like this:<br /><br /><em>“The communication object, System.ServiceModel.ServiceHost, cannot be used for communication because it is in the Faulted state.”</em><br /><br />The exception above had no any useful information about where the real problem was. The logic of my program was simple:<br /><pre><br />using(ServiceHost host = new ServiceHost(<br /> typeof(MyService), new Uri("http://localhost:8080/MyService"))<br />{<br /> host.Open();<br /> ... ...<br />}</pre><br />When I looked inside Output of VS 2005, I saw this log information:<br /><br />'System.ServiceModel.AddressAlreadyInUseException'<br /><br />But why WCF did not give me that exception directly? Finally, this blog explains the reason: <a href="http://blogs.msdn.com/salvapatuel/archive/2007/04/25/why-using-is-bad-for-your-wcf-service-host.aspx">Why "using" is bad for your WCF service host</a>.<br />------------------------------------------<br /><em><pre>ServiceHost Host = null;<br /><br />try<br />{<br /> Host = new ServiceHost(MySingletonService);<br /> Host.Open();<br /> Console.ReadKey();<br /> Host.Close();<br />}<br />finally<br />{<br /> if (Host != null)<br /> ((IDisposable)Host).Dispose();<br />}</pre><br />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.<br /><br />The lesson learn is “do not use ‘using’ to host your WCF service”.</em><br />------------------------------------------Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-52752254185177864882007-07-24T16:01:00.001-04:002010-02-04T12:42:10.066-05:00Traditional Chinese medicine to cure "incurable" diseasesI 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!<br />
<br />
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. <br />
<br />
One doctor is <a href="http://www.hantang.com/">Mr. Ni Haisha</a> (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 <a href="http://www.hantang.com/english/en_Articles/researchstudy.htm">English site</a>. <br />
<br />
Chinese medicine takes our body as a whole system. For example, the root reason for the <a href="http://www.hantang.com/english/en_Articles/breastpro-5.htm">breast cancer</a> 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.<br />
<br />
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 ...<br />
<br />
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. <br />
<br />
Currently, I know two Chinese doctors are good: <a href="http://www.hantang.com/english/en_index.html">Mr. Ni</a> and <a href="http://www.yuanji.org/contact_us.htm">Mr. Huo</a>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-22643768.post-64840269428107472262007-07-24T15:44:00.000-04:002007-07-24T15:59:32.013-04:00# in URLIt 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?<br /><br />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.<br /><br />So if web service client wants to send parameter ("#1", "#2", or "#3") to web service, sorry, the service side cannot see that parameter.<br /><br />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.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-71735199897506863172007-06-15T13:56:00.000-04:002007-06-15T14:22:49.528-04:00Crystal Report generates PDF in different fonts on different serversWe were satisfied with Crystal Report (CR) to generate PDF on the fly until we put CR templates on production servers. <br /><br />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! @^@<br /><br />I searched for reasons on Internet for hours, until I found one possible answer <a href="http://diamond.businessobjects.com/node/2905">here</a>: <span style="font-style:italic;">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. </span><br /><br />My program was a .NET web service to create PDF document using ExportToDisk not PrintToPrinter:<br /><pre>oDocument.ExportToDisk(<br /> ExportFormatType.PortableDocFormat, sOutputFile);</pre><br />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.<br /><br />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. :)<br /><br />Although we had to postpone production delivery, it's good to know some software use printer driver to arrange layout internally.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-7269235902898515312007-06-04T12:31:00.000-04:002008-11-15T03:18:08.448-05:00Zero to Biztalk WeekendIn 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. <br /><br />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.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-Q7FULjKj3p0oE0_yGkiGv-lQdZ0gpFzl5QY6ovbUFZRCg1ap7cwb8WZq5qbX9sM54OBPo3SQxT1U7gid_o1B2pmbaKmFms1XaKwFzLuSq1QB1eDm01qXsvzG0P8HEh7IPNi2MA/s1600-h/BTS_Messaging.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-Q7FULjKj3p0oE0_yGkiGv-lQdZ0gpFzl5QY6ovbUFZRCg1ap7cwb8WZq5qbX9sM54OBPo3SQxT1U7gid_o1B2pmbaKmFms1XaKwFzLuSq1QB1eDm01qXsvzG0P8HEh7IPNi2MA/s320/BTS_Messaging.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5072249133686080210" /></a><br /><br />Below are the agenda and my comments for the labs:<br /><hr /><br /><span style="font-weight:bold;">Saturday (06/02/2007)</span><br /><br /> 1. Architecture and Content-Based Routing: Deciding Where to Send a Message<br /> <br /> 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.<br /> <br /> 2. The BizTalk Mapper: Transforming Between Message Formats<br /> <br /> 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.<br /> <br /> But how to deal with non-XML input, such as flat file? Well, that is a topic in the second-day lab.<br /> <br /> 3. The SQL and FTP Adapters: Sending Messages to Databases and IIS<br /> <br /> FTP adapter has the same logic with normal FTP client software, which is easy to use.<br /> <br /> 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.<br /> <br /> 4. Creating a Simple Business Process. Publishing a Business Process as a Web Service. Using the SOAP Adapter<br /> <br /> 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.<br /> <br /> 5. Correlation: Which Instance of My Business Process Sees My Incoming Message?<br /> <br /> 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.<br /><br /><span style="font-weight:bold;">Sunday (06/03/2007)</span><br /><br /> 1. The Flat File Wizard and the Pipeline Designer: Dealing with Text Files.<br /> <br /> 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.<br /> <br /> 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.<br /> <br /> 2. Integrating with SharePoint and InfoPath<br /> <br /> 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.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTbCoduRADWYW3NZJmg_JfZfkpjeDPzy6MJwqP3npdFrO5VyoWpYoxeZNi2qPJ_zblDOqJSu754si0gw9B8bkkrVGS-3LiH0aYdh9VHrPfKWTllaOYzPPrGw7kPKMpkHehc_Qyqg/s1600-h/BTS_MOSS.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTbCoduRADWYW3NZJmg_JfZfkpjeDPzy6MJwqP3npdFrO5VyoWpYoxeZNi2qPJ_zblDOqJSu754si0gw9B8bkkrVGS-3LiH0aYdh9VHrPfKWTllaOYzPPrGw7kPKMpkHehc_Qyqg/s320/BTS_MOSS.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5072248949002486466" /></a><br /> <br /> 3. The Business Rules Engine: Separating the Business Logic from the Application<br /> <br /> 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). <br /> <br /> 4. Business Activity Monitoring: Tracking the Business Process (Demo)<br /> <br /> 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.<br /><hr /><br />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.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-78914115626642409272007-04-11T10:37:00.000-04:002008-11-15T03:18:08.664-05:00To remove “Is Identity” setting in SQL Server: Not simpleYesterday 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.<br /><br />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!<br /><br />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”:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUy7Rhy45fNwMaTwUax9GHfIWnsen3HUeAmmw78z1nao1dUCcmtmEGs05PfsG584RkNTWns6tmxKJtamGBZjLee0MjRkQP8xd4E753hZJsjCBtRP13nM9Gjz_2ziTFrv7HiFxnhg/s1600-h/GenerateSQLScript.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUy7Rhy45fNwMaTwUax9GHfIWnsen3HUeAmmw78z1nao1dUCcmtmEGs05PfsG584RkNTWns6tmxKJtamGBZjLee0MjRkQP8xd4E753hZJsjCBtRP13nM9Gjz_2ziTFrv7HiFxnhg/s320/GenerateSQLScript.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5052180562386703330" /></a><br />Yesterday, I used it to generate a complex script to remove “Identity” setting for a column:<br /><pre>-- To remove Identity setting of the Id column<br />BEGIN TRANSACTION<br />SET QUOTED_IDENTIFIER ON<br />SET ARITHABORT ON<br />SET NUMERIC_ROUNDABORT OFF<br />SET CONCAT_NULL_YIELDS_NULL ON<br />SET ANSI_NULLS ON<br />SET ANSI_PADDING ON<br />SET ANSI_WARNINGS ON<br />COMMIT<br />BEGIN TRANSACTION<br />GO<br />ALTER TABLE dbo.partner_attribute_name<br /> DROP CONSTRAINT DF_partner_attribute_name_last_update_date<br />GO<br />ALTER TABLE dbo.partner_attribute_name<br /> DROP CONSTRAINT DF_partner_attribute_name_creation_date<br />GO<br />-- Create a temp table<br />CREATE TABLE dbo.Tmp_partner_attribute_name<br /> (<br /> partner_attribute_name_id int NOT NULL,<br /> attribute_name varchar(50) NOT NULL,<br /> description varchar(200) NOT NULL,<br /> last_update_date datetime NOT NULL,<br /> creation_date datetime NOT NULL<br /> ) ON [PRIMARY]<br />GO<br />ALTER TABLE dbo.Tmp_partner_attribute_name ADD CONSTRAINT<br /> DF_partner_attribute_name_last_update_date <br /> DEFAULT (getdate()) FOR last_update_date<br />GO<br />ALTER TABLE dbo.Tmp_partner_attribute_name ADD CONSTRAINT<br /> DF_partner_attribute_name_creation_date <br /> DEFAULT (getdate()) FOR creation_date<br />GO<br />-- Copy all data to the temp table<br />IF EXISTS(SELECT * FROM dbo.partner_attribute_name)<br /> EXEC('INSERT INTO dbo.Tmp_partner_attribute_name<br /> (partner_attribute_name_id, attribute_name<br /> , description, last_update_date, creation_date)<br /> SELECT partner_attribute_name_id<br /> , attribute_name, description<br /> , last_update_date, creation_date <br /> FROM dbo.partner_attribute_name <br /> WITH (HOLDLOCK TABLOCKX)')<br />GO<br />DROP TABLE dbo.partner_attribute_name<br />GO<br />EXECUTE sp_rename N'dbo.Tmp_partner_attribute_name'<br /> , N'partner_attribute_name', 'OBJECT' <br />GO<br />ALTER TABLE dbo.partner_attribute_name ADD CONSTRAINT<br /> PK_partner_attribute_name PRIMARY KEY CLUSTERED <br /> (<br /> partner_attribute_name_id<br /> ) ON [PRIMARY]<br />GO<br />COMMIT</pre><br /><b>Note: You should generate the script BEFORE you save the changes in EM. Otherwise, that button will be disabled.</b>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-32621265805494694672007-04-05T11:49:00.000-04:002007-04-05T11:51:29.397-04:00A small compiler - Wilco Syntax HighlightingAlthough 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.<br /><br />Yesterday, I spent hours to analyze a popular syntax highlighter tool - <a href="http://www.wilcob.com/wilco/Toolbox/SyntaxHighlighter.aspx">Wilco SyntaxHighter</a>, because it is a small compiler to some degree. :)<br /><br />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.<br /><br />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. <br /><br />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.<br /><br />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.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-22643768.post-4249668943168074932007-04-05T11:02:00.000-04:002007-04-05T13:28:37.423-04:00MS AJAX UpdatePanel throws Sys.WebForms.PageRequestManagerParserErrorExceptionI 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:<br /><PRE> <span style="color: Green; font-family: Courier New; font-size: 11px;">// Stream PDF kit to client<br /></span> Byte[] buffer <span style="color: Red; font-family: Courier New; font-size: 11px; ">=</span> File.ReadAllBytes(filePath);<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">base</span>.Response.Clear();<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">base</span>.Response.ContentType <span style="color: Red; font-family: Courier New; font-size: 11px; ">=</span> <span style="color: #666666; font-family: Courier New; font-size: 11px;">"application/pdf"</span>;<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">int</span> length <span style="color: Red; font-family: Courier New; font-size: 11px; ">=</span> buffer.Length;<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">base</span>.Response.AddHeader(<span style="color: #666666; font-family: Courier New; font-size: 11px;">"Accept-Header"</span>, length.ToString());<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">base</span>.Response.AddHeader(<span style="color: #666666; font-family: Courier New; font-size: 11px;">"Content-Length"</span>, length.ToString());<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">base</span>.Response.OutputStream.Write(buffer, 0, buffer.Length);<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">base</span>.Response.Flush();<br /> <span style="color: Blue; font-family: Courier New; font-size: 11px; ">base</span>.Response.End();<br /></PRE><br />But I saw this exception message:<br /><br />Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed ...<br /><br />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 <a href="http://weblogs.asp.net/leftslipper/archive/2007/02/26/sys-webforms-pagerequestmanagerparsererrorexception-what-it-is-and-how-to-avoid-it.aspx">here</a>: <br /><br /><i>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.</i><br /><br />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.Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-22643768.post-50709632232566995632007-03-21T10:17:00.000-04:002007-03-21T10:30:21.610-04:00A missing feature of WFMicrosoft 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.<br /><br />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.<br /><br />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.<br /><br />I hope the new version of ASP.NET integrated with WF can have that "Back" button feature.Unknownnoreply@blogger.com2