<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkUHRXk-eSp7ImA9WhRVEko.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669</id><updated>2012-01-11T02:37:14.751-08:00</updated><category term="TIY" /><category term="Python" /><category term="User Interface" /><category term="jQuery" /><category term="Software Engineering" /><category term="MVC/MVVM" /><category term="Cloud Computing" /><category term="CAB" /><category term="Deployment" /><category term="我的中国" /><category term="Security" /><category term="疯人手札" /><category term="English - PDC 2008" /><category term="Algorithms" /><category term="Azure" /><category term="Computer Vision" /><category term="Windows Phone" /><category term="NDepend" /><category term="Silverlight/WPF" /><category term="WCF" /><category term="白玉美人" /><category term="Geneva" /><category term="Sync Framework" /><category term="Unity" /><category term="Digital Identity" /><category term="嘈嘈切切" /><category term="电子基盘" /><category term=".Net General" /><category term="Software Matrices" /><category term="Design Patterns" /><category term="史海钩沉" /><title>Haishi's Blog</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://haishibai.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>125</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/HaishisBlog" /><feedburner:info uri="haishisblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CE4DR3g9cCp7ImA9WhRXEEQ.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8198529976205335950</id><published>2011-12-16T19:36:00.001-08:00</published><updated>2011-12-16T19:36:16.668-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-16T19:36:16.668-08:00</app:edited><title>Tutorial: knockoutjs MVVM for XAML programmers – sprint 1</title><content type="html">&lt;p&gt;The goal of this series of posts is to help XAML programmers to transit to HTML + JavaScript world, while carrying best practices such as MVVM pattern over to the new world. In this series, we’ll build a simple but fully functional website that manage customers from different countries. We’ll also build CRUD operations on customer orders.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Series prerequisites:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Know basic MVVM pattern concepts.  &lt;li&gt;Know basics of &lt;a href="http://knockoutjs.com/"&gt;knockoutjs&lt;/a&gt;. I’ll go through some “recipes” of using knockoutjs, but you should have at least browsed through the &lt;a href="http://learn.knockoutjs.com/"&gt;wonderful tutorials&lt;/a&gt; they provided.  &lt;li&gt;Know basics of writing JavaScript in OO style.  &lt;li&gt;Know basics of HTML markups.  &lt;li&gt;Know basics of CSS.  &lt;li&gt;Know jQuery.  &lt;li&gt;Know a server side technology that serve JSON objects, such as ASP.Net MVC, PHP, etc. We won’t need it until the last sprint.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Sprint 1 backlog:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Get organized! We don’t want to create a big JavaScript file that does everything. Instead, we’ll create a folder structure to holder smaller scripts for different purposes. This will also improve code-reuse as we go along.  &lt;li&gt;Create a simple county repository that serves up list of countries (id and name)  &lt;li&gt;Create initial view model  &lt;li&gt;Create initial view with only one dropdown box to display list of countries.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Tools required for Sprint 1:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;knockoutjs  &lt;li&gt;A text editor such as Notepad  &lt;li&gt;A browser&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Without further ado, let’s roll! (Link to download source of sprint 1 is at the end of this post)&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1-1 Create folder structure&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The following picture and table show the folder structure I’m going to use. Obviously this is not the only way to get things organized. But if you’d like to follow along, I recommend you use the same folder structure to avoid confusions. And if you are familiar with ASP.Net MVC, you may find this folder structure has some resemblances with ASP.Net MVC folder structure – this is intentional so that later on it will be easier for us to merge this into a ASP.Net MVC project (if we choose to, of course).&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-fVA75AeuzaY/TuwOK3GCw5I/AAAAAAAAAa0/vIV7Chkmynw/s1600-h/image2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-7meF-5wUx0s/TuwOLCyMd3I/AAAAAAAAAa8/S9AV6RnvqPI/image_thumb.png?imgmax=800" width="153" height="170"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p align="center"&gt;Picture 1-1: Folder structure&lt;/p&gt; &lt;table border="1" cellspacing="0" cellpadding="2" width="622"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Folder&lt;/td&gt; &lt;td valign="top" width="481"&gt;Purpose&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Content&lt;/td&gt; &lt;td valign="top" width="481"&gt;Hold static assets such as style sheets and images.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Scripts&lt;/td&gt; &lt;td valign="top" width="481"&gt;Hold various JavaScript files for example jQuery files and knockoutjs files will be under this folder.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Scripts&lt;br&gt;\Formatters&lt;/td&gt; &lt;td valign="top" width="481"&gt;Scripts that are used to format data. Think them as IValueConverter implementations in you XAML project.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Scripts&lt;br&gt;\Repositories&lt;/td&gt; &lt;td valign="top" width="481"&gt;Scripts that serve as client-side repositories. Client-side repositories hide service-invocation details. In the initial sprints we’ll use a mock repository that is not connected to any services at all. Later on we’ll switch to a real repository without impacting any other client code.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Scripts&lt;br&gt;\SharedTemplates&lt;/td&gt; &lt;td valign="top" width="481"&gt;Data templates. Think them as your XAML user controls, control templates and data templates.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Scripts&lt;br&gt;\ViewModels&lt;/td&gt; &lt;td valign="top" width="481"&gt;View models. No surprises here. They correspond to VM classes you would create with C# (or VB).&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="139"&gt;Views&lt;/td&gt; &lt;td valign="top" width="481"&gt;HTML files. &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;strong&gt;1-2 Prepare the folder&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Drop knockoutjs scripts to Scripts folder. I’m using 1.3.0 beta version for this series, but other versions should also work.  &lt;li&gt;Create a new Index.html file under Views folder. This will be our view for now. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;1-3 Create mock country repository&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Create a countryRepository.js file under Scripts\Repositories folder. The mock repository defines one method: ListAllCountries, which returns a fixed set of countries:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; MockCountryRepository(){
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.ListAllCountries = &lt;span class="kwrd"&gt;function&lt;/span&gt; () {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; [{&lt;span class="str"&gt;"id"&lt;/span&gt;:1, &lt;span class="str"&gt;"name"&lt;/span&gt;: &lt;span class="str"&gt;"Belgium"&lt;/span&gt;},
                {&lt;span class="str"&gt;"id"&lt;/span&gt;:2, &lt;span class="str"&gt;"name"&lt;/span&gt;: &lt;span class="str"&gt;"Canada"&lt;/span&gt;},
                {&lt;span class="str"&gt;"id"&lt;/span&gt;:3, &lt;span class="str"&gt;"name"&lt;/span&gt;: &lt;span class="str"&gt;"China"&lt;/span&gt;},
                {&lt;span class="str"&gt;"id"&lt;/span&gt;:4, &lt;span class="str"&gt;"name"&lt;/span&gt;: &lt;span class="str"&gt;"United States"&lt;/span&gt;}];
    }
};&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Test the repository. We’ll modify the Index.html code to add some testing logics for now. This is to make sure there’s no errors before we move forward. The code creates a new instance of MockCountryRepository, invokes its ListAllCountries method, and append result to a div (“#testCanvas”):&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;KOMVVM&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;="http://code.jquery.com/jquery-latest.js"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text/javascript"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &amp;lt;script src=&lt;span class="str"&gt;"../Scripts/knockout-1.3.0beta.js"&lt;/span&gt; type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;script src=&lt;span class="str"&gt;"../Scripts/Repositories/MockCountryRepository.js"&lt;/span&gt; language=&lt;span class="str"&gt;"javascript"&lt;/span&gt; type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;div id=&lt;span class="str"&gt;"testCanvas"&lt;/span&gt; /&amp;gt;
        &amp;lt;script type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;
            &lt;span class="kwrd"&gt;var&lt;/span&gt; countryRepository = &lt;span class="kwrd"&gt;new&lt;/span&gt; MockCountryRepository();
            &lt;span class="kwrd"&gt;var&lt;/span&gt; countries = countryRepository.ListAllCountries();
            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;var&lt;/span&gt; i = 0; i &amp;lt; countries.length; i++)
                $(&lt;span class="str"&gt;"#testCanvas"&lt;/span&gt;).append(countries[i].id).append(&lt;span class="str"&gt;":"&lt;/span&gt;).append(countries[i].name).append(&lt;span class="str"&gt;"&amp;lt;br/&amp;gt;"&lt;/span&gt;);
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Open Index.html in browser. If you see a warning of blocked content, allow blocked content (JavaScript) to execute. if everything is fine, you should see an output similar to this:&lt;a href="http://lh4.ggpht.com/-FDzaThSoQ0M/TuwOLT0OmcI/AAAAAAAAAbA/AGlyyZt2QMw/s1600-h/image5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-pAOqqhuapzY/TuwOLiLNyHI/AAAAAAAAAbM/kaE4BzGzQXA/image_thumb1.png?imgmax=800" width="244" height="195"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;OK, repository is working! Now let’s create the view model.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1-4 Create view model&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Create a IndexPageViewModel.js under Scripts\ViewModels folder. This will be our main View Model for the page.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; IndexPageViewModel(countryRepository) {
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.countryRepository = countryRepository;
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.Countries = ko.observableArray([]);
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.CurrentCountry = ko.observable(&lt;span class="str"&gt;""&lt;/span&gt;);
    &lt;span class="kwrd"&gt;var&lt;/span&gt; self = &lt;span class="kwrd"&gt;this&lt;/span&gt;;
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.initialize = &lt;span class="kwrd"&gt;function&lt;/span&gt; () {
        &lt;span class="kwrd"&gt;var&lt;/span&gt; def = $.Deferred();
        $.when(countryRepository.ListAllCountries())
        .done(&lt;span class="kwrd"&gt;function&lt;/span&gt; (countries) {
            self.Countries(countries);
            def.resolve();
        });
        &lt;span class="kwrd"&gt;return&lt;/span&gt; def;
    };
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;OK, I admit it, there’s quite a jump here. What happened here are several things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the view model takes a country repository in constructor. In other words here we are injecting a country repository implementation. You’ll see later on how swapping repository implementation allows us to connect to real services without needing to worry about code changes in any view models or views. &lt;/li&gt;
&lt;li&gt;the view model has a Countries property, which is a knockoutjs observableArray type – think it as ObservableCollection in your XAML/C# world.&lt;/li&gt;
&lt;li&gt;the view mdoel has a CurrentCountry property, which is a knockoutjs observable type – think it implements INotifyPropertyChanged interface from C# world.&lt;/li&gt;
&lt;li&gt;the view model has an initialize method, which return a jQuery.Deferred() object. This is not necessary for now. But later on when we invoke multiple web requests to initialize, we need this promise mechanism so that data binding occurs only when we tell knockoujs that we are ready (by calling def.resolve()).&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;1-5 Modify the view&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now we add a dropdown list to the view and bind it to list of countries:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;KOMVVM&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;="http://code.jquery.com/jquery-latest.js"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text/javascript"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &amp;lt;script src=&lt;span class="str"&gt;"../Scripts/knockout-1.3.0beta.js"&lt;/span&gt; type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;script src=&lt;span class="str"&gt;"../Scripts/Repositories/MockCountryRepository.js"&lt;/span&gt; language=&lt;span class="str"&gt;"javascript"&lt;/span&gt; type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;script src=&lt;span class="str"&gt;"../Scripts/ViewModels/IndexPageViewModel.js"&lt;/span&gt; language=&lt;span class="str"&gt;"javascript"&lt;/span&gt; type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;div id=&lt;span class="str"&gt;"testCanvas"&lt;/span&gt; /&amp;gt;
        &amp;lt;select data-bind=&lt;span class="str"&gt;"options: Countries(), value:CurrentCountry, optionsText: 'name'"&lt;/span&gt;&amp;gt;
        &amp;lt;/select&amp;gt;
        &amp;lt;script type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;
            &lt;span class="kwrd"&gt;var&lt;/span&gt; viewModel = &lt;span class="kwrd"&gt;new&lt;/span&gt; IndexPageViewModel(&lt;span class="kwrd"&gt;new&lt;/span&gt; MockCountryRepository());
            viewModel.initialize().done(ko.applyBindings(viewModel));
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;First let’s see what’s happening in the &amp;lt;script&amp;gt; element: we created a new instance of IndexPageViewModel, providing a new instance of MockCountryRepository. Then we invoke initialize method on the view model, and when it’s finished we tell knockoutjs to perform data-binding (ko.applyBindings() call).&lt;/p&gt;
&lt;p&gt;Under our test &amp;lt;div&amp;gt; we added a &amp;lt;select&amp;gt; element, which is bound to Countries property of the view model – no surprise here. If you don’t understand the syntax, read about knockoutjs again. &lt;/p&gt;
&lt;p&gt;After the changes, reload the view and you should see something like this.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-5uyM2bwRAyc/TuwOL2IS7NI/AAAAAAAAAbU/Xn2gLCxvQ3o/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-cMkLWjV_1ys/TuwOL5eEZyI/AAAAAAAAAbc/FC039hjPTYM/image_thumb%25255B1%25255D.png?imgmax=800" width="244" height="219"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This concludes sprint 1! If you’d like to get source code of this sprint, you can download &lt;a href="https://skydrive.live.com/?cid=5df79d1efae0f08c&amp;amp;id=5DF79D1EFAE0F08C%21242"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-8198529976205335950?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rutfflaEGqEAIhJYGD3oYreao5A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rutfflaEGqEAIhJYGD3oYreao5A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rutfflaEGqEAIhJYGD3oYreao5A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rutfflaEGqEAIhJYGD3oYreao5A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/SYDXZdp70Qg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8198529976205335950/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/12/tutorial-knockoutjs-mvvm-for-xaml.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8198529976205335950?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8198529976205335950?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/SYDXZdp70Qg/tutorial-knockoutjs-mvvm-for-xaml.html" title="Tutorial: knockoutjs MVVM for XAML programmers – sprint 1" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-7meF-5wUx0s/TuwOLCyMd3I/AAAAAAAAAa8/S9AV6RnvqPI/s72-c/image_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/12/tutorial-knockoutjs-mvvm-for-xaml.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck8DQ3w9eSp7ImA9WhRQGE4.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8500868331012413076</id><published>2011-12-13T18:47:00.001-08:00</published><updated>2011-12-13T18:47:52.261-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-13T18:47:52.261-08:00</app:edited><title>ASP.NET MVVM with ASP.NET MVC 3 and knockout.js</title><content type="html">&lt;p align="justify"&gt;There’s continuously increasing attention to separating presentation layer (HTML + javascript) and business layer (ASP.NET, PHP, etc.) in web development. More and more developers are seeking for supports of MVVM pattern in their web projects.&amp;nbsp; Among various offerings that exist today, &lt;a href="http://knockoutjs.com/"&gt;knockoutjs&lt;/a&gt; is one of the most promising ones. It’s simple, it’s clean, and it has many core concepts of MVVM covered. On the server side, ASP.NET MVC 3 (and soon MVC 4) has gained great popularity in .Net communities. The purpose of this article is to explore a possible architecture that combines benefits of ASP.NET MVC 3 and knockoutjs and to provide a MVVM design pattern for common web project. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;MVVM –&amp;gt; Entities + Views + View Models + (Repositories) + Services –&amp;gt; EVVMRS pattern&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Before we go further, let’s reflect on what VM means in the MVVM pattern. In theory VM is an abstracted View, however in reality we often see VM contains other things such as business entities, entity repositories, and logics to invoke services. So here I’d like to make an explicit distinction: to get repositories and services out of VM and make them separate entities in the architecture. And here are the roles under this EVVM(R)S pattern:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;E: Business entities. These are the entities you manage. Note the entities don’t contain business logics (well, maybe some basic data validations can be allowed).  &lt;li&gt;V: Views. These are the UI presentations.  &lt;li&gt;VM: View Models. These are the logical views that handles view interactions such as commanding, notifications, etc.  &lt;li&gt;R: Repositories. These are where VMs get business entities. Repositories can also serve as the abstraction layer between VMs and Services.  &lt;li&gt;S: Services. These are where business logics are encapsulated. Note the Services can be either local or remote. Repository layer provides a location-agnostic abstraction to VMs.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;With this pattern, the architecture of a common web-based application can be illustrated as:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-kI46NSLO9Cc/TugOVj3iDfI/AAAAAAAAAak/TsVxYP5WvL4/s1600-h/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-tkKAH3zQWGU/TugOV5wgRAI/AAAAAAAAAao/i7cX0I-YnS8/image_thumb1.png?imgmax=800" width="407" height="61"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Where are Business Entities? Business Entities flow through this diagram and transform into different forms as they go. Specifically:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;From Database to Service: Services need to interact with databases with database-specific APIs. It can be ADO.Net, Entity framework, cloud storage, or other data-access APIs. Services convert these records into Business Entities. And all business logics should be built on top of these entities.  &lt;li&gt;From Services to Repositories: in the case that Services are local, Repositories can share the same Business Entity types with the Services. For remote Services, however, Repositories often don’t have direct access to Business Entity types defined on the Services. Instead, they’ll use some proxy types (such as the types you get when you add service references by using service metadata), or they’ll use totally different presentations such as XML or JSON objects (often seen in REST-ful calls). Although there are frameworks and tools that allow you to “share contracts” between your clients and servers, but the entities types on each side are still different physical types.  &lt;li&gt;From Repository to View Modes. Usually View Modes share the same Business Entity types with Repositories.  &lt;li&gt;From View Models to Views. View Models annotate Business Entities with change notification properties and supply annotated entities for UI binding to Views.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;How to fit ASP.NET MVC 3 and knockoutjs into above pattern&lt;/strong&gt;&lt;/p&gt; &lt;table border="1" cellspacing="0" cellpadding="2" width="601"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="157"&gt;&lt;strong&gt;Component&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="442"&gt;&lt;strong&gt;Role&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="161"&gt;HTML&lt;/td&gt; &lt;td valign="top" width="439"&gt;View: screen markups and templates that knockoutjs can bind View Models to.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="164"&gt;javascript “class”&lt;/td&gt; &lt;td valign="top" width="436"&gt;View Models: knockoutjs defines View Models as javascript classes.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="167"&gt;javascript&lt;/td&gt; &lt;td valign="top" width="434"&gt;Repository: this part is up to you to define &amp;amp; construct. Repositories should encapsulate Service invocations.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="169"&gt;JSON objects&lt;/td&gt; &lt;td valign="top" width="432"&gt;Business Entities: JSON are used when Services return data to client/Repositories.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="169"&gt;C# objects&lt;/td&gt; &lt;td valign="top" width="432"&gt;Business Entities: These can be POCO types or Entity Framework types that are used in Service layer.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="171"&gt;ASP.Net MVC Controller&lt;/td&gt; &lt;td valign="top" width="431"&gt;Services: REST-ful services that return JSON objects.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Under this pattern, MVC Controller will also provide “hook-up” for Views – they return Views to browser. However under this pattern they’ll simply return “untyped” views:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index()
{
   &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;In parallel MVC Controller provides Service APIs to client. For example, to supply Business Entities as JSON objects:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; JsonResult lisCustomers()
{
      &lt;span class="kwrd"&gt;return&lt;/span&gt; Json(dataContext.ListCustomers(), JsonRequestBehavior.AllowGet);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;The corresponding view (.cshtml if you are using razor) contains standard HTML and javascripts only. You’ll not use @model directive anymore. (Of course in the future Microsoft may as well get everything combined!) Instead, you’ll use knockoutjs and jQuery template syntax to create views and binding templates. I won’t go into details here as there are abundant resources on the web.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-8500868331012413076?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mpY00-T49FlxfCeiLP9pRxo031g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mpY00-T49FlxfCeiLP9pRxo031g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mpY00-T49FlxfCeiLP9pRxo031g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mpY00-T49FlxfCeiLP9pRxo031g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/OEB9m4ExYGk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8500868331012413076/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/12/aspnet-mvvm-with-aspnet-mvc-3-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8500868331012413076?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8500868331012413076?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/OEB9m4ExYGk/aspnet-mvvm-with-aspnet-mvc-3-and.html" title="ASP.NET MVVM with ASP.NET MVC 3 and knockout.js" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-tkKAH3zQWGU/TugOV5wgRAI/AAAAAAAAAao/i7cX0I-YnS8/s72-c/image_thumb1.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/12/aspnet-mvvm-with-aspnet-mvc-3-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QERnk_fSp7ImA9WhRRGEs.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-2327550489251998961</id><published>2011-12-02T15:41:00.001-08:00</published><updated>2011-12-02T15:41:47.745-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-02T15:41:47.745-08:00</app:edited><title>Entity Framework TPT Performance Quick Tips</title><content type="html">&lt;ol&gt; &lt;li&gt;When using model-first, choose TPH over TPT when possible.&lt;/li&gt; &lt;li&gt;When using database-first, remove navigation properties from corresponding entities. Obviously there’s a tradeoff here, but to get TPT to a reasonable performance the sacrifice is necessary.&lt;/li&gt; &lt;li&gt;Create views of corresponding tables and create entities on the views. &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/8122199360699827669-2327550489251998961?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/boRCNa1Qk7WbtIFmdnMlxLzzfj0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/boRCNa1Qk7WbtIFmdnMlxLzzfj0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/boRCNa1Qk7WbtIFmdnMlxLzzfj0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/boRCNa1Qk7WbtIFmdnMlxLzzfj0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/Jmx8PVd9Zjo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/2327550489251998961/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/12/entity-framework-tpt-performance-quick.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/2327550489251998961?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/2327550489251998961?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/Jmx8PVd9Zjo/entity-framework-tpt-performance-quick.html" title="Entity Framework TPT Performance Quick Tips" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/12/entity-framework-tpt-performance-quick.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QHQ3k4eyp7ImA9WhRRGEs.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-3240673649842074031</id><published>2011-10-30T15:17:00.001-07:00</published><updated>2011-12-02T15:42:12.733-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-02T15:42:12.733-08:00</app:edited><title>Azure Toss!</title><content type="html">&lt;p&gt;&lt;strong&gt;Visit CodePlex page today: &lt;a href="http://toss.codeplex.com/"&gt;http://toss.codeplex.com/&lt;/a&gt;&lt;/strong&gt;  &lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;  &lt;p&gt;With the booming of personal devices (such as iPad and Windows 8 tablets) and cloud-based services (such as Azure and iCloud), we are entering an era of highly connected yet very loosely coupled applications and services. As ISVs and application developers, you’ll find your applications need to communicate with many other applications and services in a “non-binding” way - there are no hard commitments among the applications and services to work together. Instead, services and features are discovered and consumed on an “as needed” basis. Azure Toss provides an integration platform that allows your services and applications to work together more easily and more reliably without any binding contracts. There are three levels of “tossing” under Azure Toss, which I shall explain one-by-one:  &lt;p&gt;&lt;strong&gt;Level 1 – Simple Toss. &lt;/strong&gt; &lt;p&gt;In case you haven’t noticed, there’s a universal application integration mechanism on virtually all platforms – the clipboard. By allowing simple Ctrl + C and Ctrl + V (or Command C and Command V for Mac) key strokes, many applications are able to share information among them without even knowing each other. There’s no data contract negotiation, there’s no fixed binding, applications simply try to work with the data they get through clipboard. Azure Toss Level 1 gives you a cloud-based clipboard with additional features such as publish-subscribe pattern, access control and multi-cast. Your applications and services will be able to “toss” information over the cloud to other parties without any committed contracts.  &lt;p&gt;&lt;strong&gt;Level 2- Semantic Fields.&lt;/strong&gt;  &lt;p&gt;Let’s consider a very simple integration scenario among applications – to send a picture to another application. This was not a problem in the old days when your application only needed to talk to a handful of other applications. You need to study the APIs provided by the other applications and to code for these interfaces. However, imagine you’ll need to interact with hundreds of application, many of which are not written yet! To satisfy the needs to all those interface requirements is just infeasible. The problem is that traditional data contracts and APIs define only syntax of data, not semantics of data. The picture APIs don’t say “I need a picture, in .png or .jpg format” (although the names of functions may &lt;u&gt;suggest&lt;/u&gt; that to &lt;u&gt;humans&lt;/u&gt;)”. Instead, what they are really saying is “I need a byte array with an associated utf-8 encoded string”. Without a business context, that contract can mean anything. Azure Toss semantic fields allow you to describe your data and API needs with actual semantic meanings. Your application will be able to say, “Hey, I can give you a .png image if you want.” And other applications can still reliably integrated with your application because they will clearly know what they are going to get is indeed a png image.  &lt;p&gt;&lt;strong&gt;Level 3 – Semantic service discovery and consumption &lt;/strong&gt; &lt;p&gt;Imagine you are writing a chat client that automatically translates chat messages to different languages of the participants, and you want to use an online translation service for the purpose. What you need to do nowadays is to search around for such services, study their licensing, pricing, capabilities and APIs, and pick a service to work with. This is a one-way commitment – you are committed to the service but the service is not committed to you (or even knows you). When the service changes, your application breaks. Azure Toss will help you to avoid making such commitment. You application will simply say, “I need A translation service that translates between English and Chinese.” And Azure Toss will take care of the rest. Of course you can be much more specific on your needs: “I need a translation service that is free, with a rating higher than 4, within my trusted service providers”. Yet you still don’t need to worry about any details, Azure Toss will find the service for you. And if you chose to, Azure Toss can even invoke the service for you and return you the result. With the help of semantic fields, Azure Toss will be able to tell you, “Your request of translating text from English to Chinese has been fulfilled, and here’s the result text, in Chinese language”.   &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-3240673649842074031?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FksdtxM4j-yA6Y6MFEVihkwfsKo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FksdtxM4j-yA6Y6MFEVihkwfsKo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FksdtxM4j-yA6Y6MFEVihkwfsKo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FksdtxM4j-yA6Y6MFEVihkwfsKo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/ofnuXPxrNBM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/3240673649842074031/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/10/azure-toss.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3240673649842074031?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3240673649842074031?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/ofnuXPxrNBM/azure-toss.html" title="Azure Toss!" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/10/azure-toss.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAASHoyfCp7ImA9WhdSFkk.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-6626306695360073499</id><published>2011-07-25T18:29:00.001-07:00</published><updated>2011-07-25T18:29:09.494-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-25T18:29:09.494-07:00</app:edited><title>Silverlight Quick Tip: High CPU usage of Bing map control running in OOB</title><content type="html">&lt;p&gt;If you are experiencing high CPU usage when using Bing map control in an OOB Silverlight application, try to disable GPU acceleration. In my case changing the setting brought CPU usage from 70% to 2%.&lt;/p&gt; &lt;p&gt;p.s. To quickly identify which UI part is causing the most rendering cycles, enable redraw regions:&lt;/p&gt; &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;Application.Current.Host.Settings.EnableRedrawRegions = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will make your screen blink a lot. The most flashing areas are the ones that hogging CPU cycles. &lt;/p&gt;
&lt;p&gt;Also, with VS 2010 SP1, you can use Analyze-&amp;gt;Launch Performance Wizard to profile your Silverlight application to identify high CPU users. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-6626306695360073499?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1KqgRKQduDizIiq4pkw8DyfFfN0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1KqgRKQduDizIiq4pkw8DyfFfN0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1KqgRKQduDizIiq4pkw8DyfFfN0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1KqgRKQduDizIiq4pkw8DyfFfN0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/tWaaJpfATQM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/6626306695360073499/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/07/silverlight-quick-tip-high-cpu-usage-of.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6626306695360073499?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6626306695360073499?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/tWaaJpfATQM/silverlight-quick-tip-high-cpu-usage-of.html" title="Silverlight Quick Tip: High CPU usage of Bing map control running in OOB" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/07/silverlight-quick-tip-high-cpu-usage-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEBQn49fSp7ImA9WhZWFE0.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8057726411283009784</id><published>2011-05-14T12:16:00.001-07:00</published><updated>2011-05-14T12:17:33.065-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-14T12:17:33.065-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC/MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><category scheme="http://www.blogger.com/atom/ns#" term="Digital Identity" /><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Computing" /><title>Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (5)</title><content type="html">&lt;p&gt;Finally we are ready to implement our final scenario. Again, the goal is to allow users to logon to our ASP.Net MVC 3 service site using either a local id, or any supported ids (Google, Windows Live, and Yahoo! to start with). And our service site should be shield from most of the complexity of federating with multiple identity providers.&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tc7VGMF6muI/AAAAAAAAAZM/ZDNJn7cbzSQ/s1600-h/image%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7VGlArYGI/AAAAAAAAAZQ/Nd_K5YRwIeE/image_thumb%5B1%5D.png?imgmax=800" width="299" height="249"&gt;&lt;/a&gt;This part involves quite some changes in the STS code, as we are extending the STS project to serve as both a FP and a STS. However, the service project remains intact. There’s even no configuration updates. As far as the service project concerns, it’s talking to a trusted FP, and it doesn’t need to worry about anything else.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Part I: Relocate local STS.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In this part we’ll move the Default.aspx page to a sub-folder, and set up the sub-foder to use form authentication to preserve local STS functionality.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;In STS project, create a new “STS” folder.&lt;/li&gt; &lt;li&gt;Move Default.aspx page into this folder and remove the file to TokenPoster.aspx. Renaming an ASP.Net page is a little tricky, you need to manually verify if all class names in both code-behind and aspx page are updated correctly. And you may have to reload the project to eliminate some confusions of Visual Studio.&lt;/li&gt; &lt;li&gt;Add a new Default.aspx page to the root folder of STS project. This page displays two options for user to pick from a local STS or ACS.&lt;/li&gt; &lt;li&gt;Add two buttons to the page:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:LinkButton&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Use Local STS"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="btnLocalSTS"&lt;/span&gt; 
            &lt;span class="attr"&gt;onclick&lt;/span&gt;&lt;span class="kwrd"&gt;="btnLocalSTS_Click"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:LinkButton&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Use Azure ACS"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="btnACS"&lt;/span&gt; 
            &lt;span class="attr"&gt;onclick&lt;/span&gt;&lt;span class="kwrd"&gt;="btnACS_Click"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;In code-behind, put in the following code:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
     &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(Request.QueryString[WSFederationConstants.Parameters.Action]))
        ViewState[&lt;span class="str"&gt;"F-Action"&lt;/span&gt;] = Request.QueryString[WSFederationConstants.Parameters.Action];
     &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(Request.QueryString[&lt;span class="str"&gt;"wtrealm"&lt;/span&gt;]))
        ViewState[&lt;span class="str"&gt;"F-wtrealm"&lt;/span&gt;] = Request.QueryString[&lt;span class="str"&gt;"wtrealm"&lt;/span&gt;];
}
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnLocalSTS_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        Response.Redirect(&lt;span class="str"&gt;"STS/TokenPoster.aspx?wa="&lt;/span&gt; + ViewState[&lt;span class="str"&gt;"F-Action"&lt;/span&gt;].ToString() + &lt;span class="str"&gt;"&amp;amp;wtrealm="&lt;/span&gt; + ViewState[&lt;span class="str"&gt;"F-wtrealm"&lt;/span&gt;].ToString().Replace(&lt;span class="str"&gt;":"&lt;/span&gt;, &lt;span class="str"&gt;"%3A"&lt;/span&gt;).Replace(&lt;span class="str"&gt;"/"&lt;/span&gt;, &lt;span class="str"&gt;"%2F"&lt;/span&gt;));
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception exception)
    {
        &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"An unexpected error occurred when processing the request. See inner exception for details."&lt;/span&gt;, exception);
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Modify web.config to put STS folder under form authentication protection:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  ......
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;location&lt;/span&gt; &lt;span class="attr"&gt;path&lt;/span&gt;&lt;span class="kwrd"&gt;="STS"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;authorization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;deny&lt;/span&gt; &lt;span class="attr"&gt;users&lt;/span&gt;&lt;span class="kwrd"&gt;="?"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;authorization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;location&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    ......
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;authentication&lt;/span&gt; &lt;span class="attr"&gt;mode&lt;/span&gt;&lt;span class="kwrd"&gt;="Forms"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;forms&lt;/span&gt; &lt;span class="attr"&gt;loginUrl&lt;/span&gt;&lt;span class="kwrd"&gt;="Login.aspx"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;authentication&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    ......&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Also, we need to disable default FAM redirecting by setting &lt;strong&gt;passiveRedirectEnabled&lt;/strong&gt;="&lt;strong&gt;false&lt;/strong&gt;" &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;After these modifications you should be able to use the local STS to logon. The code in step 6 is straightforward – it saves logon request when page is loaded, and it forwards the request to TokenPoster.aspx (former Default.aspx) when user clicks on the local STS link in the new Default.aspx page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Part II: Re-enabling ACS.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In step 7 above we disabled FAM default redirecting. To put FAM back to work again, we’ll need to trigger the authentication process in the code. Modify code-behind of Default.aspx page:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
   &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(Request.QueryString[WSFederationConstants.Parameters.Action]))
        ViewState[&lt;span class="str"&gt;"F-Action"&lt;/span&gt;] = Request.QueryString[WSFederationConstants.Parameters.Action];
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(Request.QueryString[&lt;span class="str"&gt;"wtrealm"&lt;/span&gt;]))
        ViewState[&lt;span class="str"&gt;"F-wtrealm"&lt;/span&gt;] = Request.QueryString[&lt;span class="str"&gt;"wtrealm"&lt;/span&gt;];
        
    var fam = FederatedAuthentication.WSFederationAuthenticationModule;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (fam.CanReadSignInResponse(Request, &lt;span class="kwrd"&gt;true&lt;/span&gt;))
    {
        &lt;span class="kwrd"&gt;string&lt;/span&gt; url = fam.GetSignInResponseMessage(Request).Context;
        SignInRequestMessage requestMessage = (SignInRequestMessage)WSFederationMessage.CreateFromUri(&lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(url + &lt;span class="str"&gt;"?wa=wsignin1.0&amp;amp;wtrealm="&lt;/span&gt; + url.Replace(&lt;span class="str"&gt;":"&lt;/span&gt;, &lt;span class="str"&gt;"%3A"&lt;/span&gt;).Replace(&lt;span class="str"&gt;"/"&lt;/span&gt;, &lt;span class="str"&gt;"%2F"&lt;/span&gt;);));
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (User != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; User.Identity != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; User.Identity.IsAuthenticated)
        {
            SecurityTokenService sts = &lt;span class="kwrd"&gt;new&lt;/span&gt; CustomSecurityTokenService(CustomSecurityTokenServiceConfiguration.Current);
            SignInResponseMessage responseMessage = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(requestMessage, User, sts);
            FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse(responseMessage, Response);
        }
    }
}

