Jekyll2023-04-04T16:14:59+00:00https://www.sunjiangong.com/feed.xmlSUN JiangongA senior .NET engineer, software craftsman. Passionate about new technologies.SUN JiangongMicrosoft .NET challenge France 2022 final2023-04-04T07:00:00+00:002023-04-04T07:00:00+00:00https://www.sunjiangong.com/2023/04/04/microsoft-dotnet-challenge-france-2022-final<p>I’ve participated the Microsoft .NET challenge France 2022 final two months ago on 19 january 2023, 2 years after have participating the <a href="https://www.sunjiangong.com/2021/12/07/microsoft-dotnet-challenge-france-2020-final.html">Microsoft .NET challenge France 2020 final</a>.</p>
<p>The Microsoft .NET challenge France is co-organized by two companies:</p>
<ul>
<li><a href="https://www.softfluent.fr" target="_blank">SoftFluent</a>, a French IT consulting company specialized in the Microsoft ecosystem with C#, .NET, Azure, SQL Server etc.</li>
<li><a href="https://editx.eu" target="_blank">EditX</a>, a Belgian company that hosts a lot of online competitions across Europe.</li>
</ul>
<p><img src="./../../../assets/img/posts/2023-04-04-dotnet-challenge-final-2022/Finale-NET-Challenge.png" alt="" /></p>
<!--more-->
<p><br /></p>
<p>Like the previous editions, there were two rounds in this competition.</p>
<p>The first round was held between the <strong>19th September</strong> and the <strong>12th December</strong> 2022.</p>
<p>There was an online quiz with around 20 questions on several subjects like C#, .NET, Azure, and Algorithm.</p>
<p>The questions will become difficult progressively and each question has a different point, from 1 to 3 points depending on its difficulty.</p>
<p>The contest is composed of:</p>
<ul>
<li>7 easy questions : 1 point</li>
<li>7 medium questions : 2 points</li>
<li>4 difficult questions : 3 points</li>
<li>In case of wrong answer : -1 point</li>
<li>No answer : 0 point</li>
</ul>
<p>There were <strong>238</strong> persons participated in the first round, with <strong>84%</strong> of .net engineers, the rest are students.</p>
<p>The best <strong>20</strong> scored engineers and the best <strong>10</strong> scored students, totalising <strong>30</strong> finalists were entering in the final.</p>
<p>The final was held online via teams on the <strong>19th january 2023</strong>.</p>
<p><img src="./../../../assets/img/posts/2023-04-04-dotnet-challenge-final-2022/la-finale.png" alt="" /></p>
<p>And there was another quiz in the final with the same format.</p>
<p>I was ended in the 3rd place! ;)</p>
<p><img src="./../../../assets/img/posts/2023-04-04-dotnet-challenge-final-2022/ranking.png" alt="" /></p>
<p><br /></p>
<h5 id="final-thoughts">Final thoughts:</h5>
<p>The .NET challenge France is an annual event.</p>
<p>It’s a good opportunity to meet your peers, expand the network, and have some fun!</p>
<p>If you are a .NET developer, feel free to participate in the next edition!</p>SUN JiangongI’ve participated the Microsoft .NET challenge France 2022 final two months ago on 19 january 2023, 2 years after have participating the Microsoft .NET challenge France 2020 final. The Microsoft .NET challenge France is co-organized by two companies: SoftFluent, a French IT consulting company specialized in the Microsoft ecosystem with C#, .NET, Azure, SQL Server etc. EditX, a Belgian company that hosts a lot of online competitions across Europe.How to monitor azure event hub events in real-time?2022-12-13T07:00:00+00:002022-12-13T07:00:00+00:00https://www.sunjiangong.com/2022/12/13/how-to-monitor-azure-event-hub-events<p>When you are debugging your application and you want to monitor the event in real-time, you can use <strong>service bus explorer</strong>.</p>
<p><img src="./../../../assets/img/posts/2022-12-13-azure-event-hub/service-bus-explorer.png" alt="" /></p>
<!--more-->
<p><br /></p>
<p>Firstly, download <a href="https://github.com/paolosalvatori/ServiceBusExplorer">service bus explorer</a> from github and unzip it.</p>
<p>Then, find out the connection string with the following path on azure portal.
“the event hub to monitor” => “Settings” => “Shared access policies” => “Policy” => “Connection string-primary key”</p>
<p>And, add connect to the event hub by pasting the chosen connection string.</p>
<p><img src="./../../../assets/img/posts/2022-12-13-azure-event-hub/connect_event_hub.png" alt="" /></p>
<p>Choose any consumer group of the event hub</p>
<p><img src="./../../../assets/img/posts/2022-12-13-azure-event-hub/consumer_group.png" alt="" /></p>
<p>And right-click the consumer group to create a listener</p>
<p><img src="./../../../assets/img/posts/2022-12-13-azure-event-hub/consumer_group_listener.png" alt="" /></p>
<p>Now you’ll see the listener interface</p>
<p><img src="./../../../assets/img/posts/2022-12-13-azure-event-hub/consumer_group_listener_interface.png" alt="" /></p>
<p>Choose “ZipEventDataInspector” and “Tracking” and the “Starting Date Time UTC” and click “Start” before your debugging.</p>
<p><img src="./../../../assets/img/posts/2022-12-13-azure-event-hub/monitor.png" alt="" /></p>
<p>Once you have sent the message to the event hub you’re listening, you will see the message displayed here.</p>
<p><img src="./../../../assets/img/posts/2022-12-13-azure-event-hub/event_message.png" alt="" /></p>SUN JiangongWhen you are debugging your application and you want to monitor the event in real-time, you can use service bus explorer.How to maintain legacy applications?2022-04-16T07:00:00+00:002022-04-16T07:00:00+00:00https://www.sunjiangong.com/2022/04/16/how-to-maintain-legacy-applications%20copySUN JiangongWhat are Azure TenantId, ClientId (Application Id) and ObjectId?2022-03-10T07:00:00+00:002022-03-10T07:00:00+00:00https://www.sunjiangong.com/2022/03/10/what-are-azure-tenantId-clientId-objectid<p>There are some Identifiers you have to know when you are using Azure.</p>
<p>They are:</p>
<ul>
<li>Tenant Id</li>
<li>Client Id (Application Id)</li>
<li>Object Id</li>
</ul>
<!--more-->
<p><br /></p>
<h3 id="tenant-id">Tenant ID</h3>
<p>Tenant Id is the Azure Active Directory’s Global unique identifier (GUID).</p>
<p>You can access it through the path: <em>Azure Portal > Azure Active Directory</em></p>
<p><img src="./../../../assets/img/posts/2022-03-10-azure-tenantid-clientid/azure-tenantid.png" alt="" /></p>
<p>An example:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"AzureAd"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"Instance"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://login.microsoftonline.com/"</span><span class="p">,</span><span class="w">
</span><span class="nl">"Domain"</span><span class="p">:</span><span class="w"> </span><span class="s2">"msidentitysamplestesting.onmicrosoft.com"</span><span class="p">,</span><span class="w">
</span><span class="nl">"TenantId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"7f58f645-c190-4ce5-9de4-e2b7acd2a6ab"</span><span class="p">,</span><span class="w">
</span><span class="nl">"ClientId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"a4c2469b-cf84-4145-8f5f-cb7bacf814bc"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p><br /></p>
<h3 id="client-id-equals-to-application-id">Client ID (Equals to Application ID)</h3>
<p>This is the unique application ID of this application in your directory. You can use this application ID if you ever need help from Microsoft Support, or if you want to perform operations against this specific instance of the application using the Azure Active Directory Graph or PowerShell APIs.</p>
<p><br />
You can find the applications registered in your Azure subscription by <em>Azure AD => Enterprise applications => Application Name</em>.</p>
<p><img src="./../../../assets/img/posts/2022-03-10-azure-tenantid-clientid/azure-applicationId.png" alt="" /></p>
<p><br />
You can log in the Azure with ClientId and ClientSecret and use it to manage user rights, or send emails etc.</p>
<p>Install the following Nuget packages to be able to authenticate in Graph API as an application.</p>
<ul>
<li>Microsoft.Identity.Client</li>
<li>Microsoft.Graph</li>
<li>Microsoft.Graph.Auth</li>
</ul>
<p><br />
Then you can create a graph service client to be able to manipulate a lot of things in Microsoft Graph API.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">authorityUri</span> <span class="p">=</span> <span class="s">$"https://login.microsoftonline.com/</span><span class="p">{</span><span class="n">_tenantId</span><span class="p">}</span><span class="s">/v2.0"</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">confidentialClientApplication</span> <span class="p">=</span> <span class="n">ConfidentialClientApplicationBuilder</span>
<span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="n">_clientId</span><span class="p">)</span>
<span class="p">.</span><span class="nf">WithClientSecret</span><span class="p">(</span><span class="n">_clientSecret</span><span class="p">)</span>
<span class="p">.</span><span class="nf">WithAuthority</span><span class="p">(</span><span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="n">authorityUri</span><span class="p">))</span>
<span class="p">.</span><span class="nf">Build</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">authProvider</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ClientCredentialProvider</span><span class="p">(</span><span class="n">confidentialClientApplication</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">graphserviceClient</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">GraphServiceClient</span><span class="p">(</span><span class="n">authProvider</span><span class="p">);</span>
</code></pre></div></div>
<p><br /></p>
<h3 id="object-id">Object Id</h3>
<p>This is the unique ID of the service principal object associated with this application. This ID can be useful when performing management operations against this application using PowerShell or other programmatic interfaces.</p>
<p>As you can see in the previous chapter, Application has an “Application ID” and an “Object ID”.</p>
<p>And an user also has an Object ID.</p>
<p><img src="./../../../assets/img/posts/2022-03-10-azure-tenantid-clientid/azure-objectId.png" alt="" /></p>
<p>You can use object IDs to retrieve all the roles assigned to an user in an application.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">async</span> <span class="n">Task</span><span class="p"><</span><span class="n">IUserAppRoleAssignmentsCollectionPage</span><span class="p">></span> <span class="nf">GetUserRolesAsync</span><span class="p">(</span><span class="kt">string</span> <span class="n">userObjectId</span><span class="p">,</span>
<span class="kt">string</span> <span class="n">applicationObjectId</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">await</span> <span class="n">graphserviceClient</span><span class="p">.</span><span class="n">Users</span><span class="p">[</span><span class="n">userObjectId</span><span class="p">].</span><span class="n">AppRoleAssignments</span><span class="p">.</span><span class="nf">Request</span><span class="p">()</span>
<span class="p">.</span><span class="nf">Filter</span><span class="p">(</span><span class="s">$"resourceId eq </span><span class="p">{</span><span class="n">applicationObjectId</span><span class="p">}</span><span class="s">"</span><span class="p">).</span><span class="nf">GetAsync</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Now you have an idea about the different identifiers in Azure.</p>SUN JiangongThere are some Identifiers you have to know when you are using Azure. They are: Tenant Id Client Id (Application Id) Object Idtypes/uuid - Uncaught TypeError Object(…) is not a function2021-12-30T07:00:00+00:002021-12-30T07:00:00+00:00https://www.sunjiangong.com/2021/12/30/types-uuid-uncaught-type-error-object-is-not-a-function<p>If you want to check if a string is an UUID (Universally Unique Identifier, aka GUID) in reactjs.</p>
<p>You can use the NPM package <a href="https://yarnpkg.com/package/@types/uuid" target="_blank">@types/uuid</a> to do it.</p>
<!--more-->
<p><br /></p>
<p>Here I created a helper class to validate a string.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">validate</span> <span class="k">as</span> <span class="nx">uuidValidate</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">uuid</span><span class="dl">'</span><span class="p">;</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">StringUtils</span> <span class="p">{</span>
<span class="kd">static</span> <span class="nx">isValidUuid</span> <span class="o">=</span> <span class="p">(</span><span class="nx">identifier</span><span class="p">:</span> <span class="nx">string</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">uuidValidate</span><span class="p">(</span><span class="nx">identifier</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><br /></p>
<p>But I’ve encountered the following error:</p>
<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">Uncaught</span> <span class="kd">TypeError</span>: <span class="kd">Object</span><span class="o">(</span>...<span class="o">)</span> <span class="kd">is</span> <span class="ow">not</span> <span class="kd">a</span> <span class="kd">function</span>
<span class="nb">at</span> <span class="kd">Function</span>.Bc.isValidUuid <span class="o">(</span><span class="kd">VM97</span> <span class="kd">main</span>.5b67c597.chunk.js:17<span class="o">)</span>
</code></pre></div></div>
<p>To fix it, I have to install the npm package <a href="https://yarnpkg.com/package/uuid" target="_blank">uuid</a>. As it has a dependency on it.</p>
<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">yarn</span> <span class="kd">add</span> <span class="kd">uuid</span>
</code></pre></div></div>
<p>or</p>
<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">npm</span> <span class="kd">install</span> <span class="kd">uuid</span> <span class="na">--save
</span></code></pre></div></div>SUN JiangongIf you want to check if a string is an UUID (Universally Unique Identifier, aka GUID) in reactjs. You can use the NPM package @types/uuid to do it.Which tools you need to develop web applications in ReactJS?2021-12-29T07:00:00+00:002021-12-29T07:00:00+00:00https://www.sunjiangong.com/2021/12/29/which-tools-you-need-to-develop-web-applications-in-reactjs<h3 id="tools">Tools:</h3>
<ul>
<li>Visual studio code</li>
<li>Chrome</li>
</ul>
<p><br /></p>
<h3 id="visual-studio-code-extensions">Visual studio code extensions:</h3>
<ul>
<li>Auto Import</li>
</ul>
<p>This extension will propose to import the related type you add in your file.
It works for scripts developed in TypeScript and TSX.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/auto-import.png" alt="" /></p>
<p><br /></p>
<!--more-->
<ul>
<li>Auto Import - ES6, TX, JSX, TSX</li>
</ul>
<p>This extension not only works for scripts developed in TypesScript, TSX, but also for scripts developed in <strong>JSX</strong>.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/auto-import-jsx.png" alt="" /></p>
<p><br /></p>
<ul>
<li>Bracket Pair Colorizer</li>
</ul>
<p>This extension will colorise your code and make it more readable.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/bracket-color.png" alt="" /></p>
<p><br /></p>
<ul>
<li>ESLint</li>
</ul>
<p>ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code, with the goal of making code more consistent and avoiding bugs.</p>
<p>ESLint supports <strong>Javascript</strong> code and <strong>TypeScript</strong> code, whereas TSLint only supports TypeScript code.</p>
<p>ESLint uses Espree for JavaScript parsing.
ESLint uses an AST to evaluate patterns in code.
ESLint is completely pluggable, every single rule is a plugin and you can add more at runtime.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/eslint.png" alt="" /></p>
<p>You can check the <a href="https://eslint.org/docs/rules/" target="_blank">rules</a> proposed by ESLint.</p>
<p><br /></p>
<ul>
<li>Reactjs code snippets</li>
</ul>
<p>ReactJs code snippets will facilitate your development by providing a lot of shortcuts to create sample codes.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/reactjs-code-snippets.png" alt="" /></p>
<p>An example:</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/reactjs-snippets-rcc.gif" alt="" /></p>
<p>Some snippets:</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/reactjs-code-common-snippets.png" alt="" /></p>
<p>You can find the full snippets list: <a href="https://marketplace.visualstudio.com/items?itemName=xabikos.ReactSnippets" target="_blank">here</a>.</p>
<p><br /></p>
<h3 id="chrome-extensions">Chrome extensions:</h3>
<ul>
<li>React Developer Tools</li>
</ul>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/react-dev-tools.png" alt="" /></p>
<p>With React Dev Tools you can visualize components and profile your application.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/react-dev-tools-components.png" alt="" /></p>
<ul>
<li>Redux DevTools</li>
</ul>
<p>You can check the redux workflow in React applications developed with Redux.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/redux-devtools.png" alt="" /></p>
<p>And you can verify the state changes in each step of the redux workflow.</p>
<p><img src="./../../../assets/img/posts/2021-12-29-reactjs-starter/redux-devtools-workflow.png" alt="" /></p>SUN JiangongTools: Visual studio code Chrome Visual studio code extensions: Auto Import This extension will propose to import the related type you add in your file. It works for scripts developed in TypeScript and TSX.An optimized version of function sys.fn_cdc_is_bit_set2021-12-08T07:00:00+00:002021-12-08T07:00:00+00:00https://www.sunjiangong.com/2021/12/08/an-optimized-version-function-sys-fn-cdc-is-bit-set<p>Change Data Capture (CDC) table uses __$update_mask to track the modifications of ordinal columns.</p>
<p>__$update_mask’s type is varbinary(128)</p>
<p>The function <strong>sys.fn_cdc_is_bit_set</strong> is provided within Microsoft SQL Server. It is used to calculate if the value of a column is modified, based on the column’s position and the __$update_mask.</p>
<!--more-->
<p><img src="./../../../assets/img/posts/2021-12-08-cdc-is-bit-set/cdc.jpg" alt="" /></p>
<p><br /></p>
<p>Its signature is:</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sys</span><span class="p">.</span><span class="n">fn_cdc_is_bit_set</span><span class="p">(</span><span class="k">position</span><span class="p">,</span> <span class="n">update_mask</span><span class="p">)</span>
</code></pre></div></div>
<p>But the function <strong>sys.fn_cdc_is_bit_set</strong> provided in SQL Server is not optimal when there are a lot of data to process.</p>
<p>Here is an optimal version:</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">FUNCTION</span> <span class="p">[</span><span class="n">dbo</span><span class="p">].[</span><span class="n">fn_cdc_is_bit_set_optimized</span><span class="p">]</span>
<span class="p">(</span>
<span class="o">@</span><span class="k">position</span> <span class="nb">INT</span><span class="p">,</span>
<span class="o">@</span><span class="n">update_mask</span> <span class="nb">VARBINARY</span><span class="p">(</span><span class="mi">128</span><span class="p">)</span>
<span class="p">)</span>
<span class="k">RETURNS</span> <span class="nb">BIT</span>
<span class="k">AS</span>
<span class="k">BEGIN</span>
<span class="k">DECLARE</span> <span class="o">@</span><span class="n">isSet</span> <span class="nb">BIT</span> <span class="o">=</span>
<span class="k">CASE</span> <span class="k">WHEN</span> <span class="k">SUBSTRING</span><span class="p">(</span><span class="o">@</span><span class="n">update_mask</span><span class="p">,</span><span class="n">DATALENGTH</span><span class="p">(</span><span class="o">@</span><span class="n">update_mask</span><span class="p">)</span> <span class="o">-</span> <span class="p">((</span><span class="o">@</span><span class="k">position</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">/</span><span class="mi">8</span><span class="p">),</span><span class="mi">1</span><span class="p">)</span> <span class="o">&</span> <span class="n">POWER</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="p">(</span><span class="o">@</span><span class="k">position</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">%</span><span class="mi">8</span><span class="p">)</span> <span class="o">></span> <span class="mi">0</span>
<span class="k">THEN</span> <span class="mi">1</span> <span class="k">ELSE</span> <span class="mi">0</span> <span class="k">END</span>
<span class="k">RETURN</span> <span class="o">@</span><span class="n">isSet</span><span class="p">;</span>
<span class="k">END</span>
</code></pre></div></div>SUN JiangongChange Data Capture (CDC) table uses __$update_mask to track the modifications of ordinal columns. __$update_mask’s type is varbinary(128) The function sys.fn_cdc_is_bit_set is provided within Microsoft SQL Server. It is used to calculate if the value of a column is modified, based on the column’s position and the __$update_mask.Microsoft .NET challenge France 2020 final2021-12-07T07:00:00+00:002021-12-07T07:00:00+00:00https://www.sunjiangong.com/2021/12/07/microsoft-dotnet-challenge-france-2020-final<p>I’ve participated in the Microsoft .NET challenge France 2020 final, eventually one year later. ;)</p>
<p>The Microsoft .NET challenge France is co-organized by several companies:</p>
<ul>
<li><a href="https://www.softfluent.fr" target="_blank">SoftFluent</a>, an IT consulting company specialized in the Microsoft ecosystem with C#, .NET, Azure, SQL Server etc</li>
<li><a href="https://editx.eu" target="_blank">EditX</a>, a company host a lot of online tests.</li>
<li><a href="https://www.microsoft.com/" target="_blank">Microsoft</a>. No need for introduction. :)</li>
</ul>
<p><img src="./../../../assets/img/posts/2021-12-07-dotnet-challenge-final-2020/dotnet-challenge-france-2020.jpg" alt="" /></p>
<!--more-->
<p><br /></p>
<p>There were two sessions in total. The first session was held between June and July 2020, and the second was held between October and November 2020. Each session lasts one month.</p>
<p>There is an online quiz of 15 questions on C#, .NET, Azure, and Algorithm in each session. The questions will become difficult progressively and each question has a different point, from 1 to 3 points depending on its difficulty.</p>
<p>More than 500 developers have participated in the two sessions. And the top 5 performed developers of each session will be invited to the final. I did not know the result until I was contacted the organizer. I won the 4th place in the second session. :)</p>
<p>The .NET challenge 2020 final was supposed to be held in the headquarter of Microsoft France. However, it was delayed a couple of times because of the Covid. :(</p>
<p>Finally, it was held on 23 September this year in <a href="https://www.epitech.eu" target="_blank">EPITECH</a>, a software engineer school near Paris.</p>
<p><br /></p>
<p>The format of the final is quite interesting.</p>
<p>There are two rounds.</p>
<h5 id="the-first-round-is-an-escape-game">The first round is an escape game</h5>
<p><br /></p>
<p><img src="./../../../assets/img/posts/2021-12-07-dotnet-challenge-final-2020/escape-game.jpg" alt="" /></p>
<p>All the 10 finalists are divided into 3 teams, each team with 4 or 3 members. Then we went to different rooms to play an escape game.</p>
<p>The idea is to try to find all the hints randomly hidden in the room and use the hints to solve several applicative problems.</p>
<p>The first team that solve all the problems will be the winner team.</p>
<p>Unfortunately, my team did not finish it first. :(</p>
<p><br /></p>
<h5 id="the-second-round-is-a-buzzer-game">The second round is a buzzer game</h5>
<p><img src="./../../../assets/img/posts/2021-12-07-dotnet-challenge-final-2020/buzzer.jpg" alt="" /></p>
<p>There are 10 questions displayed in a screen. The first person who press the buzzer will be able to answer the question. If his/her answer is correct, he/she will gain the point. The one who get the most points win the prize.</p>
<p><br /></p>
<h5 id="prize">Prize</h5>
<p>Finally, the winner gets a Microsoft Surface Go and a Surface Headphones. And every finalist gets a Surface Headphones.</p>
<p>The prizes were provided by Microsoft.</p>
<p><img src="./../../../assets/img/posts/2021-12-07-dotnet-challenge-final-2020/headphones.jpg" alt="" /></p>
<p><br /></p>
<h5 id="all-the-finalists">All the finalists</h5>
<p><br /></p>
<p><img src="./../../../assets/img/posts/2021-12-07-dotnet-challenge-final-2020/challenge-all.jpg" alt="" /></p>
<p><br /></p>
<p>A Pizza party was held in the yard of EPITECH after the final.</p>
<p><img src="./../../../assets/img/posts/2021-12-07-dotnet-challenge-final-2020/pizza-party.jpg" alt="" /></p>
<p><br /></p>
<h5 id="final-thoughts">Final thoughts:</h5>
<p><br /></p>
<p>The .NET challenge France is an annual event.</p>
<p>It is a great to test your .NET knowledge, get out of your métro-boulot-dodo (metro-work-sleep) routine, meet some interesting people/companies and have fun!</p>
<p>If you are a .NET developer and live in France or not ;), feel free to join the .NET challenge France 2022!</p>SUN JiangongI’ve participated in the Microsoft .NET challenge France 2020 final, eventually one year later. ;) The Microsoft .NET challenge France is co-organized by several companies: SoftFluent, an IT consulting company specialized in the Microsoft ecosystem with C#, .NET, Azure, SQL Server etc EditX, a company host a lot of online tests. Microsoft. No need for introduction. :)How to create integration tests with Entity Framework (EF) core?2021-11-16T07:00:00+00:002021-11-16T07:00:00+00:00https://www.sunjiangong.com/2021/11/16/how-to-create-integration-test-with-entity-framework-core<p>It’s not easy to create integration test with database, no matter whether you create queries directly against entity framework’s DbContext or you create your queries with repositary pattern which operate on your DbSets.</p>
<p>You need to always connect to your database to test your use cases with the real data or fake data you have prepared.</p>
<p>The good news is you can use the EF core’s in-memory database provider to tackle it easily.</p>
<!--more-->
<p>Firstly, install the nuget package “Microsoft.EntityFrameworkCore.InMemory”.</p>
<pre><code class="language-cmd">Install-Package Microsoft.EntityFrameworkCore.InMemory -Version 6.0.0
</code></pre>
<p>Then, you need to create an unique in-memory database instance for each test to prevent data collision in different use cases.</p>
<p>Here I use the builder pattern to create the DbContext initialization helper to use it easily in all my tests.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">TestDBContextBuilder</span>
<span class="p">{</span>
<span class="k">private</span> <span class="k">readonly</span> <span class="n">TestDBContext</span> <span class="n">_testDbContext</span><span class="p">;</span>
<span class="k">public</span> <span class="nf">TestDBContextBuilder</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">_testDbContext</span> <span class="p">=</span> <span class="k">null</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">options</span> <span class="p">=</span> <span class="k">new</span> <span class="n">DbContextOptionsBuilder</span><span class="p"><</span><span class="n">TestDBContext</span><span class="p">>()</span>
<span class="p">.</span><span class="nf">UseInMemoryDatabase</span><span class="p">(</span><span class="n">databaseName</span><span class="p">:</span> <span class="n">Guid</span><span class="p">.</span><span class="nf">NewGuid</span><span class="p">().</span><span class="nf">ToString</span><span class="p">())</span>
<span class="p">.</span><span class="n">Options</span><span class="p">;</span>
<span class="n">_testDbContext</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">TestDBContext</span><span class="p">(</span><span class="n">options</span><span class="p">);</span>
<span class="n">_testDbContext</span><span class="p">.</span><span class="n">ChangeTracker</span><span class="p">.</span><span class="n">QueryTrackingBehavior</span> <span class="p">=</span> <span class="n">QueryTrackingBehavior</span><span class="p">.</span><span class="n">NoTracking</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">TestDBContext</span> <span class="nf">Build</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">_testDbContext</span><span class="p">.</span><span class="nf">SaveChanges</span><span class="p">();</span>
<span class="k">return</span> <span class="n">_testDbContext</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">TestDBContextBuilder</span> <span class="nf">WithUsers</span><span class="p">(</span><span class="n">IList</span><span class="p"><</span><span class="n">User</span><span class="p">></span> <span class="n">users</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_testDbContext</span><span class="p">.</span><span class="n">Users</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="n">users</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">TestDBContextBuilder</span> <span class="nf">WithContracts</span><span class="p">(</span><span class="n">IList</span><span class="p"><</span><span class="n">Contract</span><span class="p">></span> <span class="n">contracts</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_testDbContext</span><span class="p">.</span><span class="n">Contracts</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="n">contracts</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Then, you just need to create your test with the prepared data and test if the code behave as you have expected.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Test</span><span class="p">]</span>
<span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">Shouw_get_users_ok</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//Arrange</span>
<span class="kt">var</span> <span class="n">users</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">User</span><span class="p">>{</span>
<span class="c1">// Code to create users</span>
<span class="p">};</span>
<span class="c1">// Initialize dbContext with the users</span>
<span class="k">using</span> <span class="nn">var</span> <span class="n">testDbContext</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">TestDBContextBuilder</span><span class="p">().</span><span class="nf">WithUsers</span><span class="p">(</span><span class="n">users</span><span class="p">).</span><span class="nf">Build</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">uow</span> <span class="p">=</span> <span class="k">new</span> <span class="n">UnitOfWork</span><span class="p"><</span><span class="n">TestDBContext</span><span class="p">>(</span><span class="n">testDbContext</span><span class="p">);</span>
<span class="n">_target</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">UserService</span><span class="p">(</span><span class="n">uow</span><span class="p">);</span>
<span class="c1">//Act</span>
<span class="kt">var</span> <span class="n">result</span> <span class="p">=</span> <span class="k">await</span> <span class="n">_target</span><span class="p">.</span><span class="nf">GetActiveUsers</span><span class="p">();</span>
<span class="c1">//Assert</span>
<span class="n">Check</span><span class="p">.</span><span class="nf">That</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">Count</span><span class="p">).</span><span class="nf">Equals</span><span class="p">(</span><span class="m">10</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>So you have all the tips to create properly the integration tests with EF core.</p>
<p>Hope you enjoyed it!</p>SUN JiangongIt’s not easy to create integration test with database, no matter whether you create queries directly against entity framework’s DbContext or you create your queries with repositary pattern which operate on your DbSets. You need to always connect to your database to test your use cases with the real data or fake data you have prepared. The good news is you can use the EF core’s in-memory database provider to tackle it easily.How to upload and download file in Angular 5+ and .net core2021-11-11T07:00:00+00:002021-11-11T07:00:00+00:00https://www.sunjiangong.com/2021/11/11/how-to-upload-and-download-file-in-angular-and-dotnet-core<p>When you develop a web application in Angular for the front-end and C# or Java in the back-end, it’s frequently that you need to upload and download files.</p>
<p>Here is an example that may inspire you in your development.</p>
<!--more-->
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- Upload file --></span>
<span class="nt"><input</span> <span class="na">hidden</span> <span class="na">#feeFile</span> <span class="na">type=</span><span class="s">"file"</span> <span class="na">#uploader</span> <span class="na">(change)=</span><span class="s">"uploadFees($event)"</span> <span class="na">accept=</span><span class="s">".xlsx, .xls"</span> <span class="nt">/></span>
<span class="nt"><button</span> <span class="na">mat-button</span> <span class="na">color=</span><span class="s">"primary"</span> <span class="na">(click)=</span><span class="s">"uploader.click()"</span><span class="nt">></span>
<span class="nt"><mat-icon</span> <span class="na">matTooltip=</span><span class="s">"Upload fees"</span> <span class="na">class=</span><span class="s">"import-export-button"</span><span class="nt">></span>cloud_upload<span class="nt"></mat-icon></span>
<span class="nt"></button></span>
<span class="c"><!-- Download file --></span>
<span class="nt"><button</span> <span class="na">mat-button</span> <span class="na">color=</span><span class="s">"primary"</span> <span class="na">(click)=</span><span class="s">"downloadFees()"</span><span class="nt">></span>
<span class="nt"><mat-icon</span> <span class="na">matTooltip=</span><span class="s">"Download fees"</span> <span class="na">class=</span><span class="s">"import-export-button"</span><span class="nt">></span>cloud_download<span class="nt"></mat-icon></span>
<span class="nt"></button></span>
</code></pre></div></div>
<p>Define a file object to use in file download and upload.</p>
<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">class</span> <span class="nx">DocumentDTO</span> <span class="p">{</span>
<span class="nx">fileName</span><span class="o">!</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
<span class="nx">fileData</span><span class="o">!</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
<span class="nx">contentType</span><span class="o">!</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Define a HHTML input event to pass the file.</p>
<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">interface</span> <span class="nx">HTMLInputEvent</span> <span class="kd">extends</span> <span class="nx">Event</span> <span class="p">{</span>
<span class="nl">target</span><span class="p">:</span> <span class="nx">HTMLInputElement</span> <span class="o">&</span> <span class="nx">EventTarget</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Define a file service to treat the file.</p>
<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">Injectable</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@angular/core</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">DocumentDTO</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@app/models/document.model</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="o">*</span> <span class="k">as</span> <span class="nx">FileSaver</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">file-saver</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">Subject</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">rxjs</span><span class="dl">'</span><span class="p">;</span>
<span class="p">@</span><span class="nd">Injectable</span><span class="p">({</span>
<span class="na">providedIn</span><span class="p">:</span> <span class="dl">'</span><span class="s1">root</span><span class="dl">'</span>
<span class="p">})</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">FileService</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
<span class="nx">saveFile</span><span class="p">(</span><span class="nb">document</span><span class="p">:</span> <span class="nx">DocumentDTO</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//Convert file content to blob</span>
<span class="kd">let</span> <span class="nx">blob</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">convertBase64StringToBlob</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">fileData</span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">contentType</span><span class="p">);</span>
<span class="c1">//Save file</span>
<span class="nx">FileSaver</span><span class="p">.</span><span class="nx">saveAs</span><span class="p">(</span><span class="nx">blob</span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">fileName</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">readFile</span><span class="p">(</span><span class="nx">file</span><span class="p">:</span> <span class="nx">File</span><span class="p">):</span> <span class="nb">Promise</span><span class="o"><</span><span class="kr">string</span><span class="o">></span> <span class="p">{</span>
<span class="c1">//Convert file to string</span>
<span class="kd">const</span> <span class="nx">sub</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Subject</span><span class="o"><</span><span class="kr">string</span><span class="o">></span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">reader</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FileReader</span><span class="p">();</span>
<span class="nx">reader</span><span class="p">.</span><span class="nx">onloadend</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="na">content</span><span class="p">:</span> <span class="kr">string</span> <span class="o">=</span> <span class="nx">reader</span><span class="p">.</span><span class="nx">result</span> <span class="k">as</span> <span class="kr">string</span><span class="p">;</span>
<span class="nx">sub</span><span class="p">.</span><span class="nx">next</span><span class="p">(</span><span class="nx">content</span><span class="p">);</span>
<span class="nx">sub</span><span class="p">.</span><span class="nx">complete</span><span class="p">();</span>
<span class="p">};</span>
<span class="nx">reader</span><span class="p">.</span><span class="nx">readAsDataURL</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">sub</span><span class="p">.</span><span class="nx">asObservable</span><span class="p">().</span><span class="nx">toPromise</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">private</span> <span class="nx">convertBase64StringToBlob</span><span class="p">(</span><span class="nx">base64</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="nx">contentType</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">Blob</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">byteCharacters</span> <span class="o">=</span> <span class="nx">atob</span><span class="p">(</span><span class="nx">base64</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">byteNumbers</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">byteCharacters</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">byteCharacters</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">byteNumbers</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">byteCharacters</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">byteArray</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">byteNumbers</span><span class="p">);</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Blob</span><span class="p">([</span><span class="nx">byteArray</span><span class="p">],</span> <span class="p">{</span> <span class="na">type</span><span class="p">:</span> <span class="nx">contentType</span> <span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Typescript code to upload and download Excel file.</p>
<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">async</span> <span class="nx">uploadFee</span><span class="p">(</span><span class="nx">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">target</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span> <span class="k">as</span> <span class="nx">HTMLInputElement</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">file</span> <span class="o">=</span> <span class="p">(</span><span class="nx">target</span><span class="p">.</span><span class="nx">files</span> <span class="k">as</span> <span class="nx">FileList</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">fileContent</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">fileService</span><span class="p">.</span><span class="nx">readFile</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span>
<span class="kd">let</span> <span class="nb">document</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">createDocumentDto</span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">fileContent</span><span class="p">);</span>
<span class="c1">//Upload file by calling web api upload file endpoint</span>
<span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="o"><</span><span class="nx">boolean</span><span class="o">></span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">apiUrl</span><span class="p">}</span><span class="s2">/document`</span><span class="p">,</span> <span class="nb">document</span><span class="p">).</span><span class="nx">toPromise</span><span class="p">();</span>
<span class="c1">//reset feeFile value to be able to reload the same file</span>
<span class="k">this</span><span class="p">.</span><span class="nx">feeFile</span><span class="p">.</span><span class="nx">nativeElement</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">private</span> <span class="nx">createDocumentDto</span><span class="p">(</span><span class="nx">file</span><span class="p">:</span> <span class="nx">File</span><span class="p">,</span> <span class="nx">content</span><span class="p">:</span> <span class="kr">string</span><span class="p">):</span> <span class="nx">DocumentDTO</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">doc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DocumentDTO</span><span class="p">();</span>
<span class="nx">doc</span><span class="p">.</span><span class="nx">fileName</span> <span class="o">=</span> <span class="nx">file</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span>
<span class="nx">doc</span><span class="p">.</span><span class="nx">contentType</span> <span class="o">=</span> <span class="nx">file</span><span class="p">.</span><span class="kd">type</span><span class="p">;</span>
<span class="nx">doc</span><span class="p">.</span><span class="nx">fileData</span> <span class="o">=</span> <span class="nx">content</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">doc</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">downloadFees</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">queryParams</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">createFilterParams</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">filter</span><span class="p">);</span>
<span class="kd">let</span> <span class="nb">document</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="o"><</span><span class="nx">DocumentDTO</span><span class="o">></span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">apiUrl</span><span class="p">}</span><span class="s2">/document`</span><span class="p">,</span> <span class="p">{</span> <span class="na">params</span><span class="p">:</span> <span class="nx">queryParams</span> <span class="p">}).</span><span class="nx">toPromise</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">fileService</span><span class="p">.</span><span class="nx">saveFile</span><span class="p">(</span><span class="nb">document</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">private</span> <span class="nx">createFilterParams</span><span class="p">(</span><span class="nx">filter</span><span class="p">:</span> <span class="nx">CodeDDGFilterDTO</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">queryParams</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HttpParams</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">filter</span><span class="p">.</span><span class="nx">Name</span> <span class="o">!==</span> <span class="kc">undefined</span><span class="p">)</span> <span class="nx">queryParams</span> <span class="o">=</span> <span class="nx">queryParams</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="dl">"</span><span class="s2">Name</span><span class="dl">"</span><span class="p">,</span> <span class="nx">filter</span><span class="p">.</span><span class="nx">Name</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">filter</span><span class="p">.</span><span class="nx">Code</span> <span class="o">!==</span> <span class="kc">undefined</span><span class="p">)</span> <span class="nx">queryParams</span> <span class="o">=</span> <span class="nx">queryParams</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="dl">"</span><span class="s2">Code</span><span class="dl">"</span><span class="p">,</span> <span class="nx">filter</span><span class="p">.</span><span class="nx">Code</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">queryParams</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Back-end code in .net core web api.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">HttpPost</span><span class="p">]</span>
<span class="p">[</span><span class="nf">Route</span><span class="p">(</span><span class="s">"document"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">async</span> <span class="n">Task</span><span class="p"><</span><span class="kt">bool</span><span class="p">></span> <span class="nf">UploadFeesExcelAsync</span><span class="p">(</span><span class="n">DocumentDTO</span> <span class="n">document</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">await</span> <span class="n">_feesImporter</span><span class="p">.</span><span class="nf">ImportDocument</span><span class="p">(</span><span class="n">document</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">[</span><span class="n">HttpGet</span><span class="p">]</span>
<span class="p">[</span><span class="nf">Route</span><span class="p">(</span><span class="s">"document"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">async</span> <span class="n">Task</span><span class="p"><</span><span class="n">DocumentDTO</span><span class="p">></span> <span class="nf">DownloadFeesExcelAsync</span><span class="p">([</span><span class="n">FromQuery</span><span class="p">]</span> <span class="n">FilterDTO</span> <span class="n">filter</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">await</span> <span class="n">_feesExporter</span><span class="p">.</span><span class="nf">GenerateDocument</span><span class="p">(</span><span class="n">filter</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Ok, you have seen the sample code. You can make your hands dirty now. :)</p>SUN JiangongWhen you develop a web application in Angular for the front-end and C# or Java in the back-end, it’s frequently that you need to upload and download files. Here is an example that may inspire you in your development.