<?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>.NET Archives - Blog IT</title>
	<atom:link href="https://blogit.create.pt/category/dotnet/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogit.create.pt/category/dotnet/</link>
	<description>Create IT blogger community</description>
	<lastBuildDate>Tue, 02 Apr 2024 16:05:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>Integration Tests in .NET WebApi</title>
		<link>https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/</link>
					<comments>https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/#respond</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Mon, 01 Apr 2024 12:47:41 +0000</pubDate>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Automatic Testing]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[inmemorydatabase]]></category>
		<category><![CDATA[integrated]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=13472</guid>

					<description><![CDATA[<p>In software development, testing is an essential aspect that ensures the stability and reliability of applications. Three primary types of tests are commonly used: unit tests, integration tests, and end-to-end tests. In this blog post, we will discuss these testing types in the context of a .NET WebAPI project and provide an example implementation of integration testing using an in-memory database.</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/">Integration Tests in .NET WebApi</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In software development, testing is an essential aspect that ensures the stability and reliability of applications. Three primary types of tests are commonly used: unit tests, integration tests, and end-to-end tests. In this blog post, we will discuss these testing types in the context of a .NET WebAPI project and provide an example implementation of integration testing using an in-memory database.</p>



<hr class="wp-block-separator has-alpha-channel-opacity" />



<h2 class="wp-block-heading">Unit Tests, Integration Tests, and End-to-End Tests: What&#8217;s the Difference?</h2>



<ul class="wp-block-list">
<li><strong>Unit tests</strong> focus on testing individual units or components of your application in isolation. This type of test verifies whether the unit/component works correctly and adheres to its business logic.</li>



<li><strong>Integration tests</strong> aim to test multiple units or components together, ensuring that they interact properly. Integration tests can uncover issues related to data flow, communication between components, and external dependencies like databases.</li>



<li><strong>End-to-end (E2E)</strong> tests simulate a complete user scenario by testing the entire application from start to finish. E2E tests can help identify issues related to multiple components, external APIs, and user interfaces.</li>
</ul>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h2 class="wp-block-heading">Example Implementation in .NET</h2>



<p>To perform integration tests, we will use an in-memory database and the <em>WebApplicationFactory </em>feature of ASP.NET Core. This approach allows us to test our WebAPI application with a real web server in memory, simulating how the components interact with each other when making requests.</p>



<p>First, let&#8217;s create an InMemoryDbAppFactory that sets up our in-memory web server and database:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
public class InMemoryDbAppFactory : WebApplicationFactory&lt;Program&gt;
{
    private readonly string _environment;

    public InMemoryDbAppFactory()
    {
        _environment = &quot;IntegrationTests&quot;;
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        Environment.SetEnvironmentVariable(&quot;ASPNETCORE_ENVIRONMENT&quot;, _environment);
        builder.UseEnvironment(_environment);
        builder.UseSetting(&quot;https_port&quot;, &quot;8080&quot;);

        builder.ConfigureTestServices(services =&gt;
        {
            services.RemoveAll&lt;ITestRepository&gt;();
            services.TryAddTransient&lt;ITestRepository, TestRepositoryTest&gt;();

            // Anonymous authentication
            services
                .AddAuthentication(&quot;Test&quot;)
                .AddScheme&lt;AuthenticationSchemeOptions, TestAuthenticationHandler&gt;(&quot;Test&quot;, options =&gt; { });
        });
    }
}
</pre></div>


<p>In order to use an in-memory database, we will override the connection string injection in our <em>ServiceCollectionExtensions</em>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
public static partial class ServiceCollectionExtensions
{
    public static IServiceCollection AddDbContexts(
        this IServiceCollection services,
        IConfiguration configuration,
        IWebHostEnvironment environment
    )
    {
        if (environment.IsEnvironment(&quot;IntegrationTests&quot;))
        {
            var connDb = new SqliteConnection(&quot;DataSource=db;mode=memory;cache=shared&quot;);
            connDb.Open();
            services.AddDbContext&lt;dbContext&gt;(options =&gt; options.UseSqlite(connDb));
        }
        else
        {
            services.AddDbContext&lt;dbContext&gt;(
                options =&gt; options.UseSqlServer(configuration.GetConnectionString(&quot;ConnectionString&quot;)).UseExceptionProcessor(),
                ServiceLifetime.Scoped
            );
        }

        return services;
    }
}
</pre></div>


<p>Finally, this is how a test looks like:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
&#x5B;Collection(&quot;MemoryDbIntegrationTests&quot;)]
public class ApiTests : IClassFixture&lt;InMemoryDbAppFactory&gt;
{
    private readonly InMemoryDbAppFactory _factory;
    private readonly HttpClient _client;

    public ApiTests(InMemoryDbAppFactory factory)
    {
        _factory = factory;
        _client = factory.CreateClient();

        // Ensures a clean database before each test
        factory.ResetDb();
    }

    &#x5B;Fact]
    public async Task GetList_Should_Return_List()
    {
        // Arrange

        // Act
        var response = await _client.GetAsync(&quot;/api/list&quot;);
        var content = await response.Content.ReadFromJsonAsync&lt;IEnumerable&lt;Dto&gt;&gt;();

        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        content.Should().NotBeNull();
        content.Should().HaveCount(2);
    }
}

</pre></div></div>
</div>



<hr class="wp-block-separator has-alpha-channel-opacity" />



<h2 class="wp-block-heading">Using an in-memory database for integration tests has both advantages and disadvantages:</h2>



<h3 class="wp-block-heading">Advantages:</h3>



<ul class="wp-block-list">
<li><strong>Faster test execution</strong>: In-memory databases provide quicker test execution times since the data is stored in memory instead of on disk. This can significantly improve your overall testing performance and help you find issues faster.</li>



<li><strong>Easy to set up and tear down</strong>: In-memory databases are easy to create, modify, and delete without the need for external dependencies or configuration changes. This makes it easier to write, run, and maintain your tests.</li>



<li><strong>Consistent test data</strong>: In-memory databases allow you to create a known set of data for your tests, ensuring that each test starts with the same initial conditions. This can help reduce the likelihood of inconsistent test results and make it easier to identify issues related to data flow or dependencies between tests.</li>
</ul>



<h3 class="wp-block-heading">Disadvantages:</h3>



<ul class="wp-block-list">
<li><strong>Limited scalability</strong>: In-memory databases have limited capacity and may not be suitable for testing large datasets or complex scenarios that require high levels of concurrency.</li>



<li><strong>Lack of realism</strong>: In-memory databases may not accurately represent the behavior or performance of a production database, especially when dealing with complex queries or data modification operations. This can make it difficult to identify issues related to database schema, indexing, and query optimization.</li>



<li><strong>Limited support for advanced features</strong>: using SQLite as our in memory database we don&#8217;t have support for multiple schemas and some advanced query features.</li>



<li><strong>Seed data</strong>: the need to create seed data can be tedious and time consuming.</li>
</ul>



<p>When deciding whether to use an in-memory database, mock data, or a real web server in memory for your integration tests, consider the specific requirements of your project and weigh the advantages and disadvantages of each approach. In many cases, using a combination of testing types and approaches can help you ensure the stability, reliability, and performance of your .NET WebAPI application.</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/">Integration Tests in .NET WebApi</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2024/04/01/integration-tests-in-net-webapi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Provision a database programmatically in Azure SQL database with a failover group</title>
		<link>https://blogit.create.pt/miguelisidoro/2024/01/24/provision-a-database-programmatically-in-azure-sql-database-with-a-failover-group/</link>
					<comments>https://blogit.create.pt/miguelisidoro/2024/01/24/provision-a-database-programmatically-in-azure-sql-database-with-a-failover-group/#respond</comments>
		
		<dc:creator><![CDATA[Miguel Isidoro]]></dc:creator>
		<pubDate>Wed, 24 Jan 2024 14:32:24 +0000</pubDate>
				<category><![CDATA[Sql Server]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Microsoft Azure]]></category>
		<category><![CDATA[azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[SQL Server]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12852</guid>

					<description><![CDATA[<p>This post will explain how to provision a database programmatically in a Azure SQL database and add it to an Azure SQL failover group. Introduction An Azure SQL Server failover group is a group of databases that can be automatically or manually failed over from a primary server to a secondary server in a different [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/miguelisidoro/2024/01/24/provision-a-database-programmatically-in-azure-sql-database-with-a-failover-group/">Provision a database programmatically in Azure SQL database with a failover group</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>This post will explain how to provision a database programmatically in a Azure SQL database and add it to an Azure SQL failover group.</p>



<h2 class="wp-block-heading">Introduction</h2>



<p>An Azure SQL Server failover group is a group of databases that can be automatically or manually failed over from a primary server to a secondary server in a different Azure region in case of a disaster in the primary server. Failover groups provide high availability and disaster recovery for Azure SQL Server databases.</p>



<p>The process described in this post is composed by two main steps:</p>



<ul class="wp-block-list">
<li>Provisioning the database</li>



<li>Adding the database to the failover group </li>
</ul>



<h2 class="wp-block-heading">Provisioning the database</h2>



<p>The first step is to create the database. This step is composed by the following actions:</p>



<ul class="wp-block-list">
<li>Get the tenant information</li>



<li>Create the database</li>
</ul>



<p>Tenant information class:</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="791" height="381" src="https://blogit.create.pt/wp-content/uploads/2024/01/Regions.jpg" alt="" class="wp-image-12869" srcset="https://blogit.create.pt/wp-content/uploads/2024/01/Regions.jpg 791w, https://blogit.create.pt/wp-content/uploads/2024/01/Regions-300x145.jpg 300w, https://blogit.create.pt/wp-content/uploads/2024/01/Regions-768x370.jpg 768w, https://blogit.create.pt/wp-content/uploads/2024/01/Regions-696x335.jpg 696w" sizes="(max-width: 791px) 100vw, 791px" /></figure>



<p>Code to create database programatically:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="722" src="https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase-1024x722.jpg" alt="" class="wp-image-12866" srcset="https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase-1024x722.jpg 1024w, https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase-300x212.jpg 300w, https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase-768x542.jpg 768w, https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase-696x491.jpg 696w, https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase-596x420.jpg 596w, https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase-100x70.jpg 100w, https://blogit.create.pt/wp-content/uploads/2024/01/CreateDatabase.jpg 1065w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Adding the database to the failover group</h2>



<p>The second step adds the newly created database to the failover group. This step is composed by the following actions:</p>



<ul class="wp-block-list">
<li>Get the failover group where we want to add the database</li>



<li>Re-add the existing databases to the failover group &#8211; necessary since when we get the failover group the list of databases of the group is empty and, without this step, the failover group would only have the new database</li>



<li>Add the new database to the failover group</li>
</ul>



<figure class="wp-block-image size-full"><img decoding="async" width="790" height="344" src="https://blogit.create.pt/wp-content/uploads/2024/01/Failovergroup.jpg" alt="" class="wp-image-12876" srcset="https://blogit.create.pt/wp-content/uploads/2024/01/Failovergroup.jpg 790w, https://blogit.create.pt/wp-content/uploads/2024/01/Failovergroup-300x131.jpg 300w, https://blogit.create.pt/wp-content/uploads/2024/01/Failovergroup-768x334.jpg 768w, https://blogit.create.pt/wp-content/uploads/2024/01/Failovergroup-696x303.jpg 696w" sizes="(max-width: 790px) 100vw, 790px" /></figure>



<h2 class="wp-block-heading">Other Articles</h2>



<p>To learn why your business should migrate to SharePoint Online and Office 365, click <a href="https://blogit.create.pt////miguelisidoro/2019/07/29/why-your-business-should-migrate-to-sharepoint-online-and-office-365-the-value-offer-part-1/" target="_blank" rel="noreferrer noopener">here</a> and <a href="https://blogit.create.pt////miguelisidoro/2019/07/29/why-your-business-should-migrate-to-sharepoint-online-and-office-365-the-value-offer-part-2/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>If you want to learn how to develop SPFx solutions, click <a href="https://blogit.create.pt/miguelisidoro/2022/05/09/sharepoint-framework-spfx-learning-guide/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>If you want to learn how you can rename a modern SharePoint site, click <a href="https://blogit.create.pt////miguelisidoro/2019/09/23/how-to-rename-a-modern-sharepoint-site-url-in-office-365/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>If you want to learn how to save time time scheduling your meetings, click&nbsp;<a href="https://blogit.create.pt////miguelisidoro/2020/04/12/save-time-scheduling-microsoft-teams-meetings-using-findtime/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>If you want to learn how to enable Microsoft Teams Attendance List Download, click&nbsp;<a href="https://blogit.create.pt////miguelisidoro/2020/09/20/how-to-enable-teams-meeting-attendance-list-download-in-microsoft-365/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>If you want to learn how to create a dynamic org-wide team in Microsoft Teams with all active employees, click&nbsp;<a href="https://blogit.create.pt/miguelisidoro/2020/09/21/how-to-create-a-dynamic-team-in-microsoft-teams-with-all-active-employees-in-microsoft-365/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>If you want to modernize your SharePoint classic root site to a modern SharePoint site, click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/08/27/how-to-modernize-your-tenant-root-site-collection-in-office-365-using-invoke-spositeswap/" target="_blank">here</a>.</p>



<p>If you are a SharePoint administrator or a SharePoint developer who wants to learn more about how to install a SharePoint 2019 farm in an automated way using PowerShell, I invite you to click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2018/12/09/how-to-install-a-sharepoint-2019-farm-using-powershell-and-autospinstaller-part-1/" target="_blank">here</a>&nbsp;and&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2018/12/09/how-to-install-a-sharepoint-2019-farm-using-powershell-and-autospinstaller-part-2/" target="_blank">here</a>.</p>



<p>If you learn how to greatly speed up your SharePoint farm update process to ensure your SharePoint farm keeps updated and you stay one step closer to start your move to the cloud, click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/05/02/how-to-speed-up-the-installation-of-sharepoint-cumulative-updates-using-powershell-step-by-step/" target="_blank">here</a>.</p>



<p>If you prefer to use the traditional method to update your farm and want to learn all the steps and precautions necessary to successfully keep your SharePoint farm updated, click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/04/08/how-to-install-sharepoint-cumulative-updates-in-a-sharepoint-farm-step-by-step/" target="_blank">here</a>.</p>



<p>If you want to learn how to upgrade a SharePoint 2013 farm to SharePoint 2019, click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/03/06/how-to-upgrade-from-sharepoint-2013-to-sharepoint-2019-step-by-step-part-1/" target="_blank">here&nbsp;</a>and&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/03/06/how-to-upgrade-from-sharepoint-2013-to-sharepoint-2019-step-by-step-part-2/" target="_blank">here</a>.</p>



<p>If SharePoint 2019 is still not an option, you can learn more about how to install a SharePoint 2016 farm in an automated way using PowerShell, click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2018/07/28/how-to-install-a-sharepoint-2016-farm-using-powershell-and-autospinstaller-part-1/" target="_blank">here</a>&nbsp;and&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2018/07/28/how-to-install-a-sharepoint-2016-farm-using-powershell-and-autospinstaller-part-2/" target="_blank">here</a>.</p>



<p>If you want to learn how to upgrade a SharePoint 2010 farm to SharePoint 2016, click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/02/04/sharepoint-upgrade-upgrading-a-sharepoint-2010-farm-to-sharepoint-2016-step-by-step-part-1/" target="_blank">here&nbsp;</a>and&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/02/04/sharepoint-upgrade-upgrading-a-sharepoint-2010-farm-to-sharepoint-2016-step-by-step-part-2/" target="_blank">here</a>.</p>



<p>If you are new to SharePoint and Office 365 and want to learn all about it, take a look at these&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2018/10/17/sharepoint-and-office-365-learning-resources/" target="_blank">learning resources</a>.</p>



<p>If you are work in a large organization who is using Office 365 or thinking to move to Office 365 and is considering between a single or multiple Office 365 tenants, I invite you to read&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2019/01/07/pros-and-cons-of-single-tenant-vs-multiple-tenants-in-office-365/" target="_blank">this article</a>.</p>



<p>If you want to know all about the latest SharePoint and Office 365 announcements from Ignite and some more recent announcements, including Microsoft Search, What’s New to Build a Modern Intranet with SharePoint in Office 365, Deeper Integration between Microsoft Teams and SharePoint and the latest news on SharePoint development, click&nbsp;<a rel="noreferrer noopener" href="https://blogit.create.pt////miguelisidoro/2018/11/21/whats-new-for-sharepoint-and-office-365-after-microsoft-ignite-2018/" target="_blank">here</a>.</p>



<p>If your organization is still not ready to go all in to SharePoint Online and Office 365, a hybrid scenario may be the best choice. SharePoint 2019 RTM was recently announced and if you to learn all about SharePoint 2019 and all its features, click <a href="https://blogit.create.pt////miguelisidoro/2018/11/01/meet-the-new-modern-sharepoint-server-sharepoint-2019-rtm-is-here/" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>Happy Coding!</p>
<p>The post <a href="https://blogit.create.pt/miguelisidoro/2024/01/24/provision-a-database-programmatically-in-azure-sql-database-with-a-failover-group/">Provision a database programmatically in Azure SQL database with a failover group</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/miguelisidoro/2024/01/24/provision-a-database-programmatically-in-azure-sql-database-with-a-failover-group/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Smaller .NET 6 docker images</title>
		<link>https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/</link>
					<comments>https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/#respond</comments>
		
		<dc:creator><![CDATA[Telmo Rodrigues]]></dc:creator>
		<pubDate>Tue, 08 Mar 2022 12:07:30 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12634</guid>

					<description><![CDATA[<p>Introduction This post compares different strategies to dockerize a .NET 6 application and how to create a &#60; 100mb docker image to host a .NET 6 asp.net web application. Using the docker multi stage builds feature and a self-contained .NET with some build options the final docker image can be reduced from 760mb to 83mb, [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/">Smaller .NET 6 docker images</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>This post compares different strategies to dockerize a .NET 6 application and how to create a &lt; 100mb docker image to host a .NET 6 asp.net web application. Using the docker multi stage builds feature and a self-contained .NET with some build options the final docker image can be reduced from 760mb to 83mb, almost 10x smaller!</p>



<p>All the images used were taken from the official Microsoft .NET docker <a href="https://hub.docker.com/_/microsoft-dotnet">repository</a>.</p>



<p></p>



<h2 class="wp-block-heading">1. .NET 6 SDK image</h2>



<p>Let&#8217;s start with a simple Dockerfile based on the official .NET 6 SDK build image.</p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0
WORKDIR /app

COPY . ./

RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish

ENTRYPOINT &#091;"dotnet", "/app/publish/WebApi.dll"]</code></pre>



<pre class="wp-block-code"><code>$ docker build -t api-aspnet .
$ docker images api-aspnet
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
api-aspnet   latest    700870327c08   1 weeks ago   761MB
</code></pre>



<p>We are using a docker single stage build using the base .net sdk image. After building the image we can see that the final image size is 761mb. Let&#8217;s try to check where the space is being used. For that we can use the docker history to see the layers created for this image.</p>



<pre class="wp-block-code"><code>$ docker history api-aspnet
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
700870327c08   1 weeks ago    ENTRYPOINT &#091;"dotnet" "/app/publish/WebApi.dl…   0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c dotnet publish "WebApi.csproj…   4.18MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c dotnet build -c Release # bui…   12.2MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY . ./ # buildkit                            721kB     buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c dotnet restore # buildkit        28.2MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY WebApi.csproj ./ # buildkit                327B      buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      2 months ago   /bin/sh -c powershell_version=7.2.1     &amp;&amp; c…   40.6MB
&lt;missing&gt;      2 months ago   /bin/sh -c curl -fSL --output dotnet.tar.gz …   392MB
&lt;missing&gt;      2 months ago   /bin/sh -c apt-get update     &amp;&amp; apt-get ins…   74.8MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS= DOTN…   0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:a54b266469a09b122…   20.3MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNET_VERSION=6.0.1 …   0B
&lt;missing&gt;      2 months ago   /bin/sh -c ln -s /usr/share/dotnet/dotnet /u…   24B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:6c537cc098876a5f6…   70.6MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV DOTNET_VERSION=6.0.1     0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS=http:…   0B
&lt;missing&gt;      2 months ago   /bin/sh -c apt-get update     &amp;&amp; apt-get ins…   37MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  CMD &#091;"bash"]                 0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) ADD file:09675d11695f65c55…   80.4MB
</code></pre>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><td>base image</td><td>20%</td></tr><tr><td>.NET SDK + runtime</td><td>60%</td></tr><tr><td>Linux libs</td><td>15%</td></tr><tr><td>Web App source + compiled code</td><td>25%</td></tr></tbody></table></figure>



<p>The .NET SDK + runtime takes most of the space, around 60%. So let&#8217;s try to shrink it.</p>



<p></p>



<h2 class="wp-block-heading">2. .NET 6 SDK image + docker multi stage build</h2>



<p>The previous section showed us that the .NET SDK + runtime takes most of the space of the final image. This is because we are using the same docker base image to build and to run the app so the final image has all the things needed to compile and run the app. Using a docker multi stage build we can cut the .NET SDK from the final image and use it only to build our app and include only the .NET runtime in the final image to run the application.</p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app

COPY . ./

RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime

WORKDIR /app
COPY --from=build /app/publish .

ENTRYPOINT &#091;"dotnet", "WebApi.dll"]</code></pre>



<p>Here we define 2 images: the <code>build</code> image used to compile the app which includes all the things needed to build our .NET 6 application and the final one, the <code>runtime</code>&nbsp; which only includes the .NET runtime to run our app. The first one to use for development (which contained everything needed to build your application), and a slimmed-down one to use for production, which only contained your compiled code and what is needed to run it. With multi-stage builds, you use multiple&nbsp;<code>FROM</code>&nbsp;statements in your Dockerfile. Each&nbsp;<code>FROM</code>&nbsp;instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.</p>



<pre class="wp-block-code"><code>$ docker build -t api-aspnet-multistage .
$ docker images api-aspnet-multistage
REPOSITORY              TAG       IMAGE ID       CREATED       SIZE
api-aspnet-multistage   latest    1021a94feca4   1 weeks ago   212MB
</code></pre>



<p>Bang, we reduced our image to 212mb, this is because the complete SDK was removed from the final image.<br>Let&#8217;s see again the layers and the space being used for each one:</p>



<pre class="wp-block-code"><code>USER@DESKTOP-BJUBV5T MINGW64 ~/Documents/sonae/identitymanager-credenciaiscontinente (fix/invalid-account-association-check)
$ docker history api-aspnet-multistage
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
1021a94feca4   1 weeks ago    ENTRYPOINT &#091;"dotnet" "WebApi.dll"]              0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY /app/publish . # buildkit                  4.18MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:a54b266469a09b122…   20.3MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNET_VERSION=6.0.1 …   0B
&lt;missing&gt;      2 months ago   /bin/sh -c ln -s /usr/share/dotnet/dotnet /u…   24B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) COPY dir:6c537cc098876a5f6…   70.6MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV DOTNET_VERSION=6.0.1     0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS=http:…   0B
&lt;missing&gt;      2 months ago   /bin/sh -c apt-get update     &amp;&amp; apt-get ins…   37MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  CMD &#091;"bash"]                 0B
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop) ADD file:09675d11695f65c55…   80.4MB
</code></pre>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><td>base image</td><td>50%</td></tr><tr><td>.NET runtime</td><td>40%</td></tr><tr><td>Web App source + compiled code</td><td>10%</td></tr></tbody></table></figure>



<p>Let´s try to reduce the bigger part, the base image.</p>



<p></p>



<h2 class="wp-block-heading">3. Multi stage build with Alpine linux Microsoft official image</h2>



<p>We can change our base image to use the Alpine Linux instead of the default one Debian bullsyeye which is the base image of the most of the official Microsoft .NET docker images.</p>



<p></p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /app

COPY . ./
RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine

WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT &#091;"dotnet", "WebApi.dll"]</code></pre>



<pre class="wp-block-code"><code>docker build -t api-multi-alpine .
docker images api-multi-alpine
REPOSITORY         TAG       IMAGE ID       CREATED       SIZE
api-multi-alpine   latest    0c7f1c3b0bfa   1 weeks ago   104MB
</code></pre>



<pre class="wp-block-code"><code>$ docker history api-multi-alpine
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
0c7f1c3b0bfa   1 weeks ago    ENTRYPOINT &#091;"dotnet" "WebApi.dll"]              0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY /app/publish . # buildkit                  4.12MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      2 months ago   /bin/sh -c wget -O aspnetcore.tar.gz https:/…   20.3MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV ASPNET_VERSION=6.0.1 …   0B
&lt;missing&gt;      2 months ago   /bin/sh -c wget -O dotnet.tar.gz https://dot…   69.8MB
&lt;missing&gt;      2 months ago   /bin/sh -c #(nop)  ENV DOTNET_VERSION=6.0.1     0B
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop)  ENV ASPNETCORE_URLS=http:…   0B
&lt;missing&gt;      3 months ago   /bin/sh -c apk add --no-cache         ca-cer…   4.35MB
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop)  CMD &#091;"/bin/sh"]              0B
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop) ADD file:762c899ec0505d1a3…   5.61MB
</code></pre>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><td>base image</td><td>10%</td></tr><tr><td>.NET runtime</td><td>80%</td></tr><tr><td>Web App source + compiled code</td><td>10%</td></tr></tbody></table></figure>



<p>Using the alpine instead of the debian base image we were able to reduce our base image size to 10% of our final image.<br>Now the .NET runtime is the part that is using most of the space of our image so let&#8217;s try to reduce this part.</p>



<p></p>



<h2 class="wp-block-heading">4. Raw alpine with a trim-self-contained and trimmed .NET build</h2>



<p>Instead of using the official Microsoft Alpine image which comes with the full .NET runtime we can use the vanilla Alpine base image and build our App using the .NET self-contained build <code>PublishSingleFile</code>  option.<br>Publishing our app as self-contained produces an application that includes the .NET runtime and libraries in a single binary, so we don&#8217;t have to use the .NET runtime installed on our base system.</p>



<p><br>We can also use the <code>PublishTrimmed</code>  option while building and publishing our app. With this options the final binary includes only a subset of the .NET framework assemblies, the assemblies that are referenced by our app. The other ones are removed from the final procuded binary file. However, there is a risk that the build-time analysis of the application can cause failures at run time, due to not being able to reliably analyze various problematic code patterns (largely centered on reflection use). To mitigate these problems, warnings are produced whenever the trimmer cannot fully analyze a code pattern. For information on what the trim warnings mean and how to resolve them, see Introduction to trim warnings.</p>



<p><br>Also, with a self-contained build we also need to specify the target platform which the final binary will be compiled. In this case we are using the alpine-x64 because our base image is the Alpine Linux.</p>



<pre class="wp-block-code"><code>FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /app

COPY . ./

RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish \
    --runtime alpine-x64 \
    --self-contained true \
    /p:PublishTrimmed=true \
    /p:TrimMode=Link \
    /p:PublishSingleFile=true

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine

WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT &#091;"./WebApi"]</code></pre>



<pre class="wp-block-code"><code>
docker build -t api-multi-alpine-raw .
docker images api-multi-alpine-raw</code></pre>



<pre class="wp-block-code"><code>$ docker history api-multi-alpine-raw
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
ac78719fc09a   1 weeks ago    ENTRYPOINT &#091;"./WebApi"]                         0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    COPY /app/publish . # buildkit                  42.2MB    buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    WORKDIR /app                                    0B        buildkit.dockerfile.v0
&lt;missing&gt;      1 weeks ago    RUN /bin/sh -c apk add --no-cache libstdc++ …   35.5MB    buildkit.dockerfile.v0
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop)  CMD &#091;"/bin/sh"]              0B
&lt;missing&gt;      3 months ago   /bin/sh -c #(nop) ADD file:8f5bc5ce64ef781ad…   5.59MB
</code></pre>



<p>The final image was reduced to 83mb because it only includes the Alpine base image and a single binary that includes our WebApp compiled code and the assemblies that are referenced by our app!</p>



<p></p>



<h2 class="wp-block-heading">References</h2>



<p><a href="https://docs.docker.com/develop/develop-images/multistage-build/">https://docs.docker.com/develop/develop-images/multistage-build/</a><br><a href="https://docs.microsoft.com/en-us/dotnet/core/deploying/">https://docs.microsoft.com/en-us/dotnet/core/deploying/</a><br><a href="https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained">https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained</a></p>



<p><a href="https://hub.docker.com/_/microsoft-dotnet">https://hub.docker.com/_/microsoft-dotnet</a></p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/">Smaller .NET 6 docker images</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/telmorodrigues/2022/03/08/smaller-net-6-docker-images/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>TWIL: The weird way .NET&#8217;s config system parses JSONs</title>
		<link>https://blogit.create.pt/hugobarroca/2022/02/07/twil-the-weird-way-nets-config-system-parses-jsons/</link>
					<comments>https://blogit.create.pt/hugobarroca/2022/02/07/twil-the-weird-way-nets-config-system-parses-jsons/#respond</comments>
		
		<dc:creator><![CDATA[Hugo Barroca]]></dc:creator>
		<pubDate>Mon, 07 Feb 2022 13:01:05 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[appsettings]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12619</guid>

					<description><![CDATA[<p>The day is a Friday. We were calmly deploying an app we tested locally to the test environment. The error we had was pointing towards the config files. Off we go to check the appsettings.json file… Every value seems correct, but the error is definitely pointing us here. Here&#8217;s a simplified version of the offending [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/hugobarroca/2022/02/07/twil-the-weird-way-nets-config-system-parses-jsons/">TWIL: The weird way .NET&#8217;s config system parses JSONs</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>The day is a Friday. We were calmly deploying an app we tested locally to the test environment. The error we had was pointing towards the config files. Off we go to check the appsettings.json file…</p>



<p>Every value seems correct, but the error is definitely pointing us here. Here&#8217;s a simplified version of the offending line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
Console.Writeline(AConfig.ASubConfig);
</pre></div>


<p>And the corresponding appsettings:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
{
    &quot;AConfig&quot; : {
        &quot;ASubConfig&quot; : &#x5B;]
    }
}
</pre></div>


<p>&#8220;But an empty array is not the same as a null value! And even if it was, it&#8217;s a value inside the &#8220;ASubConfig&#8221; property! There&#8217;s no way for this to be null!&#8221; was what I thought. And I thought wrong.</p>



<h2 class="wp-block-heading" id="how-the-file-is-actually-parsed">How the file is actually parsed</h2>



<p>Actually, there&#8217;s a way for it to be null. Or at least, the JSON Provider which is gonna look at ours JSONs thinks so. Since .NET&#8217;s config system is ready to take in different providers, it was built with the common points of said providers in mind… And hierarchies aren&#8217;t one of those points.</p>



<p>What happens is that the JSON Provider&#8217;s parser is going to look at our JSON file and it&#8217;s going to map all those informations to a dictionary, in which every value is mapped with a key which corresponds to the path to that value in the file.</p>



<p>The &#8220;gotcha&#8221; here is in the way the arrays are processed: Each index of each array is processed as a part of the path. Meaning, that the following appsettings:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
{
    &quot;AnArray&quot; : &#x5B;&quot;AThing&quot;, &quot;AnotherThing&quot;, &quot;AThirdThing&quot;]
}
</pre></div>


<p>Will originate a dictionary with the following entries:</p>



<ul class="wp-block-list"><li>AnArray:0 = &#8220;AThing&#8221;</li><li>AnArray:1 = &#8220;AnotherThing&#8221;</li><li>AnArray:2 = &#8220;AThirdThing&#8221;</li></ul>



<h2 class="wp-block-heading" id="why-do-empty-arrays-cause-an-issue">Why do empty arrays cause an issue?</h2>



<p>What happens if the array is empty? Well, by convention, an empty array wont originate any entries in our dictionary… So, to the .NET binder which is gonna look at our dictionary, that array doesn&#8217;t exist at all.</p>



<p>Even moreso, as there is no value inside that array which we can map to some path, every object on top of it in the hierarchy won&#8217;t have any value we can map either, meaning those objects won&#8217;t exist themselves (assuming they don&#8217;t have any other properties with not null values).</p>



<p>In practice, our dictionary will be empty, our .NET binder won&#8217;t be able to map anything, and the number of &#8220;WTH&#8221;s per second will spike before lunch time.</p>



<p>TLDR: .NET&#8217;s config system treats any object in appsettings.json that does not have any value associated with it&#8217;s properties as if it didn&#8217;t exist, and the same happens if that value is an empty array.</p>



<p>If anyone wants to read more on this, here&#8217;s a link for the github issue where I found most of this information:</p>



<p><a href="https://github.com/dotnet/extensions/issues/1341">https://github.com/dotnet/extensions/issues/1341</a></p>



<p>Happy coding everyone!</p>
<p>The post <a href="https://blogit.create.pt/hugobarroca/2022/02/07/twil-the-weird-way-nets-config-system-parses-jsons/">TWIL: The weird way .NET&#8217;s config system parses JSONs</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/hugobarroca/2022/02/07/twil-the-weird-way-nets-config-system-parses-jsons/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET EF Core 6 support for groupby top(n) queries</title>
		<link>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/</link>
					<comments>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/#respond</comments>
		
		<dc:creator><![CDATA[Telmo Rodrigues]]></dc:creator>
		<pubDate>Fri, 04 Feb 2022 16:14:46 +0000</pubDate>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Sql]]></category>
		<category><![CDATA[entity framework]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12605</guid>

					<description><![CDATA[<p>EF Core 6 comes with some GroupBy queries improvements. In this post I wanna talk about the improvements related to &#8220;group by top(n)&#8221; queries. Let&#8217;s say we have the following table Documents: and that we want to get the two most recent documents for each user. For instance, if we have the following records: the [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/">.NET EF Core 6 support for groupby top(n) queries</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>EF Core 6 comes with some GroupBy queries improvements. In this post I wanna talk about the improvements related to &#8220;group by top(n)&#8221; queries.</p>



<p></p>



<p></p>



<p>Let&#8217;s say we have the following table Documents:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
CREATE TABLE &#x5B;dbo].&#x5B;Documents](
    &#x5B;Id] &#x5B;integer] PRIMARY KEY,
    &#x5B;UserId] &#x5B;integer] NOT NULL,
    &#x5B;Title] &#x5B;nvarchar](50) NOT NULL,
    &#x5B;Body] &#x5B;nvarchar](250) NOT NULL,
    &#x5B;CreatedOn] &#x5B;datetime] NOT NULL
)
</pre></div>


<p>and that we want to get the two most recent documents for each user. For instance, if we have the following records:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2022/02/image-6.png" alt="" class="wp-image-12606" width="523" height="183" srcset="https://blogit.create.pt/wp-content/uploads/2022/02/image-6.png 523w, https://blogit.create.pt/wp-content/uploads/2022/02/image-6-300x105.png 300w" sizes="(max-width: 523px) 100vw, 523px" /></figure>



<p>the query should return</p>



<figure class="wp-block-image size-full"><img decoding="async" width="520" height="146" src="https://blogit.create.pt/wp-content/uploads/2022/02/image-7.png" alt="" class="wp-image-12607" srcset="https://blogit.create.pt/wp-content/uploads/2022/02/image-7.png 520w, https://blogit.create.pt/wp-content/uploads/2022/02/image-7-300x84.png 300w" sizes="(max-width: 520px) 100vw, 520px" /></figure>



<p>To do this query using EF Core and LINQ we can try to group the Documents by UserId and then sort each group by the CreatedOn column to pick the first two documents for each user.</p>



<p>We can start by trying to group all documents for each user</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
 var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
</pre></div>


<p>and then for each group we try to sort its elements by the CreatedOn column</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
        .SelectMany(userDocs =&gt; userDocs.OrderByDescending(doc =&gt; doc.CreatedOn).Take(2))
        .ToArrayAsync();
</pre></div>


<p>If we try to execute this query using a previous version of EF Core 6 we get the following error:</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
    .OrderByDescending(doc =&amp;gt; doc.CreatedOn)&#039; could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to &#039;AsEnumerable&#039;, &#039;AsAsyncEnumerable&#039;, &#039;ToList&#039;, or &#039;ToListAsync&#039;. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.&#039;
</pre></div>


<p></p>



<p>This is because the previous versions of EF don&#8217;t know how to translate the GroupBy inner expressions to sql. After following their suggestion I ended up with this query</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .Select(doc =&gt; doc.UserId)
        .Distinct()
        .SelectMany(userId =&gt; 
            ctx
            .Documents
            .Where(doc =&gt; doc.UserId == userId)
            .OrderByDescending(doc =&gt; doc.CreatedOn)
            .Take(2)
        )
        .ToArrayAsync();
</pre></div>


<p>However this query has two main issues. It does a distinct over the UserId column, loads all the user ids to application memory and then it does a query for each user resulting in a n+1 query problem.</p>



<p>One way to solve these issues is to forget LINQ and rewrite the query using raw sql with a partition by UserId and the ROW_NUMBER() window funtion, doing a CTE .</p>



<p>Now, with the EF Core 6 we can use the first version of the query, since the EF Core team has added the support for translating some GroupBy inner expressions and it can translate this LINQ query to a single sql query.</p>



<p></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    var usersDocs = await ctx
        .Documents
        .GroupBy(doc =&gt; doc.UserId)
        .SelectMany(userDocs =&gt; userDocs.OrderByDescending(doc =&gt; doc.CreatedOn).Take(2))
        .ToArrayAsync();
</pre></div>


<p>You can read more about these features and other improvements added to GroupBy queries&nbsp;<a href="https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/whatsnew#improved-groupby-support">here</a>&nbsp;and check the related github issues&nbsp;<a href="https://github.com/dotnet/efcore/issues/12088">12088</a>&nbsp;<a href="https://github.com/dotnet/efcore/issues/13805">13805</a>&nbsp;</p>



<p>Happy coding!</p>
<p>The post <a href="https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/">.NET EF Core 6 support for groupby top(n) queries</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/telmorodrigues/2022/02/04/net-ef-core-6-support-for-groupby-topn-queries/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Handle known Exceptions?</title>
		<link>https://blogit.create.pt/diogocoelho/2020/10/22/how-to-handle-known-exceptions/</link>
					<comments>https://blogit.create.pt/diogocoelho/2020/10/22/how-to-handle-known-exceptions/#respond</comments>
		
		<dc:creator><![CDATA[Diogo Coelho]]></dc:creator>
		<pubDate>Thu, 22 Oct 2020 18:11:58 +0000</pubDate>
				<category><![CDATA[Design/Integration Patterns]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Exception]]></category>
		<category><![CDATA[Exception Handling]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=12069</guid>

					<description><![CDATA[<p>This post will describe several ways to handle known Exceptions in a project. For each possible implementation, we will do an overview of the flow that the exception does to understand the context of each implementation. First, let’s do an overview of what is, normally, a basic flow in any Project. The basic flow of [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/diogocoelho/2020/10/22/how-to-handle-known-exceptions/">How to Handle known Exceptions?</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>This post will describe several ways to handle known <strong>Exceptions </strong>in a project.</p>



<p>For each possible implementation, we will do an overview of the flow that the exception does to understand the context of each implementation.</p>



<p>First, let’s do an overview of what is, normally, a basic flow in any Project.</p>



<h2 class="wp-block-heading">The basic flow of an API Project</h2>



<h2 class="wp-block-heading"></h2>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow-1.png" alt="" class="wp-image-12086" width="1064" height="641" /></figure>



<p><em>The previous Figure shows the basic flow of events inside the IDM project. The API receives an HTTP Request in a certain endpoint. The endpoints of the API are mapped in the controller layer, so when the API receives the HTTP request the controller is the first to interact with that request and sends that request to the respective service that will orchestrate all the necessities of that request. Those necessities could be, for example, retrieve some information from the Database, and that is done in the repository layer. The repository layer is where we map all the interactions with external services(DataBases, API, etc). This is a basic overview of what could be a basic API project.</em></p>



<h2 class="wp-block-heading">The Exception Handling Problem</h2>



<p>Taking into account the previous overview of the project, we want to make the process of handling exceptions the more clearest and efficient possible in terms of computational needs, but also in terms of code structure. To achieve this purpose we will describe three different ways of handling the exceptions.</p>



<p>Also, in this project, we have 2 different types of exceptions. They are:</p>



<ul class="wp-block-list"><li>DomainException &#8211; This is the type of exception that is thrown when the error that happens is something that the API already expects;</li><li>Exception &#8211; This could actually be any type of exception different from DomainException. This occurs when an unexpected error occurs in the API;</li></ul>



<h5 class="wp-block-heading">Reference to Middleware</h5>



<p>In this case, we will use the <strong>ExceptionHandler </strong>middleware layer. The middleware layer is specific to .NET Core and we will not focus on that here. Take into account that we will use <strong>ExceptionHandler </strong>in the middleware pipeline to catch all the exceptions that are not treated.</p>



<p>Here is the reference to <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1">ASP.NET Core Middleware</a>.</p>



<h2 class="wp-block-heading">First Approach: Try-Catch on Controller Layer</h2>



<p>This approach consists of catching and treating the DomainExceptions that are thrown by any of the layers (Controller, Service, or Repository) of the APIProject in the Controller layers. Take into account that all the unexpected exceptions are always treated in the ExceptionHandler of the Middleware.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow_FirstApproachV2-1.png" alt="" class="wp-image-12085" width="1064" height="1071" /></figure>



<h2 class="wp-block-heading">Second Approach: Try-Catch in all Layers</h2>



<p>This approach consists of all layers of the API Project being capable of catching exceptions and sending again the exception to the upper layers. The Controller layer is where the Domain Exceptions will be treated.</p>



<p>Take into account that in this case, the unexpected exceptions are caught by the layer that throws her and also by the rest of the upper layers. However, it is treated in the ExceptionHandler of the Middleware.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow_SecondApproach-1.png" alt="" class="wp-image-12084" width="1067" height="1095" /></figure>



<h2 class="wp-block-heading">Third Approach: Encapsulate Exception in Response Object</h2>



<p>This approach consists, as the name says, in encapsulating the exception in the Response Object. Instead of throwing the exception, we will send the Response object with a Failed message with an instance of the exception in the Response Object as a variable. This means that the system will not need to operate the throws of exceptions for the expected errors. They will be passed in the response object.</p>



<p>Take into account that only the unexpected exceptions are thrown to Middleware &#8211; <strong>ExceptionHandler </strong>to be treated.</p>



<p></p>



<h4 class="wp-block-heading" id="Normal-Response-Object">Normal Response Object</h4>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: java; title: ; notranslate">
public class OperationResult
{
        public OperationResult();

        public static OperationResult Success { get; }
        public bool Succeeded { get; protected set; }
        public IEnumerable&lt;OperationError&gt; Errors { get; }

        public static OperationResult Failed(params OperationError&#x5B;] errors);
        public override string ToString();
}
</pre></div>


<h4 class="wp-block-heading" id="New-Response-Object-for-this-approach">New Response Object for this approach</h4>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: vb; title: ; notranslate">
public class OperationResult
{
        public OperationResult();
           
        public static OperationResult Success { get; }
        public bool Succeeded { get; protected set; }
        public IEnumerable&lt;OperationError&gt; Errors { get; }

        public static OperationResult Failed(params OperationError&#x5B;] errors);
        public override string ToString();
        public Exception ExceptionHolder { get; set;} 
}
</pre></div>


<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow_ThirdApproach-2.png" alt="" class="wp-image-12083" width="1067" height="1061" /></figure>



<h2 class="wp-block-heading">Fourth Approach: Catch all exceptions in Middleware &#8211; Exception Handler</h2>



<p>The approach consists of throwing the exceptions whenever they happen and then let them be caught and treated by the middleware &#8211; ExceptionHandler. In this approach, we would create a different type of response for each type of exception for the ExceptionHandler send as Response.</p>



<p>This would centralize all the exception handling in one place.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="682" height="671" src="https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow_FourthApproach-7.png" alt="" class="wp-image-12117" srcset="https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow_FourthApproach-7.png 682w, https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow_FourthApproach-7-300x295.png 300w, https://blogit.create.pt/wp-content/uploads/2020/10/ControllerServiceRepositoryFlow_FourthApproach-7-427x420.png 427w" sizes="(max-width: 682px) 100vw, 682px" /></figure>



<p></p>



<h2 class="wp-block-heading">Comparison of Exception Handling approaches</h2>



<figure class="wp-block-table is-style-regular"><table><tbody><tr><th><strong>Exception Handling Approach</strong></th><th><strong>Pros</strong></th><th><strong>Cons</strong></th></tr><tr><td>First Approach: Try-Catch on Controller Layer</td><td>One place to treats the expected exceptions and another for the unexpected;<br><br>No need to make calls to the error page when is an expected error, thus making the operation quicker;<br><br>Only adds exception related code in the controller Layer;<br></td><td>Catch &amp; Throw of exception in the controller layer uses more computational resources;<br><br>Every endpoint mapped in the controller will need try-catch;</td></tr><tr><td>Second Approach: Try-Catch in all Layers</td><td>Easy to know where the exception happened and where it is (easy to understand the flow);<br><br>One place to treats the expected exceptions and another for the unexpected;</td><td>Exception handling code everywhere;<br><br>Can cause a bottleneck in the app because of the inherent addition of time to the response and use of computational resources;<br><br>Repeated Code;<br><br>Make logical code harder to understand;<br></td></tr><tr><td>Third Approach: Encapsulate Exception in Response Object</td><td>The runtime doesn’t need to handle the throw of expected Exceptions;<br><br>One place to treats the expected exceptions (in this case inside the response Object) and another for the unexpected;<br><br>App maintains a normal flow even to it occurred an expected exception;<br></td><td>Handling of the expected exceptions is not explicit;</td></tr><tr><td>Fourth Approach: Catch all exceptions in Middleware &#8211; Exception Handler</td><td>Aggregates the handling of all exceptions in one place;<br><br>Exception handling code is in one place and logical/business code in other;</td><td>Unexpected and Expected exceptions handling are in the same place;<br><br>Add another request to the operation because it will always need to request the errors page when an exception happens (Middleware- Exception Handler Implementation);<br></td></tr></tbody></table><figcaption></figcaption></figure>



<p></p>
<p>The post <a href="https://blogit.create.pt/diogocoelho/2020/10/22/how-to-handle-known-exceptions/">How to Handle known Exceptions?</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/diogocoelho/2020/10/22/how-to-handle-known-exceptions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Redirecting 2 domains from http to https and non-www to www</title>
		<link>https://blogit.create.pt/andresantos/2018/10/30/redirecting-2-domains-from-http-to-https-and-non-www-to-www/</link>
					<comments>https://blogit.create.pt/andresantos/2018/10/30/redirecting-2-domains-from-http-to-https-and-non-www-to-www/#respond</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Tue, 30 Oct 2018 12:25:59 +0000</pubDate>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[naked domain]]></category>
		<category><![CDATA[non-www]]></category>
		<category><![CDATA[redirection]]></category>
		<category><![CDATA[web.config]]></category>
		<category><![CDATA[www]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=7670</guid>

					<description><![CDATA[<p>Recently I had to configure some redirections in a website that contains two different domains. Both use https and I want the main site, which uses the primary domain, to only be accessible through it&#8217;s www version. For the second site, since it&#8217;s a sub-domain, I only want it to only be available in https. [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2018/10/30/redirecting-2-domains-from-http-to-https-and-non-www-to-www/">Redirecting 2 domains from http to https and non-www to www</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Recently I had to configure some redirections in a website that contains two different domains.</p>
<p>Both use https and I want the main site, which uses the primary domain, to only be accessible through it&#8217;s www version. For the second site, since it&#8217;s a sub-domain, I only want it to only be available in https.</p>
<p><span id="more-7670"></span></p>
<p>Let&#8217;s say the domain is <strong>mydomain.com</strong> and the subdomain is <strong>mysub.mydomain.com</strong>. The only URLs I want to be available are:</p>
<ul>
<li>https://www.mydomain.com</li>
<li>https://mysub.mydomain.com</li>
</ul>
<p>Typically I would make the non-www to www redirection through the DNS provider, but for this website it was not possible.</p>
<p>The following is the configuration I used in my Web.config:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;rewrite&gt;
    &lt;rules&gt;
        &lt;rule name=&quot;Redirect from non www mydomain.com&quot; stopProcessing=&quot;true&quot;&gt;
            &lt;match url=&quot;.*&quot; /&gt;
            &lt;conditions&gt;
                &lt;add input=&quot;{HTTP_HOST}&quot; pattern=&quot;^mydomain.com$&quot; /&gt;
            &lt;/conditions&gt;
            &lt;action type=&quot;Redirect&quot; url=&quot;https://www.mydomain.com/{R:0}&quot; redirectType=&quot;Permanent&quot; /&gt;
        &lt;/rule&gt;
        &lt;rule name=&quot;Redirect from non https mydomain.com&quot; stopProcessing=&quot;true&quot;&gt;
            &lt;match url=&quot;.*&quot; /&gt;
            &lt;conditions&gt;
                &lt;add input=&quot;{HTTPS}&quot; pattern=&quot;^OFF$&quot; /&gt;
                &lt;add input=&quot;{HTTP_HOST}&quot; pattern=&quot;^www.mydomain.com$&quot; /&gt;
            &lt;/conditions&gt;
            &lt;action type=&quot;Redirect&quot; url=&quot;https://www.mydomain.com/{R:0}&quot; redirectType=&quot;Permanent&quot; /&gt;
        &lt;/rule&gt;
        &lt;rule name=&quot;Redirect from non https mysub.mydomain.com&quot; stopProcessing=&quot;true&quot;&gt;
            &lt;match url=&quot;.*&quot; /&gt;
            &lt;conditions&gt;
                &lt;add input=&quot;{HTTPS}&quot; pattern=&quot;^OFF$&quot; /&gt;
                &lt;add input=&quot;{HTTP_HOST}&quot; pattern=&quot;^mysub.mydomain.com$&quot; /&gt;
            &lt;/conditions&gt;
            &lt;action type=&quot;Redirect&quot; url=&quot;https://mysub.mydomain.com/{R:0}&quot; redirectType=&quot;Permanent&quot; /&gt;
        &lt;/rule&gt;
    &lt;/rules&gt;
&lt;/rewrite&gt;
</pre>
<p>Hope this helps!</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2018/10/30/redirecting-2-domains-from-http-to-https-and-non-www-to-www/">Redirecting 2 domains from http to https and non-www to www</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2018/10/30/redirecting-2-domains-from-http-to-https-and-non-www-to-www/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Raven.Studio.zip Index.html not available</title>
		<link>https://blogit.create.pt/ricardocosta/2018/10/10/raven-studio-zip-index-html-not-available/</link>
					<comments>https://blogit.create.pt/ricardocosta/2018/10/10/raven-studio-zip-index-html-not-available/#respond</comments>
		
		<dc:creator><![CDATA[Ricardo Costa]]></dc:creator>
		<pubDate>Wed, 10 Oct 2018 14:52:19 +0000</pubDate>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[.NET]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=7580</guid>

					<description><![CDATA[<p>I had RavenDb embedded in a aspnet.core web api and I was getting this error when I tried to reach Raven Studio: The following file was not available: index.html. Please make sure that the Raven.Studio.zip file exist in the main directory (near the Raven.Server.exe). The solution was to copy Raven.Studio.zip to the root directory of [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/ricardocosta/2018/10/10/raven-studio-zip-index-html-not-available/">Raven.Studio.zip Index.html not available</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I had RavenDb embedded in a aspnet.core web api and I was getting this error when I tried to reach Raven Studio: The following file was not available: index.html. Please make sure that the Raven.Studio.zip file exist in the main directory (near the Raven.Server.exe).</p>
<p>The solution was to copy Raven.Studio.zip to the root directory of the web api.</p>
<p><img decoding="async" class="size-medium wp-image-7582" src="https://blogit.create.pt////wp-content/uploads/2018/10/Raven-Studio-Zip-300x73.png" alt="Raven Studio Zip" width="300" height="73" srcset="https://blogit.create.pt/wp-content/uploads/2018/10/Raven-Studio-Zip-300x73.png 300w, https://blogit.create.pt/wp-content/uploads/2018/10/Raven-Studio-Zip.png 458w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>&nbsp;</p>
<p>The post <a href="https://blogit.create.pt/ricardocosta/2018/10/10/raven-studio-zip-index-html-not-available/">Raven.Studio.zip Index.html not available</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/ricardocosta/2018/10/10/raven-studio-zip-index-html-not-available/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>RavenDB embedded with ASP NET Core web API</title>
		<link>https://blogit.create.pt/ricardocosta/2018/09/04/ravendb-embedded-asp-net-core-web-api/</link>
					<comments>https://blogit.create.pt/ricardocosta/2018/09/04/ravendb-embedded-asp-net-core-web-api/#respond</comments>
		
		<dc:creator><![CDATA[Ricardo Costa]]></dc:creator>
		<pubDate>Tue, 04 Sep 2018 21:38:46 +0000</pubDate>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[RavenDB]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=7417</guid>

					<description><![CDATA[<p>This post describes how you can set up a simple ASP NET Core web API with Visual Studio 2017 to use an embedded RavenDB. This is a step by step tutorial. a) You need to create a new ASP.NET Core Web Application with Visual Studio 2017 b) Choose .NET Core; ASP.NET Core 2.1; API c) [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/ricardocosta/2018/09/04/ravendb-embedded-asp-net-core-web-api/">RavenDB embedded with ASP NET Core web API</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>This post describes how you can set up a simple ASP NET Core web API with Visual Studio 2017 to use an embedded RavenDB. This is a step by step tutorial.</p>
<p>a) You need to create a new ASP.NET Core Web Application with Visual Studio 2017<br />
b) Choose .NET Core; ASP.NET Core 2.1; API<br />
c) Right click the new project -&gt; Manage NuGet packages<br />
d) You have to add a new package source. Settings. New package source.</p>
<p style="padding-left: 30px">Name: <a href="https://www.myget.org/F/ravendb/api/v3/index.json">MyGet</a><br />
Source: https://www.myget.org/F/ravendb/api/v3/index.json</p>
<p>e) Choose the new source. Add:</p>
<p style="padding-left: 30px">RavenDB.Embedded &#8211; 4.1.1-nightly-20180904-0430<br />
RavenDB.Client &#8211; 4.1.1-nightly-20180904-0430</p>
<p>f) Create a DocumentStoreHolder class</p>
<pre class="brush: csharp; title: ; notranslate">

internal class DocumentStoreHolder
{
    private static Lazy&lt;IDocumentStore&gt; store = new Lazy&lt;IDocumentStore&gt;(CreateStore);

    public static IDocumentStore Store =&gt; store.Value;

    private static IDocumentStore CreateStore()
    {
        var serverOptions = new ServerOptions()
        {
            ServerUrl = &quot;http://127.0.0.1:60956/&quot;,
        };
        EmbeddedServer.Instance.StartServer(serverOptions);

        return EmbeddedServer.Instance.GetDocumentStore(&quot;MyRavenDBStore&quot;);
    }
}

</pre>
<p>g) And that&#8217;s it 🙂</p>
<p>The post <a href="https://blogit.create.pt/ricardocosta/2018/09/04/ravendb-embedded-asp-net-core-web-api/">RavenDB embedded with ASP NET Core web API</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/ricardocosta/2018/09/04/ravendb-embedded-asp-net-core-web-api/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Adding an Angular app to your Umbraco Website</title>
		<link>https://blogit.create.pt/marionunes/2018/03/10/adding-an-angular-app-to-your-umbraco-website/</link>
					<comments>https://blogit.create.pt/marionunes/2018/03/10/adding-an-angular-app-to-your-umbraco-website/#comments</comments>
		
		<dc:creator><![CDATA[Mário Nunes]]></dc:creator>
		<pubDate>Sat, 10 Mar 2018 22:11:23 +0000</pubDate>
				<category><![CDATA[Angular]]></category>
		<category><![CDATA[Umbraco]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[.NET]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/marionunes/?p=334</guid>

					<description><![CDATA[<p>What problems does this solve? This enables you to have an Angular application alongside your Umbraco website, on a specified route. The Angular App can be protected by the Authentication of your website, if you have it. And you can make use of surface controllers for authenticated requests. The routing of your app will work [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/marionunes/2018/03/10/adding-an-angular-app-to-your-umbraco-website/">Adding an Angular app to your Umbraco Website</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><strong>What problems does this solve?</strong></p>
<ul>
<li>This enables you to have an Angular application alongside your Umbraco website, on a specified route.</li>
<li>The Angular App can be protected by the Authentication of your website, if you have it. And you can make use of surface controllers for authenticated requests.</li>
<li>The routing of your app will work as intended, for example, if your Angular app is at <strong>/app</strong> and you make a request to <strong>/app/products</strong>, the request will be routed to the angular app products&#8217; page.</li>
</ul>
<p><strong>What this is not</strong></p>
<ul>
<li>A complete front end for a Umbraco website with dynamic routes.</li>
<li>This doesn&#8217;t have dynamic routes, you have to specify them on your code.</li>
</ul>
<p><strong>Let&#8217;s get started!</strong></p>
<p>First, start by creating a controller to handle the Angular App request.</p>
<pre class="brush: csharp; title: ; notranslate">
using System.Web.Mvc;

public class AngularAppController : BaseController
{
    public ActionResult AngularAppView()
    {
        return View();
    }
}
</pre>
<p>Then, you have to decide the route where your Angular app will render. On this example it will be <strong>/angularapp</strong>.</p>
<p>On your ApplicationStarted method, put this code:</p>
<pre class="brush: csharp; title: ; notranslate">
RouteTable.Routes.MapRoute(
  &quot;AngularApp&quot;,
  &quot;angularapp/{*.}&quot;,
  new { controller = &quot;AngularApp&quot;, action = &quot;AngularAppView&quot; });
</pre>
<p>The <strong>{*.}</strong> syntax is what makes your angular app routes load and not return the 404 page.</p>
<p>If you don&#8217;t have an ApplicationStarted method, find out how you to create it here: <a href="https://our.umbraco.org/documentation/reference/events/application-startup">https://our.umbraco.org/documentation/reference/events/application-startup</a></p>
<p>Under your Views folder, create a folder with the same name as the <strong>controller</strong> you set in MapRoute. In this case it will be &#8220;AngularApp&#8221;.<br />
Inside it, create a view with the same name as the <strong>action</strong> set you set in MapRoute.<br />
<img decoding="async" src="http://blogit-create.com/wp-content/uploads/2018/03/appview.png" alt="" width="268" height="71" class="alignnone size-full wp-image-414" srcset="https://blogit.create.pt/wp-content/uploads/2018/03/appview.png 268w, https://blogit.create.pt/wp-content/uploads/2018/03/appview-265x71.png 265w" sizes="(max-width: 268px) 100vw, 268px" /></p>
<p>Inside the view put the contents of the index.html of your angular app.<br />
Then you will need to move your angular app files somewhere like you /Assets folder, and edit their paths on the view.</p>
<p>Almost done!</p>
<p>Now you need to edit the routes of your Angular app.<br />
Simply add the route you chose as a prefix to the routes.</p>
<p>From something like this:</p>
<pre class="brush: csharp; title: ; notranslate">
const routes: Routes = &#x5B;
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  { path: '/dashboard', component: DashboardComponent },
  { path: '/detail/:id', component: HeroDetailComponent },
  { path: '/heroes', component: HeroesComponent }
];
</pre>
<p>To this:</p>
<pre class="brush: csharp; title: ; notranslate">
const routes: Routes = &#x5B;
  { path: 'angularapp', redirectTo: 'angularapp/dashboard', pathMatch: 'full' },
  { path: 'angularapp/dashboard', component: DashboardComponent },
  { path: 'angularapp/detail/:id', component: HeroDetailComponent },
  { path: 'angularapp/heroes', component: HeroesComponent }
];
</pre>
<p>Thanks for reading!<br />
Mário</p>
<p>The post <a href="https://blogit.create.pt/marionunes/2018/03/10/adding-an-angular-app-to-your-umbraco-website/">Adding an Angular app to your Umbraco Website</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/marionunes/2018/03/10/adding-an-angular-app-to-your-umbraco-website/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
