<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: André Santos</title>
    <description>The latest articles on DEV Community by André Santos (@vigilnt).</description>
    <link>https://dev.to/vigilnt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F76934%2Fed76a21f-b965-4911-bcb5-ba20317b69e6.jpg</url>
      <title>DEV Community: André Santos</title>
      <link>https://dev.to/vigilnt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vigilnt"/>
    <language>en</language>
    <item>
      <title>Straight A’s in WebPagetest with Umbraco</title>
      <dc:creator>André Santos</dc:creator>
      <pubDate>Tue, 27 Nov 2018 21:40:06 +0000</pubDate>
      <link>https://dev.to/vigilnt/straight-as-in-webpagetest-with-umbraco-586c</link>
      <guid>https://dev.to/vigilnt/straight-as-in-webpagetest-with-umbraco-586c</guid>
      <description>&lt;p&gt;Before launching a new website, there’s a checklist I go through, to make sure that everything is ready. One of the items in my checklist is to test the website against &lt;strong&gt;WebPagetest&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WebPagetest is a tool that was originally developed by &lt;a href="http://dev.aol.com/" rel="noopener noreferrer"&gt;AOL&lt;/a&gt; for use internally and was open-sourced in 2008 under a BSD license. The online version at &lt;a href="https://www.webpagetest.org/" rel="noopener noreferrer"&gt;www.webpagetest.org&lt;/a&gt; is run for the benefit of the performance community with several companies and individuals providing the testing infrastructure around the globe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This tool tests any website against 6 major performance affecting factors, and provides a myriad of graphs and logs that make abundantly clear what might be slowing down your site.&lt;/p&gt;

&lt;p&gt;In this post I’ll provide ways to make your site get straight A’s in WebPagetest.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;To start this off, let’s setup our environment. We’ll just need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio 2017&lt;/li&gt;
&lt;li&gt;Microsoft Azure account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Visual Studio, let’s create a new empty ASP.NET Web Application project. Then, we’ll need the latest and greatest Umbraco NuGet package (I used version 7.12.4). Once it finishes installing, just launch the website and install Umbraco with all defaults. This will bootstrap Umbraco with the Starter Website, which we’ll use as our “guinea pig” for WebPagetest.&lt;/p&gt;

&lt;p&gt;Next: publish it! We can use the publish wizard to automatically create our new WebApp and SQL Database in Azure. Before installing Umbraco in Azure, we’ll need to change the Web.config so that the install wizard is run again (I use &lt;a href="https://filezilla-project.org/" rel="noopener noreferrer"&gt;Filezilla&lt;/a&gt; to change it in Azure):&lt;/p&gt;

&lt;p&gt;Clear the Umbraco version number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"umbracoConfigurationStatus"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clear the Umbraco connection string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"umbracoDbDSN"&lt;/span&gt; &lt;span class="na"&gt;connectionString=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;providerName=&lt;/span&gt;&lt;span class="s"&gt;"System.Data.SqlClient"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this changes in place, we’re good to go. This time, we’ll not use the defaults in the Umbraco install wizard, since we’ll want to use the SQL Database we’ve just created in Azure.&lt;/p&gt;

&lt;h1&gt;
  
  
  First test
&lt;/h1&gt;

&lt;p&gt;For our tests, we’ll use the people page of the Starter Website. This is the score I got with a standard (S0) database and a basic WebApp:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi2.wp.com%2Fblogit.create.pt%2Fwp-content%2Fuploads%2F2018%2F09%2Ffirst-webpagetest.png%3Fresize%3D300%252C91%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi2.wp.com%2Fblogit.create.pt%2Fwp-content%2Fuploads%2F2018%2F09%2Ffirst-webpagetest.png%3Fresize%3D300%252C91%26ssl%3D1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since this is a very small site, only used for demonstration purposes, half of the metrics are already cleared! However, this is not usually the case for bigger websites. For this reason, I’ll still present some solutions to improve the grade for these metrics.&lt;/p&gt;