&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnACS_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    var fam = FederatedAuthentication.WSFederationAuthenticationModule;
    var signIn = &lt;span class="kwrd"&gt;new&lt;/span&gt; SignInRequestMessage(&lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(fam.Issuer), &lt;span class="str"&gt;"http://localhost:4011/ZerodistWeb_STS/"&lt;/span&gt;);
    signIn.Context = ViewState[&lt;span class="str"&gt;"F-wtrealm"&lt;/span&gt;].ToString();
    Response.Redirect(signIn.WriteQueryString());
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;When ACS button is clicked, a sign in request is generated and forwarded to ACS. After authentication, ACS redirects back to the Default.aspx page (as configured in ACS). Then, in the Page_Load event, we examine if we can read a response message. If so, we’ll use our STS to issue a security token back to the MVC application.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Part III: Test run.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Compile and launch.&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7VG-dmEKI/AAAAAAAAAZU/xAvzVWmRrw0/s1600-h/image%5B7%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tc7VHA0-_bI/AAAAAAAAAZY/X_aQMwHnPjQ/image_thumb%5B3%5D.png?imgmax=800" width="429" height="123"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Type in http://127.0.0.1:81/Portal in address bar.&lt;/li&gt;
&lt;li&gt;You’ll see the new selection page:&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tc7VHbrVsrI/AAAAAAAAAZc/3ikMuXUbyZo/s1600-h/image%5B12%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tc7VHpY1iaI/AAAAAAAAAZg/1gWEvayktAI/image_thumb%5B6%5D.png?imgmax=800" width="427" height="122"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click on “Use Azure ACS” link. You’ll be redirected to another IDP selection page:&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7VH736wvI/AAAAAAAAAZk/QhlB5Rc49nw/s1600-h/image%5B16%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7VIC3xs7I/AAAAAAAAAZo/zGsRBWFMaDw/image_thumb%5B8%5D.png?imgmax=800" width="295" height="299"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pick an IDP and log in. You’ll be redirected back to Portal page with granted access:&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/Tc7VITf_kOI/AAAAAAAAAZs/bVcGnO6DiQ0/s1600-h/image%5B20%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tc7VI74vPUI/AAAAAAAAAZw/UcTAB7sn5O8/image_thumb%5B10%5D.png?imgmax=800" width="422" height="103"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You can repeat the steps to try out Admin page with different IDPs. It should all work fine. Optionally you can also change the STS to grant Admin role to more user names (currently we only grant Admin role to user with name “Admin”).&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Congratulations! You’ve made this far. That’s something, isn’t? &lt;/p&gt;
&lt;p&gt;However, our quest is far from over. We still need to enable HTTPS, to enable token encryption, to extend STS to do actual authentication/authorization, to deploy everything on to Azure platform … so, keep tuned!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-8057726411283009784?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/NEnpzzrhHqCz7d1Zfb_qNWipvHY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NEnpzzrhHqCz7d1Zfb_qNWipvHY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/NEnpzzrhHqCz7d1Zfb_qNWipvHY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NEnpzzrhHqCz7d1Zfb_qNWipvHY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/FM5lZLo9jFM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8057726411283009784/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_8333.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8057726411283009784?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8057726411283009784?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/FM5lZLo9jFM/tutorialaspnet-mvc-3-claim-based_8333.html" title="Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (5)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7VGlArYGI/AAAAAAAAAZQ/Nd_K5YRwIeE/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_8333.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEDRnsyfyp7ImA9WhZWE0Q.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-9075282867993964806</id><published>2011-05-14T11:26:00.001-07:00</published><updated>2011-05-14T11:27:57.597-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-14T11:27:57.597-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC/MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><category scheme="http://www.blogger.com/atom/ns#" term="Digital Identity" /><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Computing" /><title>Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (4)</title><content type="html">&lt;p&gt;(Previous parts: &lt;a href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based.html"&gt;part 1&lt;/a&gt;, &lt;a href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_11.html"&gt;part 2&lt;/a&gt;, &lt;a href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_12.html"&gt;part 3&lt;/a&gt;)&lt;/p&gt; &lt;p&gt;In this part we’ll implement the Azure ACS path in our architecture. We’ll temporarily disable the Local STS path. We’ll combine the two paths in part 5 of this post. In this part, our STS project takes over FP responsibility from the MVC 3 app and itself will morph into a combination of STS and FP in part 5. Of course we could have created separate services for the two roles, but for simplicity we’ll keep them together in the STS project. &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/Tc7JSchz0wI/AAAAAAAAAYU/rNCvtSq2zmc/s1600-h/image%5B4%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tc7JS3fo1NI/AAAAAAAAAYY/_64oJoD6Sww/image_thumb%5B1%5D.png?imgmax=800" width="288" height="241"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;&lt;strong&gt;Part I: Configure trust relationship on ACS&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Here I assume you’ve got your Windows Azure account activated, have subscribed to ACS, and have created your ACS namespace. The steps in this section covers necessary settings to be performed on Windows Azure Portal –&amp;gt; Access Control Service page.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Click on “Identity providers” link and add Windows Live ID, Google, and Yahoo! as IDPs. Accept all default settings.  &lt;li&gt;Click on “Relying party applications” link. Then click “Add” to add our STS project (NOT our web project) as RP.  &lt;li&gt;Enter the following settings (accept default settings for unmentioned fields) and save:  &lt;ul&gt; &lt;li&gt;Name: [name of your choice]  &lt;li&gt;Realm: http://localhost:4011/MyWebApp_STS  &lt;li&gt;Return URL: http://localhost:4011/MyWebApp_STS/Default.aspx  &lt;li&gt;Error URL: (leave empty)  &lt;li&gt;Token format: SAML 1.1  &lt;li&gt;Token encryption policy: None  &lt;li&gt;Token lifetime: 600&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Click on “Rule groups” and click the auto-generated role group. Click on “Generate” button to generate default set of rules. Note in this set of rules Windows Live ID doesn’t output “name” claim. This will cause problems in our STS, but we’ll leave it for now and come back later to fix.&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7JTM8lU4I/AAAAAAAAAYc/24EriLTdysc/s1600-h/image16.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tc7JTYI9JzI/AAAAAAAAAYg/nQDKg47ixYQ/image_thumb8.png?imgmax=800" width="501" height="207"&gt;&lt;/a&gt;  &lt;li&gt;At last, click on “Application integration” link and note done “WS-Federation metadata” URL.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Part II: Establish federation with ACS&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Right-click on the STS project and select “Add STS Reference…”  &lt;li&gt;Same as before, ignore the https warning and continue with the wizard.  &lt;li&gt;Select “Use an existing STS” option, and paste in your ACS WS-Federation metadata URL, which you got from the last step in part I:&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tc7JT9zsWUI/AAAAAAAAAYk/TqP1-gUQtoM/s1600-h/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7JUCx1prI/AAAAAAAAAYo/doEqUatvVPY/image_thumb1.png?imgmax=800" width="335" height="254"&gt;&lt;/a&gt;  &lt;li&gt;Select “Disable certificate chain validation” and click “Next”:&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tc7JUeG1wII/AAAAAAAAAYs/_GyQsshoDZM/s1600-h/image7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tc7JU1CoS4I/AAAAAAAAAYw/5AC8C3Qlyso/image_thumb3.png?imgmax=800" width="330" height="250"&gt;&lt;/a&gt;  &lt;li&gt;Select “No encryption” and click “Next”:&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/Tc7JVHCU3JI/AAAAAAAAAY0/dtbvlH8VrSg/s1600-h/image11.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7JVusbObI/AAAAAAAAAY4/4YC7y6YSGl4/image_thumb5.png?imgmax=800" width="328" height="248"&gt;&lt;/a&gt;  &lt;li&gt;Accept all default settings and finish the wizard.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Part III: Test run&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Compile and run. You should see the default page as before.  &lt;li&gt;Type in http://localhost:81/Portal in address bar.  &lt;li&gt;This time you’ll see an IDP selection page instead:&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7JV7dmRVI/AAAAAAAAAY8/XXugaFuzzyY/s1600-h/image20.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tc7JWW_0IsI/AAAAAAAAAZA/syFTha7Ig6E/image_thumb10.png?imgmax=800" width="315" height="284"&gt;&lt;/a&gt;  &lt;li&gt;Pick either Google or Yahoo! (remember Windows Live ID is not working yet – we’ll fix next) and logon using your credentials.  &lt;li&gt;And you’ll be granted access to the portal page with your user name displayed:&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tc7JWvMYIQI/AAAAAAAAAZE/T18Rgikucko/s1600-h/image23.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/Tc7JW8W99gI/AAAAAAAAAZI/YSzH9YnI3OI/image_thumb11.png?imgmax=800" width="244" height="128"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Part IV: Fix Windows Live ID logon&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;We couldn’t use Windows Live ID because it didn’t generate the name claim (http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name). Fortunately, ACS, as a FP by itself, allows us to define claim transformation rules. We’ll use a transform rule to translate the nameidentifier claim (http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier) into the name claim:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;On Windows Azure portal, open the rule group we’ve reviewed before and click “Add” to add a new rule.  &lt;li&gt;Use the following settings for the rule and save it:  &lt;ul&gt; &lt;li&gt;Claim issuer: Identity Provider - Windows Live ID  &lt;li&gt;Input claim type: Select type – http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier  &lt;li&gt;Input claim value: Any  &lt;li&gt;Out claim type: Select type – http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name  &lt;li&gt;Output claim value: Pass through input claim value&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Now re-launch the solution and you should be able to logon with Windows Live ID now – the user name is a weird-looking string because it’s a direct copy of nameidentifer claim. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Part V: Switch between local STS and ACS&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Switching back and forth between local STS and ACS only requires a couple of configuration change. To revert back to the scenario in part 3 of this post series, just modify the web.config file or the STS project and change &lt;strong&gt;&lt;em&gt;passiveRedirectEnabled&lt;/em&gt;&lt;/strong&gt; to &lt;em&gt;&lt;strong&gt;false&lt;/strong&gt;&lt;/em&gt;, and system.web authentication &lt;em&gt;&lt;strong&gt;mode&lt;/strong&gt;&lt;/em&gt; to &lt;strong&gt;&lt;em&gt;Forms&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;What’s next&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In the next post we’ll finally complete the original design. Users will have choice to logon using a local id, or using any ids supported by trusted identity providers.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-9075282867993964806?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Npm6pvdP5k7mt2rFUCe5_yBHwjQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Npm6pvdP5k7mt2rFUCe5_yBHwjQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Npm6pvdP5k7mt2rFUCe5_yBHwjQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Npm6pvdP5k7mt2rFUCe5_yBHwjQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/wOMGw7zK9Dg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/9075282867993964806/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_14.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/9075282867993964806?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/9075282867993964806?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/wOMGw7zK9Dg/tutorialaspnet-mvc-3-claim-based_14.html" title="Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (4)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tc7JS3fo1NI/AAAAAAAAAYY/_64oJoD6Sww/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_14.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4HRnc_fSp7ImA9WhZWE0w.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-4648261764970586351</id><published>2011-05-12T00:21:00.000-07:00</published><updated>2011-05-13T13:35:37.945-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-13T13:35:37.945-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC/MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><category scheme="http://www.blogger.com/atom/ns#" term="Digital Identity" /><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Computing" /><title>Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (3)</title><content type="html">&lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based.html"&gt;Part 1&lt;/a&gt; and &lt;a href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_11.html"&gt;part 2&lt;/a&gt; of this post series got use started with an ASP.Net MVC 3 application using claim-based architecture for identity management needs. In this post we’ll implement finer authorization controls by using role-based security. In this post, we’ll add a new administrative page and permit only users with “Admin” role accessing it.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Part I: Extend STS and AuthenticateAndAuthorizeAttribute&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Modify CustomSecurityTokenService.cs in the STS project. We’ll put the user in “Admin” role if the user name is exactly “Admin”&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IClaimsIdentity GetOutputClaimsIdentity( IClaimsPrincipal principal, RequestSecurityToken request, Scope scope )
{
    ......
    outputIdentity.Claims.Add( &lt;span class="kwrd"&gt;new&lt;/span&gt; Claim( System.IdentityModel.Claims.ClaimTypes.Name, principal.Identity.Name ) );
   &lt;font style="background-color: #ffff00"&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (principal.Identity.Name == &lt;span class="str"&gt;"Admin"&lt;/span&gt;)
        outputIdentity.Claims.Add( &lt;span class="kwrd"&gt;new&lt;/span&gt; Claim( ClaimTypes.Role, &lt;span class="str"&gt;"Admin"&lt;/span&gt; ) );
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        outputIdentity.Claims.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Claim(ClaimTypes.Role, &lt;span class="str"&gt;"User"&lt;/span&gt;));&lt;/font&gt;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; outputIdentity;
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Modify AuthenticateAndAuthorizeAttribute.cs in the web project. We’ll add a new Roles attribute where we can specify which role (for now we only support one role in the string) is required to authorize a user. Then, we’ll change authenticateUser to handle multiple realms (Portal and Admin). At last, we’ll give an easy implementation of authorizeUser to check against specified roles:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Roles { get; set; }
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; authenticateUser(AuthorizationContext context)
{
    var fam = FederatedAuthentication.WSFederationAuthenticationModule;
    var signIn = &lt;span class="kwrd"&gt;new&lt;/span&gt; SignInRequestMessage(&lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(fam.Issuer), fam.Realm + context.HttpContext.Request.FilePath);
    context.Result = &lt;span class="kwrd"&gt;new&lt;/span&gt; RedirectResult(signIn.WriteQueryString());
}
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; authorizeUser(AuthorizationContext context)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(Roles) &amp;amp;&amp;amp; !context.HttpContext.User.IsInRole(Roles))
       context.Result = &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpUnauthorizedResult();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part II: Add new Admin page.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add a new AdminController to web application’s Controllers folder. Note how the controller is decorated with additional role requirement:&lt;pre class="csharpcode"&gt;[AuthenticateAndAuthorize(Roles = &lt;span class="str"&gt;"Admin"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; AdminController : Controller
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Add a Admin folder to web app’s Views folder. Then add a new Index.cshtml as before:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Hi there, @this.Context.User.Identity.Name!&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;h2&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; @this.Context.User.IsInRole("Admin")&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;h2&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part III: Modify web.config&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now we change the web.config file to add Admin path as allowed audience. We’ll also change the realm definiation because we’ll dynamically append page path in AuthenticateAndAuthorizeAttribute class:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;microsoft.identityModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:81/Portal"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;strong&gt;&lt;u&gt;&lt;font style="background-color: #ffff00"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:81/Admin"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/font&gt;
&lt;/u&gt;&lt;/strong&gt;      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;federatedAuthentication&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsFederation&lt;/span&gt; &lt;span class="attr"&gt;passiveRedirectEnabled&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="attr"&gt;issuer&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:4011/MyWebApp_STS/"&lt;/span&gt; &lt;span class="attr"&gt;realm&lt;/span&gt;&lt;span class="kwrd"&gt;="&lt;font style="background-color: #ffff00"&gt;&lt;strong&gt;&lt;u&gt;http://localhost:81&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;"&lt;/span&gt; &lt;span class="attr"&gt;requireHttps&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;  &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        ...&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Part IV: Test run&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Launch the browser. You can go to Portal page as before. However, when you try to access Admin page, unless you entered “Admin” as user name, you’ll get 401 error:&lt;/p&gt;
&lt;h4&gt;&lt;font color="#c0504d"&gt;HTTP Error 401.0 – Unauthorized&lt;/font&gt;&lt;/h4&gt;
&lt;p&gt;Only after you entered “Admin”, you’ll be greeted to the Admin page:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TcuKZDefjbI/AAAAAAAAAYM/wlwv-5nN6Kc/s1600-h/image%5B3%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TcuKZWt160I/AAAAAAAAAYQ/KFzwThEUGOY/image_thumb%5B1%5D.png?imgmax=800" width="263" height="110"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Next we’ll chain up our FP with Azure ACS to work with other IDPs over internet such as Windows Live ID, Google ID, etc. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-4648261764970586351?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aJ6Haa3K8eARIcnxnJROq7pFGkY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aJ6Haa3K8eARIcnxnJROq7pFGkY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aJ6Haa3K8eARIcnxnJROq7pFGkY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aJ6Haa3K8eARIcnxnJROq7pFGkY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/AO08WjuZAGg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/4648261764970586351/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_12.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4648261764970586351?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4648261764970586351?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/AO08WjuZAGg/tutorialaspnet-mvc-3-claim-based_12.html" title="Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (3)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TcuKZWt160I/AAAAAAAAAYQ/KFzwThEUGOY/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_12.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4HSX8yeyp7ImA9WhZWE0w.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-5888983724600661672</id><published>2011-05-11T16:22:00.000-07:00</published><updated>2011-05-13T13:35:38.193-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-13T13:35:38.193-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC/MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><category scheme="http://www.blogger.com/atom/ns#" term="Digital Identity" /><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Computing" /><title>Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (2)</title><content type="html">&lt;p&gt;In this post we’ll continue with our scenario (see &lt;a href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based.html"&gt;Part 1&lt;/a&gt;). We’ll set up WIF and ASP.Net MVC 3 so that only certain pages are protected by the claim-based architecture. &lt;/p&gt; &lt;p&gt;(Note: this series of post use simplified version of sample codes provided by &lt;a href="http://msdn.microsoft.com/en-us/library/ff423674.aspx"&gt;MSDN&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Part I: Add a new controller and a new view&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Add a new PortalController to web application’s Controllers folder:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PortalController : Controller
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Add a Portal folder to web app’s Views folder. Then add a new Index.cshtml:&lt;/li&gt;&lt;/ol&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Hi there, @this.Context.User.Identity.Name!&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Part II: Open up website to public access&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, turn off WIF’s built-in redirection of unauthenticated sessions by modifying web.config file:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;microsoft.identityModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        ......
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;federatedAuthentication&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;wsFederation passiveRedirectEnabled="&lt;font style="background-color: #ffff00" color="#000000"&gt;&lt;strong&gt;&lt;u&gt;false&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;"
            ......&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Then, we’ll allow all users to access the site: &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;authorization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;font style="background-color: #ffff00"&gt;&lt;strong&gt;&lt;u&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;allow&lt;/span&gt; &lt;span class="attr"&gt;users&lt;/span&gt;&lt;span class="kwrd"&gt;="*"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;authorization&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    ......&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part III: Protect Portal page&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add an AuthenticateAndAuthorizeAttribute.cs to web application (we’ll handle authorization in later steps):&lt;pre class="csharpcode"&gt;[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;sealed&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; AuthenticateAndAuthorizeAttribute: FilterAttribute, IAuthorizationFilter
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnAuthorization(AuthorizationContext filterContext)
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            authenticateUser(filterContext);
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
            authorizeUser(filterContext);
    }
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; authenticateUser(AuthorizationContext context)
    {
        var fam = FederatedAuthentication.WSFederationAuthenticationModule;
        var signIn = &lt;span class="kwrd"&gt;new&lt;/span&gt; SignInRequestMessage(&lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(fam.Issuer), fam.Realm)
        {
            Context = getReturnUrl(context.RequestContext).ToString()
        };
        context.Result = &lt;span class="kwrd"&gt;new&lt;/span&gt; RedirectResult(signIn.WriteQueryString());
    }
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; authorizeUser(AuthorizationContext context)
    {
    }
    &lt;span class="kwrd"&gt;private&lt;/span&gt; Uri getReturnUrl(RequestContext context)
    {
        var request = context.HttpContext.Request;
        var reqUrl = request.Url;
        var wreply = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();

        wreply.Append(reqUrl.Scheme);
        wreply.Append(&lt;span class="str"&gt;"://"&lt;/span&gt;);
        wreply.Append(request.Headers[&lt;span class="str"&gt;"Host"&lt;/span&gt;] ?? reqUrl.Authority);
        wreply.Append(request.RawUrl);

        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!request.ApplicationPath.EndsWith(&lt;span class="str"&gt;"/"&lt;/span&gt;, StringComparison.OrdinalIgnoreCase))
        {
            wreply.Append(&lt;span class="str"&gt;"/"&lt;/span&gt;);
        }

        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(wreply.ToString());
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Mark PortalController with attribute [AuthenticateAndAuthorize]&lt;/li&gt;
&lt;li&gt;Update web.config file to update audienceUri and realm:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;microsoft.identityModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:81/&lt;font style="background-color: #ffff00"&gt;&lt;strong&gt;&lt;u&gt;Portal&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;federatedAuthentication&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsFederation&lt;/span&gt; &lt;span class="attr"&gt;passiveRedirectEnabled&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="attr"&gt;issuer&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:4011/MyWebApp_STS/"&lt;/span&gt; &lt;span class="attr"&gt;realm&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:81/&lt;font style="background-color: #ffff00"&gt;&lt;strong&gt;&lt;u&gt;Portal&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;"&lt;/span&gt; &lt;span class="attr"&gt;requireHttps&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;  &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
             ......&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part IV: Test run&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Compile and run. You can now browse to home view without authentication. Note user name is not filled yet.&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TcsaRk5cFsI/AAAAAAAAAYE/d9GG-BmGmt4/s1600-h/image%5B2%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TcsaR-Bk8xI/AAAAAAAAAYI/DRMSnBsqWOo/image_thumb.png?imgmax=800" width="244" height="136"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Now go to &lt;u&gt;&lt;font color="#4f81bd"&gt;http://127.0.0.1:81/Portal&lt;/font&gt;&lt;/u&gt;.&lt;/li&gt;
&lt;li&gt;Because you are not authenticated yet, you are redirected to STS logon page. Logon as normal and you’ll gain access to portal page this time.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;And here’s a breakdown of what happened:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User opens home page. Because the site is not protected, and WIF auto-redirection has been disabled, user is able to access the home page with no problem.&lt;/li&gt;
&lt;li&gt;Now user enters address to portal page. The request is routed to PortalController by MVC. Because the controller is decorated with an IAuthorizationFilter attribute, ASP.Net MVC invokes the OnAuthentication method on the interface before controller method is invoked.&lt;/li&gt;
&lt;li&gt;In OnAuthentication method, if user has not been authenticated, authenticateUser method is called, which generate a redirection result to FP.&lt;/li&gt;
&lt;li&gt;Browser is redirected to FAM (our FP), then in turn FP triggers logon process as in previous scenario.&lt;/li&gt;
&lt;li&gt;After FAM gets the token back, it again parse the claims and prepare an IClaimsPrincipal object for the application.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Next we’ll further extend the current web application to include an administrative page, which requires user to be in “Admin” role to access.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-5888983724600661672?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/G5jBuxxfmSt51iOjlVxOBjnYuT8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/G5jBuxxfmSt51iOjlVxOBjnYuT8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/G5jBuxxfmSt51iOjlVxOBjnYuT8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/G5jBuxxfmSt51iOjlVxOBjnYuT8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/pGm6g7wAVE8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/5888983724600661672/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_11.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/5888983724600661672?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/5888983724600661672?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/pGm6g7wAVE8/tutorialaspnet-mvc-3-claim-based_11.html" title="Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (2)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TcsaR-Bk8xI/AAAAAAAAAYI/DRMSnBsqWOo/s72-c/image_thumb.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based_11.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4ARH85fyp7ImA9WhZWEEQ.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-1276530784542169652</id><published>2011-05-11T00:27:00.001-07:00</published><updated>2011-05-11T00:29:05.127-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-11T00:29:05.127-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MVC/MVVM" /><category scheme="http://www.blogger.com/atom/ns#" term="Security" /><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><category scheme="http://www.blogger.com/atom/ns#" term="Digital Identity" /><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Computing" /><title>Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (1)</title><content type="html">&lt;p&gt;In this series of posts, I’ll present a step-by-step tutorial to build and deploy an ASP.Net MVC 3 application on Windows Azure platform. The application uses claimed-based architecture to allow users from different realms to logon to the site. In addition, the application also uses a local STS that manages users directly registered with the site. The overall architecture is as shown in the following diagram:&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tco6Oup7lWI/AAAAAAAAAXU/DhhWJ1p82vo/s1600-h/image%5B23%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tco6PBCTweI/AAAAAAAAAXY/bO1BT753p9A/image_thumb%5B13%5D.png?imgmax=800" width="340" height="292"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In this first post we’ll build the web application, a local STS, and a local Federation Provider:&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tco6PThs3pI/AAAAAAAAAXc/0bByzz04h8c/s1600-h/image%5B28%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tco6PlHLUqI/AAAAAAAAAXg/9srw4SgABeE/image_thumb%5B16%5D.png?imgmax=800" width="337" height="282"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I assume you’ve already got necessary software, including WIF SDK, ASP.Net MVC, Azure SDK etc. installed on your machine.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Part I: Set up basic project structure&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Create a new Windows Azure Project. Don’t add any roles to it. We’ll add ASP.Net MVC 3 web role later.  &lt;li&gt;Add a new ASP.Net MVC 3 empty project.  &lt;li&gt;Add the ASP.Net project as a Web Role of the Azure project.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Part II: Add a MVC controller and a view&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;In ASP.Net project, add a HomeController.cs to Controllers folder:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; HomeController: Controller
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Add a Home folder under Views folder, then add a simple MVC 3 View Page (Razor) – Index.cshtml to the Home folder:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Hi there!&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;li&gt;Compile and run. You should see “Hi there” message in browser. Note down the port number shown in browser address (it’s often 81).&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part III: Add local STS and establish federation between STS and the web application.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Right-click the web project, and select “Add STS reference…”. This will launch Federation Utility. Enter “http://localhost:81/” as “Application URI” (note the port number may differ on your machine):&lt;br clear="all"&gt;&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tco6QLTGDzI/AAAAAAAAAXk/0DObfRwiD6c/s1600-h/image%5B5%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/Tco6Qal1GRI/AAAAAAAAAXo/V20dmD9fQKY/image_thumb%5B3%5D.png?imgmax=800" width="409" height="310"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click “Next”. Ignore the https warning for now.&lt;/li&gt;
&lt;li&gt;In next screen, select “Create a new STS project in the current solution” option, and click “Next”:&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tco6Qu0RbGI/AAAAAAAAAXs/wdbDQP7QcJk/s1600-h/image%5B10%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tco6RBH3bMI/AAAAAAAAAXw/zI7v0FtyKV8/image_thumb%5B6%5D.png?imgmax=800" width="420" height="318"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click “Finish” to complete the wizard.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part IV: Update web configuration and consume the claim.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Edit ASP.Net project web.config file. Add validateRequest=”false” attribute to &amp;lt;system.web&amp;gt;&amp;lt;pages&amp;gt; element. And add &amp;lt;httpRuntime requestValidationMode=”2.0” /&amp;gt; to &amp;lt;system.web&amp;gt; element:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.web&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    ....
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;httpRuntime&lt;/span&gt; &lt;span class="attr"&gt;requestValidationMode&lt;/span&gt;&lt;span class="kwrd"&gt;="2.0"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;pages&lt;/span&gt; &lt;span class="attr"&gt;validateRequest&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    ....&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Add a reference to Microsoft.IdentityModel. Set “Copy Local” to “True” and “Specific Version” to “False”. We don’t need to do this now, but the reference is required to package and deploy the application correctly to Azure server.&lt;/li&gt;
&lt;li&gt;Modify index.cshtml to use claim:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Hi there, @this.Context.User.Identity.Name!&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;h1&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Part V: Test run&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Compile and run. You’ll be prompted to enter a user name – any user name will work, and you can leave the password empty:&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tco6RWiQoJI/AAAAAAAAAX0/bWCbYWiy8ug/s1600-h/image%5B14%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tco6RxxO6BI/AAAAAAAAAX4/UXPcdPzi2bc/image_thumb%5B8%5D.png?imgmax=800" width="305" height="223"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click “Submit”, and you’ll be redirected to your home page with user name claim filled:&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tco6SFzLiZI/AAAAAAAAAX8/TN4fLQvJmK4/s1600-h/image%5B19%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/Tco6Sa-cI6I/AAAAAAAAAYA/82SO1Yp5BS4/image_thumb%5B11%5D.png?imgmax=800" width="302" height="221"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wonderful! But what happened behind the scenes? Here is a breakdown of each step:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User opens web browser and navigate to the website (&lt;a href="http://localhost:81/"&gt;http://localhost:81/&lt;/a&gt;), which is Service Provider in the context of identity management. &lt;/li&gt;
&lt;li&gt;The web.config file loads two addition HTTP modules: WSFederationAuthenticationModule (FAM) and SessionAuthenticationModule (SAM). These two modules serve as our local Federation Provider. &lt;/li&gt;
&lt;li&gt;FAM detects unauthorized session by listening to AuthenticateRequest event and redirects user to configured identify provider. Examine the following segment of web.config. You can see the web application is configured to trust locally hosted STS (&lt;a href="http://localhost:4011/MyWebApp_STS/"&gt;http://localhost:4011/MyWebApp_STS/&lt;/a&gt;), and it requires a name claime and a role claim:&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;microsoft.identityModel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;service&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:81/"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;audienceUris&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;federatedAuthentication&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;wsFederation&lt;/span&gt; &lt;span class="attr"&gt;passiveRedirectEnabled&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt; &lt;span class="attr"&gt;issuer&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:4011/MyWebApp_STS/"&lt;/span&gt; &lt;span class="attr"&gt;realm&lt;/span&gt;&lt;span class="kwrd"&gt;="http://localhost:81/"&lt;/span&gt; &lt;span class="attr"&gt;requireHttps&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cookieHandler&lt;/span&gt; &lt;span class="attr"&gt;requireSsl&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;federatedAuthentication&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;applicationService&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;claimTypeRequired&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;claimType&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"&lt;/span&gt; &lt;span class="attr"&gt;optional&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;claimType&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"&lt;/span&gt; &lt;span class="attr"&gt;optional&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;claimTypeRequired&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            ......&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/li&gt;
&lt;li&gt;Now the user is redirected to STS logon page. The STS application is another ASP.Net application that is set to use form authentication to protect all the pages. So user is redirected to Login.aspx to logon.&lt;/li&gt;
&lt;li&gt;The Login page doesn’t do much other than set the authentication cookie for whatever user name entered by user. Then the browser is redirect to the default.aspx page.&lt;/li&gt;
&lt;li&gt;In default.aspx page, a RST (Request for Security) is sent to configured STS. &lt;/li&gt;
&lt;li&gt;After the STS returnes RSTR, FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse is invoked to write the security token to response stream.&lt;/li&gt;
&lt;li&gt;FAM get the security token, verify it, parses claims in the token and uses HttpContext.User.Identity property to present an IClaimsPrincipal object to the application.&lt;/li&gt;
&lt;li&gt;Now the MVC routing over, and because Home controller is the default controller and Index is the default action, our index view is eventually loaded.&lt;/li&gt;&lt;/ol&gt;






&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Next, before we introduce more components, we’ll turn the routing flow around to allow only selected controller/action to be protected. This is a common scenario as you usually don’t need to authenticate user on home page, but only to ask user to logon when she tries to access some protected features.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-1276530784542169652?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Di-fU4ZA3nOeh5_HUuWGRUNfuxU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Di-fU4ZA3nOeh5_HUuWGRUNfuxU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Di-fU4ZA3nOeh5_HUuWGRUNfuxU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Di-fU4ZA3nOeh5_HUuWGRUNfuxU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/acQp9PZYEzE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/1276530784542169652/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1276530784542169652?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1276530784542169652?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/acQp9PZYEzE/tutorialaspnet-mvc-3-claim-based.html" title="Tutorial–ASP.Net MVC 3, claim-based architecture and Windows Azure ACS (1)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_5uKkgbSGQ4Q/Tco6PBCTweI/AAAAAAAAAXY/bO1BT753p9A/s72-c/image_thumb%5B13%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/05/tutorialaspnet-mvc-3-claim-based.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8DRnY4fyp7ImA9WhZREUg.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8869779875801463536</id><published>2011-04-06T12:03:00.001-07:00</published><updated>2011-04-06T22:41:17.837-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-06T22:41:17.837-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>A word of caution for C# (and C++) developers using Python: to declare a class member variable</title><content type="html">&lt;p&gt;Consider the following Python code&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;hr /&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; A:
    __dic = {}
    def populate(self):
        self.__dic[&lt;span class="str"&gt;&amp;quot;A&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;
        self.__dic[&lt;span class="str"&gt;&amp;quot;B&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;b&amp;quot;&lt;/span&gt;
    def dump(self):
        print self.__dic

a1 = A()
a2 = A()
a1.populate()
a2.dump()&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;hr /&gt;What’s the result of the code? Well, it’s “{‘A’:’a’, ‘B’:’b’}” instead of empty dictionary as you may have expected. 

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;It turns out that when you use above syntax __dic is actually defined as a static member of the class so it’s actually shared by all instances! To properly define an instance variable, you need to declare the variable within __init__() method of the class and prefix your variable with “self.”, as shown below:&lt;/p&gt;

&lt;hr /&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; A:
    def populate(self):
        self.__dic = {}
        self.__dic[&lt;span class="str"&gt;&amp;quot;A&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;
        self.__dic[&lt;span class="str"&gt;&amp;quot;B&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;b&amp;quot;&lt;/span&gt;
    def dump(self):
        print self.__dic

a1 = A()
a2 = A()
a1.populate()
a2.dump()&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;hr /&gt;What’s confusing is that simple types such as strings and numbers seem to have a different behavior:

&lt;p&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; A:
    __val = &lt;span class="str"&gt;&amp;quot;ABC&amp;quot;&lt;/span&gt;
    __num = 12345
    def populate(self):
        self.__val = &lt;span class="str"&gt;&amp;quot;DEF&amp;quot;&lt;/span&gt;
        self.__num = 45678
    def dump(self):
        print self.__val
        print self.__num

a1 = A()
a2 = A()
a1.populate()
a1.dump()
a2.dump()&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;hr /&gt;In above code, both __val and __num act as instance variables&amp;#160; because dump of a1 shows “DEF” and “45678” while dump of a2 shows “ABC” and “12345”.

  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-8869779875801463536?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dK4T02Kmnd3E2UG6jKDh9QpEnAk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dK4T02Kmnd3E2UG6jKDh9QpEnAk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dK4T02Kmnd3E2UG6jKDh9QpEnAk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dK4T02Kmnd3E2UG6jKDh9QpEnAk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/0lpnjsId6wk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8869779875801463536/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/04/word-of-caution-for-c-and-c-developers.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8869779875801463536?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8869779875801463536?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/0lpnjsId6wk/word-of-caution-for-c-and-c-developers.html" title="A word of caution for C# (and C++) developers using Python: to declare a class member variable" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/04/word-of-caution-for-c-and-c-developers.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4MRnY_eip7ImA9WhZREUg.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-828307206639880898</id><published>2011-03-21T16:47:00.001-07:00</published><updated>2011-04-06T22:43:07.842-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-06T22:43:07.842-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".Net General" /><category scheme="http://www.blogger.com/atom/ns#" term="Algorithms" /><title>Slicing files dynamically: C# implementation</title><content type="html">&lt;p&gt;This implementation is based on &lt;a href="http://pdos.csail.mit.edu/papers/lbfs:sosp01/lbfs.pdf" target="_blank"&gt;this paper&lt;/a&gt; by Athicha Muthitacharoen et. al (A Low-bandwidth Network File System).&amp;#160; The main goal of the algorithm is to slice a file into different chunks so that changes to parts of files affect as less chunks as possible. For example, with a fixed chunk size, inserting one character at the beginning of a file will change all the chunks. With this algorithm, however, very often only the first chunk is detected as changed while remaining chunks are unchanged. A rolling Rabin signature of 48 bytes is used to detect boundaries of chunks. &lt;/p&gt;  &lt;hr /&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Program
&lt;/span&gt;{
&lt;span style="color: blue"&gt;    static void &lt;/span&gt;Main(&lt;span style="color: blue"&gt;string&lt;/span&gt;[] args)
    {
        Compare(&lt;span style="color: #a31515"&gt;&amp;quot;46M.txt&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;46M 2.txt&amp;quot;&lt;/span&gt;, 0x1FFF);
    }
    &lt;span style="color: blue"&gt;static void &lt;/span&gt;Compare(&lt;span style="color: blue"&gt;string &lt;/span&gt;file1, &lt;span style="color: blue"&gt;string &lt;/span&gt;file2, &lt;span style="color: blue"&gt;ulong &lt;/span&gt;boundary)
    {
        &lt;span style="color: blue"&gt;string &lt;/span&gt;A = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        &lt;span style="color: blue"&gt;string &lt;/span&gt;B = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        &lt;span style="color: blue"&gt;using &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;StreamReader &lt;/span&gt;r = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;StreamReader&lt;/span&gt;(file1))
        {
            A = r.ReadToEnd();
        }
        &lt;span style="color: blue"&gt;using &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;StreamReader &lt;/span&gt;r = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;StreamReader&lt;/span&gt;(file2))
        {
            B = r.ReadToEnd();
        }
        &lt;span style="color: #2b91af"&gt;Stopwatch &lt;/span&gt;watch = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Stopwatch&lt;/span&gt;();
        watch.Start();
        &lt;span style="color: blue"&gt;var &lt;/span&gt;listA = Slice(A, boundary);
        watch.Stop();
        &lt;span style="color: blue"&gt;long &lt;/span&gt;timeA = watch.ElapsedMilliseconds;
        watch.Reset();
        watch.Start();
        &lt;span style="color: blue"&gt;var &lt;/span&gt;listB = Slice(B, boundary);
        watch.Stop();
        &lt;span style="color: blue"&gt;long &lt;/span&gt;timeB = watch.ElapsedMilliseconds;
        &lt;span style="color: blue"&gt;int &lt;/span&gt;i = 0;
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Chunks in file '{0}'\t: {1}&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FileInfo&lt;/span&gt;(file1).Name, listA.Count));
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Chunks in file '{0}'\t: {1}&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FileInfo&lt;/span&gt;(file2).Name, listB.Count));
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;\n--------MATCHED CHUNKS--------\n&amp;quot;&lt;/span&gt;);
        &lt;span style="color: blue"&gt;int &lt;/span&gt;matchCount = 0;
        &lt;span style="color: blue"&gt;foreach &lt;/span&gt;(&lt;span style="color: blue"&gt;string &lt;/span&gt;s &lt;span style="color: blue"&gt;in &lt;/span&gt;listA)
        {
            &lt;span style="color: blue"&gt;if &lt;/span&gt;(listB.IndexOf(s) &amp;gt;= 0)
            {
                &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;{0:D4}&amp;lt;--&amp;gt;{1:D4}  (size:{2:D8} bytes)&amp;quot;&lt;/span&gt;, i, listB.IndexOf(s), s.Length);
                matchCount++;
            }
            &lt;span style="color: blue"&gt;else
                &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;{0:D4}    *     (size:{1:D8} bytes)&amp;quot;&lt;/span&gt;, i, s.Length);
            i++;
        }
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;\n------------------------------\n&amp;quot;&lt;/span&gt;);
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Matched blockes {0} (out of {1})&amp;quot;&lt;/span&gt;, matchCount, listA.Count);
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Time used to process file '{0}'\t:{1:f3} (sec)&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FileInfo&lt;/span&gt;(file1).Name, timeA / 1000.0);
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Time used to process file '{0}'\t:{1:f3} (sec)&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;FileInfo&lt;/span&gt;(file2).Name, timeB / 1000.0);
    }
    &lt;span style="color: blue"&gt;static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; Slice(&lt;span style="color: blue"&gt;string &lt;/span&gt;s, &lt;span style="color: blue"&gt;ulong &lt;/span&gt;boundary)
    {
        &lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; ret = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt;();
        &lt;span style="color: blue"&gt;ulong &lt;/span&gt;Q = 100007; //Use a much large prime number in your code!
        &lt;span style="color: blue"&gt;ulong &lt;/span&gt;D = 256;
        &lt;span style="color: blue"&gt;ulong &lt;/span&gt;pow = 1;
        &lt;span style="color: blue"&gt;int &lt;/span&gt;windowSize = 48;
        &lt;span style="color: blue"&gt;for &lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;k = 1; k &amp;lt; windowSize; k++)
            pow = (pow * D) % Q;
        &lt;span style="color: blue"&gt;ulong &lt;/span&gt;sig = 0;
        &lt;span style="color: blue"&gt;int &lt;/span&gt;lastIndex = 0;
        &lt;span style="color: blue"&gt;for &lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;i = 0; i &amp;lt; windowSize; i++)
            sig = (sig * D + (&lt;span style="color: blue"&gt;ulong&lt;/span&gt;)s[i]) % Q;
        &lt;span style="color: blue"&gt;for &lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;j = 1; j &amp;lt;= s.Length - windowSize; j++)
        {
            sig = (sig + Q - pow * (&lt;span style="color: blue"&gt;ulong&lt;/span&gt;)s[j - 1] % Q) % Q;
            sig = (sig * D + (&lt;span style="color: blue"&gt;ulong&lt;/span&gt;)s[j + windowSize -1 ]) % Q;
            &lt;span style="color: blue"&gt;if &lt;/span&gt;((sig &amp;amp; boundary) == 0)
            {
                &lt;span style="color: blue"&gt;if &lt;/span&gt;(j + 1 - lastIndex &amp;gt;= 2048)
                {
                    ret.Add(s.Substring(lastIndex, j + 1 - lastIndex));
                    lastIndex = j + 1;
                }
            }
            &lt;span style="color: blue"&gt;else if &lt;/span&gt;(j + 1 - lastIndex &amp;gt;= 65536)
            {
                ret.Add(s.Substring(lastIndex, j + 1 - lastIndex));
                lastIndex = j + 1;
            }
        }
        &lt;span style="color: blue"&gt;if &lt;/span&gt;(lastIndex &amp;lt; s.Length - 1)
            ret.Add(s.Substring(lastIndex));
        &lt;span style="color: blue"&gt;return &lt;/span&gt;ret;
    }
}&lt;/pre&gt;

