Jason Aminto2020-08-29T16:14:05+00:00http://blog.jasonaminto.comJason Amintojason@jasonaminto.comRavendb: Separating Document Id Into A Property Using The Patch Api2014-06-06T00:00:00+00:00http://blog.jasonaminto.com/development/2014/06/06/ravenDB:-separating-document-id-into-a-property-using-the-patch-api<p>It may feel a little dirty to put the same value in both the document id, for example:</p>
<p><em>id: Users/E41270DC-4E0D-48C2-B3CE-4A51FFB649E3</em></p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"> <span class="p">{</span>
<span class="dl">"</span><span class="s2">UserId</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">E41270DC-4E0D-48C2-B3CE-4A51FFB649E3</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Name</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">User</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Email</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">user@server.com</span><span class="dl">"</span><span class="p">,</span>
<span class="p">}</span></code></pre></figure>
<p>However, if UserId wasn’t included in the document as a property, then when you go to create an index on Users that needs to load related documents with ids that also contain the user id value, you’ll be in trouble. The closest thing you have to use is the <em>string</em> value of the document id (ie. <em>id: Users/E41270DC-4E0D-48C2-B3CE-4A51FFB649E3</em>). It’s very difficult, if not impossible, to pull the GUID out of the user id string from within the index.</p>
<p>If you do have millions of User documents in your database, and you <em>did not</em> remember to include the UserId property in the document, here’s an easy <a href="http://ravendb.net/docs/2.5/client-api/partial-document-updates">patch request</a> that will add this UserId property to all of your docs:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"> <span class="n">store</span><span class="p">.</span><span class="n">DatabaseCommands</span><span class="p">.</span><span class="nf">UpdateByIndex</span><span class="p">(</span><span class="s">"Raven/DocumentsByEntityName"</span><span class="p">,</span>
<span class="k">new</span> <span class="n">IndexQuery</span> <span class="p">{</span> <span class="n">Query</span> <span class="p">=</span> <span class="s">"Tag:Users"</span> <span class="p">},</span>
<span class="k">new</span> <span class="n">ScriptedPatchRequest</span>
<span class="p">{</span>
<span class="n">Script</span> <span class="p">=</span> <span class="s">@"
var currentDocId = __document_id;
var id = currentDocId.substring(currentDocId.indexOf('/')+1);
this.UserId = id;
"</span>
<span class="p">}</span>
<span class="p">);</span>
</code></pre></figure>
Removing AppName_Deploy Virtual Directory from a Site Published with Web Deploy2014-05-15T00:00:00+00:00http://blog.jasonaminto.com/deployment/2014/05/15/removing_appname_deploy_virtual_directory_from_site_published_with_web_deploy<p>By default, when using webdeploy.exe, your application will get deployed to a virtual directory similar to ApplicationName_deploy. This means instead of your page urls based of the site root, they will be based off of /ApplicationName_deploy, eg. http://<em>site</em>/ApplicationName_deploy/.
If you don’t like this, you can change by adding the following to your .csproj file:</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><DeployIisAppPath></span>Default Web Site/<span class="nt"></DeployIisAppPath></span></code></pre></figure>
<p>This is a per configuration setting, so you must add it to each configuration. For example:</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><PropertyGroup</span> <span class="na">Condition=</span><span class="s">"'$(Configuration)|$(Platform)' == 'UAT|AnyCPU'"</span><span class="nt">></span>
<span class="nt"><OutputPath></span>bin\<span class="nt"></OutputPath></span>
<span class="nt"><DeployIisAppPath></span>Default Web Site/<span class="nt"></DeployIisAppPath></span>
<span class="nt"></PropertyGroup></span></code></pre></figure>
<p>This setting used to be available in the project properties within VS, but in VS2013 at least, it is not.</p>
Using Etags In Asp.net Mvc2013-07-15T00:00:00+00:00http://blog.jasonaminto.com/development/2013/07/15/using-etags-in-asp.net-mvc<p>There are two parts to taking advantage of ETags in ASP.NET MVC (or really any other web framework):</p>
<ol>
<li>Set ETags when returning a response</li>
<li>Checking a provided ETag on a request</li>
</ol>
<p>##Setting ETags on the Response
The syntax is the easy part:
<code class="language-plaintext highlighter-rouge">Response.Cache.SetETag(responseETag);</code></p>
<p>More difficult, is deterministically creating the ETag value (<code class="language-plaintext highlighter-rouge">responseETag</code> above). The ETag should be a representation of the response content. If the response content doesn’t change, then the same ETag value should always be returned. This could be simply a last modified date, generated by hashing a file, or based off of some database value.</p>
<p>Also, another tip is that you need to set the cacheability of the response, otherwise by default it’s “private” and the ETag won’t be set in the response:</p>
<p><code class="language-plaintext highlighter-rouge">Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);</code></p>
<p>##Checking Request ETag in the Request
Here, you should check the ‘If-None-Match’ header that is sent automatically by the browser <em>if the url has been previously requested and cached by the user</em>. This value is then compared with the ETag value of the expected response. If the two match, then the server should return the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5">HTTP status code 304</a>.</p>
<p>Example code:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="kt">var</span> <span class="n">requestedETag</span> <span class="p">=</span> <span class="n">Request</span><span class="p">.</span><span class="n">Headers</span><span class="p">[</span><span class="s">"If-None-Match"</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="n">requestedETag</span> <span class="p">==</span> <span class="n">eTagOfContentToBeReturned</span><span class="p">)</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">HttpStatusCodeResult</span><span class="p">(</span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">NotModified</span><span class="p">);</span></code></pre></figure>
<p>##Full Example
So putting it all together:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Test304</span><span class="p">(</span><span class="kt">string</span> <span class="n">input</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">requestedETag</span> <span class="p">=</span> <span class="n">Request</span><span class="p">.</span><span class="n">Headers</span><span class="p">[</span><span class="s">"If-None-Match"</span><span class="p">];</span>
<span class="kt">var</span> <span class="n">responseETag</span> <span class="p">=</span> <span class="nf">LookupEtagFromInput</span><span class="p">(</span><span class="n">input</span><span class="p">);</span> <span class="c1">// lookup or generate etag however you want</span>
<span class="k">if</span> <span class="p">(</span><span class="n">requestedETag</span> <span class="p">==</span> <span class="n">responseETag</span><span class="p">)</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">HttpStatusCodeResult</span><span class="p">(</span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">NotModified</span><span class="p">);</span>
<span class="n">Response</span><span class="p">.</span><span class="n">Cache</span><span class="p">.</span><span class="nf">SetCacheability</span><span class="p">(</span><span class="n">HttpCacheability</span><span class="p">.</span><span class="n">ServerAndPrivate</span><span class="p">);</span>
<span class="n">Response</span><span class="p">.</span><span class="n">Cache</span><span class="p">.</span><span class="nf">SetETag</span><span class="p">(</span><span class="n">responseETag</span><span class="p">);</span>
<span class="k">return</span> <span class="nf">GetResponse</span><span class="p">(</span><span class="n">input</span><span class="p">);</span> <span class="c1">// do whatever work you need to obtain the result</span>
<span class="p">}</span></code></pre></figure>
Enabling Http Compression In Iis For Use With Cloudfront2012-12-19T00:00:00+00:00http://blog.jasonaminto.com/deployment/2012/12/19/enabling-http-compression-in-iis-for-use-with-cloudfront<p>##The Problem
If you <a href="http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-creating.html">create a CloundFront distribution with a custom origin</a>, and your custom origin is a windows server running IIS7 or greater, you may notice that while requests directly to the origin are served with gzip compression, the same url requested through CloudFront will not be compressed.
This is because the default configuration for IIS7 does not allow compression when requests are made via proxies.</p>
<p>##The Solution
To fix this, you need to make a change to the <code class="language-plaintext highlighter-rouge">applicationHost.config</code> file on your windows server. This is typically located at <code class="language-plaintext highlighter-rouge">C:\Windows\System32\Inetsrv\Config\applicationHost.config</code>.</p>
<p>There are few changes that need to be made.</p>
<p>First, locate the existing <a href="http://www.iis.net/configreference/system.webserver/serverruntime"><code class="language-plaintext highlighter-rouge"><serverRuntime/></code></a> node in applicationHost.config and change it to read:</p>
<p><code class="language-plaintext highlighter-rouge"><serverRuntime enabled="true" frequentHitThreshold="1" frequentHitTimePeriod="00:00:20" /></code></p>
<p>Next, locate the <a href="http://www.iis.net/configreference/system.webserver/httpcompression"><code class="language-plaintext highlighter-rouge"><httpCompression></code></a> node and add the following attributes:</p>
<p><code class="language-plaintext highlighter-rouge">noCompressionForHttp10="false" noCompressionForProxies="false"</code></p>
<p>After an <a href="http://msdn.microsoft.com/en-us/library/ms957500(v=cs.70).aspx">IISReset</a>, all requests through CloudFront should now return Gzipped content.</p>
<p>##References
A few links that helped me to this conclusion:</p>
<ul>
<li><a href="http://www.jonkragh.com/index.php/amazon-cloudfront-with-iis7/">http://www.jonkragh.com/index.php/amazon-cloudfront-with-iis7/</a></li>
<li><a href="https://forums.aws.amazon.com/thread.jspa?threadID=60812">https://forums.aws.amazon.com/thread.jspa?threadID=60812</a></li>
<li><a href="http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ServingCompressedFiles.html#CompressedCustomOrigin">http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ServingCompressedFiles.html#CompressedCustomOrigin</a></li>
<li><a href="http://stackoverflow.com/questions/2203798/in-iis7-gzipped-files-do-not-stay-that-way">http://stackoverflow.com/questions/2203798/in-iis7-gzipped-files-do-not-stay-that-way</a></li>
</ul>
Creating a Login Service for an iPhone Application using WCF2010-04-20T00:00:00+00:00http://blog.jasonaminto.com/development/2010/04/20/creating-a-login-service-for-an-iphone-application-using-wcf<p>In a <a href="/development/2009/10/19/creating-an-iphone-friendly-web-service-in-wcf">previous post</a>, we described how to create a WCF service from scratch that would easily output data from a Windows Communication Foundation (WCF) service. In this article, we’ll show you how to send data the other way - from the iPhone to a WCF service.</p>
<p>We’ll start with the sample code that was built using the instructions in the <a href="/development/2009/10/19/creating-an-iphone-friendly-web-service-in-wcf">previous post</a>. <!-- Again it is available <a href="http://avaimobile.com/Portals/32035/blogcontent/wcfservicelibrary1.zip">here</a>. --></p>
<p>For this exercise, let’s assume the hypothetical application design requires that the iPhone be able to send login credentials to the WCF service which will be validated and a response will be sent back to the iPhone indicating login success or failure.</p>
<p>Remembering that WCF automatically parses incoming data for us (when implemented correctly) and creates strongly typed, custom classes that we can use in our business logic, we’ll first create our LoginData class. Like most logins, we’ll need to take a username and a password. So in the WcfServiceLibrary1 project (which again is our WCF Service Library that contains all of the business logic for the service), create a new class with the following structure:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">[</span><span class="n">DataContract</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">LoginData</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">DataMember</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Username</span><span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;}</span>
<span class="p">[</span><span class="n">DataMember</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Password</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx">DataContract</a> attribute indicates to WCF serializer that this object should be inspected and serialized to a specific format (we’ll specify the format later in the web method definition). The <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx">DataMember</a> attribute on each property notes that the property name and value should be included in serialization.</p>
<p>Since this is the data that the iPhone developer will need to be sending, it would be useful to be able to provide an example of the exact JSON string they should be sending. To make this easy and accurate, we’ll create a test method that returns a sample login object. Add the following method to the IService1 interface:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">[</span><span class="n">OperationContract</span><span class="p">]</span>
<span class="p">[</span><span class="nf">WebGet</span><span class="p">(</span>
<span class="n">BodyStyle</span> <span class="p">=</span> <span class="n">WebMessageBodyStyle</span><span class="p">.</span><span class="n">Bare</span><span class="p">,</span>
<span class="n">RequestFormat</span> <span class="p">=</span> <span class="n">WebMessageFormat</span><span class="p">.</span><span class="n">Json</span><span class="p">,</span>
<span class="n">ResponseFormat</span> <span class="p">=</span> <span class="n">WebMessageFormat</span><span class="p">.</span><span class="n">Json</span><span class="p">,</span>
<span class="n">UriTemplate</span> <span class="p">=</span> <span class="s">"login/sample/"</span>
<span class="p">)]</span>
<span class="n">LoginData</span> <span class="nf">LoginSample</span><span class="p">();</span></code></pre></figure>
<p>Implement the method in the Service1 class:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="n">LoginData</span> <span class="nf">LoginSample</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">LoginData</span> <span class="p">{</span><span class="n">Password</span> <span class="p">=</span> <span class="s">"thisIsThePassword"</span><span class="p">,</span> <span class="n">Username</span> <span class="p">=</span> <span class="s">"thisIsTheUsername"</span><span class="p">};</span>
<span class="p">}</span></code></pre></figure>
<p>Run the web application and append Service1.svc/login/sample/ to the web dev test server location (e.g. http://localhost:52265/service1.svc/login/sample/) to see the sample data. Again this is the exact string format that the iPhone developer should send.
It should look something like this:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">{</span>
<span class="n">Password</span><span class="p">:</span> <span class="s">"thisIsThePassword"</span><span class="p">,</span>
<span class="n">Username</span><span class="p">:</span> <span class="s">"thisIsTheUsername"</span>
<span class="p">}</span></code></pre></figure>
<p><em>Again, review the <a href="/development/2009/10/19/creating-an-iphone-friendly-web-service-in-wcf">previous post</a>, on making data available for the iPhone for a better explanation of the past few steps.</em></p>
<p>Similarly, we also want to define a class that will store our login result data (whether or not the login was successful). Again in the WcfServiceLibrary1, we’ll create a new class with the following signature:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">[</span><span class="n">DataContract</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">LoginResult</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">DataMember</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="n">Success</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">DataMember</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">ErrorMessage</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Success will indicate whether or not the login succeeded, and the ErrorMessage will hold a message describing why the login failed, or will be empty if login was successful.</p>
<p>Now that we have the data transfer objects defined, we’ll create the method signature on the WCF Service Interface (IService1):</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="n">LoginResult</span> <span class="nf">Login</span><span class="p">(</span><span class="n">LoginData</span> <span class="n">data</span><span class="p">);</span></code></pre></figure>
<p>This says that we’ll be calling a method that takes the LoginData and returns a LoginResult.</p>
<p>Now we need to add the WCF magic that takes the JSON string that the iPhone sends and feeds it into our method call. While the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.aspx">WebGetAttribute</a> is used to handle web GET requests, the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webinvokeattribute.aspx">WebInvokeAttribute</a> is used for handling POST operations. So we’ll add the WebInvoke attribute to our method signature so it looks like this:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">[</span><span class="n">OperationContract</span><span class="p">]</span>
<span class="p">[</span><span class="nf">WebInvoke</span><span class="p">(</span>
<span class="n">Method</span> <span class="p">=</span> <span class="s">"POST"</span><span class="p">,</span>
<span class="n">BodyStyle</span> <span class="p">=</span> <span class="n">WebMessageBodyStyle</span><span class="p">.</span><span class="n">Bare</span><span class="p">,</span>
<span class="n">RequestFormat</span> <span class="p">=</span> <span class="n">WebMessageFormat</span><span class="p">.</span><span class="n">Json</span><span class="p">,</span>
<span class="n">ResponseFormat</span> <span class="p">=</span> <span class="n">WebMessageFormat</span><span class="p">.</span><span class="n">Json</span><span class="p">,</span>
<span class="n">UriTemplate</span> <span class="p">=</span> <span class="s">"login"</span>
<span class="p">)]</span>
<span class="n">LoginResult</span> <span class="nf">Login</span><span class="p">(</span><span class="n">LoginData</span> <span class="n">data</span><span class="p">);</span></code></pre></figure>
<p>The Method property here is set to “POST” meaning the client (the iPhone) will be POSTing data to this web method. The BodyStyle, RequestFormat, and ResponseFormat all specify that we want to send and receive JSON with no extra junk. The UriTemplate says that we will be posting data to a url similar to http://<em>server</em>/Service1.svc/login
Since we defined this method in the interface, we need to now implement this signature in the Service1 business logic class. For now we’ll let everyone in adding the following code Servic1.cs in our service library:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="n">LoginResult</span> <span class="nf">Login</span><span class="p">(</span><span class="n">LoginData</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">LoginResult</span> <span class="p">{</span><span class="n">Success</span> <span class="p">=</span> <span class="k">true</span><span class="p">};</span>
<span class="p">}</span></code></pre></figure>
<p>In a production implementation, this is where the data store would be queried and the credentials validated.</p>
<p>The coding is now all done, but testing is now the hard part. This method cannot be tested from a browser, only by a web client that can execute a POST operation. Please leave a note in the comments if you’ve found a good app to perform this testing.<br />
We’ve created our own test application for this purpose. <!-- You can download use it from [here](http://avaimobile.com/Portals/32035/blogcontent/webclienttester.zip) It is a Windows Form application that requires the .NET Framework 3.5 to run. --></p>
Creating an iPhone-friendly Web Service in WCF2009-10-19T00:00:00+00:00http://blog.jasonaminto.com/development/2009/10/19/creating-an-iphone-friendly-web-service-in-wcf<p>With the introduction of <a href="http://en.wikipedia.org/wiki/Windows_Communication_Foundation">Windows Communication Foundation</a> in the .NET Framework 3.0, the responsiblity of building your own web service interface protocol has been lifted from the developer. <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx">DataContracts</a> now provide a type-specific utility for easily sending and receiving data in either <a href="http://en.wikipedia.org/wiki/XML">XML</a> or <a href="http://en.wikipedia.org/wiki/Javascript_Object_Notation">Javascript Object Notation</a> (JSON). In our iPhone Apps, we prefer to use JSON since it is both less verbose than XML (meaning less data to transfer on cellular networks) and easier to parse on the iPhone side.</p>
<p>Setting up a JSON WCF service requires only a few simple steps.</p>
<p>First, create a new WCF Service Library Project in your Visual Studio solution and name it WcfServiceLibrary1. For demonstration purposes, we’ll modify the sample code generated by Visual Studio.</p>
<p>There are main parts to the code that is generated:</p>
<ol>
<li>The service interface definition</li>
<li>The service implementation</li>
<li>The data object definitions</li>
</ol>
<p>The IService1 interface contains all of the good stuff about WCF service. All service methods are decorated with the [OperationContract] attribute.</p>
<p>The Service1 class contains the business logic implementation of the IService1 interface.</p>
<p>The CompositeType class is the custom class returned by one of the IService1 service methods. This class uses the DataContractAttribute we mentioned before. All properties decorated with [DataMember] will be serialized (including properties marked private, so be careful) according to the serialization format you specify.</p>
<p>How do you specify the serialization format? Well that’s the interesting part.</p>
<p>Let’s create a new service method in IService1 like so:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">[</span><span class="n">OperationContract</span><span class="p">]</span>
<span class="n">CompositeType</span> <span class="nf">GetTestData</span><span class="p">();</span></code></pre></figure>
<p>Now add the attribute that specifies the output format that we want:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">[</span><span class="n">OperationContract</span><span class="p">]</span>
<span class="p">[</span><span class="nf">WebGet</span><span class="p">(</span>
<span class="n">BodyStyle</span> <span class="p">=</span> <span class="n">WebMessageBodyStyle</span><span class="p">.</span><span class="n">Bare</span><span class="p">,</span>
<span class="n">RequestFormat</span> <span class="p">=</span> <span class="n">WebMessageFormat</span><span class="p">.</span><span class="n">Json</span><span class="p">,</span>
<span class="n">ResponseFormat</span> <span class="p">=</span> <span class="n">WebMessageFormat</span><span class="p">.</span><span class="n">Json</span><span class="p">,</span>
<span class="n">UriTemplate</span> <span class="p">=</span> <span class="s">"test/random"</span>
<span class="p">)]</span>
<span class="n">CompositeType</span> <span class="nf">GetTestData</span><span class="p">();</span></code></pre></figure>
<p>This requires that a reference be added to the project to System.ServiceModel.Web and add a using statement for System.ServiceModel.Web. You can read more about these attributes <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute_members.aspx">here</a>, but this combination of attribute values will return our data in JSON format with no wrapper.</p>
<p>Next, implement the GetTestData method in Service1 like this:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="n">CompositeType</span> <span class="nf">GetTestData</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">CompositeType</span><span class="p">();</span>
<span class="p">}</span></code></pre></figure>
<p>Now we can host the service library we’ve created in a standard ASP.NET web project. So create a new ASP.NET Web Application. Now add a reference to the WcfServiceLibrary1 project that we just created. Then create a new WCF service named Service1.svc. Right click on Service1.svc and choose “View Markup”. Now we can simply configure the service to create a new instance of the Service1 class using the WebServiceHostFactory. Below is all the markup that needs to be pasted in this file:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p"><%</span><span class="err">@</span> <span class="n">ServiceHost</span> <span class="n">Language</span><span class="p">=</span><span class="s">"C#"</span> <span class="n">Debug</span><span class="p">=</span><span class="s">"true"</span> <span class="n">Service</span><span class="p">=</span><span class="s">"WcfServiceLibrary1.Service1"</span> <span class="n">Factory</span><span class="p">=</span><span class="s">"System.ServiceModel.Activation.WebServiceHostFactory"</span> <span class="p">%></span></code></pre></figure>
<p>Now it’s time to see it all in motion. Set the web application as the startup project and run it. Append Service1.svc/test/random to the path in the address bar (e.g. http://localhost:52265/Service1.svc/test/random), press enter, and take a look at the sweet JSON file that comes out, just the way the iPhone likes it.</p>
<p>Download the full sample source code <a href="/downloads/WcfServiceLibrary1.zip">here</a>.</p>
<p>Another hot tip: Download and install the <a href="https://addons.mozilla.org/en-US/firefox/addon/10869">JSONView</a> add in for Firefox to see your JSON in the browser.</p>