&lt;h1&gt;
  
  
  First Byte Time
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This test measures the time it takes for the first byte to reach the client’s browser after the initial http request.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are two main factors that influence this result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server power&lt;/li&gt;
&lt;li&gt;The webpage complexity (integrations with external services, complex logic involved, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to get an A
&lt;/h3&gt;

&lt;p&gt;The easiest way to mitigate this problem is by caching. You can see how to do output caching in Umbraco by reading this old post of mine: &lt;a href="https://dev.to/vigilnt/umbraco-and-donut-output-cache-50k7-temp-slug-1365650"&gt;https://blogit.create.pt/andresantos/2016/06/30/umbraco-and-donut-output-cache/&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Keep-alive Enabled
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Keep alive is a method to allow the same tcp connection for HTTP conversation instead of opening a new one with each new request.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to get an A
&lt;/h3&gt;

&lt;p&gt;This setting is active by default in IIS, so, it’s also active by default in Azure WebApps, so it’s easy to get an A!&lt;/p&gt;

&lt;h1&gt;
  
  
  Compress Transfer
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Gzip compresses your webpages, style sheets and javascripts, before sending them over to the browser. This drastically reduces transfer time since the files are much smaller.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to get an A
&lt;/h3&gt;

&lt;p&gt;Just add this setting to your Web.config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;httpCompression&lt;/span&gt; &lt;span class="na"&gt;dynamicCompressionEnableCpuUsage=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;dynamicCompressionDisableCpuUsage=&lt;/span&gt;&lt;span class="s"&gt;"90"&lt;/span&gt; &lt;span class="na"&gt;noCompressionForHttp10=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;noCompressionForProxies=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;staticTypes&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"text/*"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"message/*"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/javascript"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/font-woff"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/font-woff2"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/vnd.ms-fontobject"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/octet-stream"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"*/*"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/staticTypes&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dynamicTypes&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"text/*"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"message/*"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/javascript"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"*/*"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dynamicTypes&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/httpCompression&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Compress Images
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Image compression is minimizing the size in bytes of a graphics file without degrading the quality of the image to an unacceptable level.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to get an A
&lt;/h3&gt;

&lt;p&gt;In Umbraco, to get an A in this grade, you need to do two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crop every image and use srcsets where you can&lt;/li&gt;
&lt;li&gt;Use the PostProcessor plugin for Image Processor&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cropping an image is easy in Umbraco:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"employee-grid\_\_item\_\_image"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-image: url('@person.Photo.GetCropUrl(width: 323, height: 300, quality: 85)')"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to use the PostProcessor plugin, you just need to install it via nuget: &lt;a href="https://www.nuget.org/packages/ImageProcessor.Web.PostProcessor/1.3.1.25" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/ImageProcessor.Web.PostProcessor/1.3.1.25&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cache Static Content
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Static content is content that changes rarely. For this reason it can be cached in the user’s browser to avoid downloading the same file over and over again.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to get an A
&lt;/h3&gt;

&lt;p&gt;Just set the time it takes for the content to expire in the user’s browser and add extra mime types if you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;staticContent&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;clientCache&lt;/span&gt; &lt;span class="na"&gt;cacheControlMode=&lt;/span&gt;&lt;span class="s"&gt;"UseMaxAge"&lt;/span&gt; &lt;span class="na"&gt;cacheControlMaxAge=&lt;/span&gt;&lt;span class="s"&gt;"7.24:00:00"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;remove&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".air"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mimeMap&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".air"&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/vnd.adobe.air-application-installer-package+zip"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;remove&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".svg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mimeMap&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".svg"&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"image/svg+xml"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;remove&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".woff"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mimeMap&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".woff"&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/x-font-woff"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;remove&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".woff2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mimeMap&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".woff2"&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/x-font-woff2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;remove&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".less"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mimeMap&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".less"&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;remove&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".mp4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mimeMap&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".mp4"&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"video/mp4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;remove&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".json"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mimeMap&lt;/span&gt; &lt;span class="na"&gt;fileExtension=&lt;/span&gt;&lt;span class="s"&gt;".json"&lt;/span&gt; &lt;span class="na"&gt;mimeType=&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/staticContent&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Effective use of CDN
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;A content delivery network (CDN) refers to a geographically distributed group of servers which work together to provide fast delivery of Internet content. A CDN allows for the quick transfer of assets needed for loading Internet content including HTML pages, javascript files, stylesheets, images, and videos.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to get an A
&lt;/h3&gt;

&lt;p&gt;In Umbraco, you can achieve this last grade by doing two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use an Azure Blob Storage for media storage by installing this nuget package: &lt;a href="https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure" rel="noopener noreferrer"&gt;https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create an Azure CDN for serving this blobs through a content delivery network.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After creating an Azure CDN service and waiting about an hour for it to be available, the following presents my configuration for the media assets to be provided by it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;security&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;services&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;service&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"LocalFileImageService"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"ImageProcessor.Web.Services.LocalFileImageService, ImageProcessor.Web"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--Disable the LocalFileImageService and enable this one when using virtual paths. --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;service&lt;/span&gt; &lt;span class="na"&gt;prefix=&lt;/span&gt;&lt;span class="s"&gt;"media/"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"CloudImageService"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"ImageProcessor.Web.Services.CloudImageService, ImageProcessor.Web"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;settings&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"Container"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"media"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"MaxBytes"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"8194304"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"Timeout"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"30000"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"Host"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"https://&amp;lt;umbracositename&amp;gt;.blob.core.windows.net/media"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/settings&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/services&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/security&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;caching&lt;/span&gt; &lt;span class="na"&gt;currentCache=&lt;/span&gt;&lt;span class="s"&gt;"AzureBlobCache"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;caches&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;cache&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"AzureBlobCache"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"ImageProcessor.Web.Plugins.AzureBlobCache.AzureBlobCache, ImageProcessor.Web.Plugins.AzureBlobCache"&lt;/span&gt; &lt;span class="na"&gt;maxDays=&lt;/span&gt;&lt;span class="s"&gt;"365"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;settings&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"CachedStorageAccount"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"DefaultEndpointsProtocol=https;AccountName=&amp;lt;accountname&amp;gt;;AccountKey=&amp;lt;accountkey&amp;gt;;EndpointSuffix=core.windows.net"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"CachedBlobContainer"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"cache"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"UseCachedContainerInUrl"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"SourceStorageAccount"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"DefaultEndpointsProtocol=https;AccountName=&amp;lt;accountname&amp;gt;;AccountKey=&amp;lt;accountkey&amp;gt;;EndpointSuffix=core.windows.net"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"SourceBlobContainer"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"media"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"StreamCachedImage"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"CachedCDNRoot"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"https://&amp;lt;cdnrootname&amp;gt;.azureedge.net"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;setting&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"CachedCDNTimeout"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1000"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/settings&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/cache&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/caches&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/caching&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;So, if you followed this tips correctly, you’ll be able to run WebPagetest and get the same result as I did:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi2.wp.com%2Fblogit.create.pt%2Fwp-content%2Fuploads%2F2018%2F11%2FstraightAs.png%3Fresize%3D300%252C89%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi2.wp.com%2Fblogit.create.pt%2Fwp-content%2Fuploads%2F2018%2F11%2FstraightAs.png%3Fresize%3D300%252C89%26ssl%3D1" alt="straightAs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the complete report here: &lt;a href="https://www.webpagetest.org/result/181127_2A_bea6941dcd20d38ab54c29409fca9363/" rel="noopener noreferrer"&gt;https://www.webpagetest.org/result/181127_2A_bea6941dcd20d38ab54c29409fca9363/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://blogit.create.pt/andresantos/2018/11/27/straight-as-in-webpagetest-with-umbraco/" rel="noopener noreferrer"&gt;Straight A’s in WebPagetest with Umbraco&lt;/a&gt; appeared first on &lt;a href="https://blogit.create.pt" rel="noopener noreferrer"&gt;Blog IT&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>umbraco</category>
      <category>performance</category>
      <category>microsoftazure</category>
      <category>webdev</category>
    </item>
    <item>
      <title>KendoUI Grid, OData, WebAPI and Entity Framework</title>
      <dc:creator>André Santos</dc:creator>
      <pubDate>Wed, 05 Jul 2017 10:42:53 +0000</pubDate>
      <link>https://dev.to/vigilnt/kendoui-grid-odata-webapi-and-entity-framework-1hlb</link>
      <guid>https://dev.to/vigilnt/kendoui-grid-odata-webapi-and-entity-framework-1hlb</guid>
      <description>

&lt;p&gt;In the latest project I was involved with, there was a need to present database tables data directly in the Umbraco’s backoffice, where all CRUD operations must be supported. This tables could be something like 1000 to 1 million rows and both the website and database would be hosted in Azure, in a WebApp and SQL Database respectively. Users should be able to create complex filters and order the data as they wish as well as update the data individually and in batch.&lt;/p&gt;

&lt;p&gt;From the get-go there were some challenges we needed to overcome in order to create an usable system, that was user-friendly, fast, reliable, and where no conflitcts would come up when data was being updated from multiple users.&lt;/p&gt;

&lt;p&gt;The solution was a new Umbraco Package we called &lt;em&gt;Search Manager&lt;/em&gt; (since the database tables ultimately feed an Azure Search index) that uses &lt;a href="http://demos.telerik.com/kendo-ui/grid/index"&gt;Telerik’s Kendo UI Grid&lt;/a&gt;, WebAPI and Entity Framework. The following presents the process it took to reach the end result.&lt;/p&gt;

&lt;h2&gt;Step 1&lt;/h2&gt;

&lt;p&gt;We created a simple Umbraco Package that implemented a Kendo UI Grid which got its data from a WebAPI method that returned all rows from a table using Petapoco.&lt;/p&gt;

&lt;p&gt;This allowed us to have the complete table data in memory using a Kendo UI Grid. It worked great but had major problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A table with around 40k rows was actually a 40 MBs json download in order to populate the grid&lt;/li&gt;
&lt;li&gt;Users could be working with outdated data, since it was loaded in memory and changes could have been made to the source&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Step 2&lt;/h2&gt;

&lt;p&gt;We started using the server paging feature of the Kendo Grid. This dropped the download size greatly, but we still had problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even though we are working with only a subset of results client-side, we were still getting the complete table data server-side, using petapoco.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We needed an easy way to translate the client-side queries, such as filters, paging, order, etc to SQL queries.&lt;/p&gt;

&lt;h2&gt;Step 3&lt;/h2&gt;

&lt;p&gt;We changed the type of queries being generated by the Grid to OData. Using the &lt;a href="https://www.nuget.org/packages/Microsoft.AspNet.WebApi.OData"&gt;OData WebAPI nuget package&lt;/a&gt; we are able to map the odata query  to a C# object and then directly apply the query to any IQueryable data.&lt;/p&gt;

&lt;p&gt;Petapoco does not provide any IQueryable data support, so we changed our ORM to Entity Framework, which does, and &lt;em&gt;voilá&lt;/em&gt;!&lt;/p&gt;

&lt;h2&gt;Finally&lt;/h2&gt;

&lt;p&gt;With everything in place, we are able to have a filtered subset of results in a Grid, that gets exactly what it needs to display from a dynamically generated SQL query.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is fast because we only get exactly what we need:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An OData query generated by the Kendo UI Grid looks like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:14231/umbraco/backoffice/SearchManager/PricesApi/Read?%24inlinecount=allpages&amp;amp;%24top=20&amp;amp;%24skip=40&amp;amp;%24orderby=ProviderName+desc&amp;amp;%24filter=(NatureProcCode+eq+%27exames%27+and+AvgAmtClaimed+gt+10)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which is translated to the follwing SQL query:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;sp_executesql&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="s1"&gt;'SELECT 
    [Project1].[Approved] AS [Approved], 
    [Project1].[DiffWeightedRate] AS [DiffWeightedRate], 
    [Project1].[SubmitPrvId] AS [SubmitPrvId], 
    [Project1].[PracticeSeq] AS [PracticeSeq], 
    [Project1].[NatureProcCode] AS [NatureProcCode], 
    [Project1].[GroupProcCode] AS [GroupProcCode], 
    [Project1].[Network] AS [Network], 
    [Project1].[AmtClaimedWeighted] AS [AmtClaimedWeighted], 
    [Project1].[ManualPrice] AS [ManualPrice], 
    [Project1].[IsImported] AS [IsImported], 
    [Project1].[DiffCalculatedRate] AS [DiffCalculatedRate], 
    [Project1].[AmtContract] AS [AmtContract], 
    [Project1].[AvgAmtClaimed] AS [AvgAmtClaimed], 
    [Project1].[ProviderName] AS [ProviderName], 
    [Project1].[ClinicName] AS [ClinicName]
    FROM ( SELECT 
        [Extent1].[Approved] AS [Approved], 
        [Extent1].[DiffWeightedRate] AS [DiffWeightedRate], 
        [Extent1].[SubmitPrvId] AS [SubmitPrvId], 
        [Extent1].[PracticeSeq] AS [PracticeSeq], 
        [Extent1].[NatureProcCode] AS [NatureProcCode], 
        [Extent1].[GroupProcCode] AS [GroupProcCode], 
        [Extent1].[Network] AS [Network], 
        [Extent1].[AmtClaimedWeighted] AS [AmtClaimedWeighted], 
        [Extent1].[ManualPrice] AS [ManualPrice], 
        [Extent1].[IsImported] AS [IsImported], 
        [Extent1].[DiffCalculatedRate] AS [DiffCalculatedRate], 
        [Extent1].[AmtContract] AS [AmtContract], 
        [Extent1].[AvgAmtClaimed] AS [AvgAmtClaimed], 
        [Extent1].[ProviderName] AS [ProviderName], 
        [Extent1].[ClinicName] AS [ClinicName]
        FROM (SELECT 
    [PriceGrid].[Approved] AS [Approved], 
    [PriceGrid].[DiffWeightedRate] AS [DiffWeightedRate], 
    [PriceGrid].[SubmitPrvId] AS [SubmitPrvId], 
    [PriceGrid].[PracticeSeq] AS [PracticeSeq], 
    [PriceGrid].[NatureProcCode] AS [NatureProcCode], 
    [PriceGrid].[GroupProcCode] AS [GroupProcCode], 
    [PriceGrid].[Network] AS [Network], 
    [PriceGrid].[AmtClaimedWeighted] AS [AmtClaimedWeighted], 
    [PriceGrid].[ManualPrice] AS [ManualPrice], 
    [PriceGrid].[IsImported] AS [IsImported], 
    [PriceGrid].[DiffCalculatedRate] AS [DiffCalculatedRate], 
    [PriceGrid].[AmtContract] AS [AmtContract], 
    [PriceGrid].[AvgAmtClaimed] AS [AvgAmtClaimed], 
    [PriceGrid].[ProviderName] AS [ProviderName], 
    [PriceGrid].[ClinicName] AS [ClinicName]
    FROM [dbo].[PriceGrid] AS [PriceGrid]) AS [Extent1]
        WHERE ([Extent1].[NatureProcCode] = @p__linq__0) AND ([Extent1].[AvgAmtClaimed] &amp;gt; @p__linq__1)
    )  AS [Project1]
    ORDER BY [Project1].[ProviderName] DESC, [Project1].[AmtClaimedWeighted] ASC, [Project1].[AmtContract] ASC, [Project1].[Approved] ASC, [Project1].[AvgAmtClaimed] ASC, [Project1].[ClinicName] ASC, [Project1].[DiffCalculatedRate] ASC, [Project1].[DiffWeightedRate] ASC, [Project1].[GroupProcCode] ASC, [Project1].[IsImported] ASC, [Project1].[ManualPrice] ASC, [Project1].[NatureProcCode] ASC, [Project1].[Network] ASC, [Project1].[PracticeSeq] ASC, [Project1].[SubmitPrvId] ASC
    OFFSET @p__linq__2 ROWS FETCH NEXT @p__linq__3 ROWS ONLY  option (Recompile)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="s1"&gt;'@p__linq__0 varchar(8000),@p__linq__1 decimal(2,0),@p__linq__2 int,@p__linq__3 int'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;p__linq__0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'exames'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;p__linq__1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;p__linq__2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;p__linq__3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;It’s user-friendly and reliable because users can filter the data as if they were using an excel file on steroids&lt;/li&gt;
&lt;li&gt;It avoids conflicts because we only get a subset of the results each time and each change is commited in a single transaction&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Code samples:&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"#grid"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;kendoGrid&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;kendo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DataSource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;serverFiltering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;serverPaging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;serverSorting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"odata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
                &lt;span class="p"&gt;}),&lt;/span&gt;
                &lt;span class="na"&gt;dataBound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;onDataBound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;pageable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;filterable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;sortable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;scrollable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;navigatable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;resizable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;columnMenu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;editable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;toolbar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;a class="k-button k-button-icontext k-grid-save-batch" href="&lt;/span&gt;&lt;span class="err"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;#""&amp;gt;&amp;lt;span class="k-icon k-i-update"&amp;gt;&amp;lt;/span&amp;gt;Guardar Alterações&amp;lt;/a&amp;gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cancel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Cancelar"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...]&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="na"&gt;[HttpGet]&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IHttpActionResult&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ODataQueryOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PriceGrid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Mapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PriceGrid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PriceGridBO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;EntitiesContext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;qh&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HintScope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QueryHintType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Recompile&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PriceGrid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ApplyTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PriceGrids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PriceGrid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                    &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PriceGridBO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;boEntities&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Mapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PriceGrid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PriceGridBO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                    &lt;span class="n"&gt;PriceResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PriceResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Entities&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Total&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ODataProperties&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;TotalCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasValue&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ODataProperties&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;TotalCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
                    &lt;span class="p"&gt;};&lt;/span&gt;

                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://blogit.create.pt/andresantos/2017/07/05/kendoui-grid-odata-webapi-and-entity-framework/"&gt;KendoUI Grid, OData, WebAPI and Entity Framework&lt;/a&gt; appeared first on &lt;a href="https://blogit.create.pt"&gt;Blog IT&lt;/a&gt;.&lt;/p&gt;


</description>
      <category>umbraco</category>
      <category>net</category>
      <category>azure</category>
      <category>backofficeextension</category>
    </item>
  </channel>
</rss>