&lt;hr /&gt;The core algorithm implementation is in Slice() method. To test the code, you’ll need a large text file (in my case I used a file named “46M.txt”, which has, well, 46M in size). Make a copy of the file and insert some new texts randomly at different locations and name the new file “46M 2.txt”.&amp;#160; The code generated the following outputs with my test data:

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TYfjlDgOdzI/AAAAAAAAAXE/IYxFa3T5moU/s1600-h/image%5B4%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TYfjmEalyJI/AAAAAAAAAXI/yMWFkuGqUn4/image_thumb%5B2%5D.png?imgmax=800" width="379" height="287" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see the code successfully matched 1962 out of 1968 chunks despite of the random changes made in the second file. Because the code reads all contents into memory, it doesn't handle very large files. However extending the code to directly work off a stream should be an easy task for interested readers. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-828307206639880898?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mJXzWXFvsR-0gGrqdIhq45SesTg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mJXzWXFvsR-0gGrqdIhq45SesTg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mJXzWXFvsR-0gGrqdIhq45SesTg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mJXzWXFvsR-0gGrqdIhq45SesTg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/ZHnnYpqC4to" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/828307206639880898/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/03/slicing-files-dynamically-c.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/828307206639880898?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/828307206639880898?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/ZHnnYpqC4to/slicing-files-dynamically-c.html" title="Slicing files dynamically: C# implementation" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TYfjmEalyJI/AAAAAAAAAXI/yMWFkuGqUn4/s72-c/image_thumb%5B2%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/03/slicing-files-dynamically-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUFR385fyp7ImA9WhZTF04.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-7042781021355991148</id><published>2011-03-18T17:39:00.001-07:00</published><updated>2011-03-21T11:30:16.127-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-21T11:30:16.127-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".Net General" /><category scheme="http://www.blogger.com/atom/ns#" term="Algorithms" /><title>Karp-Rabin string matching algorithm: C# implementation</title><content type="html">&lt;hr /&gt;  &lt;pre class="code"&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static void &lt;/span&gt;Main(&lt;span style="color: blue"&gt;string&lt;/span&gt;[] args)
{
&lt;span style="color: blue"&gt;    string &lt;/span&gt;A = &lt;span style="color: #a31515"&gt;&amp;quot;String that contains a pattern.&amp;quot;&lt;/span&gt;;
    &lt;span style="color: blue"&gt;string &lt;/span&gt;B = &lt;span style="color: #a31515"&gt;&amp;quot;pattern&amp;quot;&lt;/span&gt;;
    &lt;span style="color: blue"&gt;ulong &lt;/span&gt;siga = 0;
    &lt;span style="color: blue"&gt;ulong &lt;/span&gt;sigb = 0;
    &lt;span style="color: blue"&gt;ulong &lt;/span&gt;Q = 100007;
    &lt;span style="color: blue"&gt;ulong &lt;/span&gt;D = 256;
    &lt;span style="color: blue"&gt;for &lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;i = 0; i &amp;lt; B.Length; i++)
    {
        siga = (siga * D + (&lt;span style="color: blue"&gt;ulong&lt;/span&gt;)A[i]) % Q;
        sigb = (sigb * D + (&lt;span style="color: blue"&gt;ulong&lt;/span&gt;)B[i]) % Q;
    }
    &lt;span style="color: blue"&gt;if &lt;/span&gt;(siga == sigb)
    {
        &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;&amp;gt;&amp;gt;{0}&amp;lt;&amp;lt;{1}&amp;quot;&lt;/span&gt;, A.Substring(0, B.Length), A.Substring(B.Length)));
        &lt;span style="color: blue"&gt;return&lt;/span&gt;;
    }
    &lt;span style="color: blue"&gt;ulong &lt;/span&gt;pow = 1;
    &lt;span style="color: blue"&gt;for &lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;k = 1; k &amp;lt;= B.Length - 1; k++)
        pow = (pow * D) % Q;
            
