<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
>

<channel>
	<title>Martin Normark&#039;s blog &#187; ASP.NET</title>
	<atom:link href="http://martinnormark.com/tag/asp-net/feed" rel="self" type="application/rss+xml" />
	<link>http://martinnormark.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 21:06:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Making your ASP.NET Global Resource files work in JavaScript. IntelliSense included!</title>
		<link>http://martinnormark.com/making-your-asp-net-global-resource-files-work-in-javascript-intellisense-included?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/making-your-asp-net-global-resource-files-work-in-javascript-intellisense-included#comments</comments>
		<pubDate>Mon, 15 Nov 2010 15:22:20 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Internationalization]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>

		<guid isPermaLink="false">http://martinnormark.com/?p=56</guid>
		<description><![CDATA[Any modern web application needs localization! You simply can't ignore the huge amounts of people who doesn't speak your language, or whose native language is different from yours. You're probably using resource files (.resx) in .NET, but how do you &#8230; <p><a class="btn small" href="http://martinnormark.com/making-your-asp-net-global-resource-files-work-in-javascript-intellisense-included">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>Any modern web application needs localization! You simply can't ignore the huge amounts of people who doesn't speak your language, or whose native language is different from yours.</p>
<p>You're probably using resource files (.resx) in .NET, but how do you go about getting values from your resource files in JavaScript?</p>
<p><a href="http://www.west-wind.com/Weblog/default.aspx">Rick Strahl</a> wrote a great <a href="http://www.west-wind.com/Weblog/posts/698097.aspx">blog post about an HttpHandler</a> that serves the content of your resource files in JavaScript. You basically add a script tag to your page that points to the HttpHandler, and the HttpHandler will produce the resources in JavaScript as an object with properties on it, like this:</p>
<blockquote><p>
[code lang="js"]var localRes = {<br />
    AreYouSureYouWantToRemoveValue: &quot;Sind Sie sicher dass Sie diesen Wert l\u00F6schen wollen?&quot;,<br />
    BackupComplete: &quot;Der Backup f\u00FChrte erfolgreich durch&quot;,<br />
    BackupFailed: &quot;Der Backup konnte nicht durchgef\u00FChrt werden&quot;,<br />
    BackupNotification: &quot;Diese Operation macht einen Backup von der Lokalisationtabelle. \nM\u00F6chten Sie fortfahren?&quot;,<br />
    Close: &quot;Schliessen&quot;,<br />
    FeatureDisabled: &quot;Diese Funktion ist nicht vorhanden im on-line Demo &quot;,<br />
    InvalidFileUploaded: &quot;Unzul\u00E4ssige Akten Format hochgeladen.&quot;,<br />
    InvalidResourceId: &quot;Unzul\u00E4ssige ResourceId&quot;,<br />
    Loading: &quot;Laden&quot;,<br />
    LocalizationTableCreated: &quot;Lokalisations Akte wurde erfolgreich erstellt.&quot;,<br />
    LocalizationTableNotCreated: &quot;Die Localizations Akte konnte nicht erstellt werden.&quot;<br />
};[/code]</p></blockquote>
<p>This is awesome! Now you can access your resource files from JavaScript. Though, I see a single improvement to be made. The thing I don't like about the HttpHandler approach, is that you don't get IntelliSense support in Visual Studio. So you have to browse your resource file and copy &amp; paste the resource key to your JavaScript files in order for this to work.</p>
<h2>Generate static JavaScript files on Post-build</h2>
<p>Instead of generating dynamic files at runtime, I prefer to generate static JavaScript files and then dynamically include the file of the current language on my pages. I do this by calling a Console Application I’ve written on the Post-build event of my ASP.NET (MVC) project, which you can set in the property pages of your project (By the way, did you know that you can open property pages of a project by double clicking the default Properties folder?):</p>
<p><a href="http://martinnormark.com/wp-content/uploads/2010/11/image1.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://martinnormark.com/wp-content/uploads/2010/11/image_thumb1.png" border="0" alt="image" width="634" height="490" /></a></p>
<p>What my JavascriptResxGenerator App does, is quite messy. But the essence of the App is, of course, to take a single (or several) .resx files and do the following:</p>
<p>1. Loop through all keys.</p>
<p>2. Make sure the key is not a <a href="http://javascript.about.com/library/blreserved.htm">JavaScript reserved word</a>.</p>
<p>3. Add the key and value to a dictionary (in JavaScript).</p>
<p>4. Write the file.</p>
<p>And for the default culture I generate a –vsdoc file, that I can use for Visual Studio IntelliSense.</p>
<h2>Using the JavaScript Resx Generator App</h2>
<p>My App supports a single file approach, and directory approach.</p>
<p><strong>Single file: </strong>JavascriptResxGenerator.exe C:\Folder\Text.resx C:\Output C:\Output\VsDoc MyApp.Namespace.Resources</p>
<p><strong>Directory: </strong>JavascriptResxGenerator.exe C:\Folder C:\Output C:\Output\VsDoc MyApp.Namespace.Resources</p>
<p>The MyApp.Namespace.Resources value, is the namespace your resource dictionary will get enclosed in.</p>
<p><a href="http://martinnormark.com/wp-content/uploads/2010/11/image2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://martinnormark.com/wp-content/uploads/2010/11/image_thumb2.png" border="0" alt="image" width="634" height="294" /></a></p>
<h2>Embedding the file on your pages</h2>
<p>To include the JavaScript resource file in your page, you simply add a script include tag that points to the correct language. The App will respect the region token used in your Resx files. So if you have a file called Text.da.resx, the JavaScript file generated will include .da.resx at the end. It’s then up to you to add the correct logic to keep hold of the current language and specify the correct region token in order to include the correct JavaScript resource file.</p>
<h2>Download</h2>
<p>You can <a href="http://cid-146a3db7b364e824.office.live.com/self.aspx/Public/JavascriptResxGenerator.zip">download the App here</a>, as a ZIP file.</p>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/making-your-asp-net-global-resource-files-work-in-javascript-intellisense-included/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Windows Live Development &#8211; Authenticating users via Windows Live ID</title>
		<link>http://martinnormark.com/windows-live-development-part-1-authenticating-users-via-windows-live-id?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/windows-live-development-part-1-authenticating-users-via-windows-live-id#comments</comments>
		<pubDate>Thu, 19 Jun 2008 23:01:34 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Windows Live]]></category>
		<category><![CDATA[Windows Live Development]]></category>

		<guid isPermaLink="false">/post/Windows-Live-Development-Part-1-Authenticating-users-via-Windows-Live-ID.aspx</guid>
		<description><![CDATA[With so many online services out there, you nearly claim a new online identity somewhere every day. You tend to use the same username and password couple for all of them, but sometimes your preferred username is taken, or your &#8230; <p><a class="btn small" href="http://martinnormark.com/windows-live-development-part-1-authenticating-users-via-windows-live-id">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>With so many online services out there, you nearly claim a new online identity somewhere every day. You tend to use the same username and password couple for all of them, but sometimes your preferred username is taken, or your password does not meet the sites' password policy. I reckon I have well over 100 online identities out there - I rely on the same 3-4 combinations of username and password, and it's really messy. In this blog post I'm going to cover how to authenticate users of an ASP.NET application against <a href="http://dev.live.com/">Windows Live</a>, using the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=24195B4E-6335-4844-A71D-7D395D20E67B&amp;displaylang=en">SDK</a> for <a href="http://dev.live.com/liveID/default.aspx">Windows Live ID</a>. I'm going use the built-in <a href="http://msdn.microsoft.com/en-us/library/yh26yfzy.aspx">ASP.NET Membership</a> mechanism and go from there.</p>
<p>I could have gone the <a href="http://openid.net/">OpenID</a> way, but <a href="http://www.hanselman.com/blog/">Scott Hanselman</a> already did an <a href="http://www.hanselman.com/blog/TheWeeklySourceCode25OpenIDEdition.aspx">example on OpenID</a>, so I thought I'd try out Windows Live. <a href="http://www.codinghorror.com">Jeff Atwood</a> asked the question, if we <a href="http://www.codinghorror.com/blog/archives/001121.html">really need another username and password</a> in the pursuit of the best authentication model for <a href="http://www.stackoverflow.com">stackoverflow.com</a>.</p>
<h3>Conceptual idea of using Windows Live ID</h3>
<p><img style="margin: 5px 15px 0px 0px;" src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/tmpF3A8_3.png" border="0" alt="tmpF3A8" width="240" height="51" align="left" />Windows Live ID, is the technology you should be quite familiar with when authenticating on Microsoft web sites, and Messenger. If you want to know more about what Windows Live ID is, take a look at <a href="http://channel9.msdn.com/posts/Charles/Lynn-Ayres-What-is-Windows-Live-ID/">this video</a> from <a href="http://channel9.msdn.com">Channel9</a>.</p>
<p>When using Windows Live ID, you redirect the user to the Windows Live login-page, with a return URL specified. When the user authenticates, Windows Live will redirect the user back to your site, and delivering a user id and a token. Here's an overview of how it looks:</p>
<p><a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/image_2.png" target="_blank"><img src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/image_thumb.png" alt="image" width="550" height="372" /></a></p>
<h3>Getting your application ID to use Windows Live ID</h3>
<p>To get started using Windows Live ID, first of all you need an application ID. Basically you need to sign up for one, and register your application. Go to <a title="https://msm.live.com/app/default.aspx" href="https://msm.live.com/app/default.aspx">https://msm.live.com/app/default.aspx</a> and click 'Register an Application'. (You can find Microsoft's guide to this here: <a title="http://msdn.microsoft.com/en-us/library/cc287659.aspx" href="http://msdn.microsoft.com/en-us/library/cc287659.aspx">http://msdn.microsoft.com/en-us/library/cc287659.aspx</a>)</p>
<p><a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/tmpF3F5_2.png" target="_blank"><img src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/tmpF3F5_thumb.png" alt="tmpF3F5" width="550" height="482" /></a></p>
<p>Leave Domain Name blank. Save your self-chosen Secret Key for later use, and submit the form. When you see the confirmation page, your application ID is shown. Copy that, as we're going to use it later.</p>
<p>In the return URL field, type the URL of your application followed by a name of a page to handle the Windows Live ID communication, like <a href="http://localhost/demoapp/webauth-handler.aspx">http://localhost/demoapp/webauth-handler.aspx</a>.</p>
<h3>Download and install Windows Live ID Web Authentication SDK</h3>
<p>Microsoft has made it quite easy for ASP.NET developers to get started, by providing an SDK. Download it here: <a title="http://www.microsoft.com/downloads/details.aspx?FamilyId=24195B4E-6335-4844-A71D-7D395D20E67B&amp;displaylang=en" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=24195B4E-6335-4844-A71D-7D395D20E67B&amp;displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyId=24195B4E-6335-4844-A71D-7D395D20E67B&amp;displaylang=en</a> and install the SDK. By default it is installed here: C:\Program Files\Windows Live ID\WebAuth</p>
<p>From the SDK we need a class called WindowsLiveLogin, located in the App_Code folder of the sample. Keep this file in mind for a few seconds.</p>
<h3>Start coding - create a new website</h3>
<p>Open Visual Studio 2005/2008 and create a new ASP.NET website the way you want it. First we will add the WindowsLiveLogin.cs file to our App_Code folder. (C:\Program Files\Windows Live ID\WebAuth\Sample\App_Code\WindowsLiveLogin.cs).</p>
<p>Leave the default.aspx page, and put the following HTML in the markup:</p>
<div style="font-size: 8pt; margin: 20px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; height: 333px; background-color: #f4f4f4; border: gray 1px solid; padding: 4px;">
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">head</span><span style="color: #0000ff;">&gt;</span>
  <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">title</span><span style="color: #0000ff;">&gt;</span>Windows Live<span style="color: #ff0000;">&amp;trade;</span> ID<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">title</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">head</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span>
  <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">iframe</span> <span style="color: #ff0000;">id</span><span style="color: #0000ff;">="WebAuthControl"</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="WebAuthControl"</span> <span style="color: #ff0000;">src</span><span style="color: #0000ff;">="http://login.live.com/controls/WebAuth.htm?appid=&lt;%=AppId%&gt;&amp;style=font-size%3A+10pt%3B+font-family%3A+verdana%3B+background%3A+white%3B"</span>
    <span style="color: #ff0000;">width</span><span style="color: #0000ff;">="80px"</span> <span style="color: #ff0000;">height</span><span style="color: #0000ff;">="20px"</span> <span style="color: #ff0000;">marginwidth</span><span style="color: #0000ff;">="0"</span> <span style="color: #ff0000;">marginheight</span><span style="color: #0000ff;">="0"</span> <span style="color: #ff0000;">align</span><span style="color: #0000ff;">="middle"</span> <span style="color: #ff0000;">frameborder</span><span style="color: #0000ff;">="0"</span>
    <span style="color: #ff0000;">scrolling</span><span style="color: #0000ff;">="no"</span><span style="color: #0000ff;">&gt;&lt;/</span><span style="color: #800000;">iframe</span><span style="color: #0000ff;">&gt;</span>
  <span style="background-color: #ffff00;">&lt;%</span>
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px;"><span style="color: #606060;">   1:</span>  <span style="color: #0000ff;">if</span> (UserId == <span style="color: #0000ff;">null</span>)</pre>
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #606060;">   2:</span>      {</pre>
<p><span style="background-color: #ffff00;">%&gt;</span><br />
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />
This application does not know who you are! Click the <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">b</span><span style="color: #0000ff;">&gt;</span>Sign in<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">b</span><span style="color: #0000ff;">&gt;</span> link above.<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />
<span style="background-color: #ffff00;">&lt;%</span></p>
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px;"><span style="color: #606060;">   1:</span>  }</pre>
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #606060;">   2:</span>      <span style="color: #0000ff;">else</span></pre>
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px;"><span style="color: #606060;">   3:</span>      {</pre>
<p><span style="background-color: #ffff00;">%&gt;</span><br />
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />
Now this application knows that you are the user with ID = "<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">b</span><span style="color: #0000ff;">&gt;</span><span style="background-color: #ffff00;">&lt;%</span></p>
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px;"><span style="color: #606060;">   1:</span> =UserId</pre>
<p><span style="background-color: #ffff00;">%&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">b</span><span style="color: #0000ff;">&gt;</span>".<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />
<span style="background-color: #ffff00;">&lt;%</span></p>
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: white; border-style: none; padding: 0px;"><span style="color: #606060;">   1:</span>  }</pre>
<p><span style="background-color: #ffff00;">%&gt;</span><br />
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span><br />
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span></pre>
</div>
<p>And this piece of code in its code-behind class.</p>
<div style="font-size: 8pt; margin: 20px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px;">
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> System;
<span style="color: #0000ff;">using</span> System.Web;
<span style="color: #0000ff;">using</span> System.IO;
<span style="color: #0000ff;">using</span> WindowsLive;

<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> DefaultPage : System.Web.UI.Page
{
  <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">string</span> LoginCookie = <span style="color: #006080;">"webauthtoken"</span>;

  <span style="color: #008000;">// Initialize the WindowsLiveLogin class.</span>
  <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> WindowsLiveLogin wll = <span style="color: #0000ff;">new</span> WindowsLiveLogin(<span style="color: #0000ff;">true</span>);

  <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">string</span> AppId = wll.AppId;
  <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">string</span> UserId;

  <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span> Page_Load(<span style="color: #0000ff;">object</span> sender, EventArgs e)
  {
    HttpRequest req = HttpContext.Current.Request;
    HttpApplicationState app = HttpContext.Current.Application;

    HttpCookie loginCookie = req.Cookies[LoginCookie];

    <span style="color: #0000ff;">if</span> (loginCookie != <span style="color: #0000ff;">null</span>)
    {
      <span style="color: #0000ff;">string</span> token = loginCookie.Value;

      WindowsLiveLogin.User user = wll.ProcessToken(token);

      <span style="color: #0000ff;">if</span> (user != <span style="color: #0000ff;">null</span>)
      {
        UserId = user.Id;
      }
    }
  }
}</pre>
</div>
<p>Default.aspx will work as a login page. Users click the Sign-in button, and is redirected to Windows Live. When they authenticate, they're redirected back to our handler page, that we will now create...</p>
<p>Create a new aspx page, and name it webauth-handler.aspx. Recall that this was the page we provided as the return URL when we registered the application at Windows Live.</p>
<p>This page will serve as the handler page for the user, when Windows Live redirects back to your site. Windows Live will post authentication specific values for you to use. Because this page is never seen by a user (we will send the user back where they began), we can simply remove all the markup.</p>
<p>Put the following code in your code-behind class for webauth-handler.aspx.</p>
<div style="font-size: 8pt; margin: 20px 0px 10px; overflow: auto; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border: gray 1px solid; padding: 4px;">
<pre style="font-size: 8pt; margin: 0em; overflow: visible; width: 100%; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> System;
<span style="color: #0000ff;">using</span> System.Web;
<span style="color: #0000ff;">using</span> System.IO;
<span style="color: #0000ff;">using</span> WindowsLive;

<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> HandlerPage : System.Web.UI.Page
{
  <span style="color: #008000;">// Relative path to the login- and logoutpage.</span>
  <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">string</span> LoginPage = <span style="color: #006080;">"default.aspx"</span>;
  <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">string</span> LogoutPage = <span style="color: #006080;">"default.aspx"</span>;
  <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">string</span> LoginCookie = <span style="color: #006080;">"webauthtoken"</span>;
  <span style="color: #0000ff;">static</span> DateTime ExpireCookie = DateTime.Now.AddYears(-10);
  <span style="color: #0000ff;">static</span> DateTime PersistCookie = DateTime.Now.AddYears(10);

  <span style="color: #008000;">// Initialize the WindowsLiveLogin class.</span>
  <span style="color: #0000ff;">static</span> WindowsLiveLogin wll = <span style="color: #0000ff;">new</span> WindowsLiveLogin(<span style="color: #0000ff;">true</span>);

  <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span> Page_Load(<span style="color: #0000ff;">object</span> sender, EventArgs e)
  {
    HttpRequest request = HttpContext.Current.Request;
    HttpResponse response = HttpContext.Current.Response;
    HttpApplicationState application = HttpContext.Current.Application;

    <span style="color: #0000ff;">string</span> action = request[<span style="color: #006080;">"action"</span>];

    <span style="color: #0000ff;">if</span> (action == <span style="color: #006080;">"logout"</span>)
    {
      HttpCookie loginCookie = <span style="color: #0000ff;">new</span> HttpCookie(LoginCookie);
      loginCookie.Expires = ExpireCookie;
      response.Cookies.Add(loginCookie);
      response.Redirect(LogoutPage);
      response.End();
    }
    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (action == <span style="color: #006080;">"clearcookie"</span>)
    {
      HttpCookie loginCookie = <span style="color: #0000ff;">new</span> HttpCookie(LoginCookie);
      loginCookie.Expires = ExpireCookie;
      response.Cookies.Add(loginCookie);

      <span style="color: #0000ff;">string</span> type;
      <span style="color: #0000ff;">byte</span>[] content;
      wll.GetClearCookieResponse(<span style="color: #0000ff;">out</span> type, <span style="color: #0000ff;">out</span> content);
      response.ContentType = type;
      response.OutputStream.Write(content, 0, content.Length);

      response.End();
    }
    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (action == <span style="color: #006080;">"login"</span>)
    {
      HttpCookie loginCookie = <span style="color: #0000ff;">new</span> HttpCookie(LoginCookie);

      WindowsLiveLogin.User user = wll.ProcessLogin(request.Form);

      <span style="color: #0000ff;">if</span> (user != <span style="color: #0000ff;">null</span>)
      {
        loginCookie.Value = user.Token;

        <span style="color: #0000ff;">if</span> (user.UsePersistentCookie)
        {
          loginCookie.Expires = PersistCookie;
        }
      }
      <span style="color: #0000ff;">else</span>
      {
        loginCookie.Expires = ExpireCookie;
      }

      response.Cookies.Add(loginCookie);
      response.Redirect(LoginPage);
      response.End();
    }
    <span style="color: #0000ff;">else</span>
    {
      response.Redirect(LoginPage);
      response.End();
    }
  }
}</pre>
</div>
<h3>The first login test</h3>
<p>Now we've got everything setup as we should, and it should be possible to login using Windows Live. View the default.aspx page in your favorite browser, and let's try.</p>
<p>First you will see out login page:<br />
<a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/tmp9D6_2.png"><img src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/tmp9D6_thumb.png" alt="tmp9D6" width="547" height="139" /></a></p>
<p>Click the Sign in link, which will take you to Windows Live:<br />
<a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/wlive_signin_2.jpg"><img src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/wlive_signin_thumb.jpg" alt="wlive_signin" width="547" height="312" /></a></p>
<p>Sign in with your Windows Live ID, and you will return to our login page - which will now welcome you and show your user ID:<br />
<a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/wlive_signin_4.jpg"><img src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/WindowsLiveDevelopmentPart1Authenticatio_130BF/wlive_signin_thumb_1.jpg" alt="wlive_signin" width="547" height="310" /></a></p>
<p>Now your user has authenticated against Windows Live, using the Windows Live ID. Now it's up to you to handle the user's Windows Live ID, which is what I'm going to blog about in part 2 of the Windows Live Development series here...</p>
<p><a href="http://www.dotnetkicks.com/kick/?url=http://www.martinnormark.com/post/Windows-Live-Development-Part-1---Authenticating-users-via-Windows-Live-ID.aspx&amp;title=Windows Live Development Part 1 - Authenticating users via Windows Live ID"><br />
<img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.martinnormark.com/post/Windows-Live-Development-Part-1---Authenticating-users-via-Windows-Live-ID.aspx" border="0" alt="kick it on DotNetKicks.com" /><br />
</a></p>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/windows-live-development-part-1-authenticating-users-via-windows-live-id/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Event performance optimization with the EventHandlerList</title>
		<link>http://martinnormark.com/event-performance-optimization-with-the-eventhandlerlist?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/event-performance-optimization-with-the-eventhandlerlist#comments</comments>
		<pubDate>Tue, 25 Dec 2007 22:35:42 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">/post/Event-performance-optimization-with-the-EventHandlerList.aspx</guid>
		<description><![CDATA[When using custom events (event delegates) in your ASP.NET pages, user controls and server controls, many developers might define their Events as public fields, like this: public event EventHandler&#60;EventArgs&#62; MyCustomEvent; And use this code to fire the event: protected void &#8230; <p><a class="btn small" href="http://martinnormark.com/event-performance-optimization-with-the-eventhandlerlist">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>When using custom events (event delegates) in your ASP.NET pages, user controls and server controls, many developers might define their Events as public fields, like this:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler&lt;EventArgs&gt; MyCustomEvent;</pre>
<p><!-- .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; } --></p>
<p>And use this code to fire the event:</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> OnMyCustomEvent(EventArgs e)
{
  <span class="kwrd">if</span>(MyCustomEvent != <span class="kwrd">null</span>)
  {
    MyCustomEvent(<span class="kwrd">this</span>, e);
  }
}</pre>
<p>Nothing is wrong with the approach of the latter, but defining the MyCustomEvent as a public field introduces two problems:</p>
<ol>
<li></li>
<li>Even though no clients have registered any delegates to the invocation list of your event, the compiler generates<br />
one private delegate field for each event delegate in your class. This is a waste of server memory, especially if<br />
you have several events inside your class.</li>
<li>One Add and one Remove method is generated for each event field of your class. When clients use += and -= to add<br />
and remove delegates from the invocation lists of your class' events, these methods are called behind the scenes.<br />
These two compiler-generated methods are thread-safe, which means they include extra code to synchronize threads<br />
that are accessing these methods. This means, that everytime a client adds or removes a delegate to or from the<br />
invocation list of an event, they have to get a lock before they can do the actual work. This introduces an<br />
unnecessary overhead because most page developers don’t use multiple threads and therefore there is no need for<br />
thread synchronization.</li>
</ol>
<p>The <a href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.eventhandlerlist(VS.80).aspx">EventHandlerList</a> is the answer to our issues. This class comes with the .NET Framework. The EventHandlerList is a linked list of delegates,which is optimized for adding and removing delegates. To use the EventHandlerList in your classes, you need to add a private static key for each event your class exposes. The code bellow defines a key for MyCustomEvent:</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> <span class="kwrd">object</span> MyCustomEventKey = <span class="kwrd">new</span> <span class="kwrd">object</span>();</pre>
<p><!-- .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; } --></p>
<p>The memory is allocated only once, because the key is static.</p>
<p>After this, you need to define your events as properties - not fields. These event properties has a different syntax that normal get-set properties. Event properties uses add-remove instead of get-set. The following property, is an event property for MyCustomEvent:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler&lt;EventArgs&gt; MyCustomEvent
{
  add { Events.AddHandler(MyCustomEventKey, <span class="kwrd">value</span>); }
  remove { Events.RemoveHandler(MyCustomEventKey, <span class="kwrd">value</span>); }
}</pre>
<pre class="csharpcode"></pre>
<p><!-- .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; } -->Every <a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.page.aspx">Page</a>, <a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.usercontrol.aspx">UserControl</a> and <a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.webcontrol.aspx">WebControl</a> - among others - has a protected property of type EventHandlerList named <a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.control.events.aspx">Events</a>. With this approach, when clients use += to add a delegate to the invocation list of the MyCustomEvent, the add method of the event property calls the AddHandler method of the EventHanderList class, as the code above will tell you. As for -= the RemoveHandler method is called.</p>
<p>The EventHandlerList class maintains a linked list which can have none or one entry for each event. The AddHandler method checks whether this internal linked list contains an entry for an event with the given event key. If it does, the method calls the Combine method of the Delegate class to add the client delegate to the invocation list of the event. If this internal list doesn’t contain an entry for an event with the given event key, the AddHandler method just adds a new entry.</p>
<p>With this new approach, we need to update our OnMyCustomEvent Method, which is responsible for firing the event:</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> OnMyCustomEvent(EventArgs e)
{
  EventHandler&lt;EventArgs&gt; handler = Events[MyCustomEventKey] <span class="kwrd">as</span> EventHandler&lt;EventArgs&gt;;

<span class="kwrd">  if</span> (handler != <span class="kwrd">null</span>)
    handler(<span class="kwrd">this</span>, e);
}</pre>
<pre class="csharpcode"></pre>
<p>This method uses the MyCustomEventKey as an index in the Events list to access the MyCustomEvent-event. The Events list will return null if it does not contain an entry at the specified index. This will happen when no clients has subscribed to the MyCustomEvent.</p>
<p>Using the EventHandlerList class automatically resolves the two previously mentioned performance problems with the event fields.</p>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:04bd604f-98de-4d6b-b3a1-7d5972689233" class="wlWriterSmartContent" style="display: inline; margin: 0px; padding: 0px;">Technorati Tags: <a rel="tag" href="http://technorati.com/tags/ASP.NET">ASP.NET</a>, <a rel="tag" href="http://technorati.com/tags/Server%20Controls">Server Controls</a></div>
<p><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fEvent-performance-optimization-with-the-EventHandlerList.aspx"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fEvent-performance-optimization-with-the-EventHandlerList.aspx" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/event-performance-optimization-with-the-eventhandlerlist/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Configuring IIS 7 default document from web.config</title>
		<link>http://martinnormark.com/configuring-iis-7-default-document-from-web-config?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/configuring-iis-7-default-document-from-web-config#comments</comments>
		<pubDate>Thu, 20 Dec 2007 20:14:00 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[IIS7]]></category>

		<guid isPermaLink="false">/post/Configuring-IIS-7-default-document-from-webconfig.aspx</guid>
		<description><![CDATA[IIS 7 has a lot of changes regarding the configuration model. Using the Integrated Configuration System in IIS 7 you can set configuration of your server on different levels, compared to IIS 6, where the ASP.NET developer were more restricted. &#8230; <p><a class="btn small" href="http://martinnormark.com/configuring-iis-7-default-document-from-web-config">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>IIS 7 has a lot of changes regarding the configuration model. Using the Integrated Configuration System in IIS 7 you can set configuration of your server on different levels, compared to IIS 6, where the ASP.NET developer were more restricted. Configuring IIS 7 from an ASP.NET Web Application's web.config file works from both ASP.NET 2.0 and ASP.NET 3.5. Note that the server can be restricted to lock certain configuration settings from above the application level, you might encounter this if your website runs in a shared hosting environment.</p>
<p><strong>Setting up the website</strong></p>
<p>To have a test website, I will setup a new website on my Vista machine running IIS 7. I don't want the website to run under the Default Web Site, so first thing, I'll add a hostname to my hosts file. This is located in the drivers\etc folder of your windows directory's system32 folder. Add the following line:</p>
<p>127.0.0.1         iis7test</p>
<p>Open up Internet Information Services (IIS) Manager, and create a new Application Pool. Name it iis7test, and leave the settings as default:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_2.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_thumb.png" border="0" alt="image" width="278" height="250" /></a></p>
<p>Add a new website with the following settings:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_4.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_thumb_1.png" border="0" alt="image" width="454" height="420" /></a></p>
<p>This should get us started. Open up Visual Studio 2008 (2005 will also work). Open the website you just created inside IIS.</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_6.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_thumb_2.png" border="0" alt="image" width="454" height="362" /></a></p>
<p>The only item in the website is a web.config. Add a new Web Form called Test.aspx.</p>
<p>Right-click the Test.aspx file and click View in browser. You could get an HTTP Error 500.00, like this:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_8.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_thumb_3.png" border="0" alt="image" width="454" height="328" /></a></p>
<p>To get rid of it, set impersonate to false in the web.config file by adding this line to the system.web section:</p>
<p>&lt;identity impersonate="false" /&gt;</p>
<p>Now your site should work fine. Edit the Test.aspx file, so it has some content. Just write Test IIS 7 or something in the HTML mark-up.</p>
<p>If you right-click the website icon in the Solution Explorer, and click View in browser, you will get an error like the one bellow:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_10.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_thumb_4.png" border="0" alt="image" width="454" height="502" /></a></p>
<p>That is because our website does not have any pages that match the name of the default documents on IIS. If you don't want to be limited by the few default documents that comes with IIS out-of-the-box, you can add your own from web.config by adding these lines:</p>
<p>&lt;system.webServer&gt;<br />
&lt;defaultDocument&gt;<br />
&lt;files&gt;<br />
&lt;clear /&gt;<br />
&lt;add value="Test.aspx" /&gt;<br />
&lt;/files&gt;<br />
&lt;/defaultDocument&gt;<br />
&lt;/system.webServer&gt;</p>
<p>Maybe the system.webServer section already existed in your web.config file. If so, just add the defaultDocument section. Here you can specify all the filenames that should act as a default document in IIS 7. The &lt;clear /&gt; line is optional. If you want to keep the default settings, and only add your own - just delete that line.</p>
<p>Now when we save the new web.config file, and refresh the browser we se our Test.aspx file:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_12.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/ConfiguringIIS7defaultdocumentfro.config_126D3/image_thumb_5.png" border="0" alt="image" width="244" height="191" /></a></p>
<p>This setting is just one of many that you can specify in your application's web.config file. In the near future I'll be blogging more about specific settings you can use to configure IIS 7 from ASP.NET.</p>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:31745098-9c0f-41f3-b271-f61a56fcdf5f" class="wlWriterSmartContent" style="display: inline; margin: 0px; padding: 0px;">Technorati Tags: <a rel="tag" href="http://technorati.com/tags/ASP.NET">ASP.NET</a>, <a rel="tag" href="http://technorati.com/tags/IIS7">IIS7</a></div>
<p><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fConfiguring-IIS-7-default-document-from-webconfig.aspx"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fConfiguring-IIS-7-default-document-from-webconfig.aspx" border="0" alt="kick it on DotNetKicks.com" width="82" height="18" /></a></p>
<div style="float: right;">
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&#038;bc1=FFFFFF&#038;IS1=1&#038;nou=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=martnormsblog-20&#038;o=1&#038;p=8&#038;l=as1&#038;m=amazon&#038;f=ifr&#038;ref=tf_til&#038;asins=0470152532" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</div>
<h3>The Integrated Programming model in IIS 7</h3>
<p>IIS 7 comes with a bunch of improvements for developers. You can do a whole lot of exciting things even from web.config, but also from code.</p>
<p>To take advantage of the powerful integrated programming model, you need to set your application pool to use the Integrated pipeline mode. There's no limit to what you can do.</p>
<p>I found a lot of great stuff in the book called <a href="http://www.amazon.com/gp/product/0470152532/ref=as_li_tf_tl?ie=UTF8&#038;tag=martnormsblog-20&#038;linkCode=as2&#038;camp=217145&#038;creative=399381&#038;creativeASIN=0470152532">Professional IIS 7 and ASP.NET Integrated Programming</a><img src="http://www.assoc-amazon.com/e/ir?t=martnormsblog-20&#038;l=as2&#038;o=1&#038;a=0470152532&#038;camp=217145&#038;creative=399381" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> and learned a lot of useful stuff.</p>
<p>IIS 7 (or 7.5) is still the preferred way to develop, test and deploy ASP.NET applications, and as a developer you must stay up-to-date on what your tools and framework has to offer!</p>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/configuring-iis-7-default-document-from-web-config/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Sending e-mails from your ASP.NET app and maintaining a list of recipients</title>
		<link>http://martinnormark.com/sending-e-mails-from-your-asp-net-app-and-maintaining-a-list-of-recipients?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/sending-e-mails-from-your-asp-net-app-and-maintaining-a-list-of-recipients#comments</comments>
		<pubDate>Tue, 18 Dec 2007 20:05:00 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">/post/Sending-e-mails-from-your-ASPNET-app-and-maintaining-a-list-of-recipients.aspx</guid>
		<description><![CDATA[Making your application send e-mails, is something you do almost in every application. It's easy - all you need is an SMTP server to relay your mail through. Sending e-mail messages to several recipients at once can also be done, &#8230; <p><a class="btn small" href="http://martinnormark.com/sending-e-mails-from-your-asp-net-app-and-maintaining-a-list-of-recipients">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>Making your application send e-mails, is something you do almost in every application. It's easy - all you need is an SMTP server to relay your mail through. Sending e-mail messages to several recipients at once can also be done, by adding multiple recipients to either of the <a href="http://msdn2.microsoft.com/en-us/library/system.net.mail.mailmessage.to.aspx">MailMessage.To</a>, <a href="http://msdn2.microsoft.com/en-us/library/system.net.mail.mailmessage.cc.aspx">MailMessage.Cc</a> or <a href="http://msdn2.microsoft.com/en-us/library/system.net.mail.mailmessage.bcc.aspx">MailMessage.Bcc</a> properties in C#. But if you send a newsletter every month, week or day, it is very important to maintain your list of recipients, so that whenever people get a new e-mail address (and they do!) and the old one stop working - you avoid those undelivered mails everytime you send your newsletter.</p>
<p>I've made this simple class called BulkSender, that takes three parameters in the constructor:<br />
mailMessage (<a href="http://msdn2.microsoft.com/en-us/library/system.net.mail.mailmessage.aspx">System.Net.Mail.MailMessage</a>), recipients (<a href="http://msdn2.microsoft.com/en-us/library/6sh2ey19.aspx">List&lt;string&gt;</a>), mailSender (<a href="http://msdn2.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx">System.Net.Mail.SmtpClient</a>).</p>
<p>It has one method: SendEmailMessage, and what it does is, that it adds all recipients to the Bcc collection on the MailMessage, and sends the mail in a try-catch block. Whenever the <a href="http://msdn2.microsoft.com/en-us/library/system.net.mail.smtpfailedrecipientsexception.aspx">SmtpFailedRecipientsException</a> or <a href="http://msdn2.microsoft.com/en-us/library/system.net.mail.smtpfailedrecipientexception.aspx">SmtpFailedRecipientException</a> is handled, it adds the e-mail address to a local List&lt;string&gt; and returns the e-mail addresses with delivery failures as a List&lt;string&gt;.</p>
<p><strong>Code snippet:</strong><br />
<a href="/image.axd?picture=WindowsLiveWriter/Sen.NETappandmaintainingalistofrecipient_123CC/image_4.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/Sen.NETappandmaintainingalistofrecipient_123CC/image_thumb_1.png" border="0" alt="image" width="604" height="543" /></a></p>
<p>When you get the List&lt;string&gt; of failed recipients, you can add your own logic to take care of maintaining your list of recipients. Maybe an e-mail address has to fail 3 times, before it is deleted, or maybe you want to delete it the first time it fails.</p>
<p>Another good thing to have in mind when sending e-mails to multiple recipients at once, is to add the mail addresses to the Bcc collection, and NOT the To or Cc collection. This way the e-mail addresses is hidden, you only get to see 'undisclosed-recipients' in you mail client:<br />
<a href="/image.axd?picture=WindowsLiveWriter/Sen.NETappandmaintainingalistofrecipient_123CC/image_6.png"><img style="border: 0px;" src="/image.axd?picture=WindowsLiveWriter/Sen.NETappandmaintainingalistofrecipient_123CC/image_thumb_2.png" border="0" alt="image" width="218" height="53" /></a></p>
<p>Note that the BulkSender class automatically clears the To, Cc and Bcc collections before adding the recipients to the Bcc collection. This way you know for sure, that you do not have any e-mail addresses publicly available when you send the e-mail.</p>
<p>You can download the code below. Feel free to tweak the class - and let me know if you have some interesting things regarding this topic.</p>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:48630124-0dcc-406f-9f7b-59632da60367" class="wlWriterSmartContent" style="display: inline; margin: 0px; padding: 0px;">Technorati Tags: <a rel="tag" href="http://technorati.com/tags/ASP.NET">ASP.NET</a>, <a rel="tag" href="http://technorati.com/tags/C#">C#</a></div>
<p><a rel="enclosure" href="/file.axd?file=BulkSender.zip">BulkSender.zip (818.00 bytes)</a></p>
<p><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fSending-e-mails-from-your-ASPNET-app-and-maintaining-a-list-of-recipients.aspx"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fSending-e-mails-from-your-ASPNET-app-and-maintaining-a-list-of-recipients.aspx" border="0" alt="kick it on DotNetKicks.com" width="82" height="18" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/sending-e-mails-from-your-asp-net-app-and-maintaining-a-list-of-recipients/feed</wfw:commentRss>
		<slash:comments>99</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>How to handle IIS Event id 1009 (Event id 5011 on IIS 7)</title>
		<link>http://martinnormark.com/how-to-handle-iis-event-id-1009-event-id-5011-on-iis-7?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/how-to-handle-iis-event-id-1009-event-id-5011-on-iis-7#comments</comments>
		<pubDate>Fri, 26 Oct 2007 17:57:00 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[IIS7]]></category>

		<guid isPermaLink="false">/post/How-to-handle-IIS-Event-id-1009-(Event-id-5011-on-IIS-7).aspx</guid>
		<description><![CDATA[Recently at work we had some serious production environment issues. Our web application basically made the IIS application pool terminate unexpectedly. And we didn't get a single stack trace or a line of code. The only thing that was logged &#8230; <p><a class="btn small" href="http://martinnormark.com/how-to-handle-iis-event-id-1009-event-id-5011-on-iis-7">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>Recently at work we had some serious production environment issues. Our web application basically made the IIS application pool terminate unexpectedly. And we didn't get a single stack trace or a line of code. The only thing that was logged inside of the Windows Event Viewer, was event id 1009, which basically told that the application pool serving our app terminated unexpectedly. And that was it. All active user sessions were wiped, and the users had to login again.</p>
<p>The error started after we did a major upgrade. A lot of our code had changed since the previous version, so we set up an new website and application pool inside IIS 6.0 for the new version, so we could upload the new application, and then turn off the old one, to get as seamless an upgrade as possible. It worked fine, and we were happy. Until a few hours later, when we saw our users were logged off.</p>
<p>At first we thought it was IIS settings we had done wrong, so we did a complete comparison with the old website and application pool to see if we forgot anything. There was no difference at all. After a while, we realized that the only thing that could make the IIS crash like that, was our own code. But with no clue of where the danger in our code were - we were lost.</p>
<p>After some time, we got WinDbg attached to the worker process of IIS, serving our application. We caught a few memory dumps, but those were not of the exception we were looking for.</p>
<p>Later I found an HttpModule for ASP.NET. Basically the .Net framework 2.0 has changed the way it handles exceptions from other threads in IIS. In ASP.NET 1.1, unhandled exceptions from asynchronous threads inside IIS were ignored. But in ASP.NET 2.0, those unhandled exceptions makes the IIS application pool crash.</p>
<h3>Make the IIS crash yourself</h3>
<p>So try to do this. Create a new ASP.NET 2.0 website running on your local IIS. You only need a single page, so you're fine with the default.aspx Visual Studio creates for you. Add a button to the page, and create an event handler for the buttons OnClick event.</p>
<p>Add this to your code-behind:</p>
<pre class="csharpcode">  <span class="rem">/// &lt;summary&gt;</span>
  <span class="rem">/// Handles the Click event of the btnMakeCrash control.</span>
  <span class="rem">/// &lt;/summary&gt;</span>
  <span class="rem">/// &lt;param name="sender"&gt;The source of the event.&lt;/param&gt;</span>
  <span class="rem">/// &lt;param name="e"&gt;The EventArgs instance containing the event data.&lt;/param&gt;</span>
  <span class="kwrd">protected</span> <span class="kwrd">void</span> btnMakeCrash_Click(<span class="kwrd">object</span> sender, EventArgs e)
  {
    ThreadPool.QueueUserWorkItem(<span class="kwrd">new</span> WaitCallback(MakeIisCrash));
  }

  <span class="rem">/// &lt;summary&gt;</span>
  <span class="rem">/// Makes the IIS crash.</span>
  <span class="rem">/// &lt;/summary&gt;</span>
  <span class="rem">/// &lt;param name="stateInfo"&gt;The state info.&lt;/param&gt;</span>
  <span class="kwrd">private</span> <span class="kwrd">void</span> MakeIisCrash(<span class="kwrd">object</span> stateInfo)
  {
    <span class="rem">// Instantiate the DataSet to null</span>
    DataSet ds = <span class="kwrd">null</span>;

    <span class="rem">// Make an unhandled NullReferenceException</span>
    ds.CaseSensitive = <span class="kwrd">true</span>;
  }</pre>
<p><!-- .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; } --></p>
<p>The buttons click event handler uses the ThreadPool to execute the MakeIisCrash() method. This method instantiates a DataSet as null, and the sets a property. Since the DataSet is null, this throws a NullReferenceException which is not handled, as you can see.</p>
<p>Click the button, and see how IIS will crash.</p>
<p>You can sense that your computer is working harder - that is because IIS terminates the application pool. If you go and check the Windows Application log, you can see that is has added an error:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/HowtohandleIISEventid1009Eventid5001onII_59F/image_2.png"><img style="border-width: 0px;" src="/image.axd?picture=WindowsLiveWriter/HowtohandleIISEventid1009Eventid5001onII_59F/image_thumb.png" border="0" alt="image" width="580" height="527" /></a></p>
<p>Now this doesn't tell you much. Imagine if you had hundreds of thousands line of code - how would you find the cause of the error?</p>
<p>Inside Visual Studio, add a new class to the website - call it UnhandledExceptionModule, and apply this code:</p>
<pre class="csharpcode"><span class="preproc">#region</span> Using

<span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Diagnostics;
<span class="kwrd">using</span> System.Globalization;
<span class="kwrd">using</span> System.IO;
<span class="kwrd">using</span> System.Runtime.InteropServices;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">using</span> System.Threading;
<span class="kwrd">using</span> System.Web;

<span class="preproc">#endregion</span>

<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Handles all unhandled exceptions from in the current AppDomain. </span>
<span class="rem">/// </span>
<span class="rem">/// Works great to catch unhandled exceptions thrown by IIS's child threads, </span><span class="rem">/// <span class="rem">which will make the </span>application pool terminate unexpectedly 

/// <span class="rem">without logging. This makes sure your Exception</span> </span><span class="rem">/// is logged to the Application event log.</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="kwrd">public</span> <span class="kwrd">class</span> UnhandledExceptionModule : IHttpModule
{
  <span class="preproc">#region</span> Fields

  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">int</span> _UnhandledExceptionCount = 0;
  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">string</span> _SourceName = <span class="kwrd">null</span>;
  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">object</span> _InitLock = <span class="kwrd">new</span> <span class="kwrd">object</span>();
  <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> _Initialized = <span class="kwrd">false</span>;

  <span class="preproc">#endregion</span>

  <span class="preproc">#region</span> IHttpModule members

  <span class="kwrd">public</span> <span class="kwrd">void</span> Init(HttpApplication app)
  {

    <span class="rem">// Do this one time for each AppDomain.</span>
    <span class="kwrd">if</span> (!_Initialized)
    {
      <span class="kwrd">lock</span> (_InitLock)
      {
        <span class="kwrd">if</span> (!_Initialized)
        {
          <span class="kwrd">string</span> webenginePath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), <span class="str">"webengine.dll"</span>);

          <span class="kwrd">if</span> (!File.Exists(webenginePath))
          {
            <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(String.Format(CultureInfo.InvariantCulture,                 <span class="str">"Failed to locate webengine.dll at '{0}'.  This module requires .NET Framework 2.0."</span>, webenginePath));
          }

          FileVersionInfo ver = FileVersionInfo.GetVersionInfo(webenginePath);
          _SourceName = <span class="kwrd">string</span>.Format(CultureInfo.InvariantCulture, <span class="str">"ASP.NET {0}.{1}.{2}.0"</span>, ver.FileMajorPart,                 ver.FileMinorPart, ver.FileBuildPart);

          <span class="kwrd">if</span> (!EventLog.SourceExists(_SourceName))
          {
            <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(String.Format(CultureInfo.InvariantCulture,                 <span class="str">"There is no EventLog source named '{0}'. This module requires .NET Framework 2.0."</span>, _SourceName));
          }

          AppDomain.CurrentDomain.UnhandledException += <span class="kwrd">new</span> UnhandledExceptionEventHandler(OnUnhandledException);

          _Initialized = <span class="kwrd">true</span>;
        }
      }
    }
  }

  <span class="kwrd">public</span> <span class="kwrd">void</span> Dispose()
  {
  }

  <span class="preproc">#endregion</span>

  <span class="preproc">#region</span> UnhandledException <span class="kwrd">event</span> handler

  <span class="kwrd">public</span> <span class="kwrd">void</span> OnUnhandledException(<span class="kwrd">object</span> o, UnhandledExceptionEventArgs e)
  {
    <span class="rem">// Let this occur one time for each AppDomain.</span>
    <span class="kwrd">if</span> (Interlocked.Exchange(<span class="kwrd">ref</span> _UnhandledExceptionCount, 1) != 0)
      <span class="kwrd">return</span>;

    StringBuilder message = <span class="kwrd">new</span> StringBuilder(<span class="str">"\r\n\r\nUnhandledException logged by UnhandledExceptionModule:\r\n\r\nappId="</span>);

    <span class="kwrd">string</span> appId = (<span class="kwrd">string</span>)AppDomain.CurrentDomain.GetData(<span class="str">".appId"</span>);
    <span class="kwrd">if</span> (appId != <span class="kwrd">null</span>)
    {
      message.Append(appId);
    }

    Exception currentException = <span class="kwrd">null</span>;
    <span class="kwrd">for</span> (currentException = (Exception)e.ExceptionObject; currentException != <span class="kwrd">null</span>; currentException = currentException.InnerException)
    {
      message.AppendFormat(<span class="str">"\r\n\r\ntype={0}\r\n\r\nmessage={1}\r\n\r\nstack=\r\n{2}\r\n\r\n"</span>,
                           currentException.GetType().FullName,
                           currentException.Message,
                           currentException.StackTrace);
    }

    EventLog Log = <span class="kwrd">new</span> EventLog();
    Log.Source = _SourceName;
    Log.WriteEntry(message.ToString(), EventLogEntryType.Error);
  }

  <span class="preproc">#endregion</span>
}</pre>
<p><!-- .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; } --></p>
<p>Modify the httpModules section inside web.config to look lige this:</p>
<pre class="csharpcode">        &lt;httpModules&gt;            &lt;add type=<span class="str">"UnhandledExceptionModule"</span> name=<span class="str">"UnhandledExceptionModule"</span>/&gt;        &lt;/httpModules&gt;</pre>
<p>This is your new friend. It is a must for any ASP.NET 2.0 application running in production environment. This will catch your exception, and write the message and the stack trace to the Windows Application Event log, and now you can see what caused the crash:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/HowtohandleIISEventid1009Eventid5001onII_59F/image_4.png"><img style="border-width: 0px;" src="/image.axd?picture=WindowsLiveWriter/HowtohandleIISEventid1009Eventid5001onII_59F/image_thumb_1.png" border="0" alt="image" width="592" height="539" /></a></p>
<p>So after we applied this HttpModule to our production environment, we get a nice entry in our Application event log from ASP.NET. It includes a stack trace, which makes us able to find the problem, and fix it!</p>
<p>Further reading regarding ASP.NET production environment issues:</p>
<ul>
<li><a href="http://blogs.msdn.com/tess/default.aspx">Tess Ferrandez</a> - She has a lot of great posts about debugging ASP.NET using <a href="http://en.wikipedia.org/wiki/WinDbg">WinDbg</a></li>
<li><a href="http://en.wikipedia.org/wiki/WinDbg">WinDbg</a></li>
<li><a href="http://blogs.msdn.com/david.wang/default.aspx">David Wang</a> - <a href="http://blogs.msdn.com/david.wang/archive/2005/08/29/HOWTO-Understand-and-Diagnose-an-AppPool-Crash.aspx">HOWTO: Understand and Diagnose an Application Pool Crash</a></li>
<li><a href="http://dotnetdebug.net/">Advanced .NET debugging</a></li>
</ul>
<p>Hope this will help someone.</p>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:751a45b8-668d-4e02-84c9-59c551706890" class="wlWriterSmartContent" style="display: inline; margin: 0px; padding: 0px;">Technorati Tags: <a rel="tag" href="http://technorati.com/tags/ASP.NET">ASP.NET</a>, <a rel="tag" href="http://technorati.com/tags/Debugging">Debugging</a>, <a rel="tag" href="http://technorati.com/tags/IIS">IIS</a>, <a rel="tag" href="http://technorati.com/tags/.NET">.NET</a></div>
<p><a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fHow-to-handle-IIS-Event-id-1009-(Event-id-5011-on-IIS-7).aspx"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.martinnormark.com%2fpost%2fHow-to-handle-IIS-Event-id-1009-(Event-id-5011-on-IIS-7).aspx" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/how-to-handle-iis-event-id-1009-event-id-5011-on-iis-7/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Web services and Silverlight 1.1 C# gotchas</title>
		<link>http://martinnormark.com/web-services-and-silverlight-1-1-c-gotchas?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/web-services-and-silverlight-1-1-c-gotchas#comments</comments>
		<pubDate>Tue, 04 Sep 2007 15:51:00 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Silverlight]]></category>

		<guid isPermaLink="false">/post/Web-services-and-Silverlight-11-C-gotchas.aspx</guid>
		<description><![CDATA[As anyone must know by now, Silverlight is Microsoft&#39;s cross-browser, cross-platform RIA (Rich Internet Application)&#160;technology - like Adobe&#39;s Flash. With Silverlight, they say the sky is the limit, and it&#39;s only up to yourself what to invent. Silverlight offers you &#8230; <p><a class="btn small" href="http://martinnormark.com/web-services-and-silverlight-1-1-c-gotchas">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>
As anyone must know by now, Silverlight is Microsoft&#39;s cross-browser, cross-platform RIA (Rich Internet Application)&nbsp;technology - like Adobe&#39;s Flash. With Silverlight, they say the sky is the limit, and it&#39;s only up to yourself what to invent. Silverlight offers you a big chunck of the .NET CLR in the browser, when using Silverlight 1.1 Alpha (Refresh). As always, there are do&#39;s and don&#39;ts when you work with new technology and in this not-known-yet-part series, I&#39;m going to recap my experience using Silverlight 1.1 Alpha and later Silverlight 1.1 Alpha Refresh to develop some sophisticated charting components.
</p>
<h2>Before you begin - general info</h2>
<p>
For the current release of Silverlight (Silverlight 1.1 Alpha Refresh) you don&#39;t have the System.Data namespace (that means no DataSets nor DataTables). Also the System.Xml namespace is very small, you don&#39;t get the XmlDocument which would have been useful. I haven&#39;t heard anything reliable about whether or not those namespaces and classes will make it into the final release of Silverlight, but it doesn&#39;t seem like it.
</p>
<p>
Maybe 3rd party components will come to help here, but that&#39;s a drawback because then the users have to install something new on their machines to be able to use your app.
</p>
<h2>Mark your webservice as a ScriptService</h2>
<p>
If you&#39;re going to use any kind of data in your Silverlight apps, and you probably are, then you have to use a webservice. Calling a webservice from Silverlight is a bit different from calling a webservice from another ASP.NET page.
</p>
<p>
First of all, you have to mark your webservice as Scriptable. The Scriptable attribute excists in the System.Web.Script.Services namespace, and is part of the ASP.NET AJAX framework (also included in the .NET Framework 3.5). If you are developing on ASP.NET 2.0, you have to make sure you have ASP.NET AJAX installed on the server, and reference the correct assemblies in your ASP.NET 2.0 application.
</p>
<p>
This is how your class definition will look like:
</p>
<pre class="csharpcode">
[WebService(Namespace = <span class="str"><a href="http://tempuri.org/">http://tempuri.org/</a></span>)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
<span class="kwrd">public</span> <span class="kwrd">class</span> SilverchartDataService : System.Web.Services.WebService{
</pre>
<pre class="csharpcode">
}
</pre>
<p>
<br />
Now your webservice can be called from Silverlight - and also JavaScript / AJAX.
</p>
<h2>Don&#39;t call a webservice on another domain</h2>
<p>
The security model of Silverlight, and also other client-side technologies, deny calling a webservice on another domain. That is also called cross-domain webservice calls, and if you do, you will get this exception when #debugging your Silverlight app using Visual Studio 2008:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/Silverlight1.1Crecipesandgotchaspart1_102EC/image.png"><img style="border-width: 0px" src="/image.axd?picture=WindowsLiveWriter/Silverlight1.1Crecipesandgotchaspart1_102EC/image_thumb.png" border="0" alt="image" width="541" height="241" /></a>
</p>
<p>
I&#39;ve seen ways to get around this problem, but it is beyond the purpose of this blog post. If you need info on this topic, try this: <a href="http://dotnetslackers.com/columns/ajax/MashitUpwithASPNETAJAX.aspx">Using a proxy to access remote APIs</a>&nbsp;(The article is for AJAX - should work for Silverlight)
</p>
<h2>JSON Serialization compatibillity with .NET</h2>
<p>
Whenever you use a webservice, all the objects transfered gets serialized. (Remember to mark your own classes as Serializable if you want to use them in your webservice.) And Silverlight uses the JSON Serialization &#39;engine&#39;. This can result in some nasty errors, yet difficult to debug. I&#39;ve found out, that some .NET classes cannot be used - these include:
</p>
<ul>
<li>decimal </li>
<li>enum (So don&#39;t use enum&#39;s with Silverlight - at least not until it is supported)</li>
</ul>
<p>
And there are probably more than those two...
</p>
<div id="0767317B-992E-4b12-91E0-4F059A8CECA8:94b31523-f28e-4a30-bc4d-93c3f9a66fce" class="wlWriterSmartContent" style="display: inline; margin: 0px; padding: 0px">
Technorati Tags: <a rel="tag" href="http://technorati.com/tags/ASP.NET">ASP.NET</a>, <a rel="tag" href="http://technorati.com/tags/C#">C#</a>, <a rel="tag" href="http://technorati.com/tags/Silverlight">Silverlight</a>, <a rel="tag" href="http://technorati.com/tags/Web%20services">Web services</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/web-services-and-silverlight-1-1-c-gotchas/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Fiddler2 and the ASP.NET Development server (Cassini)</title>
		<link>http://martinnormark.com/fiddler2-and-the-asp-net-development-server-cassini?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/fiddler2-and-the-asp-net-development-server-cassini#comments</comments>
		<pubDate>Wed, 29 Aug 2007 20:33:30 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">/post/Fiddler2-and-the-ASPNET-Development-server-(Cassini).aspx</guid>
		<description><![CDATA[If you're debugging ASP.NET apps, it can sometimes be an advantage to be able to see the actual requests, and analyze file sizes, run-time rendered code and being able to 'fiddle' with the code on run-time. Well. Fiddler2 provides extremely &#8230; <p><a class="btn small" href="http://martinnormark.com/fiddler2-and-the-asp-net-development-server-cassini">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>If you're debugging ASP.NET apps, it can sometimes be an advantage to be able to see the actual requests, and analyze file sizes, run-time rendered code and being able to 'fiddle' with the code on run-time. Well. <a href="http%3a%2f%2fwww.fiddler2.com%2ffiddler2%2f">Fiddler2</a> provides extremely useful features for doing so, but for people using the ASP.NET development server (Cassini) you have to do a few workarounds... </p>
<p>I'm running <a href="http%3a%2f%2fwww.microsoft.com%2fwindows%2fproducts%2fwinfamily%2fie%2fdefault.mspx">IE7</a> on <a href="http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2fwindowsvista%2fdefault.aspx">Windows Vista</a> (a great OS). IE7 automatically bypasses proxies for localhost, which is our main problem. When using the ASP.NET development server (Cassini), the URL looks like this one: <a href="http%3a%2f%2flocalhost%3a49950%2fapp%2fDefault.aspx">http://localhost:49950/app/Default.aspx</a>. When you open <a href="http%3a%2f%2fwww.fiddler2.com%2ffiddler2%2f">Fiddler2</a>, you see that it hasn't monitored the traffic to the localhost address. This can be fixed by applying a&nbsp;period (.) after localhost. So change the URL to this: &nbsp;<a href="http%3a%2f%2flocalhost.%3a49950%2fapp%2fDefault.aspx">http://localhost.:49950/app/Default.aspx</a> </p>
<p>In my case, that wasn't enough. I got an error from Fiddler2 in my browser. If I disabled <a href="http%3a%2f%2fwww.fiddler2.com%2ffiddler2%2f">Fiddler2</a>, it worked just fine. Then I added a rule to <a href="http%3a%2f%2fwww.fiddler2.com%2ffiddler2%2f">Fiddler2</a>. To do this, in <a href="http%3a%2f%2fwww.fiddler2.com%2ffiddler2%2f">Fiddler2</a> go to Rules &gt; Customize rules. (or hit CTRL + R). Find the OnBeforeRequest event-handler, and add the following code: </p>
<p>if (oSession.host.substr(0, 10)=="localhost.") <br />{ <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oSession.host=oSession.host.replace("localhost.", "127.0.0.1"); <br />} </p>
<p>Now - when you want to use Fiddler, just add a dot right after localhost in the URL, and Fiddler will start working! </p>
<p>That worked for me - hope it works for you too, if you're having problems. </p>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/fiddler2-and-the-asp-net-development-server-cassini/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
		<item>
		<title>Set the DataTable.Locale property – or get weird sorting</title>
		<link>http://martinnormark.com/set-the-datatable-locale-property-or-get-weird-sorting?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rss</link>
		<comments>http://martinnormark.com/set-the-datatable-locale-property-or-get-weird-sorting#comments</comments>
		<pubDate>Wed, 29 Aug 2007 18:02:59 +0000</pubDate>
		<dc:creator>Martin Normark</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">/post/Set-the-DataTableLocale-property-or-get-weird-sorting.aspx</guid>
		<description><![CDATA[If you have a monster of an ASP.NET app, and your user come from different places in the world, they are most likely to have different locales as well. I'm danish, and we have three special characters in our alphabet &#8230; <p><a class="btn small" href="http://martinnormark.com/set-the-datatable-locale-property-or-get-weird-sorting">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
			<content:encoded><![CDATA[<p>If you have a monster of an ASP.NET app, and your user come from different places in the world, they are most likely to have different locales as well. I'm danish, and we have three special characters in our alphabet - æ, ø, å. If I have a DataTable with - let's say firstname and lastname columns. I create my DataTable like this:</p>
<pre class="csharpcode">      DataTable dt = <span class="kwrd">new</span> DataTable();
      dt.Columns.Add(<span class="kwrd">new</span> DataColumn(<span class="str">"Firstname"</span>, <span class="kwrd">typeof</span>(<span class="kwrd">string</span>)));
      dt.Columns.Add(<span class="kwrd">new</span> DataColumn(<span class="str">"Lastname"</span>, <span class="kwrd">typeof</span>(<span class="kwrd">string</span>)));
      dt.Rows.Add(<span class="kwrd">new</span> <span class="kwrd">object</span>[] { <span class="str">"Øjvind"</span>, <span class="str">"Jensen"</span> });
      dt.Rows.Add(<span class="kwrd">new</span> <span class="kwrd">object</span>[] { <span class="str">"John"</span>, <span class="str">"Nielsen"</span> });
      dt.Rows.Add(<span class="kwrd">new</span> <span class="kwrd">object</span>[] { <span class="str">"Åse"</span>, <span class="str">"Østergaard"</span> });</pre>
<style type="text/css">.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; }
</style>
<p>This is how I DataBind my GridView:</p>
<pre class="csharpcode">      <span class="kwrd">if</span> (!Page.IsPostBack)
      {
        GridView1.DataSource = dt.DefaultView;
        GridView1.DataBind();
      }</pre>
<style type="text/css">.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; }
</style>
<p>With my regional settings on my machine (which in this case is also the webserver) we get the correct sorting:</p>
<p><a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/SettheDa.Localepropertyorgetweirdsorting_10C80/image_1.png" atomicselection="true"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="image" src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/SettheDa.Localepropertyorgetweirdsorting_10C80/image_thumb_1.png" width="240" border="0"></a> <br /><em>The GridView sorted by Firstname ascending.</em></p>
<p>But if I go ahead and change the settings of my machine, to English (United States), my GridView will look like this, when I sort it by Firstname ascending:</p>
<p><a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/SettheDa.Localepropertyorgetweirdsorting_10C80/image_2.png" atomicselection="true"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="220" alt="image" src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/SettheDa.Localepropertyorgetweirdsorting_10C80/image_thumb_2.png" width="245" border="0"></a> </p>
<p>This is because the server compares the strings wrong. So if you're dealing with users from around the globe - you have to set the Locale property of the DataTable - this is done like this:</p>
<pre class="csharpcode">dt.Locale = System.Globalization.CultureInfo.CurrentCulture;</pre>
<p>Now this I cannot test on a single machine. This is because the above code takes the CultureInfo of your machine, and since I just changed my regional settings, I get the GridView sorted wrong. So I fired up my old laptop, this time with FireFox the GridView looks like this:</p>
<p><a href="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/SettheDa.Localepropertyorgetweirdsorting_10C80/image_4.png" atomicselection="true"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="image" src="http://www.martinnormark.com/image.axd?picture=WindowsLiveWriter/SettheDa.Localepropertyorgetweirdsorting_10C80/image_thumb_4.png" width="249" border="0"></a> </p>
<p>From a user perspective, a GridView sorted incorrectly is very bad. So to add this single line of code is really not a big deal.</p>
<div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:cf161429-e369-47f0-883d-0150c69a7cd2" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/ASP.NET" rel="tag">ASP.NET</a>, <a href="http://technorati.com/tags/C#" rel="tag">C#</a>, <a href="http://technorati.com/tags/DataTable" rel="tag">DataTable</a>, <a href="http://technorati.com/tags/CultureInfo" rel="tag">CultureInfo</a></div>
]]></content:encoded>
			<wfw:commentRss>http://martinnormark.com/set-the-datatable-locale-property-or-get-weird-sorting/feed</wfw:commentRss>
		<slash:comments>44</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
	</item>
	</channel>
</rss>

