<?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/"
	>

<channel>
	<title>Temp Folder - Mostly .NET</title>
	<atom:link href="http://sim4all.com/blogging/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://sim4all.com/blogging</link>
	<description>I hate fixing problems, prefer preventing them.</description>
	<lastBuildDate>Mon, 11 Jun 2012 01:15:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Running TestSwarm in WebMatrix</title>
		<link>http://sim4all.com/blogging/?p=373</link>
		<comments>http://sim4all.com/blogging/?p=373#comments</comments>
		<pubDate>Mon, 11 Jun 2012 01:01:34 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[IIS Express]]></category>
		<category><![CDATA[JavaScript Unit Testing]]></category>
		<category><![CDATA[TestSwram]]></category>
		<category><![CDATA[WebMatrix]]></category>
		<category><![CDATA[TestSwarm]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=373</guid>
		<description><![CDATA[For last few weeks I have been exploring a subject of JavaScript Unit Testing. I looked at testing frameworks, runners, IDE and CI integration. One of the last items on my list of topics to explore was to find production &#8230; <a href="http://sim4all.com/blogging/?p=373">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For last few weeks I have been exploring a subject of JavaScript Unit Testing. I looked at testing frameworks, runners, IDE and CI integration. One of the last items on my list of topics to explore was to find production ready solutions for continuous integration scenarios. Because I work in Microsoft .NET environment CI integration seemed to be a rather uncharted territory. This post describes my experience with getting TestSwarm to run in windows centric settings. </p>
<p>The next two paragraphs describe what <strong><a href="https://github.com/jquery/testswarm" title="TestSwarm" target="_blank">TestSwarm</a></strong> is and why it might be an important to learn about it, a rationale behind the whole effort.</p>
<p><strong><a href="https://github.com/jquery/testswarm" title="TestSwarm" target="_blank">TestSwarm</a></strong>, <strong><a href="http://ejohn.org/" title="John Resig" target="_blank">John Resig’s</a></strong> open source project for supporting distributed continuous integration testing for JavaScript, while still in an alpha development stage, generates a lot of interest among web UI developers and project managers. As UI development shifts towards client side technologies, particularly JavaScript, the need for the same level of support that has been in place, for many years already, for server side technologies  is now expected for client side development as well. </p>
<p>JavaScript unit testing has been used for quite some time now. There are more than a few established unit testing frameworks and IDE support for some of them is either available or in works. Missing though is support for running JavaScript unit tests in continuous integration scenarios. Before the <strong>TestSwarm</strong> the most popular option for handling CI scenarios seemed to be using <strong><a href="http://code.google.com/p/js-test-driver/" title="JSTestDriver" target="_blank">JSTesDriver</a></strong> from <strong>Google</strong>. One inconvenience of using <strong>JSTestDriver</strong> is the need for developing an adapter to integrate a unit testing framework and <strong>JSTestDriver</strong> runner. When a framework and a runner evolve, quite a bit of maintenance overhead is being added for keeping them both in synch (updating an adapter). In contrast, <strong>TestSwarm</strong> integration is framework independent. The only moving part is a script that needs to understand test results. Thus, it seems that <strong>TestSwarm</strong> should be considered a serious player in the area of JavaScript Unit Testing and Continuous Integration.</p>
<p>Back to technology then, these are the parts that will be needed:</p>
<ul>
<li><a href="https://github.com/jquery/testswarm" title="TestSwarm Code"><strong>TestSwarm</strong></a></li>
<li><a href="http://www.microsoft.com/web/" title="WebMatrix" target="_blank"><strong>WebMatrix</strong></a></li>
<li><a href="http://www.microsoft.com/web/gallery/categories.aspx" title="WordPress" target="_blank"><strong>WordPress</strong></a> it&#8217;s an easy way of getting PHP and MySQL on windows machine and you will have some PHP code to look at or compare if needed.</li>
<li><a href="http://www.mysql.com/products/workbench/" title="MySQL Workbench" target="_blank"><strong>MySQL Workbench</strong></a> if you need GUI for MySQL management tasks.</li>
<li><a href="http://www.iis.net/download/URLRewrite" title="IIS URL Rewrite Module" target="_blank"><strong>IIS URL Rewrite Module</strong></a></strong> to get import Apache <strong>.htaccess</strong> url rewriting rules into <strong>IIS Express</strong> .</li>
<li><a href="http://docs.jquery.com/QUnit" title="QUnit" target="_blank"><strong>QUnit</strong></a>for creating demo JavaScript unit testing project.</li>
</ul>
<p>Getting it all working:</p>
<p><strong>Step 1.</strong></p>
<p>In WebMatrix open directory with TestSwarm files downloaded from git repository. Read TestSwarm configuration instructions either in <em>ReadMe</em>file or in <em>Wiki</em>. I used <em>WebMatrix</em> to run the <em>TestSwarm</em> which means that <em>IIS Express</em> was used as a web server and that <em>TestSwarm</em> ran in the root of the site (on random port).<br />
In <strong>testswarm.json</strong> I needed to modify <em>contextpath</em>&#8220;: &#8220;<strong>/testswarm</strong>&#8221; to <em>contextpath</em>&#8220;: &#8220;<strong>/</strong>&#8220;. Otherwise, images and css would not load correctly. <em>TestSwarm </em>application depends on url rewriting rules in .htaccess file. Use IIS URL Rewrite extension to Import those rules to IIS. Just copy the results from the Import screen and add them to your IIS Express configuration file. Delete this: <em>RewriteEngine On RewriteBase /</em> from <strong>Rewrite Rules</strong> box to make the error seen in <strong>Converted Rules</strong> box disappear.</p>
<div id="attachment_385" class="wp-caption aligncenter" style="width: 289px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/RewiteRules.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/RewiteRules-279x300.png" alt="Import Rewrite Rules" title="Import Rewrite Rules" width="279" height="300" class="size-medium wp-image-385" /></a><p class="wp-caption-text">Import Rewrite Rules</p></div>
<p>Add the ruele to IIS Express configuration file (<strong>applicationhost.config</strong>) which should be located in C:\Users\<em>yourUserName</em>\Documents\IISExpress\config folder. The section shown below should be added at the end of that configuration file.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;location path=&quot;testswarm&quot;&gt;
        &lt;system.webServer&gt;

&lt;rewrite&gt;
            &lt;rules&gt;
                &lt;rule name=&quot;Imported Rule 1&quot; stopProcessing=&quot;true&quot;&gt;
                    &lt;match url=&quot;^&quot; ignoreCase=&quot;false&quot; /&gt;
                    &lt;conditions logicalGrouping=&quot;MatchAny&quot;&gt;
                        &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsFile&quot; ignoreCase=&quot;false&quot; /&gt;
                        &lt;add input=&quot;{REQUEST_FILENAME}&quot; matchType=&quot;IsDirectory&quot; ignoreCase=&quot;false&quot; /&gt;
                    &lt;/conditions&gt;
                    &lt;action type=&quot;None&quot; /&gt;
                &lt;/rule&gt;
                &lt;rule name=&quot;Imported Rule 2&quot;&gt;
                    &lt;match url=&quot;^(.*)/$&quot; ignoreCase=&quot;false&quot; /&gt;
                    &lt;action type=&quot;Redirect&quot; url=&quot;{R:1}&quot; appendQueryString=&quot;true&quot; redirectType=&quot;Permanent&quot; /&gt;
                &lt;/rule&gt;
                &lt;rule name=&quot;Imported Rule 3&quot;&gt;
                    &lt;match url=&quot;^([a-z]*)$&quot; ignoreCase=&quot;false&quot; /&gt;
                    &lt;action type=&quot;Rewrite&quot; url=&quot;index.php?action={R:1}&quot; appendQueryString=&quot;true&quot; /&gt;
                &lt;/rule&gt;
                &lt;rule name=&quot;Imported Rule 4&quot;&gt;
                    &lt;match url=&quot;^([a-z]*)/(.*)$&quot; ignoreCase=&quot;false&quot; /&gt;
                    &lt;action type=&quot;Rewrite&quot; url=&quot;index.php?action={R:1}&amp;amp;item={R:2}&quot; appendQueryString=&quot;true&quot; /&gt;
                &lt;/rule&gt;
            &lt;/rules&gt;
        &lt;/rewrite&gt;

        &lt;/system.webServer&gt;
    &lt;/location&gt;
</pre>
<p>At this point TestSwarm should be looking like working. It should load pages and images. But, you still would not be able to add jobs or run any tests.</p>
<p><strong>Step 2.</strong></p>
<p>Go to <em>http://localhost:51336/signup</em> to create a user account (just notice <em>51336</em> is a random port number, yours will be different).<br />
Your account should get created and when you open <em>MySQL Workbench</em> and navigate to a table you should see an entry in a <strong>users</strong> table.<br />
The important thing to note about the user data is to copy the value from &#8220;<strong>auth</strong>&#8221; column. It will be needed for crating jobs. If you do not see a value of that field but just a &#8220;BLOB&#8221; word, go to <strong>Edit</strong> &#8211;> <strong>Preferences</strong> an open <strong>SQL Editor Tab</strong> and check &#8220;<em>Treat BINARY/VARBINARY as nonbinary character string</em>&#8220;.</p>
<div id="attachment_395" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/SQLEditor.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/SQLEditor-300x289.png" alt="SQL Editor" title="SQL Editor" width="300" height="289" class="size-medium wp-image-395" /></a><p class="wp-caption-text">SQL Editor</p></div>
<p>Now, you should be ready for adding jobs.</p>
<p><strong>Step 3.</strong><br />
Before you can actually add a job you need to have a JavaScript code to test. So, create a web application and add a JavaScript file to it. Next, decide which JavaScript unit testing framework you are going to use. My recommendation is to use <strong>QUnit</strong> as it&#8217;s one with greatest support in TestSwarm. For start, you just want to get things running. Next, create a unit test for your script. Verify that the tests passes. </p>
<p>Copy a <strong>inject.js</strong> from a <strong>js</strong> folder in <strong>TestSwarm</strong> to your demo application and make sure to add a link to it in a <em>QUnit</em> test <em>html</em> file.</p>
<p>The head tag in a test html file should look like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;head&gt;
    &lt;meta http-equiv=&quot;cache-control&quot; content=&quot;no-cache&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=Edge&quot;&gt;

    &lt;title&gt;QUnit Testing&lt;/title&gt;
    &lt;link href=&quot;qunit.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
    &lt;script src=&quot;qunit.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;inject.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
</pre>
<p>You are still not ready, at least very likely, for adding jobs though. Go to the next step to see what else might be missing.</p>
<p><strong>Step 4.</strong></p>
<p>On my installation I ran into a problem. Adding jobs failed because a <strong>results</strong> column in <em>run_client</em> table would not allow <em>NULL</em> and somehow a <em>NULL</em> was being inserted. <strong>Results</strong> column is a <em>TEXT</em> field and a default value of <em>empty string</em> cannot be set on it. It&#8217;s probably an issue with MySQL version. So, I modified the column and made it <em>nullable</em>.</p>
<div id="attachment_400" class="wp-caption aligncenter" style="width: 143px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/ResultsColumn.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/ResultsColumn-133x300.png" alt="Results Column" title="Results Column" width="133" height="300" class="size-medium wp-image-400" /></a><p class="wp-caption-text">Results Column</p></div>
<p><strong>Step 4.</strong></p>
<p>Go to <em>http://localhost:51336/addjob</em> page and enter the required information. For start, I would suggest to check <em>desktop browsers</em> option, it will be easier to analyze the data changes in a database in a response to TestSwarm UI actions. Also, enter only one run. It will be easier to troubleshoot if things do not go right. In the <em>URL</em> field for the run enter the URL of the <strong>test</strong> <em>html</em> page from your <em>demo web app</em>.</p>
<p>All should work now and you should see this confirmation message:</p>
<div id="attachment_403" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/AddJob.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/AddJob-300x91.png" alt="Add Job" title="Add Job" width="300" height="91" class="size-medium wp-image-403" /></a><p class="wp-caption-text">Add Job</p></div>
<p><strong>Step 5.</strong></p>
<p>You ready to add agents (browsers) for running jobs now. Navigate to <em>http://localhost:51336/run/testuser2</em> (<em>testuser2</em> needs to be a username that you created in <strong>step 2</strong>) in your choice of the browser and you should see the message that a job run. Do the same for other browsers and you should similar messages.</p>
<p>Now if you go to <em>http://localhost:51336/job/6</em> (<strong>6</strong> is my job number, yours might be different of course, it&#8217;s just <em>RESTful Url</em>) you will see a page looking like this:</p>
<div id="attachment_404" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/JobStatus.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/JobStatus-300x92.png" alt="Job Status" title="Job Status" width="300" height="92" class="size-medium wp-image-404" /></a><p class="wp-caption-text">Job Status</p></div>
<p>In this particular case you can see that runs in IE, Opera and Safari succeeded and that other agents are probably not available or have not been run yet. You can click on a note icon to see the details of the run. The details will be just html form a QUnit test page, see example below.</p>
<div id="attachment_405" class="wp-caption aligncenter" style="width: 269px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/RunDetails.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/RunDetails-259x300.png" alt="Run Details" title="Run Details" width="259" height="300" class="size-medium wp-image-405" /></a><p class="wp-caption-text">Run Details</p></div>
<p><strong>Read this if things still do not work</strong></p>
<p>If it looks like you still cannot run jobs. Here is another hint, something that I did to make attaching clients work on my system. I had a problem with a call to <em>gzencode</em> (line <strong>57</strong> in <em>SeverunAction.php</em> file.</p>
<div id="attachment_406" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/ServerunAction.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/ServerunAction-300x264.png" alt="ServerunAction.php page" title="ServerunAction.php page" width="300" height="264" class="size-medium wp-image-406" /></a><p class="wp-caption-text">ServerunAction.php page</p></div>
<p>I modified that line (<strong>57</strong>) to be like <strong>58</strong>.</p>
<pre class="brush: php; title: ; notranslate">
57. // $results = gzencode( $request-&gt;getVal( &quot;results&quot;, &quot;&quot; ) );
58. $results = $request-&gt;getVal( &quot;results&quot;, &quot;&quot; );
</pre>
<p>and to make things symmetrical also had to modify (comment out) a line <strong>37</strong>  </p>
<pre class="brush: php; title: ; notranslate">

36. header( &quot;Content-Type: text/html; charset=utf-8&quot; );
37. // header( &quot;Content-Encoding: gzip&quot; );
</pre>
<p>in <em>ResultsPage.php</em></p>
<div id="attachment_407" class="wp-caption aligncenter" style="width: 210px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/06/ResultsPage.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/06/ResultsPage-200x300.png" alt="Results Page" title="Results Page" width="200" height="300" class="size-medium wp-image-407" /></a><p class="wp-caption-text">Results Page</p></div>
<p>In the end all troubles with a NULL in a Results table and trouble with <strong>gzip</strong> encoding might have been a LINUX vs Windows issue (I did not investigate a root cause, just tried to get things running).</p>
<p><strong>Summary</strong><br />
The goal of this blog post was to show how to setup a <strong>TestSwarm</strong> with <strong>WebMatrix</strong>. Setting up TestSwarm in <strong>CI</strong> scenario would require more effort but steps would be very similar. Also, one easy step to take would be to use <strong>SQL Express</strong> in place of <strong>MySQL</strong>. Converting <strong>PHP</strong> code to <strong>MVC Razor</strong> syntax would be probably more difficult but also very likely some fun. </p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=373</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bing Maps Ajax Control 7.0 Widget – Search, Zoom and Undo</title>
		<link>http://sim4all.com/blogging/?p=352</link>
		<comments>http://sim4all.com/blogging/?p=352#comments</comments>
		<pubDate>Sun, 01 Apr 2012 03:35:03 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Bing Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Widget]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=352</guid>
		<description><![CDATA[This is part 3 of the Bing Maps Ajax Control 7.0 Widget. Part 2 can be found here: Bing Maps Ajax Control 7.0 Widget – Drawing Circles and Rectangles. Refer to the previous post for the introduction. In this part &#8230; <a href="http://sim4all.com/blogging/?p=352">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is part 3 of the <strong>Bing Maps Ajax Control 7.0 Widget</strong>. Part <strong>2</strong> can be found here:  <a href="http://sim4all.com/blogging/?p=319" title="Bing Maps Ajax Control 7.0 Widget – Drawing Circles and Rectangles">Bing Maps Ajax Control 7.0 Widget – Drawing Circles and Rectangles</a>. Refer to the previous post for the introduction. In this part I will quickly show how to add Find Location, Rectangle Zooming and Undo functionality. </p>
<p>First we need to add  few controls to  the HTML page hosting Bing Maps Control:</p>
<pre class="brush: xml; highlight: [18,19,20,21,22,23]; title: ; notranslate">
&lt;!doctype html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Bings Map Widget Demo&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;scripts/jquery-1.7.1.js&quot;&gt;&lt;/script&gt;
        &lt;script src=&quot;http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.min.js&quot;&gt;&lt;/script&gt;
    &lt;/head&gt;
&lt;body&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnLineDrawCustom&quot;&gt;Draw Line&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnPolyDrawCustom&quot;&gt;Draw Polygon&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnRectangleDrawCustom&quot;&gt;Draw Rectangle&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnCircleDrawCustom&quot;&gt;Draw Circle&lt;/button&gt;
    &lt;input type=&quot;text&quot; id=&quot;txtRadius&quot; value=&quot;5&quot; size=&quot;3&quot; /&gt;
            &lt;select id=&quot;ddlRadius&quot;&gt;
				&lt;option value=&quot;m&quot; selected=&quot;selected&quot;&gt;miles&lt;/option&gt;
				&lt;option value=&quot;k&quot;&gt;kilometers&lt;/option&gt;
            &lt;/select&gt;&lt;button type=&quot;button&quot; id=&quot;btnCircleDrawWithRadiusCustom&quot;&gt;Draw Circle with Radius&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnCancel&quot;&gt;Cancel Last Action&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnClearAll&quot;&gt;Clear All&lt;/button&gt;
    &lt;br /&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnZoomToRectangle&quot;&gt;Zoom To Rectangle&lt;/button&gt;
    &lt;input type=&quot;text&quot; id=&quot;txtSearch&quot; size=&quot;30&quot; value=&quot;College Park, md&quot; /&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnFindOnMap&quot;&gt;Find Location&lt;/button&gt;
   &lt;hr /&gt;
    &lt;div id=&quot;bingMapsToolbox&quot; /&gt;
    &lt;div id='mapDiv' name='mapDiv' style=&quot;position:relative; float: left;&quot;/&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/cm-utils.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/cm-widgets.bingMaps7.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/startup.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
</pre>
<p>In a startup script buttons click events are bound to method calls on the Bing Maps Widget:</p>
<pre class="brush: jscript; title: ; notranslate">
 (&quot;#btnCancel&quot;).bind('click', function () {
     bingMaps7.bingMaps7('cancelLastAction'); return false;
 });
 $(&quot;#btnClearAll&quot;).bind('click', function () {
     bingMaps7.bingMaps7('clearMap'); return false;
 });
 $(&quot;#btnZoomToRectangle&quot;).bind('click', function () {
     bingMaps7.bingMaps7('zoomToRectangle'); return false;
 });
 $(&quot;#btnFindOnMap&quot;).bind('click', function () {
    bingMaps7.bingMaps7('findOnMap', $(&quot;#txtSearch&quot;).val()); return false;
 });
</pre>
<p>The new methods added to the Widget to handle new functionality:</p>
<h3>Clear All</h3>
<pre class="brush: jscript; title: ; notranslate">
 clearMap: function () {
            logger.log(&quot;clearMap&quot;);
            that._detachEventHandlers();
            pushpins.clear();
            polylines.clear();
            shapes.clear();
        },
</pre>
<h3>Undo Last Action</h3>
<pre class="brush: jscript; title: ; notranslate">
cancelLastAction: function () {
            that._detachEventHandlers();
            logger.log(&quot;cancelLastAction&quot;);
            logger.log(&quot;pushpins to clear: &quot; + pushPinsStack.getLength());
            logger.log(&quot;polylines to clear: &quot; + polylinesStack.getLength());
            logger.log(&quot;shapes to clear: &quot; + shapesStack.getLength());

            while (true) {
                var pp = pushPinsStack.pop();
                if (pp == null) break;
                pushpins.remove(pp);
            }

            while (true) {
                var pl = polylinesStack.pop();
                if (pl == null) break;
                polylines.remove(pl);
            }

            while (true) {
                var sh = shapesStack.pop();
                if (sh == null) break;
                shapes.remove(sh);
            }

        },
</pre>
<h3>Zoom To Rectangle</h3>
<pre class="brush: jscript; title: ; notranslate">
zoomToRectangle: function () {
            that._initializeMapAction(&quot;zoomToRectangle&quot;);

            points = [];
            var point1, point2, lastPoint;
            var isCapturingMouse = false;

            var handleRectangleZooming = function (e) {
                logger.log(&quot;handleRectangleZooming&quot;);
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);

                if (e.eventName === &quot;mousedown&quot;) {
                    point1 = new MM.Point(e.getX(), e.getY());
                    lastPoint = point1;
                    isCapturingMouse = true;
                    that._addHandler(mapMousemoveEventName, handleRectangleZooming);
                } else if (isCapturingMouse &amp;&amp; e.eventName === &quot;mousemove&quot;) {
                    point2 = new MM.Point(e.getX(), e.getY());
                    if (!that._arePointsEqual(lastPoint, point2)) {
                        points = that._getRectangleVertices(point1, point2);
                        points.push(points[0].clone());
                        logger.log(&quot;Poly Line Points Count: &quot; + points.length);
                        that._createPolyLine(points, lastPoint !== point1);
                        lastPoint = point2;
                    }
                } else if (e.eventName === &quot;mouseup&quot;) {
                    that._detachEventHandlers();
                    logger.log(&quot;Finshing Zoom Rectangle ....&quot;);
                    isCapturingMouse = false;
                    point2 = new MM.Point(e.getX(), e.getY());
                    var withReplace = false;
                    if (!that._arePointsEqual(lastPoint, point2)) {
                        lastPoint = point2;
                        points = that._getRectangleVertices(point1, point2);
                        withReplace = true;
                    }
                    var drawRectangle = points.length &gt; 0;
                    if (drawRectangle) {
                        points.push(points[0].clone());
                        that._createPolyLine(points, withReplace);

                        var cornerLocationA = map.tryPixelToLocation(points[0]);
                        var cornerLocationB = map.tryPixelToLocation(points[2]);
                        var viewRect = MM.LocationRect.fromCorners(cornerLocationA, cornerLocationB);
                        map.setView({ bounds: viewRect });
                        that.cancelLastAction();
                    } else {
                        logger.log(&quot;No rectangle to zoom into....;&quot;);
                    }
                    map.setOptions({ disablePanning: false, disableZooming: false });
                }
            }

            that._addHandler(mapMousedownEventName, handleRectangleZooming);
            that._addHandler(mapMouseupEventName, handleRectangleZooming);
        },
</pre>
<h3>Find Location</h3>
<pre class="brush: jscript; title: ; notranslate">
findOnMap: function (searchTerm) {
            that._initializeMapAction(&quot;findOnMap&quot;);

            function geocode() {
                map.getCredentials(makeGeocodeRequest);
            }

            function makeGeocodeRequest(credentials) {

                var geocodeRequest = &quot;http://dev.virtualearth.net/REST/v1/Locations?query=&quot; + encodeURI(searchTerm) + &quot;&amp;key=&quot; + credentials;
                $.ajax({
                    url: geocodeRequest,
                    dataType: 'jsonp',
                    jsonp: 'jsonp',
                    success: function (result) {
                        if (result &amp;&amp;
                                result.resourceSets &amp;&amp;
                                result.resourceSets.length &gt; 0 &amp;&amp;
                                result.resourceSets[0].resources &amp;&amp;
                                result.resourceSets[0].resources.length &gt; 0) {

                            var bbox = result.resourceSets[0].resources[0].bbox;
                            var viewBoundaries = MM.LocationRect.fromLocations(new MM.Location(bbox[0], bbox[1]), new MM.Location(bbox[2], bbox[3]));
                            map.setView({ bounds: viewBoundaries });

                            var location = new MM.Location(result.resourceSets[0].resources[0].point.coordinates[0], result.resourceSets[0].resources[0].point.coordinates[1]);
                            that._createPushpinFromLocation(location);
                            map.setOptions({ disablePanning: false, disableZooming: false });
                        }
                    }
                });
            }
            geocode();
        },
</pre>
<p>In the next post I will create a slick UI for the widget with <a href="http://www.kendoui.com/?utm_source=telerik&#038;utm_medium=index-divs&#038;utm_campaign=box" target="_blank">Kendo UI</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=352</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bing Maps Ajax Control 7.0 Widget – Drawing Circles and Rectangles</title>
		<link>http://sim4all.com/blogging/?p=319</link>
		<comments>http://sim4all.com/blogging/?p=319#comments</comments>
		<pubDate>Sun, 26 Feb 2012 16:34:59 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Bing Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Widget]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=319</guid>
		<description><![CDATA[This is part 2 of the Bing Maps Ajax Control 7.0 Widget. Part 1 can be found here: Bing Maps Ajax Control 7.0 Widget – Drawing Lines and Polygons. Refer to the previous post for the introduction. In this part &#8230; <a href="http://sim4all.com/blogging/?p=319">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is part 2 of the <strong>Bing Maps Ajax Control 7.0 Widget</strong>. Part <strong>1</strong> can be found here:  <a href="http://sim4all.com/blogging/?p=297" title="Bing Maps Ajax Control 7.0 Widget – Drawing Lines and Polygons">Bing Maps Ajax Control 7.0 Widget – Drawing Lines and Polygons</a>. Refer to the previous post for the introduction. In this part I will quickly show how to add rectangle and circle drawing capability. </p>
<p>First we need to add  few controls to  the HTML page hosting Bing Maps Control:</p>
<pre class="brush: xml; highlight: [11,12,13,14,15,16,17]; title: ; notranslate">
&lt;!doctype html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Bings Map Widget Demo&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;scripts/jquery-1.7.1.js&quot;&gt;&lt;/script&gt;
        &lt;script src=&quot;http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.min.js&quot;&gt;&lt;/script&gt;
    &lt;/head&gt;
&lt;body&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnLineDrawCustom&quot;&gt;Draw Line&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnPolyDrawCustom&quot;&gt;Draw Polygon&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnRectangleDrawCustom&quot;&gt;Draw Rectangle&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnCircleDrawCustom&quot;&gt;Draw Circle&lt;/button&gt;
    &lt;input type=&quot;text&quot; id=&quot;txtRadius&quot; value=&quot;5&quot; size=&quot;3&quot; /&gt;
            &lt;select id=&quot;ddlRadius&quot;&gt;
				&lt;option value=&quot;m&quot; selected=&quot;selected&quot;&gt;miles&lt;/option&gt;
				&lt;option value=&quot;k&quot;&gt;kilometers&lt;/option&gt;
            &lt;/select&gt;&lt;button type=&quot;button&quot; id=&quot;btnCircleDrawWithRadiusCustom&quot;&gt;Draw Circle with Radius&lt;/button&gt;
   &lt;hr /&gt;
    &lt;div id=&quot;bingMapsToolbox&quot; /&gt;
    &lt;div id='mapDiv' name='mapDiv' style=&quot;position:relative; float: left;&quot;/&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/cm-utils.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/cm-widgets.bingMaps7.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/startup.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
</pre>
<p>Next we need to add a little bit of the jQuery code to the startup script to bind buttons click events to method calls on the Bing Maps Widget:</p>
<pre class="brush: jscript; highlight: [14,15,16,17,18,19,20,21,22,23,24,25]; title: ; notranslate">
(function ($) {
    $(document).ready(function () {
        var bingMaps7 = $(&quot;#mapDiv&quot;).bingMaps7({
            appKey: &quot;Your Bing Maps Key&quot;,
            zoom: 12, centerX: 38.809771, centerY: -77.0321543125,
            width: 1000, height: 800
        });
        $(&quot;#btnLineDrawCustom&quot;).bind('click', function () {
             bingMaps7.bingMaps7('drawLine'); return false;
        });
        $(&quot;#btnPolyDrawCustom&quot;).bind('click', function () {
             bingMaps7.bingMaps7('drawPolygon'); return false;
        });
        $(&quot;#btnRectangleDrawCustom&quot;).bind('click', function () {
             bingMaps7.bingMaps7('drawRectangle'); return false;
        });
        $(&quot;#btnCircleDrawCustom&quot;).bind('click', function () {
             bingMaps7.bingMaps7('drawCircle'); return false;
        });
        $(&quot;#btnCircleDrawWithRadiusCustom&quot;).bind('click', function () {
            bingMaps7.bingMaps7('drawCircleWithRadius',
                $(&quot;#txtRadius&quot;).val(),
                $(&quot;#ddlRadius :selected&quot;).val());
            return false;
        });
    });

} (jQuery));
</pre>
<p>The last step is to add rectangle and circle drawing code to the widget. Notice that I added a new class to the widget to handle finding locations on the circle given the center and the point somewhere on the circumference. I found the code for handling it in few blog posts and modified it slightly. Notice: <em>Drawing a circle with a predefined radius requires selection of the Unit</em>.</p>
<pre class="brush: jscript; highlight: [28,110,325,393,395,455,457,488]; title: ; notranslate">
(function ($) {
    var map,
       mapDiv,
       jqMapDiv,
       that,
       actionType,
       step,
       points,
       lineDrawingStyle,
       polyDrawingStyle,
       polyFillStyle,
       pushpins,
       polylines,
       shapes,
       mapClickEventHandler = null,
       mapMouseDownEventHandler = null,
       mapMouseUpEventHandler = null,
       mapMouseMoveEventHandler = null,
       mapClickEventName = 'click',
       mapMousedownEventName = 'mousedown',
       mapMouseupEventName = 'mouseup',
       mapMousemoveEventName = 'mousemove',
       logger;

    //console.log(&quot;Start up&quot;);
    var MM = Microsoft.Maps;

    var bingUtils = {
        BingMapsHelper: function () {
            //console.log(&quot;BingMapsHelper&quot;);
            this.EarthRadiusInMiles = 3956.0;
            this.EarthRadiusInKilometers = 6367.0;
            this.rad = Math.PI / 180;
            this.invRad = 180 / Math.PI;
            this.angleToRadian = function (angle) {
                 return angle * this.rad;
            };
            this.radianToAngle = function (radian) {
                 return radian * this.invRad;
            };
            this.edgeSegment = 0.1;
            this.useEdgeSegment = false;

            this.getLocationsOnCircle = function (pointA, pointB) {
                var location1 = map.tryPixelToLocation(pointA);
                var location2 = map.tryPixelToLocation(pointB);

                var lat = this.angleToRadian(location1.latitude);
                var lon = this.angleToRadian(location1.longitude);
                var locs = [];
                var distanceInRadians = this.getDistanceInRadians(location1, location2);
                var latRadians, lngRadians;
                if (this.useEdgeSegment &amp;&amp; this.edgeSegment) {
                    logger.log(&quot;Creating Circle with specified edge segment length of: &quot;
                        + this.edgeSegment);
                    var limit = Math.ceil(2 * Math.PI / this.edgeSegment)
                        + this.edgeSegment;
                    logger.log(&quot;Limit is: &quot; + limit);
                    var rds, rd; //, i = 0;
                    for (rds = 0; rds &lt;= limit; rds += this.edgeSegment) {
                        rd = this.edgeSegment * rds;
                        //i++;
                        latRadians = Math.asin(Math.sin(lat) * Math.cos(distanceInRadians)
                            + Math.cos(lat) * Math.sin(distanceInRadians) * Math.cos(rd));
                        lngRadians = lon + Math.atan2(Math.sin(rd) * Math.sin(distanceInRadians) * Math.cos(lat),
                            Math.cos(distanceInRadians) - Math.sin(lat) * Math.sin(latRadians));
                        locs.push(new MM.Location(this.radianToAngle(latRadians),
                            this.radianToAngle(lngRadians)));
                    }
                } else {
                    logger.log(&quot;Creating Circle with 1 deg step&quot;);
                    for (var deg = 0; deg &lt;= 360; deg += 1) {
                        var degAsRadian = this.angleToRadian(deg);
                        latRadians = Math.asin(Math.sin(lat) * Math.cos(distanceInRadians)
                            + Math.cos(lat) * Math.sin(distanceInRadians) * Math.cos(degAsRadian));
                        lngRadians = lon + Math.atan2(Math.sin(degAsRadian) * Math.sin(distanceInRadians) * Math.cos(lat),
                            Math.cos(distanceInRadians) - Math.sin(lat) * Math.sin(latRadians));
                        locs.push(new MM.Location(this.radianToAngle(latRadians), this.radianToAngle(lngRadians)));
                    }
                }
                logger.log(&quot;Created &quot; + locs.length + &quot; points.&quot;);
                return locs;
            };

            this.getLocationsOnCircleWithRadius = function (originPoint, radius, unit) {
                logger.log(&quot;Get Locations on Circle with given Radius&quot;);
                logger.log(&quot;Origin: &quot; + originPoint + &quot;, Radius: &quot; + radius + &quot;, Unit: &quot; + unit);
                var earthRadius = unit === &quot;m&quot; ? this.EarthRadiusInMiles : this.EarthRadiusInKilometers;
                var originLocation = map.tryPixelToLocation(originPoint);
                var distanceAsAngle = parseFloat(radius) / earthRadius;
                var lat = this.angleToRadian(originLocation.latitude);
                var lon = this.angleToRadian(originLocation.longitude);
                var latRadians = Math.asin(Math.sin(lat) * Math.cos(distanceAsAngle)
                    + Math.cos(lat) * Math.sin(distanceAsAngle) * Math.cos(0));
                var lngRadians = lon + Math.atan2(Math.sin(0) * Math.sin(distanceAsAngle) * Math.cos(lat),
                    Math.cos(distanceAsAngle) - Math.sin(lat) * Math.sin(latRadians));
                var secondLocation = new MM.Location(this.radianToAngle(latRadians),
                    this.radianToAngle(lngRadians));
                var secondPoint = map.tryLocationToPixel(secondLocation);
                return this.getLocationsOnCircle(originPoint, secondPoint);
            };

            this.getDistanceInRadians = function (location1, location2) {
                return 2 * Math.asin(Math.min(1, Math.sqrt((Math.pow(Math.sin((this.angleToRadian(location2.latitude)
                    - this.angleToRadian(location1.latitude)) / 2.0), 2.0)
                    + Math.cos(this.angleToRadian(location1.latitude)) * Math.cos(this.angleToRadian(location2.latitude)) * Math.pow(Math.sin((this.angleToRadian(location2.longitude)
                        - this.angleToRadian(location1.longitude)) / 2.0), 2.0)))));
            };
        }
    };

    $.widget('cm-widgets.bingMaps7', {

        options: {
            width: 1000,
            height: 800,
            centerX: 38.809771,
            centerY: -77.0321543125,
            //38.889824, -77.008938
            zoom: 12,
            appKey: null,
            dataUrl: '',
            step: 20,
            lineDrawingStyle: { strokeColor: new MM.Color(255, 0, 0, 255), strokeThickness: 8 },
            polyDrawingStyle: { strokeColor: new MM.Color(255, 0, 0, 255), strokeThickness: 1 },
            polyFillStyle: { strokeColor: new MM.Color(255, 0, 0, 255),
                strokeThickness: 1, fillColor: new MM.Color(80, 0, 255, 0) },
            polyLocationsDrawingStyle: { strokeColor: new MM.Color(255, 128, 128, 128), strokeThickness: 2 },
            polyLocationsFillStyle: { strokeColor: new MM.Color(255, 0, 0, 255),
                strokeThickness: 1, fillColor: new MM.Color(80, 0, 0, 255) },
            logger: new cmUtils.Logger()
        },

        _create: function () {
            logger = this.options.logger;
            logger.enabled = false;
            that = this;
            var name = this.name, options = this.options, elem = this.element.context;
            step = options.step;
            lineDrawingStyle = options.lineDrawingStyle;
            polyDrawingStyle = options.polyDrawingStyle;
            polyFillStyle = options.polyFillStyle;
            polyLocationsDrawingStyle = options.polyLocationsDrawingStyle;
            polyLocationsFillStyle = options.polyLocationsFillStyle;
            var mapOptions = { credentials: options.appKey, zoom: options.zoom,
                center: new MM.Location(options.centerX, options.centerY) };
            mapDiv = document.getElementById(elem.id);
            mapDiv.style.height = options.height + &quot;px&quot;;
            mapDiv.style.width = options.width + &quot;px&quot;;
            map = new MM.Map(mapDiv, mapOptions);
            jqMapDiv = $('#' + mapDiv.id);

            pushpins = new MM.EntityCollection();
            polylines = new MM.EntityCollection();
            shapes = new MM.EntityCollection();

            map.entities.push(shapes);
            map.entities.push(polylines);
            map.entities.push(pushpins);

            logger.log(&quot;created &quot; + name);
        },

        drawLine: function () {
            that._initializeMapAction(&quot;drawLine&quot;);
            points = [];

            var handleLineDrawingMousedown = function (e) {
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                points.push(point);
                that._createPushpin(point);
                that._addHandler(mapMousemoveEventName, handleLineDrawingMousemove);
            }

            var handleLineDrawingMouseup = function (e) {
                logger.log(e);
                logger.log(e.eventName);
                //fix for chrome, ff and safari
                //if (e.targetType !== &quot;map&quot;) return;
                if (e.eventName !== 'mouseup') {
                    logger.log(&quot;unbinding fixer&quot;);
                    jqMapDiv.unbind('mouseup', fixerHandler); return;
                }
                var point = new MM.Point(e.getX(), e.getY());
                if (!that._arePointsEqual(point, points[0])) {
                    logger.log(&quot;distance between points ok, adding second pushpin...&quot;);
                    if (points.lenght &gt; 1) { points.pop(); }
                    points.push(point);
                    that._createPushpin(point);
                }
                else {
                    logger.log(&quot;distance between points too short, removing first pushpin...&quot;);
                    points.pop();
                    that._popPushpin();
                }
                that._detachEventHandlers();
                map.setOptions({ disablePanning: false, disableZooming: false });
            }

            var handleLineDrawingMousemove = function (e) {
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                var lastPoint = (points.length === 1) ? points[0] : points[points.length - 2];
                logger.log(points.length);
                logger.log(point + &quot;,&quot; + lastPoint);
                if (!that._arePointsEqual(point, lastPoint)) {
                    var withReplace = points.length &gt; 1;
                    if (withReplace) points.pop();
                    points.push(point);
                    that._createLine(points[0], point, withReplace);
                }
            }

            that._addHandler(mapMousedownEventName, handleLineDrawingMousedown);
            that._addHandler(mapMouseupEventName, handleLineDrawingMouseup);
            //fix for chrome, ff and safari
            var fixerHandler = function (ev) { handleLineDrawingMouseup(ev); };
            jqMapDiv.bind('mouseup', fixerHandler);

        },

        drawPolygon: function () {
            that._initializeMapAction(&quot;drawPolygon&quot;);

            points = [];
            var firstPoint = null;
            var lastPoint = null;
            var linePoints = [];
            var isCapturingMouse = false;

            var handleLineDrawingMousedown = function (e) {
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                if (firstPoint === null) {
                    points.push(point);
                    linePoints = [];
                    linePoints.push(point);
                    firstPoint = point;
                    that._createPushpin(point);
                    that._addHandler(mapMousemoveEventName, handleLineDrawingMousemove);
                    isCapturingMouse = true;
                }
                else if (that._arePointsEqual(point, lastPoint)) {
                    logger.log(&quot;clicked on the last point&quot;);
                    linePoints = [];
                    linePoints.push(lastPoint);
                    that._addHandler(mapMousemoveEventName, handleLineDrawingMousemove);
                    isCapturingMouse = true;
                }

            }

            var handleLineDrawingMouseup = function (e) {
                if (!isCapturingMouse) return;
                //fix for chrome, ff and safari
                //if (e.targetType !== &quot;map&quot;) return;
                logger.log(e);
                logger.log(e.eventName);
                if (mapMouseMoveEventHandler !== null) MM.Events.removeHandler(mapMouseMoveEventHandler);
                if (e.eventName !== 'mouseup') {
                    logger.log(&quot;unbinding fixer&quot;);
                    jqMapDiv.unbind('mouseup', fixerHandler);
                    return;
                }
                var point = new MM.Point(e.getX(), e.getY());
                if (!that._arePointsEqual(point, linePoints[0])) {
                    if (linePoints.length &gt; 1) { linePoints.pop(); }
                    if (points.length &gt; 2 &amp;&amp; that._arePointsEqual(firstPoint, point)) {
                        point = new MM.Point(firstPoint.x, firstPoint.y);
                        points.push(point);
                        that._detachEventHandlers();
                        map.setOptions({ disablePanning: false, disableZooming: false });
                        logger.log(&quot;Closing Poly....&quot;);
                        that._createLine(firstPoint, point, true, polyDrawingStyle);
                        that._createShape(points);
                        return; //done

                    }
                    lastPoint = point;
                    points.push(lastPoint);
                    that._createPushpin(lastPoint);
                    isCapturingMouse = false;
                }
                else {
                    logger.log(&quot;distance between points too short, removing first pushpin...&quot;);
                    linePoints.pop();
                    isCapturingMouse = false;
                    if (lastPoint === null) {
                        points.pop();
                        that._popPushpin();
                        that._detachEventHandlers();
                        map.setOptions({ disablePanning: false, disableZooming: false });
                        return;
                    }
                }
            }

            var handleLineDrawingMousemove = function (e) {
                if (!isCapturingMouse) return;
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                var lastLinePoint = (linePoints.length === 1) ? linePoints[0] : linePoints[linePoints.length - 2];
                logger.log(linePoints.length);
                logger.log(point + &quot;,&quot; + lastLinePoint);
                if (!that._arePointsEqual(point, lastLinePoint)) {
                    var withReplace = linePoints.length &gt; 1;
                    if (withReplace) linePoints.pop();
                    linePoints.push(point);
                    that._createLine(lastLinePoint, point, withReplace, polyDrawingStyle);
                }
            }

            that._addHandler(mapMousedownEventName, handleLineDrawingMousedown);
            that._addHandler(mapMouseupEventName, handleLineDrawingMouseup);
            //fix for chrome, ff and safari
            var fixerHandler = function (ev) { handleLineDrawingMouseup(ev); };
            jqMapDiv.bind('mouseup', fixerHandler);
        },

        drawRectangle: function () {
            that._initializeMapAction(&quot;drawRectangle&quot;);

            points = [];
            var point1, point2, lastPoint;
            var isCapturingMouse = false;

            var handleRectangleDrawing = function (e) {
                logger.log(&quot;handleRectangleDrawing&quot;);
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);

                if (e.eventName === &quot;mousedown&quot;) {
                    point1 = new MM.Point(e.getX(), e.getY());
                    lastPoint = point1;
                    isCapturingMouse = true;
                    that._addHandler(mapMousemoveEventName, handleRectangleDrawing);
                }
                else if (isCapturingMouse &amp;&amp; e.eventName === &quot;mousemove&quot;) {
                    point2 = new MM.Point(e.getX(), e.getY());
                    if (!that._arePointsEqual(lastPoint, point2)) {
                        points = getRectangleVertices(point1, point2);
                        points.push(points[0].clone());
                        logger.log(&quot;Poly Line Points Count: &quot; + points.length);
                        that._createPolyLine(points, lastPoint !== point1);
                        lastPoint = point2;
                    }
                }
                else if (e.eventName === &quot;mouseup&quot;) {
                    that._detachEventHandlers();
                    logger.log(&quot;Finshing Rectangle ....&quot;);
                    isCapturingMouse = false;
                    point2 = new MM.Point(e.getX(), e.getY());
                    var withReplace = false;
                    if (!that._arePointsEqual(lastPoint, point2)) {
                        lastPoint = point2;
                        points = getRectangleVertices(point1, point2);
                        withReplace = true;
                    }
                    var drawRectangle = points.length &gt; 0;
                    if (drawRectangle) {
                        for (var i = 0; i &lt; points.length; i++) {
                            that._createPushpin(points[i]);
                        }
                        points.push(points[0].clone());
                        that._createPolyLine(points, withReplace);
                        that._createShape(points);
                    }
                    else {
                        logger.log(&quot;No rectangle to draw....;&quot;);
                    }
                    map.setOptions({ disablePanning: false, disableZooming: false });
                }
            }

            function getRectangleVertices(pointA, pointC) {
                var pointB = new MM.Point(pointC.x, pointA.y);
                var pointD = new MM.Point(pointA.x, pointC.y);
                logger.log(&quot;Rectangle:&quot;);
                logger.log(&quot;A: &quot; + pointA);
                logger.log(&quot;B: &quot; + pointB);
                logger.log(&quot;C: &quot; + pointC);
                logger.log(&quot;D: &quot; + pointD);
                return [pointA, pointB, pointC, pointD];
            }

            that._addHandler(mapMousedownEventName, handleRectangleDrawing);
            that._addHandler(mapMouseupEventName, handleRectangleDrawing);
        },

        drawCircle: function () {
            that._initializeMapAction(&quot;drawCircle&quot;);

            points = [];
            var point1, point2, lastPoint; ;
            var isCapturingMouse = false;

            var handleCircleDrawing = function (e) {
                logger.log(&quot;handleCircleDrawing&quot;);
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);

                if (e.eventName === &quot;mousedown&quot;) {
                    point1 = new MM.Point(e.getX(), e.getY());
                    lastPoint = point1;
                    isCapturingMouse = true;
                    that._createPushpin(point1);
                    that._addHandler(mapMousemoveEventName, handleCircleDrawing);
                }
                else if (isCapturingMouse &amp;&amp; e.eventName === &quot;mousemove&quot;) {
                    point2 = new MM.Point(e.getX(), e.getY());
                    if (!that._arePointsEqual(lastPoint, point2)) {
                        logger.log(&quot;need to add new point&quot;);
                        that._createLine(point1, point2, (lastPoint !== point1), polyLocationsDrawingStyle);
                        lastPoint = point2;
                    }
                }
                else if (e.eventName === &quot;mouseup&quot;) {
                    that._detachEventHandlers();
                    logger.log(&quot;Finshing Circle ....&quot;);
                    isCapturingMouse = false;
                    point2 = new MM.Point(e.getX(), e.getY());
                    var withReplace = false;

                    if (!that._arePointsEqual(lastPoint, point2)) {
                        lastPoint = point2;
                        withReplace = true;
                    }
                    var drawCircle = !that._arePointsEqual(point1, lastPoint);
                    if (drawCircle) {
                        that._createPushpin(lastPoint);
                        that._createLine(point1, lastPoint, withReplace, polyLocationsDrawingStyle);
                        var bingHelper = new bingUtils.BingMapsHelper();
                        //bingHelper.edgeSegment = 0.05;
                        //bingHelper.useEdgeSegment = true;
                        var locations = bingHelper.getLocationsOnCircle(point1, lastPoint);
                        //that._createPolyLineFromLocations(locations, false);
                        that._createShapeFromLocations(locations);
                    }
                    else {
                        logger.log(&quot;No circle to draw....;&quot;);
                        that._popPushpin();
                    }
                    map.setOptions({ disablePanning: false, disableZooming: false });
                }
            }

            that._addHandler(mapMousedownEventName, handleCircleDrawing);
            that._addHandler(mapMouseupEventName, handleCircleDrawing);

        },

        drawCircleWithRadius: function (radius, unit) {
            that._initializeMapAction(&quot;drawCircleWithRadius&quot;);

            points = [];
            var centerPoint;

            var handleCircleDrawing = function (e) {
                logger.log(&quot;handleCircleDrawing&quot;);
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);

                if (e.eventName === &quot;click&quot;) {
                    if (!radius || radius &lt;= 0) {
                        logger.log(&quot;No circle to draw....;&quot;);
                        return;
                    }
                    that._detachEventHandlers();
                    centerPoint = new MM.Point(e.getX(), e.getY());
                    that._createPushpin(centerPoint);
                    var bingHelper = new bingUtils.BingMapsHelper();
                    //bingHelper.edgeSegment = 0.05;
                    //bingHelper.useEdgeSegment = true;
                    var locations = bingHelper.getLocationsOnCircleWithRadius(centerPoint, radius, unit);
                    //that._createPolyLineFromLocations(locations, false);
                    that._createShapeFromLocations(locations);
                    map.setOptions({ disablePanning: false, disableZooming: false });
                }
            }

            that._addHandler(mapClickEventName, handleCircleDrawing);

        },        

        _initializeMapAction: function (actionName) {
            logger.log(actionName);
            map.setOptions({ disablePanning: true, disableZooming: true });
            that._detachEventHandlers();
        },

        _addHandler: function (evtName, handler) {
            logger.log(&quot;_addHandler &quot; + evtName);
            switch (evtName) {
                case 'mousedown':
                    mapMouseDownEventHandler = MM.Events.addHandler(map, evtName, handler);
                    break;
                case 'mouseup':
                    mapMouseUpEventHandler = MM.Events.addHandler(map, evtName, handler);
                    break;
                case 'mousemove':
                    mapMouseMoveEventHandler = MM.Events.addHandler(map, evtName, handler);
                    break;
                case 'click':
                    mapClickEventHandler = MM.Events.addHandler(map, evtName, handler);
                    break;
            }
        },

        _arePointsEqual: function (point1, point2) {
            var deltaX = point1.x - point2.x;
            var deltaY = point1.y - point2.y;
            var distance = 0.5 * (Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)));
            logger.log(&quot;distance - dx=&quot; + deltaX + &quot;, dy=&quot; + deltaY + &quot;: distance=&quot; + distance + &quot;, step=&quot; + step);
            return distance &lt; step;
        },

        _createPushpin: function (point) {
            logger.log(&quot;_createPushpin&quot;);
            var loc = map.tryPixelToLocation(point);
            pushpins.push(new MM.Pushpin(loc));
        },

        _popPushpin: function () {
            pushpins.pop();
        },

        _createLine: function (point1, point2, withReplace, drawingStyle) {
            logger.log(&quot;_createLine&quot;);
            var lineVertices = [map.tryPixelToLocation(point1), map.tryPixelToLocation(point2)];
            if (withReplace) polylines.pop();
            polylines.push(new MM.Polyline(lineVertices, (!drawingStyle) ? lineDrawingStyle : drawingStyle));
        },

        _createPolyLine: function (vertices, withReplace, drawingStyle) {
            logger.log(&quot;_createPolyLine&quot;);
            if (withReplace) {
                polylines.pop();
            }
            var lineVertices = [];
            for (var i = 0; i &lt; vertices.length; i++) {
                var location = map.tryPixelToLocation(vertices[i]);
                lineVertices.push(location);
                logger.log(location);
            }
            polylines.push(new MM.Polyline(lineVertices, (!drawingStyle) ? polyDrawingStyle : drawingStyle));
        },

        _createPolyLineFromLocations: function (locations, withReplace, drawingStyle) {
            logger.log(&quot;_createPolyLineFromLocations&quot;);
            if (withReplace) {
                polylines.pop();
            }
            polylines.push(new MM.Polyline(locations, (!drawingStyle) ? polyLocationsDrawingStyle : drawingStyle));
        },

        _createShape: function (shapePoints, shapeStyle) {
            logger.log(&quot;_createShape&quot;);
            var locations = [];
            for (var i = 0; i &lt; shapePoints.length; i++) {
                var loc = map.tryPixelToLocation(shapePoints[i]);
                locations.push(loc);
                logger.log(&quot;Point: &quot; + shapePoints[i].x + &quot;, &quot; + shapePoints[i].y);
                logger.log(&quot;Loc: &quot; + loc.longitude + &quot;, &quot; + loc.latitude);
            }
            shapes.push(new MM.Polygon(locations, (!shapeStyle) ? polyFillStyle : shapeStyle));
        },

        _createShapeFromLocations: function (locations, shapeStyle) {
            logger.log(&quot;_createShapeFromLocations&quot;);
            shapes.push(new MM.Polygon(locations, (!shapeStyle) ? polyLocationsFillStyle : shapeStyle));
        },

        _detachEventHandlers: function () {
            logger.log(&quot;_detachEventHandlers&quot;);
            if (mapClickEventHandler !== null) MM.Events.removeHandler(mapClickEventHandler);
            if (mapMouseDownEventHandler !== null) MM.Events.removeHandler(mapMouseDownEventHandler);
            if (mapMouseUpEventHandler !== null) MM.Events.removeHandler(mapMouseUpEventHandler);
            if (mapMouseMoveEventHandler !== null) MM.Events.removeHandler(mapMouseMoveEventHandler);
        },

        destroy: function () {
            logger.log(&quot;destroy&quot;);
            $.Widget.prototype.destroy.call(this);
            this.mapDiv.remove();
        }

    });

} (jQuery));
</pre>
<p>The resulting Widget:</p>
<div id="attachment_346" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/02/bingMapsWidget_screen2.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/02/bingMapsWidget_screen2-300x252.png" alt="Bing Maps Widget Screen - Part 2" title="bingMapsWidget_screen2" width="300" height="252" class="size-medium wp-image-346" /></a><p class="wp-caption-text">Bing Maps Widget Screen - Part 2</p></div>
<p>In the next blog post I will add a few more features: <strong>Clear All, Undo Last Action, Search and Custom Zooming</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=319</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bing Maps Ajax Control 7.0 Widget &#8211; Drawing Lines and Polygons</title>
		<link>http://sim4all.com/blogging/?p=297</link>
		<comments>http://sim4all.com/blogging/?p=297#comments</comments>
		<pubDate>Sun, 12 Feb 2012 15:42:22 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Bing Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Widget]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=297</guid>
		<description><![CDATA[I recently explored Project Silk and experimented with Bing Maps Ajax Control 7.0 SDK. During the process I got an idea of creating a jQuery Widget for the latest version of Bing Maps SDK. Bing Maps Ajax Control 7.0 is a very lightweight &#8230; <a href="http://sim4all.com/blogging/?p=297">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I recently explored <a title="Project Silk" href="http://msdn.microsoft.com/en-us/library/hh396380.aspx">Project Silk</a> and experimented with <strong><a title="Bing Maps 7.0 SDK" href="http://msdn.microsoft.com/en-us/library/gg427610.aspx">Bing Maps Ajax Control 7.0 SDK</a></strong>. During the process I got an idea of creating a<strong> <a title="jQuery Widget" href="http://wiki.jqueryui.com/w/page/12138135/Widget-factory">jQuery Widget</a></strong> for the latest version of Bing Maps SDK. <strong>Bing Maps Ajax Control 7.0</strong> is a very lightweight version of its predecessor. You can explore an <a href="http://www.bingmapsportal.com/isdk/ajaxv7">interactive demo of the SDK here</a> or you can study the <a title="Bing Maps Ajax Control 7.0" href="http://msdn.microsoft.com/en-us/library/gg427610.aspx">APIs in depth here.</a></p>
<p>The best tutorials about <strong>jQuery Widgets</strong> that I found are: <a href="http://msdn.microsoft.com/en-us/library/hh404085.aspx">Project Silk – Chapter 3</a> and <a href="http://msdn.microsoft.com/en-us/library/hh404102.aspx">Project Silk – Chapter 14</a> and of course <a title="jQuery Widget Tutorial" href="http://wiki.jqueryui.com/w/page/12138135/Widget-factory">jQuery Widget Tutorial</a> on a <strong><a title="jQuery UI" href="http://wiki.jqueryui.com/w/page/12137947/FrontPage">jQuery</a></strong> site.</p>
<p>The Bing Maps Ajax Control Widget enhances the control by adding line and polygon drawing capabilities. In the next post I will expand drawing capabilities with rectangle and circle drawing.</p>
<h3>HTML Page to Host the Widget</h3>
<p>Making a widget out of Bing Map ontrol is easy. This is the bare bones html page that includes the Bing Maps Control.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!doctype html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Bings Map Widget Demo&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;scripts/jquery-1.7.1.js&quot;&gt;&lt;/script&gt;
        &lt;script src=&quot;http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.min.js&quot;&gt;&lt;/script&gt;
    &lt;/head&gt;
&lt;body&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnLineDrawCustom&quot;&gt;Draw Line&lt;/button&gt;
    &lt;button type=&quot;button&quot; id=&quot;btnPolyDrawCustom&quot;&gt;Draw Polygon&lt;/button&gt;
   &lt;hr /&gt;
    &lt;div id=&quot;bingMapsToolbox&quot; /&gt;
    &lt;div id='mapDiv' name='mapDiv' style=&quot;position:relative; float: left;&quot;/&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/cm-utils.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/cm-widgets.bingMaps7.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;scripts/startup.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Buttons on the top are for testing the functionality and can be replaced with something else.</p>
<h3>Listig of the included Javascript files</h3>
<ul>
<li>jQuery</li>
<li>jQuery Ui</li>
<li>Microsoft Bing Maps AJax Control</li>
<li><em>Helper utility for logging</em></li>
<li><em>Bing Maps Control Drawing Widget</em></li>
<li><em>Start-up script</em></li>
</ul>
<h3>Helper utility for logging</h3>
<pre class="brush: jscript; title: ; notranslate">
var cmUtils = {
    logType: { log: &quot;log&quot;, info: &quot;info&quot;, warn: &quot;warn&quot;, error: &quot;error&quot; },
    Logger: function () {
        this.enabled = true;
        this.log = function (message, severity) {
            if (!this.enabled) return;
            var reason = severity || cmUtils.logType.log;
            switch (reason) {
                case cmUtils.logType.info:
                    console.info(message);
                    return;
                case cmUtils.logType.warn:
                    console.warn(message);
                    return;
                case cmUtils.logType.error:
                    console.error(message);
                    return;
                case cmUtils.logType.log:
                    console.log(message);
                    return;
            }
        }
    }
};
</pre>
<p>This is a helper logging class. It works with all latest version of the most popular browsers(<em>IE, FF, Chrome, Safari</em>).<br/><br />
<strong>* Note</strong><em>In IE you need to run the Developer tools otherwise you will get an error if you eneabel the logging.</em></p>
<h3>Start-up script</h3>
<pre class="brush: jscript; title: ; notranslate">
(function ($) {
    $(document).ready(function () {
        var bingMaps7 = $(&quot;#mapDiv&quot;).bingMaps7({
            appKey: &quot;Your Bing Maps key here&quot;, zoom: 12, centerX: 38.809771, centerY: -77.0321543125, width: 1000, height: 800
        });
        $(&quot;#btnLineDrawCustom&quot;).bind('click', function () { bingMaps7.bingMaps7('drawLine'); return false; });
        $(&quot;#btnPolyDrawCustom&quot;).bind('click', function () { bingMaps7.bingMaps7('drawPolygon'); return false; });
    });
} (jQuery));
</pre>
<p>This code initializes the widget and wires-up the buttons for testing.</p>
<h3>Bing Maps Control Drawing Widget</h3>
<pre class="brush: jscript; title: ; notranslate">
//http://www.jslint.com/
(function ($) {

    var map,
       mapDiv,
       jqMapDiv,
       that,
       actionType,
       step,
       points,
       lineDrawingStyle,
       polyDrawingStyle,
       polyFillStyle,
       pushpins,
       polylines,
       shapes,
    //mapClickEventHandler = null,
       mapMouseDownEventHandler = null,
       mapMouseUpEventHandler = null,
       mapMouseMoveEventHandler = null,
    //mapClickEventName = 'click',
       mapMousedownEventName = 'mousedown',
       mapMouseupEventName = 'mouseup',
       mapMousemoveEventName = 'mousemove',
       logger;

    //console.log(&quot;Start up&quot;);
    var MM = Microsoft.Maps;

    $.widget('cm-widgets.bingMaps7', {

        options: {
            width: 1000,
            height: 800,
            centerX: 38.809771,
            centerY: -77.0321543125,
            zoom: 12,
            appKey: null,
            dataUrl: '',
            step: 20,
            lineDrawingStyle: { strokeColor: new MM.Color(255, 0, 0, 255), strokeThickness: 8 },
            polyDrawingStyle: { strokeColor: new MM.Color(255, 0, 0, 255), strokeThickness: 1 },
            polyFillStyle: { strokeColor: new MM.Color(255, 0, 0, 255), strokeThickness: 1, fillColor: new MM.Color(80, 0, 255, 0) },
            logger: new cmUtils.Logger()
        },

        _create: function () {
            logger = this.options.logger;
            logger.enabled = false;
            that = this;
            var name = this.name, options = this.options, elem = this.element.context;
            step = options.step;
            lineDrawingStyle = options.lineDrawingStyle;
            polyDrawingStyle = options.polyDrawingStyle;
            polyFillStyle = options.polyFillStyle;
            var mapOptions = { credentials: options.appKey, zoom: options.zoom, center: new MM.Location(options.centerX, options.centerY) };
            mapDiv = document.getElementById(elem.id);
            mapDiv.style.height = options.height + &quot;px&quot;;
            mapDiv.style.width = options.width + &quot;px&quot;;
            map = new MM.Map(mapDiv, mapOptions);
            jqMapDiv = $('#' + mapDiv.id);

            pushpins = new MM.EntityCollection();
            polylines = new MM.EntityCollection();
            shapes = new MM.EntityCollection();

            map.entities.push(shapes);
            map.entities.push(polylines);
            map.entities.push(pushpins);

            logger.log(&quot;created &quot; + name);
        },

        drawLine: function () {
            logger.log(&quot;drawLine&quot;);

            map.setOptions({ disablePanning: true, disableZooming: true });
            that._detachEventHandlers();

            points = new Array();

            var handleLineDrawingMousedown = function (e) {
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                points.push(point);
                that._createPushpin(point);
                that._addHandler(mapMousemoveEventName, handleLineDrawingMousemove);
            }

            var handleLineDrawingMouseup = function (e) {
                logger.log(e);
                logger.log(e.eventName);
                //fix for chrome, ff and safari
                //if (e.targetType !== &quot;map&quot;) return;
                if (e.eventName !== 'mouseup') {
                    logger.log(&quot;unbinding fixer&quot;);
                    jqMapDiv.unbind('mouseup', fixerHandler); return;
                }
                //logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                if (!that._arePointsEqual(point, points[0])) {
                    logger.log(&quot;distance between points ok, adding second pushpin...&quot;);
                    if (points.lenght &gt; 1) { points.pop(); }
                    points.push(point);
                    that._createPushpin(point);
                }
                else {
                    logger.log(&quot;distance between points too short, removing first pushpin...&quot;);
                    points.pop();
                    that._popPushpin();
                }
                that._detachEventHandlers();
                map.setOptions({ disablePanning: false, disableZooming: false });
            }

            var handleLineDrawingMousemove = function (e) {
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                var lastPoint = (points.length == 1) ? points[0] : points[points.length - 2];
                logger.log(points.length);
                logger.log(point + &quot;,&quot; + lastPoint);
                if (!that._arePointsEqual(point, lastPoint)) {
                    var withReplace = points.length &gt; 1;
                    if (withReplace) points.pop();
                    points.push(point);
                    that._createLine(points[0], point, withReplace);
                }
            }

            that._addHandler(mapMousedownEventName, handleLineDrawingMousedown);
            that._addHandler(mapMouseupEventName, handleLineDrawingMouseup);
            //fix for chrome, ff and safari
            var fixerHandler = function () { handleLineDrawingMouseup(event); };
            jqMapDiv.bind('mouseup', fixerHandler);

        },

        drawPolygon: function () {
            logger.log(&quot;drawPolygon&quot;);
            map.setOptions({ disablePanning: true, disableZooming: true });
            that._detachEventHandlers();

            points = new Array();
            var firstPoint = null;
            var lastPoint = null;
            var linePoints = new Array();
            var isCapturingMouse = false;

            var handleLineDrawingMousedown = function (e) {
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                if (firstPoint === null) {
                    points.push(point);
                    linePoints = new Array();
                    linePoints.push(point);
                    firstPoint = point;
                    that._createPushpin(point);
                    that._addHandler(mapMousemoveEventName, handleLineDrawingMousemove);
                    isCapturingMouse = true;
                }
                else if (that._arePointsEqual(point, lastPoint)) {
                    logger.log(&quot;clicked on the last point&quot;);
                    linePoints = new Array();
                    linePoints.push(lastPoint);
                    that._addHandler(mapMousemoveEventName, handleLineDrawingMousemove);
                    isCapturingMouse = true;
                }

            }

            var handleLineDrawingMouseup = function (e) {
                if (!isCapturingMouse) return;
                //fix for chrome, ff and safari
                //if (e.targetType !== &quot;map&quot;) return;
                logger.log(e);
                logger.log(e.eventName);
                if (mapMouseMoveEventHandler !== null) MM.Events.removeHandler(mapMouseMoveEventHandler);
                if (e.eventName !== 'mouseup') {
                    logger.log(&quot;unbinding fixer&quot;);
                    jqMapDiv.unbind('mouseup', fixerHandler);
                    return;
                }
                var point = new MM.Point(e.getX(), e.getY());
                if (!that._arePointsEqual(point, linePoints[0])) {
                    if (linePoints.length &gt; 1) { linePoints.pop(); }
                    if (points.length &gt; 2 &amp;&amp; that._arePointsEqual(firstPoint, point)) {
                        point = new MM.Point(firstPoint.x, firstPoint.y);
                        points.push(point);
                        that._detachEventHandlers();
                        map.setOptions({ disablePanning: false, disableZooming: false });
                        logger.log(&quot;Closing Poly....&quot;);
                        that._createShape(points);
                        return; //done

                    }
                    lastPoint = point;
                    points.push(lastPoint);
                    that._createPushpin(lastPoint);
                    isCapturingMouse = false;
                }
                else {
                    logger.log(&quot;distance between points too short, removing first pushpin...&quot;);
                    linePoints.pop();
                    isCapturingMouse = false;
                    if (lastPoint === null) {
                        points.pop();
                        that._popPushpin();
                        that._detachEventHandlers();
                        map.setOptions({ disablePanning: false, disableZooming: false });
                        return;
                    }
                }
            }

            var handleLineDrawingMousemove = function (e) {
                if (!isCapturingMouse) return;
                if (e.targetType !== &quot;map&quot;) return;
                logger.log(e.eventName);
                var point = new MM.Point(e.getX(), e.getY());
                var lastLinePoint = (linePoints.length == 1) ? linePoints[0] : linePoints[linePoints.length - 2];
                logger.log(linePoints.length);
                logger.log(point + &quot;,&quot; + lastLinePoint);
                if (!that._arePointsEqual(point, lastLinePoint)) {
                    var withReplace = linePoints.length &gt; 1;
                    if (withReplace) linePoints.pop();
                    linePoints.push(point);
                    that._createLine(lastLinePoint, point, withReplace, polyDrawingStyle);
                }
            }

            that._addHandler(mapMousedownEventName, handleLineDrawingMousedown);
            that._addHandler(mapMouseupEventName, handleLineDrawingMouseup);
            //fix for chrome, ff and safari
            var fixerHandler = function () { handleLineDrawingMouseup(event); };
            jqMapDiv.bind('mouseup', fixerHandler);
        },

        _addHandler: function (evtName, handler) {
            logger.log(&quot;_addHandler &quot; + evtName);
            switch (evtName) {
                case 'mousedown':
                    mapMouseDownEventHandler = MM.Events.addHandler(map, evtName, handler);
                    break;
                case 'mouseup':
                    mapMouseUpEventHandler = MM.Events.addHandler(map, evtName, handler);
                    break;
                case 'mousemove':
                    mapMouseMoveEventHandler = MM.Events.addHandler(map, evtName, handler);
                    break;
                //                case 'click':
                //                    mapClickEventHandler = MM.Events.addHandler(map, evtName, handler);
                //                    break;
            }
        },

        _arePointsEqual: function (point1, point2) {
            var deltaX = point1.x - point2.x;
            var deltaY = point1.y - point2.y;
            var distance = 0.5 * (Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)));
            logger.log(&quot;distance - dx=&quot; + deltaX + &quot;, dy=&quot; + deltaY + &quot;: distance=&quot; + distance + &quot;, step=&quot; + step);
            return distance &lt; step;
        },

        _createPushpin: function (point) {
            logger.log(&quot;_createPushpin&quot;);
            var loc = map.tryPixelToLocation(point);
            pushpins.push(new MM.Pushpin(loc));
        },

        _popPushpin: function () {
            pushpins.pop();
        },

        _createLine: function (point1, point2, withReplace, drawingStyle) {
            logger.log(&quot;_createLine&quot;);
            var lineVertices = new Array(map.tryPixelToLocation(point1), map.tryPixelToLocation(point2));
            if (withReplace) polylines.pop();
            polylines.push(new MM.Polyline(lineVertices, (!drawingStyle) ? lineDrawingStyle : drawingStyle));
        },

        _createShape: function (shapePoints, shapeStyle) {
            logger.log(&quot;_createShape&quot;);
            var locations = new Array();
            for (var i = 0; i &lt; shapePoints.length; i++) {
                var loc = map.tryPixelToLocation(shapePoints[i]);
                locations.push(loc);
                logger.log(&quot;Point: &quot; + shapePoints[i].x + &quot;, &quot; + shapePoints[i].y);
                logger.log(&quot;Loc: &quot; + loc.longitude + &quot;, &quot; + loc.latitude);
            }
            shapes.push(new MM.Polygon(locations, (!shapeStyle) ? polyFillStyle : shapeStyle));
        },

        _detachEventHandlers: function () {
            logger.log(&quot;_detachEventHandlers&quot;);
            //if (mapClickEventHandler !== null) MM.Events.removeHandler(mapClickEventHandler);
            if (mapMouseDownEventHandler !== null) MM.Events.removeHandler(mapMouseDownEventHandler);
            if (mapMouseUpEventHandler !== null) MM.Events.removeHandler(mapMouseUpEventHandler);
            if (mapMouseMoveEventHandler !== null) MM.Events.removeHandler(mapMouseMoveEventHandler);
        },
        destroy: function () {
            logger.log(&quot;destroy&quot;);
            $.Widget.prototype.destroy.call(this);
            this.mapDiv.remove();
        }
    });
} (jQuery));
</pre>
<p>The code should be self-explanatory (at leats I hope so).</p>
<div id="attachment_314" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2012/02/bingMapsWidget_screen1.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2012/02/bingMapsWidget_screen1-300x257.png" alt="Bing Maps Ajax Control jQuery Widget in Action" title="Bing Maps Ajax Control jQuery Widget in Action" width="300" height="257" class="size-medium wp-image-314" /></a><p class="wp-caption-text">Bing Maps Ajax Control jQuery Widget in Action</p></div>
<p>In the next post I will add rectangle and circle drawing.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=297</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cross-Platform Mobile Development with WP7, PhoneGap and .NET 4.0 WCF REST – Part 3</title>
		<link>http://sim4all.com/blogging/?p=266</link>
		<comments>http://sim4all.com/blogging/?p=266#comments</comments>
		<pubDate>Sat, 03 Dec 2011 03:51:09 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[VS 2010]]></category>
		<category><![CDATA[WCF REST]]></category>
		<category><![CDATA[Windows Phone]]></category>
		<category><![CDATA[WP7]]></category>
		<category><![CDATA[Safari]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=266</guid>
		<description><![CDATA[This is Part 3 of the walkthrough that demonstrates cross-platform mobile application development with PhoneGap, WP7 and .NET 4.0 WCF REST Services. For a description of the PhoneGap, for a WP7 installation review Part 1. For a descripion of the .NET &#8230; <a href="http://sim4all.com/blogging/?p=266">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is Part 3 of the walkthrough that demonstrates cross-platform mobile application development with <a title="PhoneGap" href="http://phonegap.com/" target="_blank">PhoneGap</a>, <a title="WP7" href="http://create.msdn.com/en-US/" target="_blank">WP7</a> and .NET 4.0 WCF REST Services.</p>
<p>For a description of the <a title="PhoneGap" href="http://phonegap.com/" target="_blank">PhoneGap</a>, for a <a title="WP7" href="http://create.msdn.com/en-US/" target="_blank">WP7</a> installation review Part 1. For a descripion of the .NET 4.0 WCF REST Template installation refer to Part 2.</p>
<p>Developing in a PhoneGap application is quite cumbersome. It takes too much time to start debugging and push the code to the phone emulator or the actual device. In order to expedite the process my suggestion is to develop and run web pages, css styles and javascript files in the WCF Rest Services application. That way there is no problem with AJAX and <a title="CORS" href="http://www.w3.org/TR/access-control/" target="_blank">CORS</a> (Cross-Origin Resource Sharing) when testing and all the code, with just few corrections, can be just copied and pasted to PhoneGap application (both for WP7 or iPad).</p>
<p>One problem that needs to be solved when using web pages running in the browser for PhoneGap development is the need to emulate device specific functionality, which is expected by the PhoneGap template code. This can be seen below in the copy of the index.html page supplied with the template. Notice PhoneGap specific event listener in <strong>init() </strong> function:</p>
<pre class="brush: jscript; title: ; notranslate">
function init()
        {
            document.addEventListener(&quot;deviceready&quot;,
                onDeviceReady,false);
        }
</pre>
<p>The full <strong>index.html</strong> page:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=320; user-scalable=no&quot; /&gt;
    &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt;

    &lt;title&gt;PhoneGap WP7&lt;/title&gt;

	  &lt;link rel=&quot;stylesheet&quot; href=&quot;master.css&quot; type=&quot;text/css&quot; media=&quot;screen&quot; title=&quot;no title&quot; charset=&quot;utf-8&quot;/&gt;

	  &lt;script type=&quot;text/javascript&quot;&gt;
		  // provide our own console if it does not exist, huge dev aid!
		  if(typeof window.console == &quot;undefined&quot;)
		  {
		  window.console = {log:function(str){window.external.Notify(str);}};
		  }

		  // output any errors to console log, created above.
		  window.onerror=function(e)
		  {
			  console.log(&quot;window.onerror ::&quot; + JSON.stringify(e));
		  };

		  console.log(&quot;Installed console ! &quot;);
      &lt;/script&gt;

      &lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;phonegap-1.1.0.js&quot;&gt;&lt;/script&gt;

      &lt;script type=&quot;text/javascript&quot;&gt;
        function init()
        {
        document.addEventListener(&quot;deviceready&quot;,onDeviceReady,false);
        }

        // once the device ready event fires, you can safely do your thing! -jm
        function onDeviceReady()
        {
            document.getElementById(&quot;welcomeMsg&quot;).innerHTML += &quot;PhoneGap is ready!&quot;;
        }
      &lt;/script&gt;  

  &lt;/head&gt;
  &lt;body onLoad=&quot;init();&quot;&gt;
    &lt;h1&gt;Hello PhoneGap&lt;/h1&gt;
    &lt;div id=&quot;welcomeMsg&quot;&gt;&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>A very good solution to it (which I borrowed) can be found at <a href="http://www.codeproject.com/Articles/262101/Developing-Windows-Phone-7-HTML5-apps-with-PhoneGa" title="Colin Eberhardt Code" target="_blank">code project (author: Colin Eberhardt)</a>. PhoneGapMock.js is a javascript code file that does the trick.</p>
<p>You should also expect problems with the &#8220;windows.console&#8221; code in the <strong>index.html</strong>. It will work in Chrome for example but not in IE. </p>
<p>The next step is to separte javascript code into separate files. The final content of the <strong>www</strong> folder inside the WCF template project should look like this:</p>
<div id="attachment_275" class="wp-caption aligncenter" style="width: 205px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/12/wwwInWebApp.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2011/12/wwwInWebApp.png" alt="www folder in WCF Rest Services Web Application" title="www folder in WCF Rest Services Web Application" width="195" height="150" class="size-full wp-image-275" /></a><p class="wp-caption-text">www folder in WCF Rest Services Web Application</p></div>
<p>The content of the files:</p>
<p><strong>index.html</strong></p>
<pre class="brush: xml; title: ; notranslate">
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=320 user-scalable=no&quot; /&gt;
    &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt;
    &lt;title&gt;PhoneGap WP7&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;master.css&quot; type=&quot;text/css&quot; media=&quot;screen&quot; title=&quot;no title&quot; charset=&quot;utf-8&quot; /&gt;
    &lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;console.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;jquery-1.6.4.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;phonegapMock.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;init.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div&gt;
    &lt;h1 id=&quot;welcomeMsg&quot;&gt;Welcome&lt;/h1&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;login(); return false;&quot;&gt;log in&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;getAjax(); return false;&quot;&gt;Get Ajax&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;postAjax(); return false;&quot;&gt;Post Ajax&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;getSingle(); return false;&quot;&gt;Get Single Item&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;deleteSingle(); return false;&quot;&gt;Delete&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;updateSingle(); return false;&quot;&gt;Update&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;identify(); return false;&quot;&gt;Identify&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;logViaForm(); return false;&quot;&gt;Log via Form&lt;/a&gt;&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;#&quot; onclick=&quot;logout(); return false;&quot;&gt;log out&lt;/a&gt;&lt;/p&gt;

    &lt;p id=&quot;errorMessage&quot; class=&quot;err&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;loginCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;ajaxCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;postAjaxCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;getSingleCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;deleteSingleCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;updateSingleCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;identifyCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;logViaFormCall&quot;&gt;&lt;/p&gt;
    &lt;p id=&quot;logoutCall&quot;&gt;&lt;/p&gt;
    &lt;input type=&quot;text&quot; id=&quot;myTest&quot; value=&quot;1&quot; name=&quot;myTest&quot; /&gt;

   &lt;/div&gt;

  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong>console.js</strong></p>
<pre class="brush: jscript; title: ; notranslate">
// provide our own console if it does not exist, huge dev aid!
if (typeof window.console == &quot;undefined&quot;) {
    window.console = { log: function (str) { window.external.Notify(str); } };
}

// output any errors to console log, created above.
window.onerror = function (e) {
    console.log(&quot;window.onerror ::&quot; + JSON.stringify(e));
};

console.log(&quot;Installed console ! &quot;);
</pre>
<p><strong>phoneGapMock.js</strong></p>
<pre class="brush: jscript; title: ; notranslate">
document.addEventListener = function (evt, handler, capture) {
  $(&quot;body&quot;).bind(evt, handler);
};

$(document).ready(function () {
  setTimeout(function () {
    $(&quot;body&quot;).trigger(&quot;deviceready&quot;);
  }, 100);
});
</pre>
<p><strong>init.js</strong></p>
<pre class="brush: jscript; title: ; notranslate">

$(document).ready(function () {
    document.addEventListener(&quot;deviceready&quot;, onDeviceReady, false);
});

// phonegap is initialised
function onDeviceReady() {
    $(&quot;#welcomeMsg&quot;).append(&quot;...Ready&quot;);
}

function showAlert(msg) {
    //alert(msg);
}

function showError(error, otherInfo) {
    var element = document.getElementById('errorMessage');
    element.innerHTML = &quot;Errors: &quot; + error.Message + &quot;&lt;br&gt;&quot; + (otherInfo ? otherInfo : &quot;&quot;);
}

function getAjax() {
    var jqxhr = $.ajax({
        url: '../service1/',
        //headers:
        beforeSend: function (xhr) {
            //xhr.overrideMimeType('text/plain; charset=x-user-defined');
        },
        dataType: 'json'
    })
    .done(function (data) {
        var element = document.getElementById('ajaxCall');
        element.innerHTML = JSON.stringify(data, null, &quot;\t&quot;);
    })
     .fail(function (xhr, status, error) {
         showError(error);
     })
     .always(function () { showAlert(&quot;complete&quot;); });
}

function postAjax(parameters) {
    var jqxhr = $.ajax({
        url: '../service1/',
        type: 'POST',
        //headers:
        //beforeSend: function (xhr) {
        //},
        dataType: 'json',
        contentType: 'application/json; charset=utf-8',
        data: '{ &quot;Id&quot;:2, &quot;StringValue&quot;: &quot;jerry&quot; }'
    })
    .done(function (data) {
        var element = document.getElementById('postAjaxCall');
        element.innerHTML = JSON.stringify(data, null, &quot;\t&quot;);
    })
     .fail(function (xhr, status, error) { showError(error); })
     .always(function () { showAlert(&quot;complete&quot;); });
}

function login() {
    var jqxhr = $.ajax({
        url: '../login/',
        type: 'POST',
        //headers:
        //beforeSend: function (xhr) {
        //},
        dataType: 'json',
        contentType: 'application/json; charset=utf-8',
        data: '{ &quot;Username&quot;:&quot;test&quot;, &quot;Password&quot;: &quot;test&quot; }'
    })
    .done(function (data) {
        var element = document.getElementById('loginCall');
        element.innerHTML = &quot;Login Succesfull ? &quot; + data;
    })
    .fail(function (xhr, status, error) { showError(error); })
    .always(function () { showAlert(&quot;complete&quot;); });
}

function logout() {
    var jqxhr = $.ajax({
        url: '../login/logout',
        type: 'POST',
        //headers:
        //beforeSend: function (xhr) {
        //},
        dataType: 'json',
        contentType: 'application/json; charset=utf-8'
    })
    .done(function (data) {
        var element = document.getElementById('logoutCall');
        element.innerHTML = &quot;Login Out Succesfull ? &quot; + data;
    })
    .fail(function (xhr, status, error) { showError(error); })
    .always(function () { showAlert(&quot;complete&quot;); });
}

function getSingle(parameters) {
    var jqxhr = $.ajax({
        url: '../service1/88',
        type: 'GET',
        //headers:
        beforeSend: function (xhr) {
            //xhr.overrideMimeType('text/plain; charset=x-user-defined');
        },
        dataType: 'json',
        contentType: 'application/json; charset=utf-8'
    })
    .done(function (data) {
        var element = document.getElementById('getSingleCall');
        element.innerHTML = JSON.stringify(data, null, &quot;\t&quot;);
    })
    .fail(function (xhr, status, error) { showError(error); })
    .always(function () { showAlert(&quot;complete&quot;); });
}

function deleteSingle(parameters) {
    var jqxhr = $.ajax({
        url: '../service1/88',
        type: 'DELETE',
        //headers:
        beforeSend: function (xhr) {
            //xhr.overrideMimeType('text/plain; charset=x-user-defined');
        },
        dataType: 'json',
        contentType: 'application/json; charset=utf-8'
    })
    .done(function (data) {
        var element = document.getElementById('deleteSingleCall');
        element.innerHTML = JSON.stringify(data, null, &quot;\t&quot;);
    })
     .fail(function (xhr, status, error) { showError(error); })
     .always(function () { showAlert(&quot;complete&quot;); });
}

function updateSingle(parameters) {
    var jqxhr = $.ajax({
        url: '../service1/99',
        type: 'PUT',
        //headers:
        beforeSend: function (xhr) {
            //xhr.overrideMimeType('text/plain; charset=x-user-defined');
        },
        dataType: 'json',
        contentType: 'application/json; charset=utf-8',
        data: '{ &quot;Id&quot;:99, &quot;StringValue&quot;: &quot;JERRY &quot; }'
    })
    .done(function (data) {
        var element = document.getElementById('updateSingleCall');
        element.innerHTML = JSON.stringify(data, null, &quot;\t&quot;);
    })
    .fail(function (xhr, status, error) { showError(error); })
    .always(function () { showAlert(&quot;complete&quot;); });
}

function identify(parameters) {
    var jqxhr = $.ajax({
        url: '../login/identify',
        type: 'GET',
        dataType: 'json',
        contentType: 'application/json; charset=utf-8'
    })
     .done(function (data) {
         var element = document.getElementById('identifyCall');
         element.innerHTML = JSON.stringify(data, null, &quot;\t&quot;);
     })
      .fail(function (xhr, status, error) { showError(error); })
      .always(function () { showAlert(&quot;complete&quot;); });
}

function logViaForm() {
    var jqxhr = $.ajax({
        url: '../login.aspx',
        type: 'GET',
        dataType: 'html'
    })
                .done(function (data) {
                    var eventVal = $(data).find('#__EVENTVALIDATION').attr('value');
                    var viewState = $(data).find('#__VIEWSTATE').attr('value');
                    //build post data
                    var postData = { __VIEWSTATE: viewState, __EVENTVALIDATION: eventVal, UserName: &quot;test&quot;, Password: &quot;test&quot;, LoginButton: &quot;Log In&quot; };

                    var jqxhr1 = $.ajax({
                        url: '../login.aspx',
                        type: 'POST',
                        dataType: 'html',
                        contentType: 'application/x-www-form-urlencoded; charset=utf-8',
                        data: postData
                    })
                    .done(function (data1, status, jqxhr1) {
                        //this works but we will get an error dues to the redirect to the home.aspx
                        //TODO: need to handle that
                        var element = document.getElementById('logViaFormCall');
                        element.innerHTML = &quot;Login Succesfull ! &quot; + jqxhr1.status;
                    })
                     .fail(function (xhr, status, error) {
                         showError(error, &quot;TODO: Works but need to handle redirect!!&quot;);

                         //but it really works!
                         var element = document.getElementById('logViaFormCall');
                         element.innerHTML = &quot;Login Succesfull ! Verify that Authenticated AJAX calls work!&quot;;
                     })
                     .always(function () { showAlert(&quot;complete login&quot;); });
                })
                .fail(function (xhr, status, error) { showError(error); })
                .always(function () { showAlert(&quot;complete&quot;); });
}
</pre>
<p>Web Page Preview:</p>
<div id="attachment_283" class="wp-caption aligncenter" style="width: 324px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/12/webPage2.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2011/12/webPage2.png" alt="Web Page Preview in Chrome" title="Web Page Preview in Chrome" width="314" height="493" class="size-full wp-image-283" /></a><p class="wp-caption-text">Web Page Preview in Chrome</p></div>
<p>The Web Page View after testing all functionality:</p>
<div id="attachment_284" class="wp-caption aligncenter" style="width: 322px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/12/webPageAfterTests.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2011/12/webPageAfterTests.png" alt="Web Page after testing functionality" title="Web Page after testing functionality" width="312" height="446" class="size-full wp-image-284" /></a><p class="wp-caption-text">Web Page after testing functionality</p></div>
<p><strong>To Note:</strong></p>
<ul>
<li>AJAX requests for protected resources will succeed only after a call to the login service (“log in” link) or after a call to the login form (“Log via Form” link). </li>
<li>The code will not handle the redirects for failed unauthenticated AJAX requests </li>
<li>The code will not fully handle the login via the form (it will fail on the redirect to <em>home.aspx</em>), but the login will succeed and the subsequent AJAX requests will work. The error in red is the result of that redirect that is not beinh handled.</li>
</ul>
<p><strong>The Result:</strong><br />
The above results page demonstrates that GET, POST, PUT and DELETE AJAX requests are handled by .NET WCF REST Services hosted in the web application with FBA enabled.</p>
<p><strong>Transferring HTML application to PhoneGap Application</strong></p>
<ul>
<li>
Copy the content of the <strong>www</strong> folder to PhoneGap&#8217;s <strong>www</strong> folder with an exception of the <em>PhoneGapMock.js</em> file (also remove the link to <em>PhoneGapMock.js</em> from <em>index.html</em>.
</li>
<li>
Modify <em>showAlert()</em> function to use native dialogs. See below.
</li>
<li>Modify all <strong>urls</strong> in the code to use an absolute link (for example): <em>url: &#8216;https://machine.domain.com/appName/service1&#8242;</em></li>
<p>Modified <em>showAlert()</em> function:</p>
<pre class="brush: jscript; title: ; notranslate">
function showAlert(msg) {
                navigator.notification.alert(
                    msg, // message
                    alertDismissed, // callback
                    'Alert', // title
                    'Done'  // buttonName
                    );
            }
</pre>
<p><strong>That&#8217;s all that should be needed to run the application on iPad.</strong></p>
<p><strong>Windows Phone Only:</strong><br />
Add CORS support in jQuery by adding one line of the code to <em>$(document).ready(function ()&#8230;</em></p>
<pre class="brush: jscript; title: ; notranslate">
$(document).ready(function () {
    document.addEventListener(&quot;deviceready&quot;, onDeviceReady, false);
    jQuery.support.cors = true; //Cross-Origin Resource Sharing
});
</pre>
<p>Also (<em>for Windows Phone 7</em>), right click GapSourceDictionary.tt file and execute &#8220;Run Custom Tool&#8221; to make sure that all added files will be included in the build and transferred to the device.</p>
<p><strong>Final PhoneGap application files:</strong></p>
<div id="attachment_286" class="wp-caption aligncenter" style="width: 252px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/12/wwwInPhoneGap.png"><img src="http://sim4all.com/blogging/wp-content/uploads/2011/12/wwwInPhoneGap.png" alt="www folder in PhoneGap application" title="www folder in PhoneGap application" width="242" height="342" class="size-full wp-image-286" /></a><p class="wp-caption-text">www folder in PhoneGap application</p></div>
<p><strong>Summary</strong></p>
<p>This post demonstrates PhoneGap application code that runs on both <strong>iOS</strong> and <strong>Windows Phone 7</strong> devices. The application also runs as a web application (client side code only) which makes development more robust. It&#8217;s easier to troubleshot and test functionality in the regular browser during the initial development phase than using a simulator/emulator or the physical device for that purpose.</p>
<p>Moreover, the post demonstrates how to create PhoneGap application utilizing .NET WCF REST Services hosted in a web application protected by Forms Based Authentication.  This might be a likely scenario for legacy LOB applications.</p>
<p>Test PhoneGap application was developed for and deployed to iPad and WP7.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=266</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cross-Platform Mobile Development with WP7, PhoneGap and .NET 4.0 WCF REST – Part 2</title>
		<link>http://sim4all.com/blogging/?p=246</link>
		<comments>http://sim4all.com/blogging/?p=246#comments</comments>
		<pubDate>Tue, 15 Nov 2011 04:57:08 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[WCF REST]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=246</guid>
		<description><![CDATA[This is Part 2 of the walkthrough that demonstrates cross-platform mobile application development with PhoneGap, WP7 and .NET 4.0 WCF REST Services. The following section describes modifications to the installed, as described in Part 1 of this blog, .NET 4.0 &#8230; <a href="http://sim4all.com/blogging/?p=246">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is <strong>Part 2</strong> of the walkthrough that demonstrates<strong> cross-platform</strong> mobile application development with <a href="http://phonegap.com/">PhoneGap</a>, <a href="http://create.msdn.com/en-US/">WP7</a> and .NET 4.0 WCF REST Services.</p>
<p>The following section describes modifications to the installed, as described in<strong> </strong><a href="http://sim4all.com/blogging/?p=235" target="_blank"><strong>Part 1</strong></a> of this blog, .NET 4.0 WCF REST Template.</p>
<p><strong>1)</strong> Add Forms Authentication to web.config file. The mobile application will be accessing protected data. Make note of the setting <span style="background-color: #ffff00;">cookieless=”UseCookies”.</span> This is to make sure that iPad Simulator will be correctly recognized as supporting cookies. I got this troubleshooting tip from <a href="http://groups.google.com/group/phonegap/browse_thread/thread/4e18f47d2d860e1e" target="_blank">here</a>.</p>
<pre class="code"><span style="color: blue;">&lt;</span><span style="color: #a31515;">authentication </span><span style="color: red;">mode</span><span style="color: blue;">=</span>"<span style="color: blue;">Forms</span>"<span style="color: blue;">&gt; </span></pre>
<pre class="code"><span style="color: blue;">&lt;</span><span style="color: #a31515;">forms </span><span style="color: red;">defaultUrl</span><span style="color: blue;">=</span>"<span style="color: blue;">home.aspx</span>" <span style="color: red;">timeout</span><span style="color: blue;">=</span>"<span style="color: blue;">20</span>"
     <span style="color: red;">ticketCompatibilityMode</span><span style="color: blue;">=</span>"<span style="color: blue;">Framework40</span>"
     <span style="color: red;">loginUrl</span><span style="color: blue;">=</span>"<span style="color: blue;">login.aspx</span>" <span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">Mobile-Rest-Api</span>"</pre>
<pre class="code"><span style="background-color: #ffff00;"><span style="color: red;">cookieless</span><span style="color: blue;">=</span>"<span style="color: blue;">UseCookies</span>"</span><span style="color: blue;">/&gt;</span>
<span style="color: blue;">&lt;/</span><span style="color: #a31515;">authentication</span><span style="color: blue;">&gt; </span>
<span style="color: blue;">&lt;</span><span style="color: #a31515;">authorization</span><span style="color: blue;">&gt; </span></pre>
<pre class="code"><span style="color: blue;">&lt;</span><span style="color: #a31515;">deny </span><span style="color: red;">users</span><span style="color: blue;">=</span>"<span style="color: blue;">?</span>" <span style="color: blue;">/&gt; &lt;</span><span style="color: #a31515;">allow </span><span style="color: red;">users</span><span style="color: blue;">=</span>"<span style="color: blue;">*</span>"<span style="color: blue;">/&gt;</span></pre>
<pre class="code"><span style="color: blue;"> &lt;/</span><span style="color: #a31515;">authorization</span><span style="color: blue;">&gt;</span></pre>
<p>&nbsp;</p>
<p><strong>2)</strong> Add additional forms to the WcfRestServiceApp to test forms authentication:</p>
<ul>
<li>home.aspx</li>
<li>login.aspx</li>
</ul>
<p>The markup for the login page:</p>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">form </span><span style="color: red;">id</span><span style="color: blue;">=&#8221;form1&#8243; </span> <span style="color: red;">runat</span><span style="color: blue;">=&#8221;server&#8221;&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">div</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">fieldset</span><span style="color: blue;">&gt; &lt;</span><span style="color: maroon;">legend</span><span style="color: blue;">&gt;</span>Log In<span style="color: blue;">&lt;/</span><span style="color: maroon;">legend</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">p</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">Label </span><span style="color: red;">ID</span><span style="color: blue;">=&#8221;UserNameLabel&#8221; </span><span style="color: red;">runat</span><span style="color: blue;">=&#8221;server&#8221; </span></div>
<div class="code"><span style="color: red;">    AssociatedControlID</span><span style="color: blue;">=&#8221;UserName&#8221;&gt; </span>Username:<span style="color: blue;">&lt;/</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">Label</span><span style="color: blue;">&gt;          </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">TextBox </span><span style="color: red;">ID</span><span style="color: blue;">=&#8221;UserName&#8221; </span><span style="color: red;">runat</span><span style="color: blue;">=&#8221;server&#8221; &gt;&lt;/</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">TextBox</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">p</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">p</span><span style="color: blue;">&gt;&lt;</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">Label </span><span style="color: red;">ID</span><span style="color: blue;">=&#8221;PasswordLabel&#8221; </span><span style="color: red;">runat</span><span style="color: blue;">=&#8221;server&#8221; </span></div>
<div class="code"><span style="color: blue;">     </span><span style="color: red;">AssociatedControlID</span><span style="color: blue;">=&#8221;Password&#8221;&gt; </span>Password:<span style="color: blue;">&lt;/</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">Label</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">TextBox </span><span style="color: red;">ID</span><span style="color: blue;">=&#8221;Password&#8221; </span><span style="color: red;">runat</span><span style="color: blue;">=&#8221;server&#8221; </span><span style="color: red;">TextMode</span><span style="color: blue;">=&#8221;Password&#8221;&gt;&lt;/</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">TextBox</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">p</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">fieldset</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">p </span><span style="color: blue;">&gt;&lt;</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">Button </span><span style="color: red;">ID</span><span style="color: blue;">=&#8221;LoginButton&#8221; </span><span style="color: red;">runat</span><span style="color: blue;">=&#8221;server&#8221; </span><span style="color: red;">CommandName</span><span style="color: blue;">=&#8221;Login&#8221; </span><span style="color: red;">Text</span><span style="color: blue;">=&#8221;Log In&#8221;</span><span style="color: red;">  OnClick</span><span style="color: blue;">=&#8221;LoginButton_Click&#8221; /&gt;</span></div>
<div class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">p</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">p</span><span style="color: blue;">&gt;&lt;</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">label </span><span style="color: red;">runat</span><span style="color: blue;">=&#8221;server&#8221; </span><span style="color: red;">ID</span><span style="color: blue;">=&#8221;lblError&#8221; </span><span style="color: red;">ForeColor</span><span style="color: blue;">=&#8221;red&#8221;&gt;&lt;/</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">label</span><span style="color: blue;">&gt;</span></div>
<div class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">p</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">div</span><span style="color: blue;">&gt; </span></div>
<div class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">form</span><span style="color: blue;">&gt; </span></div>
<p>&nbsp;</p>
<p>The code for the login page:</p>
<pre class="code"><span style="color: blue;">protected void </span>Page_Load(<span style="color: blue;">object </span>sender, <span style="color: #2b91af;">EventArgs </span>e)
{

}

<span style="color: blue;">protected void </span>LoginButton_Click(<span style="color: #2b91af;">Object </span>source, <span style="color: #2b91af;">EventArgs </span>e)
{
    Session.Clear();

    <span style="color: blue;">if </span>(IsValid)
    {
        <span style="color: blue;">var </span>userNameAsEntered = UserName.Text;
        <span style="color: blue;">var </span>userPassword = Password.Text;

        <span style="color: blue;">if </span>(userNameAsEntered == <span style="color: #a31515;">"test" </span>&amp;&amp; userPassword == <span style="color: #a31515;">"test"</span>)
        {
            lblError.Text = <span style="color: #2b91af;">String</span>.Empty;
            <span style="color: #2b91af;">FormsAuthentication</span>.RedirectFromLoginPage(
                userNameAsEntered, <span style="color: blue;">false</span>);
        }
        lblError.Text = <span style="color: #a31515;">"Inalid Login"</span>;
    }
}</pre>
<p>&nbsp;</p>
<p>The markup for the home page:</p>
<pre class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">form </span><span style="color: red;">id</span><span style="color: blue;">="form1" </span><span style="color: red;">runat</span><span style="color: blue;">="server"&gt; &lt;</span><span style="color: maroon;">div</span><span style="color: blue;">&gt; </span>Home Page! Welcome:</pre>
<pre class="code"><span style="color: blue;">&lt;</span><span style="color: maroon;">p</span><span style="color: blue;">&gt; &lt;</span><span style="color: maroon;">asp</span><span style="color: blue;">:</span><span style="color: maroon;">loginname </span><span style="color: red;">ID</span><span style="color: blue;">="Loginname1" </span><span style="color: red;">runat</span><span style="color: blue;">="server" /&gt;&lt;/</span><span style="color: maroon;">p</span><span style="color: blue;">&gt; &lt;/</span><span style="color: maroon;">div</span><span style="color: blue;">&gt; </span></pre>
<pre class="code"><span style="color: blue;">&lt;/</span><span style="color: maroon;">form</span><span style="color: blue;">&gt; </span></pre>
<p>Make sure that Forms Authentication works and that home page can be accesses only after the successful login (<strong><em>test,test</em></strong>).</p>
<p><strong>3)</strong>  Modify Global.aspx. Add Route to the login service:</p>
<pre class="code"><span style="color: blue;">private void </span>RegisterRoutes()
       {
           <span style="color: #2b91af;">RouteTable</span>.Routes.Add(<span style="color: blue;">new </span><span style="color: #2b91af;">ServiceRoute</span>(
               <span style="color: #a31515;">"Service1"</span>, <span style="color: blue;">new </span><span style="color: #2b91af;">WebServiceHostFactory</span>(),
               <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">Service1</span>)));</pre>
<p><span style="background-color: #ffff00;"><span style="color: #2b91af;">                                RouteTable</span>.Routes.Add(<span style="color: blue;">new </span><span style="color: #2b91af;">ServiceRoute</span>( <span style="color: #a31515;">&#8220;Login&#8221;</span>, <span style="color: blue;">new</span><span style="color: #2b91af;">         WebServiceHostFactory</span>(), <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">LoginManager</span>)));</span></p>
<pre class="code">       }</pre>
<p>&nbsp;</p>
<p>Make sure that the login service is accessible to unauthenticated users. Add location path to the web.config:</p>
<pre class="code">  <span style="color: blue;">&lt;</span><span style="color: #a31515;">location </span><span style="color: red;">path</span><span style="color: blue;">=</span>"<span style="color: blue;">login</span>"<span style="color: blue;">&gt; &lt;</span><span style="color: #a31515;">system.web</span><span style="color: blue;">&gt; </span></pre>
<pre class="code"><span style="color: blue;">&lt;</span><span style="color: #a31515;">authorization</span><span style="color: blue;">&gt; &lt;</span><span style="color: #a31515;">allow </span><span style="color: red;">users</span><span style="color: blue;">=</span>"<span style="color: blue;">*</span>" <span style="color: blue;">/&gt; &lt;/</span><span style="color: #a31515;">authorization</span><span style="color: blue;">&gt; </span></pre>
<pre class="code"><span style="color: blue;">&lt;/</span><span style="color: #a31515;">system.web</span><span style="color: blue;">&gt; &lt;/</span><span style="color: #a31515;">location</span><span style="color: blue;">&gt; </span></pre>
<p>Also make sure that <strong><em>Service1</em></strong> path can only be accessed by authenticated users.</p>
<p><strong>4)</strong> Add two new classes <strong>LoginManager.cs</strong> and <strong>ServiceUser.cs</strong>.</p>
<pre class="code"><span style="color: blue;">public class </span><span style="color: #2b91af;">ServiceUser </span>{
    <span style="color: blue;">public string </span>Username { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }
    <span style="color: blue;">public string </span>Password { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }
}</pre>
<pre class="code">[<span style="color: #2b91af;">ServiceContract</span>]
    [<span style="color: #2b91af;">AspNetCompatibilityRequirements</span>(
        RequirementsMode =
        <span style="color: #2b91af;">AspNetCompatibilityRequirementsMode</span>.Allowed)]
    [<span style="color: #2b91af;">ServiceBehavior</span>(
        InstanceContextMode = <span style="color: #2b91af;">InstanceContextMode</span>.PerCall)]
    <span style="color: blue;">public class </span><span style="color: #2b91af;">LoginManager </span>{
        [<span style="color: #2b91af;">WebInvoke</span>(UriTemplate = <span style="color: #a31515;">""</span>, Method = <span style="color: #a31515;">"POST"</span>)]
        <span style="color: blue;">public bool </span>Login(<span style="color: #2b91af;">ServiceUser </span>user)
        {
            <span style="color: green;">//</span><span style="color: #00008b;">TODO: Add real login </span><span style="color: blue;">if </span>( user.Username == <span style="color: #a31515;">"test" </span></pre>
<pre class="code">&amp;&amp; user.Password == <span style="color: #a31515;">"test" </span>)
            {
                <span style="color: #2b91af;">FormsAuthentication</span>.SetAuthCookie(
                    user.Username, <span style="color: blue;">false</span>);
                <span style="color: blue;">return true</span>;
            }
            <span style="color: blue;">return false</span>;
        }

        [<span style="color: #2b91af;">WebInvoke</span>(UriTemplate = <span style="color: #a31515;">"logout"</span>, Method = <span style="color: #a31515;">"POST"</span>)]
        <span style="color: blue;">public bool </span>LogOut(<span style="color: blue;">string </span>userName)
        {
            <span style="color: #2b91af;">FormsAuthentication</span>.SignOut();
            <span style="color: blue;">return true</span>;
        }

        [<span style="color: #2b91af;">WebGet</span>(UriTemplate = <span style="color: #a31515;">"identify"</span>)]
        <span style="color: blue;">public string </span>Identify()
        {
            <span style="color: blue;">var </span>uri = <span style="color: #2b91af;">OperationContext</span>.Current
                .Channel.LocalAddress.ToString();
            <span style="color: blue;">return </span>uri;

        }
    }</pre>
<p>&nbsp;</p>
<p><strong>5)</strong> Modify <strong>Service1.cs</strong> class. Add some code to unfinished template methods. We will test all of them.</p>
<pre class="code"><span style="color: green;">// Start the service and browse to </span></pre>
<pre class="code"><span style="color: green;">//http://&lt;machine_name&gt;:&lt;port&gt;/Service1/help </span></pre>
<pre class="code"><span style="color: green;">//to view the service's generated help page </span></pre>
<pre class="code">[<span style="color: #2b91af;">ServiceContract</span>]
    [<span style="color: #2b91af;">AspNetCompatibilityRequirements</span>(
        RequirementsMode =
        <span style="color: #2b91af;">AspNetCompatibilityRequirementsMode</span>.Allowed)]
    [<span style="color: #2b91af;">ServiceBehavior</span>(
        InstanceContextMode =
        <span style="color: #2b91af;">InstanceContextMode</span>.PerCall)]
    <span style="color: blue;">public class </span><span style="color: #2b91af;">Service1 </span>{
        [<span style="color: #2b91af;">WebGet</span>(UriTemplate = <span style="color: #a31515;">""</span>)]
        <span style="color: blue;">public </span><span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">SampleItem</span>&gt; GetCollection()
        {
            <span style="color: blue;">return new </span><span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">SampleItem</span>&gt;()
                       {
                           <span style="color: blue;">new </span><span style="color: #2b91af;">SampleItem</span>()
                           {
                               Id = 1,
                               StringValue = <span style="color: #a31515;">"Hello" </span>}
                       };
        }

        [<span style="color: #2b91af;">WebInvoke</span>(UriTemplate = <span style="color: #a31515;">""</span>, Method = <span style="color: #a31515;">"POST"</span>)]
        <span style="color: blue;">public </span><span style="color: #2b91af;">SampleItem </span>Create(<span style="color: #2b91af;">SampleItem </span>instance)
        {
            <span style="color: blue;">return new </span><span style="color: #2b91af;">SampleItem</span>() {
                Id = 2,
                StringValue = <span style="color: #a31515;">"Hello 2" </span>};
        }

        [<span style="color: #2b91af;">WebGet</span>(UriTemplate = <span style="color: #a31515;">"{id}"</span>)]
        <span style="color: blue;">public </span><span style="color: #2b91af;">SampleItem </span>Get(<span style="color: blue;">string </span>id)
        {
            <span style="color: blue;">return new </span><span style="color: #2b91af;">SampleItem</span>()
                       {
                           Id = <span style="color: blue;">int</span>.Parse(id),
                           StringValue = <span style="color: #a31515;">"Single Item " </span>+ id
                       };
        }

        [<span style="color: #2b91af;">WebInvoke</span>(UriTemplate = <span style="color: #a31515;">"{id}"</span>,
            Method = <span style="color: #a31515;">"PUT"</span>)]
        <span style="color: blue;">public </span><span style="color: #2b91af;">SampleItem </span>Update(<span style="color: blue;">string </span>id, <span style="color: #2b91af;">SampleItem </span>instance)
        {
            instance.StringValue += <span style="color: #a31515;">"Updated"</span>;
            <span style="color: blue;">return </span>instance;
        }

        [<span style="color: #2b91af;">WebInvoke</span>(UriTemplate = <span style="color: #a31515;">"{id}"</span>,
            Method = <span style="color: #a31515;">"DELETE"</span>)]
        <span style="color: blue;">public string </span>Delete(<span style="color: blue;">string </span>id)
        {
            <span style="color: blue;">return </span><span style="color: #a31515;">"deleted"</span>; <span style="color: green;">//make sure we are getting here </span>}

    }</pre>
<p>&nbsp;</p>
<p><strong>6)</strong> Starting the  WcfRestServiceApp and browsing to &#8220;http://<machine_name"><em>http://&lt;machine_name</em><em>&gt;:&lt;port&gt;/Service1/help</em></p>
<p>should bring this page:</p>
<p>&nbsp;</p>
<div id="attachment_247" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/11/service1Help.png"><img class="size-medium wp-image-247" title="Service1 generated help page" src="http://sim4all.com/blogging/wp-content/uploads/2011/11/service1Help-300x158.png" alt="Service1 help page" width="300" height="158" /></a><p class="wp-caption-text">Service1 generated help page</p></div>
<p>Starting the WcfRestServiceApp and browsing to &#8220;http://<machine_name>:</p>
<port>/login/help&#8221;><em>:/login/help&#8221;&gt;http://&lt;machine_name&gt;:&lt;port&gt;/login/help</em></p>
<p>should bring this page: </p>
<div id="attachment_248" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/11/loginHelp.png"><img class="size-medium wp-image-248" title="Login service generated help page" src="http://sim4all.com/blogging/wp-content/uploads/2011/11/loginHelp-300x139.png" alt="Login service generated help page" width="300" height="139" /></a><p class="wp-caption-text">Login service generated help page</p></div>
<p></p>
<p><strong>7)</strong> The next step is to create an Html page that will be our PhoneGap application. The page will function as a PhoneGap page with only one minor change. Check out Part 3 of <strong>Cross-Platform Mobile Development with WP7, PhoneGap and .NET 4.0 WCF REST </strong>for details.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=246</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cross-Platform Mobile Development with WP7, PhoneGap and .NET 4.0 WCF REST &#8211; Part 1</title>
		<link>http://sim4all.com/blogging/?p=235</link>
		<comments>http://sim4all.com/blogging/?p=235#comments</comments>
		<pubDate>Mon, 31 Oct 2011 01:02:34 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[WCF REST]]></category>
		<category><![CDATA[Windows Phone]]></category>
		<category><![CDATA[WP7]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=235</guid>
		<description><![CDATA[This is Part 1 of the walkthrough that demonstrates cross-platform mobile application with PhoneGap, WP7 and .NET 4.0 WCF REST Services. At least Part 2 will be needed to demonstrate a working application without making this post too long. In order &#8230; <a href="http://sim4all.com/blogging/?p=235">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is <strong>Part 1</strong> of the walkthrough that demonstrates<strong> cross-platform</strong> mobile application with <a title="PhoneGap" href="http://phonegap.com/">PhoneGap</a>, <a title="WP7" href="http://create.msdn.com/en-US/">WP7</a> and .NET 4.0 WCF REST Services. At least Part 2 will be needed to demonstrate a working application without making this post too long.</p>
<p>In order to create the demo app the following items will be needed:</p>
<ol>
<li><strong>.NET 4.0 WCF REST Template</strong> for quick and easy service starter.</li>
<li><a title="PhoneGap" href="http://phonegap.com/">PhoneGap 1.1.0</a> (current version is: callback-phonegap-1.1.0-0-gc81c02b).</li>
</ol>
<p>To install WCF REST Template open <strong>Extensions Manager</strong> in Visual Studio and search for <strong>WCF REST Service Template</strong> 40 in Online Gallery.</p>
<div id="attachment_236" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/10/WcfRestTempl.png"><img class="size-medium wp-image-236" title="Locate .NET 4.0 WCF REST Template" src="http://sim4all.com/blogging/wp-content/uploads/2011/10/WcfRestTempl-300x178.png" alt="Locate .NET 4.0 WCF REST Template" width="300" height="178" /></a><p class="wp-caption-text">Locate .NET 4.0 WCF REST Template</p></div>
<p>After installation the template should be available in Visual Studio.</p>
<div id="attachment_223" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/10/SelectTemplate1.png"><img class="size-medium wp-image-223" title="Select WCF REST Template" src="http://sim4all.com/blogging/wp-content/uploads/2011/10/SelectTemplate1-300x149.png" alt="Select WCF REST Template" width="300" height="149" /></a><p class="wp-caption-text">Select WCF REST Template</p></div>
<p>Visit <a title="PhoneGap" href="http://phonegap.com/">PhoneGap</a> to obtain PhoneGap template for Visual Studio. The downloaded file <strong>callback-phonegap-1.1.0-0-gc81c02b.zip</strong> will contain the template in <em>callback-phonegap-1.1.0-0-gc81c02b\callback-phonegap-c81c02b\WP7</em> directory. Copy zipped template to your <em>Documents\Visual Studio 2010\Templates\ProjectTemplates</em> as in the image below (<strong>GapAppStarter.zip</strong> is a template).</p>
<div id="attachment_225" class="wp-caption aligncenter" style="width: 265px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/10/PhoneGapTemplateLocation.png"><img class="size-full wp-image-225" title="PhoneGap Template Location" src="http://sim4all.com/blogging/wp-content/uploads/2011/10/PhoneGapTemplateLocation.png" alt="PhoneGap Template Location" width="255" height="226" /></a><p class="wp-caption-text">PhoneGap Template Location</p></div>
<p>&nbsp;</p>
<p>Now the PhoneGap template should be available in Visual Studio when you navigate all the way up to Visual C# in <strong>Add New Project Window</strong>. If you do not see it type <strong>phonegap</strong> in the <strong>Search Installed Templates</strong> box in the top right. It should show up after you start typing.</p>
<div id="attachment_227" class="wp-caption aligncenter" style="width: 310px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/10/PhoneGap.png"><img class="size-medium wp-image-227" title="PhoneGap Installed Template" src="http://sim4all.com/blogging/wp-content/uploads/2011/10/PhoneGap-300x205.png" alt="PhoneGap Installed Template" width="300" height="205" /></a><p class="wp-caption-text">PhoneGap Installed Template</p></div>
<p>Next create a solution with two projects. First created from WCF REST template and a second created from PhoneGap template.</p>
<div id="attachment_229" class="wp-caption aligncenter" style="width: 183px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/10/WcfRestProject.png"><img class="size-full wp-image-229" title="WCF REST Project" src="http://sim4all.com/blogging/wp-content/uploads/2011/10/WcfRestProject.png" alt="WCF REST Project" width="173" height="148" /></a><p class="wp-caption-text">WCF REST Project</p></div>
<p>&nbsp;</p>
<div id="attachment_231" class="wp-caption aligncenter" style="width: 167px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/10/PhoneGapProject.png"><img class="size-medium wp-image-231" title="PhoneGap Project" src="http://sim4all.com/blogging/wp-content/uploads/2011/10/PhoneGapProject-157x300.png" alt="PhoneGap Project" width="157" height="300" /></a><p class="wp-caption-text">PhoneGap Project</p></div>
<p>Make PhoneGap project a startup project to verify that it compiles and deploys to the emulator.</p>
<div id="attachment_233" class="wp-caption aligncenter" style="width: 190px"><a href="http://sim4all.com/blogging/wp-content/uploads/2011/10/phoneGapStarter.png"><img class="size-medium wp-image-233" title="PhoneGap App in the Emulator" src="http://sim4all.com/blogging/wp-content/uploads/2011/10/phoneGapStarter-180x300.png" alt="PhoneGap App in the Emulator" width="180" height="300" /></a><p class="wp-caption-text">PhoneGap App in the Emulator</p></div>
<p>After that make WCF REST Service the startup project because this is where the cross-platform demo app development will start in Part 2. In the process functionalities, capabilities and limitations of .NET 4.0 WCF REST and PhoneGap for Windows Phone will be explored.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=235</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SharePoint 2007 WCF Services Reference in VS 2010 and XmlElement vs. XElement confusion.</title>
		<link>http://sim4all.com/blogging/?p=218</link>
		<comments>http://sim4all.com/blogging/?p=218#comments</comments>
		<pubDate>Tue, 27 Sep 2011 04:45:00 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[VS 2010]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=218</guid>
		<description><![CDATA[I have been a victim of this VS 2010 behavior the second time around. For the record then, I am going to make a note of it (who knows, it might hunt me again). I added a Service Reference to &#8230; <a href="http://sim4all.com/blogging/?p=218">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have been a victim of this VS 2010 behavior the second time around. For the record then, I am going to make a note of it (who knows, it might hunt me again).</p>
<p>I added a Service Reference to SharePoint 2007 asmx services in VS 2010 and tried to reuse my old code for parsing the returned XML. The old code was created in VS 2008.</p>
<p>Surprisingly, I saw red and blue squiggles under parameters and return values from my parsing methods. The error message stated that I tried to substitute <strong>XmlElement</strong> in <em>System.Xml</em> with <strong>XElement</strong> in <em>System.Xml.Linq</em>.</p>
<p>I found the solution here: <a href="http://www.go4answers.com/Example/generated-service-references-xelement-170554.aspx" target="_blank">Answer 7 is the solution</a>. To stop VS 2010 from mixing up XmlElement vs. XElement problem make sure that <strong>System.Xml.Linq</strong> is not being referenced in a project when you create the proxy. VS will use XmlElement for Xml nodes returned from the service methods and the legacy code will compile.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=218</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Investigating EnableViewState and ViewStateMode in .NET 4.0</title>
		<link>http://sim4all.com/blogging/?p=199</link>
		<comments>http://sim4all.com/blogging/?p=199#comments</comments>
		<pubDate>Fri, 19 Aug 2011 04:24:24 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ViewState]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=199</guid>
		<description><![CDATA[Today, I stumbled upon a problem with enabling a view state for a control.&#160; It took me about 2 hours to fully comprehend the scope of the problem and to find the fix. I hope that sharing my findings might &#8230; <a href="http://sim4all.com/blogging/?p=199">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today, I stumbled upon a problem with enabling a view state for a control.&#160; It took me about 2 hours to fully comprehend the scope of the problem and to find the fix. I hope that sharing my findings might actually help out somebody. </p>
<p>In .NET 4.0 there are two properties that control the <strong>ViewState</strong>.     <br /><strong>ViewStateEnabled</strong> (<em>true or false</em>) and <strong>ViewStateMode</strong> (<em>Enabled, Disabled, Inherit</em>).     <br /><strong>ViewStateEnabled</strong> can be set for the whole application in a <strong>web.config</strong>.&#160; </p>
<p><span style="color: blue">&lt;</span><span style="color: #a31515">pages </span><span style="color: red">enableViewState</span><span style="color: blue">=</span>&quot;<font color="#0000ff">true|false</font>&quot; <span style="color: blue">/&gt;</span></p>
<p>I used an <strong>asp dropdown list</strong> on my page and I needed to get the <em>selected value</em> upon the post back. Sounds simple and straightforward, as long as the <strong>pages “enableViewState”</strong> property is set to <strong>true</strong> (it is by default).</p>
<p>Let’s start an experiment and create a web application with two pages. Both pages host a dropdown list and the <strong>first objective</strong> is to retrieve the value of the selected item upon the postback. To make things not trivial set this in the <strong>web.config</strong> :&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">pages </span><span style="color: red">enableViewState</span><span style="color: blue">=</span>&quot;<span style="color: blue">false</span>&quot; <span style="color: blue">/&gt;. </span>The pages are almost identical but one of them is a page with a Master and the other is Master less.</p>
<p>We want the pages look like this:</p>
<p><a href="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithMaster.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Postback with Master Page" border="0" alt="Postback with Master Page" src="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithMaster_thumb.png" width="244" height="121" /></a></p>
<p><a href="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithoutMaster.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Postback without Master Page" border="0" alt="Postback without Master Page" src="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithoutMaster_thumb.png" width="244" height="95" /></a></p>
<p> <span style="color: blue"></span>
<p>And this is how they start:</p>
<p><a href="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithMasterEmptyPostback.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Empty Postback with Master Page" border="0" alt="Empty Postback with Master Page" src="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithMasterEmptyPostback_thumb.png" width="244" height="118" /></a></p>
<p><a href="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithoutMasterEmptyPostback.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Empty Postback without Master Page" border="0" alt="Empty Postback without Master Page" src="http://sim4all.com/blogging/wp-content/uploads/2011/08/WithoutMasterEmptyPostback_thumb.png" width="244" height="97" /></a></p>
<p>In case of the Page without the Master enabling ViewState on the <strong>page level</strong> is the quickest way to make the ViewState work for the control.</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Page </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot;
    </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;NoMasterPage.aspx.cs&quot;
    </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;ViewStateApp.NoMasterPage&quot;
    </span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot; </span><span style="background: yellow">%&gt;
</span></pre>
<p>&#160;</p>
<p>In a case of the Page with a Master Page, enabling the ViewState on the <strong>page level</strong> is not enough. Setting this:</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Page </span><span style="color: red">Title</span><span style="color: blue">=&quot;Home Page&quot; </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot;
    </span><span style="color: red">MasterPageFile</span><span style="color: blue">=&quot;~/Site.master&quot;
    </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot;
    </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;Default.aspx.cs&quot;
    </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;ViewStateApp._Default&quot; </span><span style="background: yellow">%&gt;
</span></pre>
<p>&#160;</p>
<p>will not make the control ViewState work. But enabling the ViewState on the <strong>Master Page</strong> as well, will do the trick and make the ViewState work for the dropdown list.</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Master </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot;
</span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;Site.master.cs&quot; </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;ViewStateApp.SiteMaster&quot;
</span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot;  </span><span style="background: yellow">%&gt;
</span></pre>
<p>&#160;</p>
<p>While both solution are quick. They bloat the site of the pages because the view state gets enabled for all controls. So, now let’s move&#160; to an <strong>objective number two. </strong>Make the ViewState work for the dropdown lists but keep the ViewState as small as possible. </p>
<p>This is where the ViewStateMode comes to the rescue.</p>
<p>The <strong>Page directive</strong> for a&#160; <em>No Master Page</em> and the <strong>control settings</strong> should look like this:</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Page </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot;
    </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;NoMasterPage.aspx.cs&quot;
    </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;ViewStateApp.NoMasterPage&quot;
    </span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">ViewStateMode</span><span style="color: blue">=&quot;Disabled&quot; </span><span style="background: yellow">%&gt;
</span></pre>
<pre class="code"> <span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">dropdownlist </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">ID</span><span style="color: blue">=&quot;ddlItems&quot; </span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">ViewStateMode</span><span style="color: blue">=&quot;Enabled&quot;  &gt;
</span></pre>
<p>&#160;</p>
<p>The <strong>page directive</strong>, the <strong>Master Page directive</strong> and the <strong>control settings</strong> should look like this for the <em>Page with the Master</em>:</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Page </span><span style="color: red">Title</span><span style="color: blue">=&quot;Home Page&quot; </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot;
    </span><span style="color: red">MasterPageFile</span><span style="color: blue">=&quot;~/Site.master&quot;
    </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot;
    </span><span style="color: red">ViewStateMode</span><span style="color: blue">=&quot;Disabled&quot;
    </span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;Default.aspx.cs&quot;
    </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;ViewStateApp._Default&quot; </span><span style="background: yellow">%&gt;
</span></pre>
<p>&#160;</p>
<pre class="code"><span style="background: yellow">&lt;%</span><span style="color: blue">@ </span><span style="color: maroon">Master </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot;
</span><span style="color: red">CodeBehind</span><span style="color: blue">=&quot;Site.master.cs&quot; </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;ViewStateApp.SiteMaster&quot;
</span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot;
</span><span style="color: red">ViewStateMode</span><span style="color: blue">=&quot;Disabled&quot;  </span><span style="background: yellow">%&gt;

</span></pre>
<p>&#160;</p>
<pre class="code">  <span style="color: blue">&lt;</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">dropdownlist </span><span style="color: red">runat</span><span style="color: blue">=&quot;server&quot; </span><span style="color: red">ID</span><span style="color: blue">=&quot;ddlItems&quot;
  </span><span style="color: red">EnableViewState</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">ViewStateMode</span><span style="color: blue">=&quot;Enabled&quot;&gt;
  &lt;/</span><span style="color: maroon">asp</span><span style="color: blue">:</span><span style="color: maroon">dropdownlist</span><span style="color: blue">&gt;
</span></pre>
<p>&#160;</p>
<p><em>Hope it helps</em>. Just remember about the <strong>Master Page</strong> when considering how ViewState settings are inherited.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=199</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Refreshing Entities in WCF Data Services&#8211;Handling Database Triggers</title>
		<link>http://sim4all.com/blogging/?p=186</link>
		<comments>http://sim4all.com/blogging/?p=186#comments</comments>
		<pubDate>Sun, 07 Aug 2011 21:45:00 +0000</pubDate>
		<dc:creator>KJRB</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Triggers]]></category>
		<category><![CDATA[WCF Data Services]]></category>

		<guid isPermaLink="false">http://sim4all.com/blogging/?p=186</guid>
		<description><![CDATA[WCF Data Service Context is very smart when it comes to loading entities the data source. It attempts to do it just once. This is to avoid problems related to requesting the same data multiple times, which is bad in &#8230; <a href="http://sim4all.com/blogging/?p=186">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>WCF Data Service Context is very smart when it comes to loading entities the data source. It attempts to do it just once. This is to avoid problems related to requesting the same data multiple times, which is bad in a case of the local database and even worse in a case of the remote service.</p>
<p>The side effect of this behavior can cause some trouble for WCF Data Services beginners when the reload behavior is actually needed.</p>
<p>There are few options to force the context to refresh entities.</p>
<p>To refresh a child entity that was modified by some external process (for example a trigger fired when the entity was added to the database) you can use <strong>LoadProperty</strong> method:</p>
<pre class="code"><span style="color: blue;">var child = new ChildEntity </span>{ Name = “child 1”, Property1 = 1 }
_context.AddObject(<span style="color: #a31515;">"ChildEntities"</span>, child);
_context.SaveChanges();
_context.LoadProperty(parent, <span style="color: #a31515;">"ChildEntities"</span>);</pre>
<p>Calling this method forces the context object to reload the requested property and bring the changed entity back.</p>
<p>To refresh the root entity you can do this:</p>
<pre class="code">_context.AddObject(<span style="color: #a31515;">"Profiles"</span>, profile);
_context.SaveChanges();
var mergeOptions = _context.MergeOption;
_context.MergeOption = MergeOption.OverwriteChanges;
profile = GetProfile(profile.UserName); //on another context
_context.MergeOption = mergeOptions;</pre>
<p>or you can try this:</p>
<pre class="code">_context.AddObject(<span style="color: #a31515;">"Profiles"</span>, profile);
<span style="color: blue;">var </span>userName = profile.UserName;
_context.Detach(profile);
profile = _context.CrmProfiles
.Where(p =&gt; p.UserName == userName).Single();</pre>
<p>In both cases the entity will be updated with the changes caused by the database trigger.</p>
]]></content:encoded>
			<wfw:commentRss>http://sim4all.com/blogging/?feed=rss2&#038;p=186</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