&lt;span style="color: blue"&gt;&lt;font color="#333333"&gt;    &lt;/font&gt;for &lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;j = 1; j &amp;lt;= A.Length - B.Length; j++)
    {
        siga = (siga + Q - pow * (&lt;span style="color: blue"&gt;ulong&lt;/span&gt;)A[j - 1] %Q) % Q;
        siga = (siga * D + (&lt;span style="color: blue"&gt;ulong&lt;/span&gt;)A[j + B.Length - 1]) % Q;
        &lt;span style="color: blue"&gt;if &lt;/span&gt;(siga == sigb)
        {
            &lt;span style="color: blue"&gt;if &lt;/span&gt;(A.Substring(j, B.Length) == B)
            {
                &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;{0}&amp;gt;&amp;gt;{1}&amp;lt;&amp;lt;{2}&amp;quot;&lt;/span&gt;, A.Substring(0, j), 
                                                                 A.Substring(j, B.Length), 
                                                                 A.Substring(j + B.Length)));
&lt;span style="color: blue"&gt;&lt;font color="#333333"&gt;                &lt;/font&gt;return&lt;/span&gt;;
            }
        }
    }
    &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;Not found!&amp;quot;&lt;/span&gt;);
}&lt;/pre&gt;&lt;hr /&gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-7042781021355991148?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GMdvVhgYQp3JV9djhUM03n19_us/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GMdvVhgYQp3JV9djhUM03n19_us/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GMdvVhgYQp3JV9djhUM03n19_us/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GMdvVhgYQp3JV9djhUM03n19_us/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/zOm9J1X_dSw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/7042781021355991148/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/03/karp-rabin-string-matching-algorithm-c.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7042781021355991148?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7042781021355991148?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/zOm9J1X_dSw/karp-rabin-string-matching-algorithm-c.html" title="Karp-Rabin string matching algorithm: C# implementation" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/03/karp-rabin-string-matching-algorithm-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEENSH09eip7ImA9WhZREUw.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-7599719782332310627</id><published>2011-02-25T11:56:00.001-08:00</published><updated>2011-04-06T12:04:59.362-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-06T12:04:59.362-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight/WPF" /><title>Complete Tutorial: Host WordPress on Windows and host Silverlight on WordPress (Part 2 of 2)</title><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2011/02/complete-tutorial-part-i-of-iihost.html"&gt;Part 1&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Set up Silverlight Plug-in for WordPress&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download Silverlight WordPress plug-in from &lt;a href="http://wordpress.org/extend/plugins/silverlight-for-wordpress/"&gt;here&lt;/a&gt;.&lt;/li&gt;    &lt;li&gt;Extract the silverlight.php file in this package to your WordPress wp-content\plugins folder.&lt;/li&gt;    &lt;li&gt;Go to http://localhost:81/wordpress/wp-admin. Log in as administrator. Then click on “Plugins” link to the left.&lt;/li&gt;    &lt;li&gt;You should see “Sliverlight for WorPress” listed as one of the plugins. Click on “Activate” link below it:&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TWgJYAJWO2I/AAAAAAAAAW0/wQWbvOJPUVU/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TWgJYgjamnI/AAAAAAAAAW4/KoFA5hUO1Tc/image_thumb%5B1%5D.png?imgmax=800" width="364" height="45" /&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Create Hello World! Silverlight Application&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Create a new Silverlight Application, and let’s name it SilverWordPress. You don’t need to create a web host because we are hosting the application on WordPress (it doesn’t hurt to create one either).&lt;/li&gt;    &lt;li&gt;Add something simple such as a TextBlock showing “Hello World”:&lt;/li&gt;    &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt; &lt;span class="attr"&gt;FontSize&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;60&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;VerticalAlignment&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;HorizontalAlignment&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Center&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
  &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

  &lt;li&gt;Compile the solution. What we need is the SilverWordPress.xap file, which will be under your project’s Bin\Debug folder by default.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Hosting Silverlight Application on WordPress&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Copy the XAP file you’ve got to your WordPress root folder. This is the default location where the plug-in looks for the file. You can change this location in plug-in settings.&lt;/li&gt;

  &lt;li&gt;Edit any page in HTML view and add tag:&lt;/li&gt;

  &lt;pre class="csharpcode"&gt;[silverlight: SilverWordPress.xap]&lt;/pre&gt;
  &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

  &lt;li&gt;Save the page and load it up! &lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TWgJZS0PgpI/AAAAAAAAAW8/joCAWkM2CAQ/s1600-h/image%5B6%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TWgJZ7-lx8I/AAAAAAAAAXA/aH4ccs9RXIQ/image_thumb%5B2%5D.png?imgmax=800" width="225" height="244" /&gt;&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;The plug-in support additional parameters to adjust application size and initialization parameters – read its readme.txt for details.&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/8122199360699827669-7599719782332310627?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SByB_F7unwbG9KyeuTaR3PmXHJE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SByB_F7unwbG9KyeuTaR3PmXHJE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SByB_F7unwbG9KyeuTaR3PmXHJE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SByB_F7unwbG9KyeuTaR3PmXHJE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/plXEWGYTGas" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/7599719782332310627/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/02/complete-tutorial-host-wordpress-on.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7599719782332310627?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7599719782332310627?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/plXEWGYTGas/complete-tutorial-host-wordpress-on.html" title="Complete Tutorial: Host WordPress on Windows and host Silverlight on WordPress (Part 2 of 2)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TWgJYgjamnI/AAAAAAAAAW4/KoFA5hUO1Tc/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/02/complete-tutorial-host-wordpress-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEENSH09eyp7ImA9WhZREUw.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-3313465823937717941</id><published>2011-02-24T15:43:00.001-08:00</published><updated>2011-04-06T12:04:59.363-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-06T12:04:59.363-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight/WPF" /><title>Complete tutorial: Host WordPress on Windows and host Silverlight on WordPress (Part 1 of 2)</title><content type="html">&lt;p&gt;This is the first part of two-part tutorial that provides detailed steps of setting up WordPress on a Windows system, and how to enable Silverlight applications on WordPress pages. The first part focuses on how to set up WordPress on a Windows system from scratch.&amp;#160; You’ll be setting up Apache, MySQL, WordPress, and finally create your first locally-hosted page. In the next part I’ll guide you through the process of enabling Silverlight plugin and creating your first Silverlight application on WordPress.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Install Apache 2.2.17&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download Apache from &lt;a href="http://httpd.apache.org/download.cgi" target="_blank"&gt;official site.&lt;/a&gt; On the page, look for “Win32 Binary including OpenSSL…” link under “Apache HTTP Server (httpd) 2.2.17 section. Click on the link to download. Sometimes the mirror site might be down. Try some other mirror sits under “Mirror” section if that happens. &lt;/li&gt;    &lt;li&gt;Launch the MSI and follow the wizard to complete installation. You can accept all default settings. &lt;/li&gt;    &lt;li&gt;If you see error “could not bind to address 0.0.0.0:80”, most likely you have another service (maybe IIS) that is already listening port 80. You can assign a new port to Apache server:      &lt;ol&gt;       &lt;li&gt;Edit c:\Program Files\Apache Software Foundation\Apache2.2\conf\httpd.conf file. Change line “Listen 80” to some other port such as “Listen 81”. &lt;/li&gt;        &lt;li&gt;Restart Apache2.2 service from Control Panel or use command “httpd –k restart” under C:\Program Files\Apache Software Foundation\Apache2.2\bin folder. You should see an Apache icon with a green arrow on your task bar if everything is fine&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtB744iuI/AAAAAAAAAVo/u5tt39b_4Wc/s1600-h/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/TWbtCIsF7OI/AAAAAAAAAVs/3j8bqm2BscE/image_thumb1.png?imgmax=800" width="30" height="30" /&gt;&lt;/a&gt; &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;Launch your browser and go to &lt;a href="http://localhost:81/"&gt;http://localhost:81/&lt;/a&gt; (or the port you’ve chosen). It should say “It works!” &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Install PHP&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download PHP Windows installer &lt;a href="http://windows.php.net/download/" target="_blank"&gt;here.&lt;/a&gt; I chose to use version 5.3.5, VC9 x86 Thread Safe version. &lt;/li&gt;    &lt;li&gt;Follow the wizard to complete installation. When asked “Web Sever Setup” options, choose the first option – “Apache 2.2.x Module”.&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtCXK2IlI/AAAAAAAAAVw/uV6WQiW2HLU/s1600-h/image10.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TWbtCx9xkAI/AAAAAAAAAV0/sXG_4lMhSFM/image_thumb4.png?imgmax=800" width="293" height="235" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;In the next screen, browse to the folder that contains Apache httpd.conf file (default is at C:\Program Files\Apache Software Foundation\Apache2.2\conf).&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtDWZSP_I/AAAAAAAAAV4/7SXIlz6IpKA/s1600-h/image15.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TWbtD1QBweI/AAAAAAAAAV8/GO6lrjnCiPs/image_thumb7.png?imgmax=800" width="307" height="251" /&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Install MySQL&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download MySQL Community Server from &lt;a href="http://www.mysql.com/downloads/mysql/" target="_blank"&gt;here&lt;/a&gt;. I chose to use 5.5.9 Windows (x86, 32-bit) installer. You need to register a user id before you can download. &lt;/li&gt;    &lt;li&gt;Follow the installation wizard. At the end of wizard select to launch Server Instance Configuration Wizard. &lt;/li&gt;    &lt;li&gt;In Server Instance Configuration Wizard, select “Standard Configuration”. In next screen, check “Include Bin Directory in Windows PATH”. Then in the next screen specify a root password. Finish the wizard. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Download WordPress&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This &lt;a href="http://codex.wordpress.org/Installing_WordPress#Things_You_Need_to_Do_to_Install_WordPress" target="_blank"&gt;official instruction page&lt;/a&gt;&amp;#160; contains very detailed instructions of installing WordPress. Follow the instructions on the page to complete this part. Or, you can following the instructions below, which are tailored specifically for Windows users.&lt;/p&gt;  &lt;p&gt;Download WordPress from this &lt;a href="http://wordpress.org/download/" target="_blank"&gt;download page&lt;/a&gt;. It’s a zip file that you can unzip the wordpress folder to C:\Program Files\Apache Software Foundation\Apache2.2\htdocs. &lt;/p&gt;  &lt;p&gt;Now you can go to http://localhost:81/wordpress/wp-admin/install.php and to examine if PHP is working. If you see PHP source code is displayed, it means your PHP is not configured properly with Apache. In this case, you should examine httpd.conf file under C:\Program Files\Apache Software Foundation\Apache2.2\conf folder. Specifically, you should have these two lines at the end of the file: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;PHPIniDir &amp;quot;c:\Program Files\PHP&amp;quot;      &lt;br /&gt;LoadModule php5_module &amp;quot;c:\Program Files\PHP\php5apache2_2.dll&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Make sure the settings match with your environment. Update the file if necessary, and restart Apache server then try again. If you see a page with “Create a Configuration File”, your PHP is working! Don’t click on the button yet, we’ll do that in a bit.&amp;#160; While you are on this file, change the default page of Apache as well. This will allow your WordPress to load correctly as you navigate to the page URL. Find this line: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;DirectoryIndex index.html &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;And append index.php to the end of the line. The modified line looks like:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;DirectoryIndex index.html index.php&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Create WordPress database and user&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Launch a command-line prompt. If you’ve added bin directory in Windows Path (step 3 in “Install MySQL), you should be able to use MySQL commands right away. Otherwise you’ll need to go to the bin folder of your MySQL installation first. &lt;/li&gt;    &lt;li&gt;The following is a screenshot of commands you use, as well as MySQL’s responses, to create your WordPress database. The highlighted parts are the parts you may want to change: “WordPressDB” can be any database name of your choice; “wpuser” can be any user id of your choice; and “password” can be any password you choose for that user.&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtEae2oOI/AAAAAAAAAWA/vF601MBKbKE/s1600-h/image20.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/TWbtFAsdnEI/AAAAAAAAAWE/ZOeyZfMAFvw/image_thumb10.png?imgmax=800" width="604" height="282" /&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Configure WordPress&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Go to http://localhost:81/wordpress/wp-admin/install.php. Note the exact port and folder may differ depends your choices in above steps. If everything is fine, you’ll see this page:&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TWbtFenDjiI/AAAAAAAAAWI/Gq-hzm6xbPg/s1600-h/image26.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TWbtF5wDpnI/AAAAAAAAAWM/OuKW4HrP3V4/image_thumb14.png?imgmax=800" width="601" height="117" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Click on “Create a Configuration File” button. On next page, click “Let’s go!” button. &lt;/li&gt;    &lt;li&gt;Enter MySQL database info you created above, and click on “Submit” button.&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TWbtGWV3KhI/AAAAAAAAAWQ/nOBZRv0RKyk/s1600-h/image30.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TWbtGiKkMAI/AAAAAAAAAWU/LZ0OdF3wQ2Q/image_thumb16.png?imgmax=800" width="457" height="297" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;If everything is entered correctly, you should see the following page. Click “Run the install” button to continue:&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtHLh_X8I/AAAAAAAAAWY/vnrO_G7MSrw/s1600-h/image34.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtHbcS8AI/AAAAAAAAAWc/EH6uNUH58_o/image_thumb18.png?imgmax=800" width="461" height="122" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Pick site title, administrator user name, password, and e-Mail. Then click “Install WordPress” button to install:&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/TWbtIG5BmYI/AAAAAAAAAWg/4pW9SgVec7g/s1600-h/image39.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TWbtImN-LUI/AAAAAAAAAWk/4BrCDbs_-6U/image_thumb21.png?imgmax=800" width="390" height="422" /&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Success! &lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtI4AowoI/AAAAAAAAAWo/6NPJuyS2aKo/s1600-h/image44.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TWbtJSJ-u2I/AAAAAAAAAWs/FcXKmk1f64A/image_thumb24.png?imgmax=800" width="380" height="232" /&gt;&lt;/a&gt; &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/8122199360699827669-3313465823937717941?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xygzY6jl466iycMEVMjzfRwetbg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xygzY6jl466iycMEVMjzfRwetbg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xygzY6jl466iycMEVMjzfRwetbg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xygzY6jl466iycMEVMjzfRwetbg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/gJmWpfkA0_Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/3313465823937717941/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/02/complete-tutorial-part-i-of-iihost.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3313465823937717941?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3313465823937717941?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/gJmWpfkA0_Q/complete-tutorial-part-i-of-iihost.html" title="Complete tutorial: Host WordPress on Windows and host Silverlight on WordPress (Part 1 of 2)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_5uKkgbSGQ4Q/TWbtCIsF7OI/AAAAAAAAAVs/3j8bqm2BscE/s72-c/image_thumb1.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/02/complete-tutorial-part-i-of-iihost.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IHQnkyfyp7ImA9Wx9UF0Q.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-4949171394537682926</id><published>2011-02-15T11:51:00.001-08:00</published><updated>2011-02-15T11:52:13.797-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-15T11:52:13.797-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".Net General" /><title>Consuming anonymous types across function boundaries</title><content type="html">&lt;p&gt;As I was reading ASP.Net MVC 3 introduction, I noticed how HTML helper constructs an action link and provides parameters to the link. For example: &lt;/p&gt;  &lt;p&gt;&lt;code&gt;@Html.ActionLink(“Edit”, &amp;quot;Edit&amp;quot;, new { id =123, name = &amp;quot;some name&amp;quot; })     &lt;br /&gt;&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;Note the last parameter is an anonymous type. This makes sense because HTML helper can’t anticipate the exact information layouts to be passed. The anonymous type gives us flexibility of passing arbitrary key-value pairs using a &lt;u&gt;simply syntax&lt;/u&gt; (after all a full-scale Dictionary could have been chosen but that doesn’t resonate with Razor’s simply-flow philosophy).&amp;#160; However, as the anonymous type has method boundary, the parameter will be passed as an object to the consuming method. How to use the values contained by the anonymous type across function boundaries? There are several options, as presented below. Note that you don’t need to do any of the following when using ASP.Net MVC 3. The following is a generic discussion of different possible ways of consuming anonymous types across function boundaries.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Use reflection. The anonymous type is a real type, you can use regular reflection methods to retrieve its properties:     &lt;hr /&gt;      &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static void &lt;/span&gt;Main(&lt;span style="color: blue"&gt;string&lt;/span&gt;[] args)
{
  Test(&lt;span style="color: blue"&gt;new &lt;/span&gt;{ id = 123, name = &lt;span style="color: #a31515"&gt;&amp;quot;ABC&amp;quot; &lt;/span&gt;});
}
&lt;span style="color: blue"&gt;static void &lt;/span&gt;Test(&lt;span style="color: blue"&gt;object &lt;/span&gt;val)
{
&lt;span style="color: #2b91af"&gt;&lt;font color="#333333"&gt;  &lt;/font&gt;Type &lt;/span&gt;type = val.GetType();
&lt;span style="color: blue"&gt;&lt;font color="#333333"&gt;  &lt;/font&gt;foreach &lt;/span&gt;(&lt;span style="color: blue"&gt;var &lt;/span&gt;prop &lt;span style="color: blue"&gt;in &lt;/span&gt;type.GetProperties())
&lt;span style="color: #2b91af"&gt;&lt;font color="#333333"&gt;    &lt;/font&gt;Console&lt;/span&gt;.WriteLine(prop.Name + &lt;span style="color: #a31515"&gt;&amp;quot;=&amp;quot; &lt;/span&gt;+ prop.GetValue(val,&lt;span style="color: blue"&gt;null&lt;/span&gt;));
}&lt;hr /&gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Use a cast. This method uses the fact that two separately declared anonymous types are considered compatible types if they had same property layout:
    &lt;hr /&gt;

    &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static void &lt;/span&gt;Test(&lt;span style="color: blue"&gt;object &lt;/span&gt;val)
{
&lt;span style="color: blue"&gt;  var &lt;/span&gt;dict = Cast(val, &lt;span style="color: blue"&gt;new &lt;/span&gt;{ id = 0, name = &lt;span style="color: #a31515"&gt;&amp;quot;&amp;quot; &lt;/span&gt;});
  &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;id=&amp;quot; &lt;/span&gt;+ dict.id);
  &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;name=&amp;quot; &lt;/span&gt;+ dict.name);
}
&lt;span style="color: blue"&gt;static &lt;/span&gt;T Cast&amp;lt;T&amp;gt;(&lt;span style="color: blue"&gt;object &lt;/span&gt;o, T type)
{
&lt;span style="color: blue"&gt;&lt;font color="#333333"&gt;  &lt;/font&gt;return &lt;/span&gt;(T)o;
}
&lt;hr /&gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Use dynamic type. Dynamic type gives us the simplest syntax to consume a anonymous type passed in as an object, as shown in the following modified Test() method (with the price of losing compile-time type check):
    &lt;hr /&gt;

    &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static void &lt;/span&gt;Test(&lt;span style="color: blue"&gt;object &lt;/span&gt;val)
{
&lt;span style="color: blue"&gt;&lt;font color="#333333"&gt;  &lt;/font&gt;dynamic &lt;/span&gt;dict = val;
&lt;span style="color: #2b91af"&gt;&lt;font color="#333333"&gt;  &lt;/font&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;id=&amp;quot; &lt;/span&gt;+ dict.id);
&lt;span style="color: #2b91af"&gt;&lt;font color="#333333"&gt;  &lt;/font&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;&amp;quot;name=&amp;quot; &lt;/span&gt;+ dict.name);
}
&lt;hr /&gt;&lt;/pre&gt;
  &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/8122199360699827669-4949171394537682926?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CIVB0ZbfYJbKT7b_A_BjPULr1cg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CIVB0ZbfYJbKT7b_A_BjPULr1cg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CIVB0ZbfYJbKT7b_A_BjPULr1cg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CIVB0ZbfYJbKT7b_A_BjPULr1cg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/i0ZCPjSEpAU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/4949171394537682926/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/02/consuming-anonymous-types-across.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4949171394537682926?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4949171394537682926?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/i0ZCPjSEpAU/consuming-anonymous-types-across.html" title="Consuming anonymous types across function boundaries" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/02/consuming-anonymous-types-across.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEGQns7fyp7ImA9Wx9UFEg.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-4098306106499345734</id><published>2011-02-11T11:46:00.001-08:00</published><updated>2011-02-11T11:47:03.507-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-11T11:47:03.507-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Modifying global variables in a Python script</title><content type="html">&lt;p&gt;Reading the following simple Python script, can you tell if the final output is ‘abc’ or ‘def’?   &lt;hr /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;a = &amp;quot;abc&amp;quot;     &lt;br /&gt;def f():      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; print(a)      &lt;br /&gt;def main():      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; a = &amp;quot;def&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; f()      &lt;br /&gt;if __name__ == &amp;quot;__main__&amp;quot;:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; main()&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;   &lt;hr /&gt;&lt;/p&gt;  &lt;p&gt;The result maybe surprising – it’s ‘abc’. Although the main() method explicitly set the global variable ‘a’ to value ‘def’ before calling the f() method, the value assignment took no effect. &lt;/p&gt;  &lt;p&gt;Why? This is because the variable namespace. When you say a = ‘def’ in main() method, Python thinks you’ve declared a new local variable with name ‘a’. So ‘def’ is assigned to this new local variable instead of the global variable. To change the global variable ‘a’, you’ll need to add:&lt;/p&gt;  &lt;p&gt;   &lt;hr /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;global a&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;   &lt;hr /&gt;&lt;/p&gt;  &lt;p&gt;before the assignment. The statement informs Python that the variable ‘a’ referred in the method is indeed a global variable, not a local variable.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-4098306106499345734?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Bi7wICbmXdk-9-dfGNprGF3BoSY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Bi7wICbmXdk-9-dfGNprGF3BoSY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Bi7wICbmXdk-9-dfGNprGF3BoSY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Bi7wICbmXdk-9-dfGNprGF3BoSY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/wa3NpFofAAI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/4098306106499345734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/02/modifying-global-variables-in-python.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4098306106499345734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/4098306106499345734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/wa3NpFofAAI/modifying-global-variables-in-python.html" title="Modifying global variables in a Python script" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/02/modifying-global-variables-in-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIERHY-cCp7ImA9Wx9UEU4.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-7448127561850169738</id><published>2011-02-07T18:44:00.001-08:00</published><updated>2011-02-07T18:51:45.858-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-07T18:51:45.858-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Logging Python method calls using method decorators</title><content type="html">&lt;p&gt;Python decorator is not necessarily the easiest concept to understand. This post provides a complete sample of using Python method decorator to control how method calls are logged. I hope you can use this sample as a reference while trying to understand the decorator concept. In the code I defined a class “C” that has three methods, “Func1”, “Func2”, and “Func3”. Each function is decorated by one of the two decorators, “tracing” and “logging”, defined in the code. “tracing” decorator logs method calls before and after a method is invoked; and “logging” decorator controls logging behaviors by returning different callables based on the Level parameter.&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;     &lt;hr /&gt;def tracing(F):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def wrapper(*args):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print(&amp;quot;\nBefore calling '{0}'&amp;quot;.format(F.__name__))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; F(*args)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print(&amp;quot;After calling '{0}'\n&amp;quot;.format(F.__name__))       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return wrapper&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;def logging(Level):      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def actualDecorator(F):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if Level ==&amp;quot;Verbose&amp;quot;:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return tracing(F)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return F       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return actualDecorator&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Log_Level = &amp;quot;Verbose&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;class C:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @logging(Log_Level)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def Func1(self):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print(&amp;quot;Calling Func1&amp;quot;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @logging(&amp;quot;None&amp;quot;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def Func2(self):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print(&amp;quot;Calling Func2&amp;quot;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @tracing       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; def Func3(self):       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; print(&amp;quot;Calling Func3&amp;quot;)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;c = C()      &lt;br /&gt;c.Func1()&amp;#160;&amp;#160; #Func1 is logged when global Log_Level is set to “Verbose”       &lt;br /&gt;c.Func2()&amp;#160;&amp;#160; #Func2 overrides global flag with “None”       &lt;br /&gt;c.Func3()&amp;#160;&amp;#160; #Func3 is logged always as it skips log level checks      &lt;hr /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Above code outputs this when executed:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;     &lt;hr /&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Before calling 'Func1'      &lt;br /&gt;Calling Func1       &lt;br /&gt;After calling 'Func1'&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Calling Func2&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Before calling 'Func3'      &lt;br /&gt;Calling Func3       &lt;br /&gt;After calling 'Func3'&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;gt;&amp;gt;&amp;gt;      &lt;hr /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Two key points to take away:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;In Python, a decorator is a callable that returns a callable. &lt;/li&gt;    &lt;li&gt;A parameterized decorator is a callable that returns a decorator (so it’s a callable that returns a callable that returns a callable). &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/8122199360699827669-7448127561850169738?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LoWuE1k2veOyLdORk_gRg3CAVm4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LoWuE1k2veOyLdORk_gRg3CAVm4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LoWuE1k2veOyLdORk_gRg3CAVm4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LoWuE1k2veOyLdORk_gRg3CAVm4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/iYhcsisTJkc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/7448127561850169738/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/02/logging-python-method-calls-using.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7448127561850169738?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7448127561850169738?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/iYhcsisTJkc/logging-python-method-calls-using.html" title="Logging Python method calls using method decorators" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/02/logging-python-method-calls-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMCR3g4fSp7ImA9Wx9UEU4.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-3229624433804384410</id><published>2011-02-01T11:00:00.001-08:00</published><updated>2011-02-07T18:51:06.635-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-07T18:51:06.635-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Setting up Python on IIS 7</title><content type="html">&lt;p&gt;(This instruction is based the post &lt;a href="http://forums.iis.net/t/1122937.aspx" target="_blank"&gt;here&lt;/a&gt;, with added details).&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Make sure Python is installed properly (I’m using Python 2.7.1 in this example). &lt;/li&gt;    &lt;li&gt;If you don’t have IIS CGI module installed, you can go to Control Panel-&amp;gt;Programs and Features, and then click on “Turn Windows features on or off”. Then, in “Windows Features” window, make sure Internet Information Service-&amp;gt;World Wide Web Services-&amp;gt;Application Development Features-&amp;gt;CGI is checked (IMG 1). Click “OK” to apply changes. &lt;/li&gt;    &lt;li&gt;Launch IIS Manager (Control Panel-&amp;gt;Administrative Tools-&amp;gt;Internet Information Services (IIS) Manager). &lt;/li&gt;    &lt;li&gt;Right click on “Default Web Site” and select “Add Application…”. &lt;/li&gt;    &lt;li&gt;Enter an application Alias, and specify a local path where you’ll put your Python scripts (IMG 2). Click “OK”. &lt;/li&gt;    &lt;li&gt;With the new application node selected, double-click on “Handler Mappings” in the middle panel. Then, click “Add Script Map…” link in “Actions” box to the right. &lt;/li&gt;    &lt;li&gt;In “Add Script Map” window, enter “*.py” as Request Path, and your python.exe as Executable. Note two parameters (-u %s) are added to the command line. Give the mapping a name (such as “Python”) and then click “OK”. &lt;/li&gt;    &lt;li&gt;Create a new Python script in your script folder in step 5. Note that you’ll need to return complete HTTP header for your script to work:      &lt;hr /&gt;&lt;font size="3" face="Courier New"&gt;&lt;font style="background-color: #ffff00"&gt;print &amp;quot;Status: 200 OK&amp;quot;          &lt;br /&gt;print &amp;quot;Content-Type: text/plain;charset=utf-8&amp;quot;           &lt;br /&gt;print           &lt;br /&gt;&lt;/font&gt;print &amp;quot;Hello Python!&amp;quot;&lt;/font&gt;       &lt;hr /&gt;&lt;/li&gt;    &lt;li&gt;Launch browse and navigate to the script (http://localhost/PythonApplication/HelloPython.py) to see the result. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/TVCFh-XksUI/AAAAAAAAAVQ/hcgxO97RkHI/s1600-h/image%5B4%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TVCFiRutDeI/AAAAAAAAAVU/nism4FDbXIc/image_thumb%5B1%5D.png?imgmax=800" width="327" height="376" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;IMG 1: IIS CGI Module&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_5uKkgbSGQ4Q/TVCFi2IU-LI/AAAAAAAAAVY/EaTeknPDdy4/s1600-h/image%5B8%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_5uKkgbSGQ4Q/TVCFjanWI5I/AAAAAAAAAVc/c5vBQ2wVOU8/image_thumb%5B3%5D.png?imgmax=800" width="373" height="265" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;IMG 2: Application settings.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TVCFjyntNkI/AAAAAAAAAVg/FsoGfpgnpTo/s1600-h/image%5B12%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TVCFkcIlIGI/AAAAAAAAAVk/_0Ps_mATces/image_thumb%5B5%5D.png?imgmax=800" width="359" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;IMG 3: Python mapping.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-3229624433804384410?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nOB4_1_dkUKXeAnaKWJ0B6qkESA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nOB4_1_dkUKXeAnaKWJ0B6qkESA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nOB4_1_dkUKXeAnaKWJ0B6qkESA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nOB4_1_dkUKXeAnaKWJ0B6qkESA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/b2sM6FZeZIQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/3229624433804384410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2011/02/setting-up-python-on-iis-7_01.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3229624433804384410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/3229624433804384410?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/b2sM6FZeZIQ/setting-up-python-on-iis-7_01.html" title="Setting up Python on IIS 7" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TVCFiRutDeI/AAAAAAAAAVU/nism4FDbXIc/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2011/02/setting-up-python-on-iis-7_01.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQFRn8zfip7ImA9Wx9RFEk.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-8813404177868716810</id><published>2010-12-15T13:24:00.001-08:00</published><updated>2010-12-15T13:25:17.186-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-15T13:25:17.186-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="WCF" /><title>Quick Tip: Enum types in WCF DataContract - Enum value '0' is invalid for type …</title><content type="html">&lt;p&gt;I’ve seen people proposing different solutions, which include:&lt;/p&gt;  &lt;p&gt;1) Add value ‘0’ as one of the values of your enum type.&lt;/p&gt;  &lt;p&gt;2) Set the enum value in the constructor of the containing type.&lt;/p&gt;  &lt;p&gt;Neither is desirable in all cases and sometimes they don’t work anyway. What I’ve found working is to add IsRequired attribute on the enum types in your data contracts:&lt;/p&gt;  &lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;DataContract&lt;/span&gt;]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SomeItem 
&lt;/span&gt;{
   [&lt;span style="color: #2b91af"&gt;DataMember&lt;/span&gt;(IsRequired=&lt;span style="color: blue"&gt;true&lt;/span&gt;)]
   &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ItemType &lt;/span&gt;ItemType { &lt;span style="color: blue"&gt;get&lt;/span&gt;; &lt;span style="color: blue"&gt;set&lt;/span&gt;; }
   …&lt;/pre&gt;

&lt;pre class="code"&gt;}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-8813404177868716810?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Dp3ElcvxAzbdQwKZFvnw82Pi_pI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Dp3ElcvxAzbdQwKZFvnw82Pi_pI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Dp3ElcvxAzbdQwKZFvnw82Pi_pI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Dp3ElcvxAzbdQwKZFvnw82Pi_pI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/wtTsPLOjNmk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/8813404177868716810/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2010/12/quick-tip-enum-types-in-wcf.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8813404177868716810?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/8813404177868716810?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/wtTsPLOjNmk/quick-tip-enum-types-in-wcf.html" title="Quick Tip: Enum types in WCF DataContract - Enum value &amp;#39;0&amp;#39; is invalid for type …" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2010/12/quick-tip-enum-types-in-wcf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cAQXg4fCp7ImA9Wx9REE8.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-7376530670280885741</id><published>2010-12-10T16:56:00.001-08:00</published><updated>2010-12-10T16:57:20.634-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-10T16:57:20.634-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".Net General" /><category scheme="http://www.blogger.com/atom/ns#" term="User Interface" /><title>Quick Tip: Show taskbar icon context menu at correct position</title><content type="html">&lt;p&gt;There isn’t a straight-forward public method on either NotifyIcon or ContextMenuStrip that allows you to show taskbar icon context menu at correct position, however there is a “ShowContextMenu” private method on NotifyIcon that brings up its context menu at correct position:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;MethodInfo &lt;/span&gt;methodInfo = &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;NotifyIcon&lt;/span&gt;).GetMethod(&lt;span style="color: #a31515"&gt;"ShowContextMenu"&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.Instance | &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.NonPublic);
methodInfo.Invoke(notifyIcon, &lt;span style="color: blue"&gt;null&lt;/span&gt;); &lt;/pre&gt;&lt;pre class="code"&gt;&amp;nbsp;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-7376530670280885741?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SgHi15DOwL7AxN5AqlKzAPgfY5w/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SgHi15DOwL7AxN5AqlKzAPgfY5w/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SgHi15DOwL7AxN5AqlKzAPgfY5w/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SgHi15DOwL7AxN5AqlKzAPgfY5w/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/oOgNL2fQam4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/7376530670280885741/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2010/12/quick-tip-show-taskbar-icon-context.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7376530670280885741?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/7376530670280885741?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/oOgNL2fQam4/quick-tip-show-taskbar-icon-context.html" title="Quick Tip: Show taskbar icon context menu at correct position" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2010/12/quick-tip-show-taskbar-icon-context.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcCRXg6cCp7ImA9Wx9TEEw.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-1308477567095962318</id><published>2010-11-17T00:43:00.001-08:00</published><updated>2010-11-17T10:21:04.618-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-17T10:21:04.618-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Software Matrices" /><category scheme="http://www.blogger.com/atom/ns#" term="Algorithms" /><title>A simple model to measure customer perceived software quality by number of support calls</title><content type="html">&lt;p&gt;This post proposes a simple probability-based model to estimate customer perceived software quality by measuring number of support calls. This model is suitable for measuring existing deployment base with active users. It’s not designed to predicate number of support calls, nor does it work well during active roll-out phase of a software product. Instead, the model uses non-intrusive measurements that are often collected by software vendors for various purposes to calculate how well the product is received by customers.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Perceived software quality&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Many factors contribute to customer perceived software quality, including UI attractiveness, number of crashes, or level of complexity, etc. In this post we’ll use a simple measurement – &lt;strong&gt;the probability of an end user to notice a software defect&lt;/strong&gt;. This is a very straightforward measurement because users are mostly discouraged by software defects. The more defects the users encounter, the lower customers’ satisfaction with the product will be. And, because bug-fixing usually takes up a major portion of engineering efforts, the measurement can also be correlated to engineering efforts required to improve software quality. At last, the measurement covers a variety of situations as it doesn’t assume the nature of the defects. The defects can be UI design problem, work flow problem, software bugs, or other defects such as documentation problems. This kind of abstraction matches well with the inclusive nature of customer perceptions. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Model of support calls&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Assume during a certain period of time a software is shipped to X number of customers and the company receives Y number of support calls as results of software defects. The relation between X and Y can be described by this model (Y equals X multiple by a series of probabilities):&lt;/p&gt;&lt;p align="center"&gt;&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TOOVs-lT7QI/AAAAAAAAAUM/fle1zEbpFnw/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TOOVtQaYDaI/AAAAAAAAAUQ/WZevN_6yn3M/image_thumb%5B1%5D.png?imgmax=800" width="116" height="67" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Where the list of probabilities is the set:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;P1=Probability of installation (installation ratio)&lt;/li&gt;
&lt;li&gt;P2=Probability of active usage&lt;/li&gt;
&lt;li&gt;P3=Probability of the user to notice a software defect&lt;/li&gt;
&lt;li&gt;P4=Probability of the user to report the defect&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Obviously, a company usually has good ideas about value X and Y. If we can reasonably infer value P1, P2, and P4, then our measurement (P3) can be simply calculated by:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TOOVttO_NbI/AAAAAAAAAUU/hgbJI3HjTSQ/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TOOVuO_S1zI/AAAAAAAAAUY/8EiZ_mqSbQE/image_thumb%5B2%5D.png?imgmax=800" width="186" height="32" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Now the question is how to figure out values of P1, P2, and P4.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;P1&lt;/strong&gt;: For a software that is sold separately, this value is usually 1 or very close to 1, except for the exceptional event when a user purchased your software and just put on the shelf. &lt;/p&gt;&lt;p&gt;For a software is purchased by download, you can calculate the ratio by dividing number of installations (if you trace the value by, for instance, number of active licenses) by number of total downloads.&lt;/p&gt;&lt;p&gt;For a software that is bundled with hardware or other software products, this number is a little hard to come by. You’ll need to contact your partners to collect number of sold units in total, and then use it to divide number of installations.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;P2&lt;/strong&gt;: Commonly this value is close to 1, and the reason is simple: if a user installs a software, she’s usually intended to use it. However, the assumption doesn’t always hold. Sometimes a user may have been motivated to install the software (for instance, lured by promotion or forced by company policy) but doesn’t actually need to use it. You should adjust the value to match with the specific situation of your software. On the other hand, if your software is equipped with user activity tracking capabilities (such as by a central license server or by phone-home reports), you can collect the probability from those data as well.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;P4&lt;/strong&gt;: 0.15, which means once a user sees an error, there’s 15 percent of chance for her to report the error back to the vender. This is a number provided by a product manager based on his experiences and previous studies. However, the number may be affected by other facts such as ease of reporting an error, if the product is mission-critical, etc. The value here is based on experiences on a small size end-user product only. If you, the reader, can contribute some numbers from existing study results I’d be much obliged.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;A sample scenario&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;A company sells software that is bundled with a hardware device. The hardware vender sold 1 million copies of units in the course of 6 months, and the company has traced that 30% of users had installed the software, and most of the users (90%) who installed the software are active users. The company receives 30 support calls per day on average during the same period. From our model we can calculate that customer perceived quality is:&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TOOVuYPU7aI/AAAAAAAAAUc/WARhP3NckyM/image_thumb%5B4%5D.png?imgmax=800" width="282" height="62" /&gt;&lt;/p&gt;&lt;p&gt;Which means roughly 1 out of 10 users will observe software defects while using the product. 10% is not necessarily too bad, but a value above 30% clearly indicates serious quality issues in the product.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-1308477567095962318?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/K34qMY79JtP6BCyyFoVA0rU741E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K34qMY79JtP6BCyyFoVA0rU741E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/K34qMY79JtP6BCyyFoVA0rU741E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K34qMY79JtP6BCyyFoVA0rU741E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/k304KuMGr4k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/1308477567095962318/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2010/11/simple-model-to-measure-customer.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1308477567095962318?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1308477567095962318?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/k304KuMGr4k/simple-model-to-measure-customer.html" title="A simple model to measure customer perceived software quality by number of support calls" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TOOVtQaYDaI/AAAAAAAAAUQ/WZevN_6yn3M/s72-c/image_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2010/11/simple-model-to-measure-customer.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAHQHo_cCp7ImA9Wx5aGEs.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-1414560386987365497</id><published>2010-11-15T15:36:00.001-08:00</published><updated>2010-11-15T15:45:31.448-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-15T15:45:31.448-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".Net General" /><category scheme="http://www.blogger.com/atom/ns#" term="User Interface" /><title>Create a complex custom list view that supports data binding using Windows Form (C#)</title><content type="html">&lt;p&gt;Out-of-box Windows Form provides&amp;#160; only basic list box views that can display a list of texts or a list of check boxes. If you want to display richer content per list item you’ll need to use custom user controls or third-party controls. I’ve seen several different implementations of such list boxes, and here’s my suggested implementation. This list box supports:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Complete data binding. You can bind a list directly to the control and the control reflects list changes automatically. This behavior fits well in MVVM pattern.&lt;/li&gt;
&lt;li&gt;Minimum custom code. There’s no custom paint or any convoluted control manipulation, the code is straight and simple.&lt;/li&gt;
&lt;li&gt;No third-party dependency. Everything is plain .Net framework.&lt;/li&gt;
&lt;/ul&gt;&lt;h5&gt;The Entity to be bound to the UI.&lt;/h5&gt;&lt;p&gt;Our list box can be bound to a list of objects. Here I’ll use a very simple class, which contains only one “Name” field, as an example. As you can see, the class (named “A”) needs to implement INotifyPropertyChanged interface. The interface defines one PropertyChanged event that needs to be triggered whenever interested properties on the class instance are changed:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;    public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;A&lt;/span&gt;: &lt;span style="color: #2b91af"&gt;INotifyPropertyChanged
    &lt;/span&gt;{
        &lt;span style="color: blue"&gt;private static int &lt;/span&gt;mCount = 0;
        &lt;span style="color: blue"&gt;private string &lt;/span&gt;mName;
        &lt;span style="color: blue"&gt;public string &lt;/span&gt;Name
        {
            &lt;span style="color: blue"&gt;get&lt;/span&gt;{ &lt;span style="color: blue"&gt;return &lt;/span&gt;mName; }
            &lt;span style="color: blue"&gt;set 
            &lt;/span&gt;{
                mName = &lt;span style="color: blue"&gt;value&lt;/span&gt;;
                &lt;span style="color: blue"&gt;if &lt;/span&gt;(PropertyChanged != &lt;span style="color: blue"&gt;null&lt;/span&gt;)
                    PropertyChanged(&lt;span style="color: blue"&gt;this&lt;/span&gt;, &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;PropertyChangedEventArgs&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;));
            }
        }
        &lt;span style="color: blue"&gt;public &lt;/span&gt;A()
        {
            Name = mCount.ToString();
            mCount++;
        }

        &lt;span style="color: blue"&gt;#region &lt;/span&gt;INotifyPropertyChanged Members
        &lt;span style="color: blue"&gt;public event &lt;/span&gt;&lt;span style="color: #2b91af"&gt;PropertyChangedEventHandler &lt;/span&gt;PropertyChanged;
        &lt;span style="color: blue"&gt;#endregion
    &lt;/span&gt;}&lt;/pre&gt;&lt;p&gt;(The static private member “mCount” is for the purpose of generating a new name whenever an instance of “A” is created).&lt;/p&gt;&lt;h5&gt;The UserControl to display a single instance of class “A”.&lt;/h5&gt;&lt;p&gt;We’ll create a new UserControl (named "ADisplay") to display content of an “A” instance. The control provides an item view within our final list presentation, and of course you are free to use any supported controls and layouts to design this view. In this example, however, we’ll just create a UserControl with a single Label, which is used to display the “Name” property of "A". Bind the “Text” property of this Label to A.Name using DataBinding dialog. The object-based project data source is named “aBindingSource” in the following example.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TOHD_S7W-LI/AAAAAAAAAUE/HHNx7HRzlUU/s1600-h/S1%5B4%5D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top: 0px; border-right: 0px; padding-top: 0px" title="S1" border="0" alt="S1" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TOHD_6Ed00I/AAAAAAAAAUI/gpuD6rCsGyA/S1_thumb%5B2%5D.png?imgmax=800" width="440" height="327" /&gt;&lt;/a&gt;Then, define a “A” property on the UserControl and set it as data binding source when the property is set:    &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;        public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;A &lt;/span&gt;A
        {
            &lt;span style="color: blue"&gt;set
            &lt;/span&gt;{
                aBindingSource.DataSource = &lt;span style="color: blue"&gt;value&lt;/span&gt;;
            }
        }&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;That’s all we have to do for the item display. We’ll work on the list display next.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;The list box with custom item display.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Our list box is a simple container that inherits from System.Windows.Form.Panel. We’ll set it’s AutoScroll property to “True” so we can get automatic scroll-bars as we add more items to the list. The following is the complete code of this custom control:   &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ComplexList &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;Panel
    &lt;/span&gt;{
        &lt;span style="color: #2b91af"&gt;BindingList&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;gt; mAs;
        &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;BindingList&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;gt; As
        {
            &lt;span style="color: blue"&gt;get
            &lt;/span&gt;{
                &lt;span style="color: blue"&gt;return &lt;/span&gt;mAs;
            }
            &lt;span style="color: blue"&gt;set
            &lt;/span&gt;{
                mAs = &lt;span style="color: blue"&gt;value&lt;/span&gt;;
                &lt;span style="color: blue"&gt;if &lt;/span&gt;(mAs != &lt;span style="color: blue"&gt;null&lt;/span&gt;)
                {
                    mAs.ListChanged += &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ListChangedEventHandler&lt;/span&gt;(mAs_ListChanged);
                    resetList();       
                }
            }
        }
        &lt;span style="color: blue"&gt;void &lt;/span&gt;resetList()
        {
            &lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.Clear();
            &lt;span style="color: blue"&gt;for &lt;/span&gt;(&lt;span style="color: blue"&gt;int &lt;/span&gt;i = 0; i &amp;lt; mAs.Count; i++)
            {
                &lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.Add(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ADisplay&lt;/span&gt;() { A = mAs[i], Dock = &lt;span style="color: #2b91af"&gt;DockStyle&lt;/span&gt;.Top });
                &lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.SetChildIndex(&lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls[&lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.Count - 1], 0);
            }
        }
        &lt;span style="color: blue"&gt;void &lt;/span&gt;mAs_ListChanged(&lt;span style="color: blue"&gt;object &lt;/span&gt;sender, &lt;span style="color: #2b91af"&gt;ListChangedEventArgs &lt;/span&gt;e)
        {
            &lt;span style="color: blue"&gt;switch &lt;/span&gt;(e.ListChangedType)
            {
                &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ListChangedType&lt;/span&gt;.ItemAdded:
                    &lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.Add(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ADisplay&lt;/span&gt;() { A = mAs[e.NewIndex], Dock = &lt;span style="color: #2b91af"&gt;DockStyle&lt;/span&gt;.Top });
                    &lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.SetChildIndex(&lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls[&lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.Count - 1], 0);
                    &lt;span style="color: blue"&gt;break&lt;/span&gt;;
                &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ListChangedType&lt;/span&gt;.ItemDeleted:
                    &lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.RemoveAt(&lt;span style="color: blue"&gt;this&lt;/span&gt;.Controls.Count - 1 - e.NewIndex);
                    &lt;span style="color: blue"&gt;break&lt;/span&gt;;
                &lt;span style="color: blue"&gt;case &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ListChangedType&lt;/span&gt;.Reset:
                    resetList();
                    &lt;span style="color: blue"&gt;break&lt;/span&gt;;
            }
        }
    }&lt;/pre&gt;The code is straightforward – we declare a BindingList&amp;lt;A&amp;gt; property on the control. When the property is set, we’ll reset the list by removing all existing controls and create a new item view for each list member (resetList method). At the same time we’ll subscribe to ListChanged event and respond to different list changes to make UI reflect those changes. A couple of pointers:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;I’m using DockStyle to dock the controls so that I don’t need to manually maintain controls’ positions. However since docking order is affected by control index, I need to shift control indexes by calling SetChildIndex() method.&lt;/li&gt;
&lt;li&gt;For same reason, the removal index is reversed so correct item view can be deleted.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Drop the custom list box to a Form, create a new BindingList&amp;lt;A&amp;gt; list and bind the list to the control. Then, you can add, edit, remove list items and see the UI automatically refreshed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-1414560386987365497?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rOtRIGYC-ZzGCulky7aqqmgj8TY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rOtRIGYC-ZzGCulky7aqqmgj8TY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rOtRIGYC-ZzGCulky7aqqmgj8TY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rOtRIGYC-ZzGCulky7aqqmgj8TY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/lkEEfNFslsg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/1414560386987365497/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2010/11/create-complex-custom-list-view-that.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1414560386987365497?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/1414560386987365497?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/lkEEfNFslsg/create-complex-custom-list-view-that.html" title="Create a complex custom list view that supports data binding using Windows Form (C#)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TOHD_6Ed00I/AAAAAAAAAUI/gpuD6rCsGyA/s72-c/S1_thumb%5B2%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2010/11/create-complex-custom-list-view-that.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEACRn86fip7ImA9Wx5bGU4.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-6406790385935058203</id><published>2010-11-04T21:44:00.001-07:00</published><updated>2010-11-04T21:52:47.116-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-04T21:52:47.116-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone" /><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><category scheme="http://www.blogger.com/atom/ns#" term="Digital Identity" /><title>CardSpace, Windows Phone 7 and cloud services</title><content type="html">&lt;p&gt;CardSpace is a good concept and has been included in latest Windows systems. However, the adoption of CardSpace doesn’t seem to have picked up yet after several years since CardSpace had been first released. I think part of the reason is because CardSpace lacks of mobility. On one hand, users don’t really get the experience of pulling out a card from their wallets and swap it on a machine.On the other hand, users need to import their cards on all the machines they want to use, and this is very undesirable especially on public machines.&lt;/p&gt;&lt;p&gt;What if, we put cell phone into the picture? Users’ cards will be installed onto their phones so users can literally carry them around. When user click on CardSpace icon on a website, a notification is sent to the phone, and user will use the phone to pick and submit a matching card. Then the card is presented back to the website to finish logon process. This process solves both of above problems by providing a very intuitive and consistent logon experience, as shown in the following mockups:&lt;/p&gt;&lt;p&gt;1. User access a website protected by CardSpace. User clicks CardSpace icon to logon.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TNOLkPTCv7I/AAAAAAAAATI/Bcw0DBSu2aQ/s1600-h/P1%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P1" border="0" alt="P1" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TNOLkoBVk4I/AAAAAAAAATM/KHr0lcyQ5-E/P1_thumb%5B1%5D.png?imgmax=800" width="326" height="227" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;2.&amp;#160; (Modified) Card selector is invoked. The selector prompts user to enter a cell phone number to forward logon request to. &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TNOLkwwIN2I/AAAAAAAAATQ/T7tox3jtm84/s1600-h/P8%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P8" border="0" alt="P8" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TNOLlLGr30I/AAAAAAAAATU/Cmx7aTuJxZA/P8_thumb%5B1%5D.png?imgmax=800" width="331" height="231" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;3. A notification is pushed to phone. In case of Windows Phone 7, user may see a new logon request on her home screen as shown below:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TNOLlapKiGI/AAAAAAAAATY/RcUj8DcE4Oc/s1600-h/P3%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P3" border="0" alt="P3" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TNOLlh58seI/AAAAAAAAATc/Dmv1TKi18M8/P3_thumb.png?imgmax=800" width="130" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;4. User picks a matching card. The selected card is forward back to the Card selector on PC. &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TNOLmH_d88I/AAAAAAAAATg/Upmt7vnkH_0/s1600-h/P4%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P4" border="0" alt="P4" src="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TNOLmc8qDLI/AAAAAAAAATk/IhJB7sG4TI4/P4_thumb.png?imgmax=800" width="129" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;5.&amp;#160; Finally the card is used to logon to the site.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TNOLmiDERjI/AAAAAAAAATo/6e-8FJR_-FA/s1600-h/P5%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P5" border="0" alt="P5" src="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TNOLmwrKAHI/AAAAAAAAATw/dH_FxLPP-kg/P5_thumb%5B1%5D.png?imgmax=800" width="331" height="229" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;During the process a couple of cloud-based services are required. The first one is a notification service that pushes logon requests to phones. The second one is a deliver service that security deliver the card from cell phone back to the card selector running on PC. Obviously the first service exists (and free by Microsoft). The second service is easy to make – it just needs to pass a xml payload securely. A public service on Azure can be provided to all such requests (hint hint).&lt;/p&gt;&lt;p&gt;I do intend to actually build such a prototype but I have too much work at hand. So, I’m providing the idea here instead. And I'll update the post if I ever get around to do it. Hope this can provide some foods for thoughts. And if you’d like to build a commercial solution based on this idea, I’d like to know as well :). &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-6406790385935058203?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/KXDHEnVITFtgzshsiAG_KPF-5hE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KXDHEnVITFtgzshsiAG_KPF-5hE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/KXDHEnVITFtgzshsiAG_KPF-5hE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KXDHEnVITFtgzshsiAG_KPF-5hE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/JDoSV5cvj6s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/6406790385935058203/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2010/11/cardspace-windows-phone-7-and-cloud.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6406790385935058203?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/6406790385935058203?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/JDoSV5cvj6s/cardspace-windows-phone-7-and-cloud.html" title="CardSpace, Windows Phone 7 and cloud services" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_5uKkgbSGQ4Q/TNOLkoBVk4I/AAAAAAAAATM/KHr0lcyQ5-E/s72-c/P1_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2010/11/cardspace-windows-phone-7-and-cloud.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EGQHc8eyp7ImA9Wx5bGEU.&quot;"><id>tag:blogger.com,1999:blog-8122199360699827669.post-968123294882394796</id><published>2010-11-04T08:45:00.001-07:00</published><updated>2010-11-04T08:47:01.973-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-04T08:47:01.973-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone" /><category scheme="http://www.blogger.com/atom/ns#" term="Azure" /><category scheme="http://www.blogger.com/atom/ns#" term="Digital Identity" /><title>Tutorial – use ASP.Net membership provider with Azure table storage and Windows Phone 7 (2)</title><content type="html">&lt;p&gt;&lt;a href="http://haishibai.blogspot.com/2010/11/tutorial-use-aspnet-membership-provider.html"&gt;Part 1&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To continue with the previous post, we’ll enable Windows Phone 7 users to log on from their phones. &lt;/p&gt;  &lt;p&gt;First, we’ll modify AccountController in TestRole project to introduce a new log on method for the phone users. The method takes user name and password as parameters, and returns log on result as a simple string. Note that we force to enable persistence cookie here because the phone clients will provide the authorization cookie back as security token when they try to invoke protected methods:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult SimpleLogOn(&lt;span class="kwrd"&gt;string&lt;/span&gt; userName, &lt;span class="kwrd"&gt;string&lt;/span&gt; password)
{
     &lt;span class="kwrd"&gt;if&lt;/span&gt; (MembershipService.ValidateUser(userName, password))
    {
        FormsService.SignIn(userName, &lt;font color="#0000ff"&gt;&lt;strong&gt;true&lt;/strong&gt;&lt;/font&gt;);
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Content(&lt;span class="str"&gt;&amp;quot;OK&amp;quot;&lt;/span&gt;);
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Content(&lt;span class="str"&gt;&amp;quot;The user name or password provided is incorrect.&amp;quot;&lt;/span&gt;);
}&lt;/pre&gt;

&lt;p&gt;The next step is to create the phone application:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Add a new Windows Phone project to the solution.&lt;/li&gt;

  &lt;li&gt;In MainPage.xml, Replace the default “ContentPanel” Grid with a stack panel that contains a user name text box, a password box, and a logon button:&lt;/li&gt;

  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;StackPanel&lt;/span&gt; &lt;span class="attr"&gt;Grid&lt;/span&gt;.&lt;span class="attr"&gt;Row&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBox&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtUserName&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;PasswordBox&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtPassword&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Button&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnLogon&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Content &lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Logon&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Click&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnLogon_Click&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;StackPanel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
  &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

  &lt;li&gt;Implement the button’s click event handler. We’ll use a HttpWebRequest to send the request. The cookie container is assigned to a page-level instance:&lt;/li&gt;

  &lt;pre class="csharpcode"&gt;CookieContainer cookieJar = &lt;span class="kwrd"&gt;new&lt;/span&gt; CookieContainer();
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnLogon_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)
{
    HttpWebRequest request = HttpWebRequest.CreateHttp(&lt;span class="str"&gt;&amp;quot;http://127.0.0.1:81/Account/SimpleLogon?UserName=&amp;quot;&lt;/span&gt; + txtUserName.Text + &lt;span class="str"&gt;&amp;quot;&amp;amp;password=&amp;quot;&lt;/span&gt; + txtPassword.Password);
    request.CookieContainer = cookieJar;
    request.BeginGetResponse(&lt;span class="kwrd"&gt;new&lt;/span&gt; AsyncCallback((result) =&amp;gt;
    {
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(response.GetResponseStream()))
        {
            &lt;span class="kwrd"&gt;string&lt;/span&gt; res = sr.ReadToEnd();
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Dispatcher.BeginInvoke(() =&amp;gt; MessageBox.Show(res));
        }
    }), &lt;span class="kwrd"&gt;null&lt;/span&gt;);
}&lt;/pre&gt;
  &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/ol&gt;

&lt;p&gt; Set both the phone application and TestService project as solution start up projects. Then compile and run the solution. After the Azure web role has been initialized and running, use the phone to logon.&lt;/p&gt;

&lt;p&gt;Now the scenario is complete, let’s verify if we really logged on. &lt;/p&gt;

&lt;p&gt;Add a new method “DoSomething” to HomeController and mark it with [Authorize] attribute: &lt;/p&gt;

&lt;pre class="csharpcode"&gt;[Authorize]
&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult DoSomething(&lt;span class="kwrd"&gt;string&lt;/span&gt; payload)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; Content(&lt;span class="str"&gt;&amp;quot;Payload is &amp;quot;&lt;/span&gt; + payload);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;This is a protected method that can’t be called without logging in first. If you type in “http://127.0.0.1:81/Home/DoSomething?payload=Test” in your IE address bar, you’ll be redirected to logon page. And only after you log on, you can invoke the method successfully. Now let’s modify the phone client to call this method.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Add a couple of more UI elements to the phone:&lt;/li&gt;

  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Protected Call&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;TextBlock&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TextBox&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;txtPayload&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Button&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnCall&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Content&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Call method&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;Click&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;btnCall_Click&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
  &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

  &lt;li&gt;Handle btnCall click event:&lt;/li&gt;

  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnCall_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)
{
    HttpWebRequest request = HttpWebRequest.CreateHttp(&lt;span class="str"&gt;&amp;quot;http://127.0.0.1:81/Home/DoSomething?payload=&amp;quot;&lt;/span&gt; + txtPayload.Text);
    &lt;strong&gt;request.CookieContainer = cookieJar;
&lt;/strong&gt;    request.BeginGetResponse(&lt;span class="kwrd"&gt;new&lt;/span&gt; AsyncCallback((result) =&amp;gt;
    {
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(response.GetResponseStream()))
        {
            &lt;span class="kwrd"&gt;string&lt;/span&gt; res = sr.ReadToEnd();
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Dispatcher.BeginInvoke(()=&amp;gt;MessageBox.Show(res));
        }
    }), &lt;span class="kwrd"&gt;null&lt;/span&gt;);
}&lt;/pre&gt;
  &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/ol&gt;

&lt;p&gt;Note I’m using the same cookie container, which is populated by previous successful logon requests. Now launch the solution again. If you click on “Call method” button directly you’ll see a long error page content displayed as text in a message box. After logon, however, you should be able to call the method and get expected result:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_5uKkgbSGQ4Q/TNLVGoe8uZI/AAAAAAAAATA/pnFokV6nb9Q/s1600-h/T2%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="T2" border="0" alt="T2" src="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TNLVHOxTkyI/AAAAAAAAATE/QUBUrhCL_uE/T2_thumb%5B1%5D.png?imgmax=800" width="204" height="371" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To recap what we’ve just done: We’ve switched to a new membership provide that uses Azure table as identity storage, and we’ve enabled Windows Phone client to logon and to consume protected methods. Both the phone and the website are protected by the same membership provider.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8122199360699827669-968123294882394796?l=haishibai.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/exSRlGnc0PLilMBL3_VAW2SNRYw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/exSRlGnc0PLilMBL3_VAW2SNRYw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/exSRlGnc0PLilMBL3_VAW2SNRYw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/exSRlGnc0PLilMBL3_VAW2SNRYw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/HaishisBlog/~4/PSlNgI3NAYw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://haishibai.blogspot.com/feeds/968123294882394796/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://haishibai.blogspot.com/2010/11/tutorial-use-aspnet-membership-provider_04.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/968123294882394796?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8122199360699827669/posts/default/968123294882394796?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/HaishisBlog/~3/PSlNgI3NAYw/tutorial-use-aspnet-membership-provider_04.html" title="Tutorial – use ASP.Net membership provider with Azure table storage and Windows Phone 7 (2)" /><author><name>Haishi</name><uri>http://www.blogger.com/profile/05217897042910076935</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_5uKkgbSGQ4Q/TNLVHOxTkyI/AAAAAAAAATE/QUBUrhCL_uE/s72-c/T2_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://haishibai.blogspot.com/2010/11/tutorial-use-aspnet-membership-provider_04.html</feedburner:origLink></entry></feed>

