<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Dotnet The Right Way]]></title><description><![CDATA[Dotnet The Right Way]]></description><link>https://maharjansachin.com.np</link><generator>RSS for Node</generator><lastBuildDate>Thu, 14 May 2026 12:35:22 GMT</lastBuildDate><atom:link href="https://maharjansachin.com.np/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Streamlining .NET Development: Building a CI/CD Pipeline with GitLab Runner, Docker Swarm, and Portainer]]></title><description><![CDATA[Containerizing Dotnet Web Application
The .NET application was containerized using Docker to ensure consistency across development and production environments.
A Dockerfile was created at the root of the project directory. This Dockerfile defined a m...]]></description><link>https://maharjansachin.com.np/streamlining-net-development-building-a-cicd-pipeline-with-gitlab-runner-docker-swarm-and-portainer</link><guid isPermaLink="true">https://maharjansachin.com.np/streamlining-net-development-building-a-cicd-pipeline-with-gitlab-runner-docker-swarm-and-portainer</guid><category><![CDATA[cicd]]></category><category><![CDATA[Docker]]></category><category><![CDATA[docker swarm]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[GitLab]]></category><category><![CDATA[GitLab-CI]]></category><category><![CDATA[Portainer]]></category><dc:creator><![CDATA[sachin maharjan]]></dc:creator><pubDate>Sun, 08 Sep 2024 05:10:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725770120692/5a93b490-53e1-4669-bb08-d569c66d99ef.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-containerizing-dotnet-web-application">Containerizing Dotnet Web Application</h3>
<p>The .NET application was containerized using Docker to ensure consistency across development and production environments.</p>
<p>A <code>Dockerfile</code> was created at the root of the project directory. This <code>Dockerfile</code> defined a multi-stage build, where the application was built and run in a minimal environment. The build stage involved using the .NET SDK to restore dependencies and publish the application, while the runtime stage used the <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core image to run the application.</p>
<p>An example of the <code>Dockerfile</code> is shown below:</p>
<pre><code class="lang-plaintext"># Build stage
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /app

# Copy project files and restore dependencies
COPY *.csproj ./
RUN dotnet restore

# Copy remaining application files and build
COPY . ./
RUN dotnet publish -c Release -o out

# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
COPY --from=build-env /app/out .

# Expose port 80 and run the application
EXPOSE 80
ENTRYPOINT ["dotnet", "MyDotnetApp.dll"]
</code></pre>
<p>The image was then built using Docker with the following command:</p>
<pre><code class="lang-plaintext">bashCopy codedocker build -t &lt;MyRegistryURL&gt;:&lt;Port&gt;:latest .
</code></pre>
<p>This command created a Docker image tagged as <code>my-dotnet-app:latest</code>, ready to be pushed to a registry.</p>
<h3 id="heading-setting-up-a-private-docker-registry">Setting Up a Private Docker Registry</h3>
<p>A private Docker registry was set up to store and manage Docker images, enabling secure access across different servers. Docker’s official Registry 2 image was used to achieve this.</p>
<p>The registry was started with the following command:</p>
<pre><code class="lang-plaintext">bashCopy codedocker run -d -p 5000:5000 --name registry --restart=always registry:2
</code></pre>
<p>This command deployed a registry container that listens on port 5000. The <code>--restart=always</code> flag ensured that the registry would restart automatically in case of server restarts or failures.</p>
<p>Afterward, the Docker image created earlier was tagged for the private registry and pushed:</p>
<pre><code class="lang-plaintext"># Tagging the image
docker tag my-dotnet-app:latest localhost:5000/my-dotnet-app:latest

# Pushing the image to the private registry
docker push localhost:5000/my-dotnet-app:latest
</code></pre>
<p>The image was successfully stored in the private registry, making it accessible to other servers in the Docker Swarm cluster.</p>
<h3 id="heading-configuring-a-docker-swarm-cluster">Configuring a Docker Swarm Cluster</h3>
<p>A Docker Swarm cluster configuration is essential for deploying the application across multiple servers. Docker Swarm simplifies the orchestration and management of containerized applications by enabling clustering, load balancing, and service discovery.</p>
<h5 id="heading-step-1-initialize-docker-swarm"><strong>Step 1: Initialize Docker Swarm</strong></h5>
<p>First, one of the servers was chosen as the <strong>Swarm Manager</strong>, who was responsible for managing the entire cluster. The Swarm was initialized using the following command:</p>
<pre><code class="lang-plaintext">docker swarm init --advertise-addr &lt;manager-ip&gt;
</code></pre>
<ul>
<li><code>--advertise-addr</code> specifies the IP address of the manager node so that other nodes can discover and join the swarm.</li>
</ul>
<p>After running this command, Docker outputs a unique token, which is used to add worker nodes to the swarm.</p>
<h5 id="heading-step-2-add-worker-nodes-to-the-swarm"><strong>Step 2: Add Worker Nodes to the Swarm</strong></h5>
<p>The remaining two servers were designated as <strong>Worker Nodes</strong>, which will host the application containers. To join these worker nodes to the swarm, the token from the previous step was used:</p>
<pre><code class="lang-plaintext">docker swarm join --token &lt;swarm-join-token&gt; &lt;manager-ip&gt;:2377
</code></pre>
<ul>
<li><p><code>&lt;swarm-join-token&gt;</code>: The token provided when initializing the swarm on the manager.</p>
</li>
<li><p><code>&lt;manager-ip&gt;</code>: The IP address of the swarm manager.</p>
</li>
</ul>
<p>This command connects the worker nodes to the swarm, allowing them to be managed by the Swarm Manager.</p>
<p>To confirm that the nodes had successfully joined the swarm, the following command was run on the manager node:</p>
<pre><code class="lang-plaintext">Copy codedocker node ls
</code></pre>
<p>This command lists all the nodes in the swarm and shows their status. The manager node is marked as the leader, and the worker nodes are shown as active members of the swarm.</p>
<h3 id="heading-installing-git">Installing Git</h3>
<p>You can use <code>sudo apt install git</code> it in Debian servers.</p>
<h3 id="heading-installing-gitlab-task-runner">Installing Gitlab Task Runner</h3>
<p>To run GitLab CI pipelines, GitLab Runner must be installed. GitLab Runner is an application used to run jobs in the GitLab CI/CD pipeline.</p>
<ol>
<li><p><strong>Add the GitLab Runner Repository</strong><br /> Add the official GitLab Runner repository to your system:</p>
<pre><code class="lang-plaintext"> curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
</code></pre>
</li>
<li><p><strong>Install GitLab Runner</strong><br /> After downloading the binary, you need to install the GitLab Runner using the following command:</p>
<pre><code class="lang-plaintext"> sudo apt install gitlab-runner
</code></pre>
<p> Verify that GitLab Runner has been installed successfully by checking its version:</p>
<pre><code class="lang-plaintext"> gitlab-runner --version
</code></pre>
</li>
</ol>
<h4 id="heading-step-3-register-gitlab-runner"><strong>Step 3: Register GitLab Runner</strong></h4>
<p>To make GitLab Runner work with GitLab CI pipelines, it needs to be registered with the GitLab instance.</p>
<ol>
<li><p><strong>Get the GitLab Runner Token</strong><br /> Go to your GitLab project and navigate to:<br /> <code>Settings &gt; CI / CD &gt; Runners</code>.<br /> Here, you’ll find the registration token, which is needed to register the runner.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725771260980/4a752378-4626-4eae-bbe6-cbff878258a7.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Register the Runner</strong><br /> Run the following command to register the GitLab Runner:</p>
<pre><code class="lang-plaintext"> sudo gitlab-runner register
</code></pre>
<p> The system will ask for the following details:</p>
<ul>
<li><p><strong>GitLab instance URL</strong>: e.g., <a target="_blank" href="https://gitlab.example.com/"><code>https://gitlab.example.com/</code></a></p>
</li>
<li><p><strong>Registration token</strong>: The token from your GitLab project</p>
</li>
<li><p><strong>Description</strong>: Name for your runner</p>
</li>
<li><p><strong>Tags</strong>: Optional tags to identify the runner</p>
</li>
<li><p><strong>Executor</strong>: Choose the executor to run your jobs (e.g., <code>shell</code>, <code>docker</code>, etc.).</p>
</li>
</ul>
</li>
<li><p><strong>Start GitLab Runner</strong><br /> After registration, the runner service can be started with:</p>
<pre><code class="lang-plaintext"> sudo gitlab-runner start
</code></pre>
<h3 id="heading-setting-up-cicd-pipeline-for-dockerized-net-applications-using-gitlab-ci"><strong>Setting Up CI/CD Pipeline for Dockerized .NET Applications using GitLab CI</strong></h3>
<p> In modern software development, automating the build, test, and deployment process is crucial for efficiency and reliability. GitLab CI/CD provides a robust pipeline setup for automating these tasks. In this step, a Continuous Integration (CI) and Continuous Deployment (CD) pipeline is described for Dockerized .NET applications using GitLab CI. The setup will build and push Docker images to a private registry, then deploy them using Docker Swarm.</p>
<h4 id="heading-pipeline-configuration-overview"><strong>Pipeline Configuration Overview</strong></h4>
<p> The <code>.gitlab-ci.yml</code> file is the main configuration file used by GitLab CI to define the pipeline stages and scripts to execute. Below is an explanation of the pipeline defined for a Dockerized .NET project.</p>
<pre><code class="lang-plaintext"> image: docker:latest

 stages:
   - build
   - deploy

 variables:
   REGISTRY_URL: "&lt;your Registry URL&gt;"
   IMAGE_TAG: "&lt;latest image tag&gt;"
</code></pre>
<ul>
<li><p><strong>Docker Image</strong>: The pipeline uses the <code>docker:latest</code> image, which includes Docker CLI tools for building, pushing, and managing containers.</p>
</li>
<li><p><strong>Stages</strong>: Two stages are defined—<code>build</code> and <code>deploy</code>.</p>
</li>
<li><p><strong>Variables</strong>: The <code>REGISTRY_URL</code> specifies the location of the private Docker registry, and <code>IMAGE_TAG</code> defines the version of the images being built and deployed.</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-build-stage"><strong>Build Stage</strong></h4>
<p>    The <code>build</code> stage involves compiling the Docker images for two services, the API Gateway and the IVR Service, and pushing them to the private registry.</p>
<pre><code class="lang-plaintext">    build:
      stage: build
      script:
        - docker build -t $REGISTRY_URL/dmn/apigateway:$IMAGE_TAG  APIGateway/DMNMiddleware.APIGateway
        - docker push $REGISTRY_URL/dmn/apigateway:$IMAGE_TAG

        - docker build -t $REGISTRY_URL/dmn/ivrservice:$IMAGE_TAG IVRService/DMNMiddleware.IVRService/
        - docker push $REGISTRY_URL/dmn/ivrservice:$IMAGE_TAG
      tags:
        - dmnmiddleware
      only:
        - master
</code></pre>
<ul>
<li><p><strong>Docker Build</strong>: Two Docker images are built—one for the API Gateway (<code>APIGateway/DMNMiddleware.APIGateway</code>) and another for the IVR Service (<code>IVRService/DMNMiddleware.IVRService</code>).</p>
<ul>
<li>The <code>docker build</code> command is used to create the image, tagged with the registry URL and the image version.</li>
</ul>
</li>
<li><p><strong>Docker Push</strong>: After building the images, they are pushed to the private Docker registry at <code>192.168.48.107:5000</code>.</p>
<ul>
<li>The <code>docker push</code> command uploads the images to the specified registry.</li>
</ul>
</li>
<li><p><strong>Tags</strong>: The runner is configured to use <code>dmnmiddleware</code> as a tag, ensuring that only appropriate runners will execute the job.</p>
</li>
<li><p><strong>Branch Limitation</strong>: This step is set to run only on the <code>master</code> branch to avoid deploying from other branches.</p>
</li>
</ul>
<h4 id="heading-deploy-stage"><strong>Deploy Stage</strong></h4>
<p>    The <code>deploy</code> stage involves deploying the services using Docker Swarm by using a pre-configured <code>docker-stack.yml</code> file.</p>
<pre><code class="lang-plaintext">    deploy:
      stage: deploy
      script:
        - echo "Deploying DMN Middleware ..."
        - docker stack rm dmn_middleware
        - sleep 10
        - docker stack deploy -c docker-stack.yml dmn_middleware
      tags:
        - dmnmiddleware
      needs:
        - build
      only:
        - master
</code></pre>
<ul>
<li><p><strong>Deployment Script</strong>:</p>
<ul>
<li><p><strong>Docker Stack Removal</strong>: The <code>docker stack rm</code> the command removes the existing stack named <code>dmn_middleware</code> to ensure that old services are stopped and replaced by the new deployment.</p>
</li>
<li><p><strong>Delay</strong>: A 10-second delay (<code>sleep 10</code>) is introduced to give Docker time to clean up the previous deployment before redeploying.</p>
</li>
<li><p><strong>Docker Stack Deployment</strong>: The <code>docker stack deploy</code> command is used to deploy the updated images to the Docker Swarm cluster using the <code>docker-stack.yml</code> configuration file.</p>
<h4 id="heading-example-docker-stackyml-file"><strong>Example</strong> <code>docker-stack.yml</code> File</h4>
<p>  Following is just an sample example of docker-stack yml file.</p>
<pre><code class="lang-plaintext">  version: '3.8'

  services:
    apigateway:
      image: 192.168.48.107:5000/dmn/apigateway:1.0.0
      deploy:
        replicas: 2
        restart_policy:
          condition: on-failure
      ports:
        - "8080:80"
      networks:
        - dmn_network

    ivrservice:
      image: 192.168.48.107:5000/dmn/ivrservice:1.0.0
      deploy:
        replicas: 2
        restart_policy:
          condition: on-failure
      ports:
        - "8081:80"
      networks:
        - dmn_network

  networks:
    dmn_network:
      driver: overlay

  volumes:
    data:
</code></pre>
<h4 id="heading-explanation-of-the-docker-stackyml-file"><strong>Explanation of the</strong> <code>docker-stack.yml</code> File</h4>
<ul>
<li><p><strong>Version</strong>: Specifies the version of the Docker Compose file format. <code>3.8</code> is used in this example, compatible with Docker Swarm.</p>
</li>
<li><p><strong>Services</strong>: Defines the different services in the stack.</p>
<ul>
<li><p><strong>apigateway</strong>:</p>
<ul>
<li><p><strong>image</strong>: Specifies the Docker image for the API Gateway. The image is pulled from the private Docker registry at <code>192.168.48.107:5000</code> with the tag <code>1.0.0</code>.</p>
</li>
<li><p><strong>deploy</strong>: Configures deployment settings:</p>
<ul>
<li><p><strong>replicas</strong>: Sets the number of replicas (containers) to run for the service.</p>
</li>
<li><p><strong>restart_policy</strong>: Defines the conditions under which the service should be restarted.</p>
</li>
</ul>
</li>
<li><p><strong>ports</strong>: Maps port <code>80</code> in the container to port <code>8080</code> on the host, allowing external access.</p>
</li>
<li><p><strong>networks</strong>: Connects the service to the <code>dmn_network</code>.</p>
</li>
</ul>
</li>
<li><p><strong>ivrservice</strong>:</p>
<ul>
<li><p><strong>image</strong>: Specifies the Docker image for the IVR Service, similarly pulled from the private Docker registry.</p>
</li>
<li><p><strong>deploy</strong>: Configures deployment settings, including <code>replicas</code> and <code>restart_policy</code>.</p>
</li>
<li><p><strong>ports</strong>: Maps port <code>80</code> in the container to port <code>8081</code> on the host.</p>
</li>
<li><p><strong>networks</strong>: Connects the service to the <code>dmn_network</code>.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Networks</strong>:</p>
<ul>
<li><strong>dmn_network</strong>: Defines an overlay network that allows services to communicate with each other within the Docker Swarm cluster.</li>
</ul>
</li>
<li><p><strong>Volumes</strong>:</p>
<ul>
<li><strong>data</strong>: Declares a volume named <code>data</code>, which can be used for persisting data across container restarts. It is not used in this example but is included to show how volumes are defined.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Dependency on Build Stage</strong>: The <code>deploy</code> job is dependent on the successful completion of the <code>build</code> job using the <code>needs: - build</code> directive, ensuring that only freshly built images are deployed.</p>
</li>
<li><p><strong>Tags and Branch Restriction</strong>: Similar to the build stage, the deploy stage runs only on runners tagged with <code>dmnmiddleware</code> and only on the <code>master</code> branch.</p>
</li>
</ul>
<h3 id="heading-monitoring-using-portainer">Monitoring Using Portainer</h3>
<p>    Portainer is a lightweight management UI that simplifies container management for Docker environments. It provides an intuitive web interface for managing Docker containers, images, volumes, networks, and more. Portainer supports Docker Swarm and Kubernetes, making it versatile for both single-host and multi-host setups. Its user-friendly dashboard helps streamline container operations and monitoring, improving overall efficiency.<br />    I don't talk here about how to install portainer because it is quite simple. You can follow the official documentation of portainer for quick up and running. After successful completion of the CI-CD job you can see your stack in portainer.</p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725771923115/54440f03-10b4-47e1-bc5e-f5f5cc3c592b.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-thank-you-for-reading-my-blog">Thank you for reading my blog.</h4>
<p>    Have a nice day and Happy Coding :)</p>
]]></content:encoded></item><item><title><![CDATA[Deploying Applications in Docker Swarm]]></title><description><![CDATA[Prerequisites
1. Operating System Installation: Ensure the required operating system is installed on all nodes.
2. Network Configuration: Verify that the physical network between all nodes is correctly configured and that the nodes can communicate wi...]]></description><link>https://maharjansachin.com.np/deploying-applications-in-docker-swarm</link><guid isPermaLink="true">https://maharjansachin.com.np/deploying-applications-in-docker-swarm</guid><category><![CDATA[Docker]]></category><category><![CDATA[Dockerswarm]]></category><dc:creator><![CDATA[sachin maharjan]]></dc:creator><pubDate>Sat, 31 Aug 2024 13:35:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725111189064/3e0c9098-794e-444b-8a33-1c073a036838.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Prerequisites</strong></p>
<p><strong>1. Operating System Installation:</strong> Ensure the required operating system is installed on all nodes.</p>
<p><strong>2. Network Configuration:</strong> Verify that the physical network between all nodes is correctly configured and that the nodes can communicate with each other.</p>
<p><strong>Docker Installation</strong></p>
<p>1. Install Docker: Install Docker on all nodes (both master and worker nodes) following the official Docker documentation:  <a target="_blank" href="https://docs.docker.com/engine/install/ubuntu/">https://docs.docker.com/engine/install/ubuntu/</a></p>
<p>   Ensure Docker is properly installed by running:</p>
<p>   <code>docker --version</code></p>
<p><strong>Setting Up Docker Swarm</strong></p>
<p><strong>1. Initialize Docker Swarm on the Master Node:</strong></p>
<ul>
<li><p>On the master node, initialize the Docker Swarm by running:</p>
<p><code>docker swarm init</code></p>
</li>
<li><p>Note the command and token provided after the initialization. This token is required for worker nodes to join the swarm.</p>
</li>
</ul>
<p><strong>2. Join Worker Nodes to the Swarm:</strong></p>
<ul>
<li><p>On each worker node, use the command provided by the master node to join the swarm:</p>
<p><code>docker swarm join --token &lt;worker-token&gt; &lt;master-node-ip&gt;:2377</code></p>
</li>
<li><p>Verify that the worker nodes have successfully joined the swarm by running the following command on the master node:</p>
<p><code>docker node ls</code></p>
</li>
</ul>
<p><strong>Deploying the Stack</strong></p>
<p><strong>1. Create/Update the Stack YML File:</strong></p>
<ul>
<li>Ensure that the stack YML file (e.g., <code>docker-stack.yml</code>) is up to date with the necessary services and configurations.</li>
</ul>
<p><strong>2. Deploy the Stack:</strong></p>
<ul>
<li><p>Deploy the stack using the following command on the master node:</p>
<p><code>docker stack deploy -c docker-stack.yml &lt;stack-name&gt;</code></p>
</li>
<li><p>Confirm that all services are running as expected:</p>
<p><code>docker stack services &lt;stack-name&gt;</code></p>
</li>
</ul>
<p><strong>Troubleshooting Ingress Network Issues</strong></p>
<p><strong>1. Network Troubleshooting:</strong></p>
<ul>
<li><p>If there are issues related to the ingress network, such as network connectivity problems between nodes, use the following command on the affected node(s) to disable checksum offloading:</p>
<p><code>ethtool -k ens160 tx-checksum-ip-generic off</code></p>
</li>
<li><p>Replace <code>ens160</code> with the appropriate network interface name for your environment.</p>
</li>
</ul>
<p><strong>2. Verify Network Configuration:</strong></p>
<ul>
<li>Ensure that all nodes can communicate over the required ports and that no firewall or network issues are causing problems.</li>
</ul>
<p><strong>Additional Considerations</strong></p>
<p>1. <strong>Regular Monitoring:</strong> Continuously monitor the health and performance of the Docker Swarm cluster using tools like <code>docker service ps</code>, <code>docker node ls</code>, and Docker logs.</p>
<p><strong>2. Scaling Services:</strong> Adjust the number of replicas or scale services as needed using the stack YML file or <code>docker service scale</code> command.</p>
<p><strong>3. Updating Services:</strong> Update services in the stack by modifying the YML file and re-running the <code>docker stack deploy</code> command.</p>
<p><strong>Container Registry</strong></p>
<p>We use Docker’s open-source container registry, <strong>Registry 2</strong>, to store our container images. This registry can be easily installed and configured within Docker.</p>
<p><code>docker run -d -p 5000:5000 –restart=always –name registry \</code></p>
<p><code>-v /opt/docker-registry/data: /var/lib/registry\</code></p>
<p><code>registry:2</code></p>
<p>This command sets up the registry as a Docker container, with persistent storage for your images at /opt/docker-registry/data.</p>
<p>Note: We must build an image and make the tag to push it in the registry.  Also, we need to add insecure registries in the daemon.json of docker. Deamon.json file can be found in <em>/etc/docker/</em></p>
<p><code>docker build -t dmn/image_name path_to_dockerfile</code></p>
<p><code>docker tag local_image image_with_registry_url</code></p>
<p><code>docker push image_with_registry_url</code></p>
]]></content:encoded></item><item><title><![CDATA[Quick Intro To Session In DotNet]]></title><description><![CDATA[So, What does Session mean ...
Let me give you a meaningful analogy first.Imagine you're at a magical tea party with your favorite stuffed animals. Each of them has a unique personality, and they're all eager to join in the fun. You pour pretend tea,...]]></description><link>https://maharjansachin.com.np/quick-intro-to-session-in-dotnet</link><guid isPermaLink="true">https://maharjansachin.com.np/quick-intro-to-session-in-dotnet</guid><dc:creator><![CDATA[sachin maharjan]]></dc:creator><pubDate>Mon, 11 Mar 2024 15:38:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1-aA2Fadydc/upload/8b6cedab8cbef8698e69341273288b2f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So, What does Session mean ...</p>
<p>Let me give you a meaningful analogy first.<br />Imagine you're at a magical tea party with your favorite stuffed animals. Each of them has a unique personality, and they're all eager to join in the fun. You pour pretend tea, share imaginary snacks and have delightful conversations with your furry friends. The party continues until you decide it's time to say goodbye and put your toys away. Just like how you remember the tea party's adventures the next time you play, computers also remember what you were doing during a session. They keep track of the websites you visit, the games you play, and the tasks you complete until you're ready to close the computer or log out. So, think of a session as a magical tea party with your computer, where together, you create delightful memories in the digital world!</p>
<p>A session is a method used for managing state in web development. It functions by storing data on the server, allowing for the storage of various types of objects, including custom ones. Sessions are regarded as a highly effective state management technique because they store data based on the client, ensuring that each user's data is kept separate and secure on the server. This is particularly important in web development because the HTTP protocol, which the web utilizes, is stateless. This means that each time a client sends a request to the server, a new instance of the page is created, rendering the previous data inaccessible. Therefore, to fulfill requirements such as storing and passing control values between web forms, state management techniques like sessions are indispensable.</p>
<p>In <a target="_blank" href="http://ASP.NET">ASP.NET</a>, sessions are a crucial aspect of state management, allowing developers to maintain user-specific data across multiple requests. There are several types of sessions in <a target="_blank" href="http://ASP.NET">ASP.NET</a>, each with its own use cases, advantages, and disadvantages:</p>
<p>In <a target="_blank" href="http://ASP.NET">ASP.NET</a>, sessions are a crucial aspect of state management, allowing developers to maintain user-specific data across multiple requests. There are several types of sessions in <a target="_blank" href="http://ASP.NET">ASP.NET</a>, each with its own use cases, advantages, and disadvantages:</p>
<ol>
<li><p><strong>In-Proc Session State</strong>:</p>
<ul>
<li><p><strong>Use Case</strong>: In-Proc session state is the default session state mode in <a target="_blank" href="http://ASP.NET">ASP.NET</a>. It stores session data in the web server's memory. It is ideal for applications with a single web server and low to moderate traffic.</p>
</li>
<li><p><strong>Advantages</strong>:</p>
<ul>
<li><p>Fast access to session data since it's stored in-memory.</p>
</li>
<li><p>No external dependencies or configuration required.</p>
</li>
</ul>
</li>
<li><p><strong>Disadvantages</strong>:</p>
<ul>
<li><p>Session data is lost if the web server is restarted or recycled.</p>
</li>
<li><p>Not suitable for web farms or load-balanced environments as session data is not shared between servers.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>StateServer Session State</strong>:</p>
<ul>
<li><p><strong>Use Case</strong>: StateServer session state mode stores session data in a separate process called the <a target="_blank" href="http://ASP.NET">ASP.NET</a> State Service. It is suitable for web applications hosted on multiple servers or in a web farm environment.</p>
</li>
<li><p><strong>Advantages</strong>:</p>
<ul>
<li><p>Session data is preserved even if the web server is restarted or recycled.</p>
</li>
<li><p>Suitable for load-balanced environments as session data is stored externally and can be accessed by multiple servers.</p>
</li>
</ul>
</li>
<li><p><strong>Disadvantages</strong>:</p>
<ul>
<li><p>Slower access to session data compared to In-Proc session state due to network communication with the State Service.</p>
</li>
<li><p>Limited to storing serializable objects in session due to the need for data to be marshaled across processes.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>SQLServer Session State</strong>:</p>
<ul>
<li><p><strong>Use Case</strong>: SQLServer session state mode stores session data in a SQL Server database. It is suitable for web applications requiring high scalability, reliability, and persistence of session data.</p>
</li>
<li><p><strong>Advantages</strong>:</p>
<ul>
<li><p>Session data is persisted in a SQL Server database, ensuring data integrity and availability.</p>
</li>
<li><p>Suitable for web farms or load-balanced environments as session data is stored centrally in the database.</p>
</li>
</ul>
</li>
<li><p><strong>Disadvantages</strong>:</p>
<ul>
<li><p>Slower access to session data compared to In-Proc or StateServer session state due to database communication overhead.</p>
</li>
<li><p>Requires additional setup and configuration, including setting up the SQL Server database and configuring connection strings.</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>Each type of session state in <a target="_blank" href="http://ASP.NET">ASP.NET</a> offers different trade-offs in terms of performance, scalability, and reliability. The choice of session state mode depends on the specific requirements and constraints of the web application.</p>
]]></content:encoded></item><item><title><![CDATA[Demystifying IoC and Dependency Injection In ASP Dot Net Core]]></title><description><![CDATA[Dependency Injection
DI is a technique in software development that manages the dependencies between different components or modules in the system.
This is done by providing a component with its required dependencies from an external source instead o...]]></description><link>https://maharjansachin.com.np/demystifying-ioc-and-dependency-injection-in-asp-dot-net-core</link><guid isPermaLink="true">https://maharjansachin.com.np/demystifying-ioc-and-dependency-injection-in-asp-dot-net-core</guid><category><![CDATA[dotnet]]></category><category><![CDATA[ioc]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[sachin maharjan]]></dc:creator><pubDate>Mon, 27 Feb 2023 13:42:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/lCSBOoe0iS4/upload/48a8fedac6f5ecc308c49c63feea880b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-dependency-injection">Dependency Injection</h3>
<p>DI is a technique in software development that manages the dependencies between different components or modules in the system.</p>
<p>This is done by providing a component with its required dependencies from an external source instead of allowing it to create or manage its dependencies.</p>
<h3 id="heading-inversion-of-control-ioc">Inversion of Control (IoC)</h3>
<p>It is a design pattern that allows the flow of control in a program to be inverted or reversed. Instead of the program controlling the flow of execution, the flow is controlled by an external framework or container.</p>
<p><strong>So, Why should we use IoC?</strong></p>
<p>By applying IoC, an application can decouple its components, making them more modular and easier to test and maintain.</p>
<p>IoC promotes the uses of interfaces and abstraction which makes the code more flexible and extensible.</p>
<h3 id="heading-types-of-di">Types of DI</h3>
<p><strong>Constructor Injection</strong></p>
<p>This involves injecting dependencies through a class's constructor. This is the most common form of DI and is often used when a class has mandatory dependencies that it needs in order to function correctly.</p>
<p><strong>Property Injection</strong></p>
<p>This involves injecting dependencies through a class's public properties. Property injection is less common than Constructor injection and is often used when you need to inject optional dependencies.</p>
<p><strong>Method Injection</strong></p>
<p>This involves injecting dependencies through a method call. Method injection is the least common form of DI and is often used when a dependency is only required for a specific method call.</p>
<h3 id="heading-di-in-net-core">DI in .NET Core</h3>
<p>DI in .NET core is a built-in feature that allows you to separate the creation of object graphs from your application code.</p>
<p>To Use DI, you need to register your services with a service container by specifying which services your application needs and how to create them.</p>
<p><strong>Lifetime Management</strong></p>
<p>Lifetime management in Dependency injection refers to the way in which instances of a service are created and managed by the Dependency Injection container. In other words, it determines the lifespan of an object created through Dependency Injection.</p>
<p>The three-lifetime management options are as follow:</p>
<ol>
<li><p>Transient</p>
</li>
<li><p>Scoped</p>
</li>
<li><p>Singleton</p>
</li>
</ol>
<p><strong>Transient Method</strong></p>
<p>This is the default lifetime management in the .NET core. A new instance of the service is created each time it is requested from the container.</p>
<p>Methods</p>
<p>AddTransient: Registers a service with transient lifetime management.</p>
<p>Add Transient&lt;TService, TImplementation&gt;: Registers a service and its implementation with transient lifetime management.</p>
<p>When you have a lightweight and stateless service that does not maintain any state between requests, such as a logger or a helper class. When you want to ensure that a new instance of the service is created every time it is requested from the container. This can help prevent issues with thread-saÿety or shared state.</p>
<p><strong>Scoped Method</strong></p>
<p>A single instance of the service is created for each scope. A scope typically corresponds to a web request in a web application.</p>
<p>Methods</p>
<p>AddScoped: Registers a service with the scoped lifetime management. AddScoped&lt;TService, TImplementation&gt;: Registers a service and its implementation with the scoped lifetime management.  </p>
<p>When you have a service that needs to maintain a state between requests, but that should not be shared.</p>
<p><strong>Singleton Method</strong></p>
<p>A single instance of the service is created and shared throughout the lifetime of the application. This can be useful for services that are expensive to create or for services that need to maintain state.</p>
<p>Methods</p>
<p>AddSingleton: Registers a service with singleton lifetime management.</p>
<p>AddSingleton&lt;TService, TImplementation&gt;: Registers a service and its implementation with the singleton lifetime management.</p>
<p>Be aware that a single instance of the service will be created and shared throughout the lifetime of the application. This can lead to issues with shared state or thread safety if the service is not designed to be used in this way. Be sure to handle any concurrency issues that may arise when using a singleton.</p>
]]></content:encoded></item><item><title><![CDATA[Security Test Your API Endpoints With Pynt]]></title><description><![CDATA[Have you ever been worried about the security of your API endpoints? This is the question that raises in our minds very few times. The reason behind this is very simple, nobody cares about security until an incident happens. In DishHome and in dish h...]]></description><link>https://maharjansachin.com.np/security-test-your-api-endpoints-with-pynt</link><guid isPermaLink="true">https://maharjansachin.com.np/security-test-your-api-endpoints-with-pynt</guid><category><![CDATA[Postman]]></category><category><![CDATA[APIs]]></category><category><![CDATA[OWASP TOP 10]]></category><category><![CDATA[Security]]></category><category><![CDATA[pynt]]></category><dc:creator><![CDATA[sachin maharjan]]></dc:creator><pubDate>Fri, 03 Feb 2023 15:33:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1675436448417/bc023a8f-9a75-4e9a-a09d-3bdd6e264d64.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever been worried about the security of your API endpoints? This is the question that raises in our minds very few times. The reason behind this is very simple, nobody cares about security until an incident happens. In DishHome and in dish home ott API had been compromised. A bug bounty is given to the person who has given information about security flaws in our API. It is obvious that when you are a junior developer you focus most of your time on how to do it rather than how to secure it. If you really don't know how to do it then what you are going to secure at all? When you are a beginner you write code to login, code to generate bearer tokens and you ignore all the details behind you. That step might be good because when you are learning, it may be overwhelming when you focus a lot on details because you have to learn to make things work first. But once you become confident in doing such work then you need to start to focus on security factors also. If you don't limit the rate of generation of bearer tokens then users may keep on generating tokens which may over-traffic our web servers. Every year top 10 security vulnerabilities are listed on the OWASP website which is also called OWASP 10 vulnerabilities. OWASP 10 commonly consists of security threats like broken authentication, SQL injections, cross-site request forgery, and many others.</p>
<p>In this article, I going to guide you to get started with pynt to security test your API. So, you are thinking what a hell is in the earth is pynt. Pynt is a free API security solution that generates automated security tests from your existing functional test collection in a few minutes. Pynt (<a target="_blank" href="http://pynt.io">pynt.io</a>) is a free API security solution that runs seamlessly in Postman. It generates automated security tests based on your existing functional test collection. Simply input your functional test collection name into the Pynt collection and run it to get the security testing coverage for your</p>
<h3 id="heading-tools-you-need-to-install">Tools you need to install</h3>
<ol>
<li><p>Ensure you are working with the Postman app (install from <a target="_blank" href="https://www.postman.com/downloads">https://www.postman.com/downloads</a>). Please note that the Pynt solution is based on docker and requires access to the local host, so it doesn't support the Postman web.</p>
</li>
<li><p>Ensure the Docker engine is available and running on your machine (install it from: <a target="_blank" href="https://docs.docker.com/engine/install/">https://docs.docker.com/engine/install/</a>).</p>
</li>
</ol>
<h3 id="heading-getting-started"><strong>Getting Started:</strong></h3>
<ul>
<li><p>Open your workspace from the Postman desktop app.</p>
</li>
<li><p>Download and run the Pynt docker by executing the following command (port number can be changed if already taken):</p>
<ul>
<li><p><strong>Docker Desktop for Windows, Mac, or Linux</strong> - run from cmd/terminal: <code>docker run -p 5001:5001 --pull always</code> [<code>ghcr.io/pynt-io/pynt:postman-latest</code>(the](http://ghcr.io/pynt-io/pynt:postman-latest(the) left port can be changed if already taken on your machine)</p>
</li>
<li><p><strong>Docker engine for Linux</strong> - run from terminal: <code>docker run --pull always --network=host</code> <a target="_blank" href="http://ghcr.io/pynt-io/pynt:postman-latest"><code>ghcr.io/pynt-io/pynt:postman-latest</code></a></p>
</li>
</ul>
</li>
</ul>
<p>This step should be repeated if you restarted your PC.</p>
<p><img src="https://content.pstmn.io/86b6541a-a763-4e9c-b65a-50d7ce2db185/aW1hZ2UucG5n" alt="Run%20Pynt%20docker" /></p>
<p><code>Run Pynt docker</code></p>
<h3 id="heading-how-to-run"><strong>How to Run:</strong></h3>
<p>Make sure Pynt's docker is still up.</p>
<ul>
<li><p>Click on the '<strong>Variables</strong>' tab of the '<strong>Pynt</strong>' collection and fill in the values of the required parameters, in the 'CURRENT VALUE' column:</p>
<ul>
<li><p><code>API-KEY</code> - your postman API key - If you previously saved and have your API key, enter it here under the 'Current Value' tab. If not, enter <a target="_blank" href="https://postman.co/settings/me/api-keys">https://postman.co/settings/me/api-keys</a> to generate or regenerate your API key as for security reasons it can only be copied at the time of creation. You won't need to modify this parameter again until the API-key expires.</p>
</li>
<li><p><code>PYNT-PORT</code> - the left port number used in the docker run command (default-5001).</p>
</li>
<li><p><code>YOUR-COLLECTION</code>- your functional test collection name, or the collection UID (both are acceptable, UID is preferred if you have two collections with the same name associated with the API-KEY). Pynt will refer to this collection to generate the automated security tests.<br />  If you wish to have a reference application to test, Pynt provides a vulnerable app example called '<strong>goat</strong>' that you can fork from Pynt's public workspace: <a target="_blank" href="https://www.postman.com/pynt-io/workspace/pynt">https://www.postman.com/pynt-io/workspace/pynt</a> and use it here.</p>
</li>
<li><p><code>scanId</code> - output variable, used internally. Ignore.</p>
</li>
<li><p>Click 'Save'.</p>
</li>
</ul>
</li>
<li><p>Run the '<strong>Pynt</strong>' collection to get the security results:</p>
<ul>
<li><p>The security results for OWASP-10 categories will appear on the main console screen.</p>
</li>
<li><p>Click on 'View Summary' to view the results summary.</p>
</li>
<li><p>In order to see the full report, uncollapse the '<strong>Pynt</strong>' collection, go to the last request '<strong>Show Report</strong>' and click on 'Send'. choose the 'Visualize' tab on the lower section to see the full report.</p>
</li>
</ul>
</li>
</ul>
<p><em>If you modified your test collection in any way, simply re-run Pynt collection.  
</em>Should you need to test another collection, simply update the <code>YOUR-COLLECTION</code>variable and re-run the 'Pynt' collection.</p>
<p><strong>See also screenshot examples:</strong></p>
<p><img src="https://user-images.githubusercontent.com/107360829/184632643-ba29d4d6-b4f6-4d8b-a025-bf42b5662639.png" alt="Image%201%20-%20Generate/copy%20API%20Key%20if%20forgotten" /></p>
<p><em>Image 1 - Generate/copy API Key if forgotten</em></p>
<p><img src="https://content.pstmn.io/547baa18-0cdc-4738-ae4b-42adbf4a4e66/SW1hZ2UxX1VwZGF0ZVB5bnRWYXJpYWJsZXMucG5n" alt="Image%202%20-%20Enter%20'Pynt'%20collection%20parameters" /></p>
<p><em>Image 2 - Enter 'Pynt' collection parameters</em></p>
<p><img src="https://content.pstmn.io/fdf66bb2-0f07-4c3d-af54-6013da63462a/SW1hZ2UyX1J1blB5bnQucG5n" alt="Image%203%20-%20Run%20the%20'Pynt'%20collection%20to%20generate%20full%20OWASP-10%20API-security%20tests%20for%20your%20collection" /></p>
<p><em>Image 3 - Run the 'Pynt' collection to generate full OWASP-10 API-security tests for your collection</em></p>
<p><img src="https://content.pstmn.io/9fdaa0e7-6d3f-4ef5-9208-fb3e1cdb7bc2/SW1hZ2UzX1ZpZXdSZXN1bHRzLnBuZw==" alt="Image%204%20-%20View%20the%20API%20security%20test%20results" /></p>
<p>Image 4 - View the API security test results</p>
<p><img src="https://content.pstmn.io/99c68252-a398-4c0b-927b-e7991fc8cece/SW1hZ2U0X1ZpZXdTdW1tYXJ5LnBuZw==" alt="Image%205%20-%20View%20results%20summary" /></p>
<p><em>Image 5 - View results summary</em></p>
<p><img src="https://content.pstmn.io/df120d8d-48cf-4d69-8e4c-e8783e2b239a/SW1hZ2U2X1Zpc3VhbGl6ZVN1bW1hcnkucG5n" alt="Image%206%20-%20View%20visualize%20report%20for%20security%20summary" /></p>
<p><em>Image 6 - View visualize report for security summary</em></p>
<p><img src="https://content.pstmn.io/a86d823d-ee6c-4dcd-9d5c-b0f117a6d740/SW1hZ2U2X1Zpc3VhbGl6ZURldGFpbGVkLnBuZw==" alt="Image%207%20-%20View%20visualize%20report%20for%20detailed%20findings" /></p>
<p><em>Image 7 - View visualize report for detailed findings</em></p>
]]></content:encoded></item><item><title><![CDATA[MinIO For Dotnet Developers]]></title><description><![CDATA[Before you started
I assume you have basic knowledge of C# programming language and the basics of dotnet MVC application.
What is MinIO?
MinIO is a high-performance, distributed object storage system. It is open-source software under GNU 3.0 license....]]></description><link>https://maharjansachin.com.np/minio-for-dotnet-developers</link><guid isPermaLink="true">https://maharjansachin.com.np/minio-for-dotnet-developers</guid><category><![CDATA[#minio]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[C#]]></category><category><![CDATA[object storage]]></category><category><![CDATA[Amazon S3]]></category><dc:creator><![CDATA[sachin maharjan]]></dc:creator><pubDate>Tue, 31 Jan 2023 07:34:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1675088327539/c2e61fee-91cc-4977-bdbc-e9cc0a5d7343.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-before-you-started">Before you started</h3>
<p>I assume you have basic knowledge of C# programming language and the basics of dotnet MVC application.</p>
<h3 id="heading-what-is-minio">What is MinIO?</h3>
<p>MinIO is a high-performance, distributed object storage system. It is open-source software under GNU 3.0 license. MinIO is AWS S3 compatible but mainly used in a private cloud. MinIO provides a lot of benefits to developers and system engineers. Some of them are given below:</p>
<ul>
<li><p>High availability</p>
</li>
<li><p>Data redundancy</p>
</li>
<li><p>Native Kubernetes support</p>
</li>
<li><p>Horizontal and vertical scaling</p>
</li>
<li><p>Two-factor data encryption</p>
</li>
<li><p>Detailed performance monitoring</p>
</li>
<li><p>IAM framework that offers more flexible access configuration</p>
</li>
<li><p>Notifications about downloading and uploading data in a queue</p>
</li>
</ul>
<h3 id="heading-installing-minio-in-windows">Installing MinIO In Windows</h3>
<p>For this particular demo, I am using the windows 11 operating System. To install minio we have to download minio.exe first. So, let's browse minio official website, and then click the download button on the very first landing page. Then will see different options for different platforms like windows, mac, linux, docker, Kubernetes, etc. I am using windows that is why I click the windows option. After that, I will download the minio.exe file from there.</p>
<p>Now, open the command prompt and move to the directory where you downloaded minio.exe. Then execute it using the command given below:</p>
<p><code>minio.exe server D:\minio --console-address :9090</code></p>
<p>The above command tells minio to start the server and save the uploaded file in <code>D:\minio</code> directory. Now you will see the result shown in the image below:</p>
<pre><code class="lang-bash">MinIO Object Storage Server
Copyright: 2015-2023 MinIO, Inc.
License: GNU AGPLv3 &lt;https://www.gnu.org/licenses/agpl-3.0.html&gt;
Version: RELEASE.2023-01-12T02-06-16Z (go1.19.4 windows/amd64)

Status:         1 Online, 0 Offline.
API: http://192.168.137.220:9000  http://172.27.112.1:9000  http://127.0.0.1:9000
RootUser: minioadmin
RootPass: minioadmin
Console: http://192.168.137.220:9090 http://172.27.112.1:9090 http://127.0.0.1:9090
RootUser: minioadmin
RootPass: minioadmin

Command-line: https://min.io/docs/minio/linux/reference/minio-mc.html<span class="hljs-comment">#quickstart</span>
   $ mc.exe <span class="hljs-built_in">alias</span> <span class="hljs-built_in">set</span> myminio http://192.168.137.220:9000 minioadmin minioadmin

Documentation: https://min.io/docs/minio/linux/index.html
Warning: The standard parity is <span class="hljs-built_in">set</span> to 0. This can lead to data loss.

+---------------------------------------------------------------+
| You are running an older version of MinIO released 1 week ago |
| Update: Run `mc admin update`                                 |
+---------------------------------------------------------------+
</code></pre>
<p>Open browser and enter localhost:9090 in the url. Then you will see the minio login pages.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675089906032/a1d9a04f-109e-45a3-a32f-3b6d846ffd5b.png" alt class="image--center mx-auto" /></p>
<p>Enter the username and password that you can find in the command prompt. In my case username = <code>minioadmin</code> and password = <code>minioadmin</code>.</p>
<p>Then you will see the minio dashboard as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675090084573/b2983489-1338-4307-8f06-ff95a3a08909.png" alt class="image--center mx-auto" /></p>
<p>Create a new bucket from the side menu in minio dashboard. MinIO Object Storage uses buckets to organize objects. A <strong><em>bucket</em></strong> is similar to a folder or directory in a filesystem, where each bucket can hold an arbitrary number of objects. MinIO buckets provide the same functionality as <strong><em>AWS S3</em></strong> buckets. I have created a bucket name oss as you can see in the image object.</p>
<h3 id="heading-connecting-dotnet-mvc-application-to-minio-server">Connecting Dotnet MVC application to MinIO server</h3>
<p>Create a new MVC application using dotnet cli.</p>
<p><code>dotnet new mvc -n sampleapp -o src</code></p>
<p>Install minio client package for dotnet.</p>
<p><code>dotnet add package minio</code></p>
<p>Now in the index view of the home controller create a form that has file input and a button to submit.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">asp-controller</span>=<span class="hljs-string">"Home"</span> <span class="hljs-attr">asp-action</span>=<span class="hljs-string">"Upload"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">file</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"file"</span>/&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Upload<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Now, Let's write a backend when we submit the above HTML form. Before writing the backend code you have to generate the access key and secret key from minio dashboard. Go to your minio console and find the Users page. You can create a new user and set it <code>MINIO_ACCESS_KEY</code> and <code>MINIO_SECRET_KEY</code> or can view user credentials. Note that your policy must allow for credentials reset, the default policy consoleAdmin allows for that.</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">Upload</span>(<span class="hljs-params">IFormFile file</span>)</span>
{
    <span class="hljs-keyword">var</span> endpoint = <span class="hljs-string">"127.0.0.1:9000"</span>;
    <span class="hljs-keyword">var</span> accessKey = <span class="hljs-string">"XXXXXXXXXXX"</span>;
    <span class="hljs-keyword">var</span> secretKey = <span class="hljs-string">"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"</span>;
    <span class="hljs-keyword">var</span> minio = <span class="hljs-keyword">new</span> MinioClient()
                .WithEndPoint(endpoint)
                .WithCredentials(accessKey, secretKey)
                .Build();
    Uploader.Run(minio, file).Wait();
    <span class="hljs-keyword">return</span> View(<span class="hljs-string">"Index"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> <span class="hljs-keyword">static</span> Task <span class="hljs-title">Run</span>(<span class="hljs-params">MinioClient minio, IFormFile file</span>)</span>
{
    <span class="hljs-keyword">var</span> bucketName = <span class="hljs-string">"oss"</span>;
    <span class="hljs-keyword">var</span> objectName = file.FileName;
    <span class="hljs-keyword">var</span> contentType = file.ContentType:
    <span class="hljs-keyword">try</span>
    {
        <span class="hljs-keyword">var</span> beArgs = <span class="hljs-keyword">new</span> BucketExistArgs().WithBucket(bucketName);
        <span class="hljs-keyword">bool</span> found = <span class="hljs-keyword">await</span> minio.BucketExistAsync(beArgs).Configure(<span class="hljs-literal">false</span>);
        <span class="hljs-keyword">if</span>(!found)
        {
            <span class="hljs-keyword">var</span> mbArgs = <span class="hljs-keyword">new</span> MakeBucketArgs().WithBucket(bucketName);
            <span class="hljs-keyword">await</span> minio.MakeBucketAsync(mbArgs).ConfigureAwait(<span class="hljs-literal">false</span>);
        }    
        <span class="hljs-keyword">using</span>(<span class="hljs-keyword">var</span> fileStream = <span class="hljs-keyword">new</span> MemoryStream())
        {
            file.CopyTo(fileStream);
            <span class="hljs-keyword">var</span> fileBytes = fileStream.ToArray();
            <span class="hljs-keyword">var</span> putObjectArgs = <span class="hljs-keyword">new</span> PutObjectArgs()
                            .WithBucket(bucketName)
                            .WithObject(objectName)
                            .WithStreamData(<span class="hljs-keyword">new</span>                     MemoryStream(fileBytes))
                            .WithObjectSize(fileStream.Length)
                        .WithContentType(<span class="hljs-string">"application/octet-stream"</span>);
            <span class="hljs-keyword">await</span> minio.PutObjectAsync(putObjectArgs).ConfigureAwait(<span class="hljs-literal">false</span>);
        }
    }
    <span class="hljs-keyword">catch</span>(Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
</code></pre>
<p>Now, run the MVC application and try to upload the file. It will be uploaded to the bucket in mino.</p>
<p>Thank you! Happy Coding :)</p>
]]></content:encoded></item><item><title><![CDATA[Setting Up a Development Environment With Docker For .NET With Postgres SQL]]></title><description><![CDATA[In this article, we are going to set up a developer-friendly environment for the asp.net MVC application in visual studio code. In addition, we are going to containerize the MVC application with postgres SQL database along with Pgadmin4. When it come...]]></description><link>https://maharjansachin.com.np/setting-up-a-development-environment-with-docker-for-net-with-postgres-sql</link><guid isPermaLink="true">https://maharjansachin.com.np/setting-up-a-development-environment-with-docker-for-net-with-postgres-sql</guid><category><![CDATA[Docker]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[pgAdmin]]></category><category><![CDATA[vscode]]></category><dc:creator><![CDATA[sachin maharjan]]></dc:creator><pubDate>Mon, 30 Jan 2023 08:16:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1675057600165/ff12def6-bedd-4c98-854a-e7c2377f9339.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we are going to set up a developer-friendly environment for the asp.net MVC application in visual studio code. In addition, we are going to containerize the MVC application with postgres SQL database along with Pgadmin4. When it comes to development debugging is a crucial task. we also set up debugging functionality to code in the docker container. So, without wasting time let's get started!</p>
<h3 id="heading-what-will-we-learn-from-this-article">What will we learn from this article?</h3>
<p>This article guide teaches you how to set up containerized .NET application using docker and how to use it in a developer environment with the debugger.</p>
<ul>
<li><p>Create a simple dot net MVC application</p>
</li>
<li><p>Create a new Dockerfile which contains instructions required to build a. Net image.</p>
</li>
<li><p>Set up docker-compose which set up postgres sql database, pgadmin to monitor postgres database.</p>
</li>
<li><p>Set up vs code debugger in the visual studio code editor.</p>
</li>
</ul>
<h3 id="heading-docker">Docker</h3>
<p>Docker is a software platform that enables rapid development, testing, and deployment of applications. Docker encapsulates software into standardized units called containers that have everything (i.e all dependencies) the software needs to run including libraries, system tools, code, runtime, and settings.</p>
<h3 id="heading-container">Container</h3>
<p>A container is a standard unit of software that packages up code and all its dependencies to that application and runs quickly and reliably from one computing environment to another. We can think container as an isolated process in the operating system which has its own networking and file system. A Docker Container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries, and settings.</p>
<h3 id="heading-dotnet">DotNet</h3>
<p>.NET is an open-source developer platform, created by Microsoft, for building many different types of applications. .Net is a free, cross-platform, open-source developer platform for building different types of applications.</p>
<p>With .NET, you can use multiple languages, editors, and libraries to build for web, mobile, desktop, games, IoT, and more. You can write .NET apps in C#, F#, and many other dot net languages.</p>
<h3 id="heading-software-prerequistes">Software Prerequistes</h3>
<p>Before diving into the coding section, we have to make sure the following software is installed. I am using windows 11 for this guide. You can use other operating systems as well.</p>
<ol>
<li><p>Docker Desktop with docker-compose</p>
</li>
<li><p>Visual Studio Code</p>
</li>
<li><p>Dotnet Sdk 7</p>
</li>
<li><p>Any Web Browser</p>
</li>
</ol>
<h3 id="heading-creating-new-net-mvc-application">Creating New .NET MVC Application</h3>
<p>For our sample application, let's create a simple application from a template using .NET CLI. Create a directory in our local machine named sampleapp. Open a cmd and change to that directory. Run the following <code>dotnet new</code> command to create a C# app using the ASP.NET MVC template.</p>
<pre><code class="lang-bash">mkdir sampleapp
<span class="hljs-built_in">cd</span> sampleapp
dotnet new mvc -n sampleapp -o src --no-https
</code></pre>
<p>Above command will create an src file inside sampleapp folder. Furthermore, inside src, we will get asp.net MVC project folders and files. The further structure will look like following</p>
<pre><code class="lang-bash">├── src
├── Controllers
│ └── HomeController.cs
├── Models
│ └── ErrorViewModel.cs
├── Views
│ └── Home
│     └── Index.cshtml
│     └── Privacy.cshtml
├── Program.cs
├── Properties
│ └── launchSettings.json
├── appsettings.Development.json
├── appsettings.json
├── sampleapp.csproj
├── obj
│ ├── sampleapp.csproj.nuget.dgspec.json
│ ├── sampleapp.csproj.nuget.g.props
│ ├── sampleapp.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
└── wwwroot
  ├── css
  ├── favicon.ico
  ├── js
  └── lib
</code></pre>
<p>Now, Let's start our application and make sure it's running properly. In the command prompt navigate to the src folder and use the <code>dotnet run</code> command.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /path/to/sampleapp/src
dotnet run --urls http://localhost:5000
</code></pre>
<p>Ouput similar to the following appears.</p>
<pre><code class="lang-bash">Building...
info: Microsoft.Hosting.Lifetime[0]
    Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
    Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
    Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
    Content root path: C:\Users\username\sampleapp\src
</code></pre>
<p>Now you will see the following page in the browser:</p>
<p><img src="https://docs.docker.com/language/dotnet/images/dotnet-app-verify-build.png" alt class="image--center mx-auto" /></p>
<p>If you get the result as the above image then you will install mvc project correctly and you</p>
<p>are ready to go further.</p>
<h3 id="heading-create-a-dockerfile">Create a Dockerfile</h3>
<p>In <code>sampleapp</code> directory, create a file named <code>Dockerfile</code> And paste the following code.</p>
<pre><code class="lang-plaintext">FROM mcr.microsoft.com/dotnet/sdk:7.0 as debug

#install debugger for NET Core
RUN apt-get update
RUN apt-get install -y unzip
RUN curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l ~/vsdbg

RUN mkdir /src/
WORKDIR /src/

COPY ./src/testapp.csproj /src/sampleapp.csproj
RUN dotnet restore

COPY ./src/ /src/
RUN mkdir /out/
RUN dotnet publish --no-restore --output /out/ --configuration Release
EXPOSE 80
CMD dotnet run --urls "http://0.0.0.0:80"
</code></pre>
<p>The above Dockerfiel is used for building and running a .NET Core application in a Docker Container.</p>
<p>It starts with the base image <code>mcr.microsoft.com/dotnet/sdk:7.0</code> and tags it as <code>debug</code>.</p>
<p>In summary above docker file will do the following tasks step by step one at a time.</p>
<ol>
<li><p>Installs the debugger for .NET Core by updating the package list and installing unzip, then downloading and installing the latest version of vsdbg.</p>
</li>
<li><p>Creates a directory '/src/' as the working directory.</p>
</li>
<li><p>Copies the project file 'sampleapp.csproj' to '/src/' and restores the dependencies.</p>
</li>
<li><p>Copies the source code to '/src/' and runs the publish command to build and output the application to '/out/'.</p>
</li>
<li><p>Exposes port 80 for external access.</p>
</li>
<li><p>Runs the application with the command <code>dotnet run --urls "</code><a target="_blank" href="http://0.0.0.0:80"><code>http://0.0.0.0:80</code></a><code>"</code>.</p>
</li>
</ol>
<h3 id="heading-create-docker-composeyml-file">Create docker-compose.yml File</h3>
<p>Docker Compose is a tool for defining and running multi-container Docker applications. It allows you to define an application’s services, networks, and volumes in a single file, then start and stop the services using a single command.</p>
<p>Open the <code>sampeapp</code> directory in vs code and create a file named <code>docker-compose.yml</code> . Copy and paste the following contents into the file.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">"3.0"</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-attr">db:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">postgres</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"5432"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">postgres:/var/lib/postgresql/data</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">password</span>
      <span class="hljs-attr">POSTGRES_USER:</span> <span class="hljs-string">sachin</span>

  <span class="hljs-attr">pg_admin:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">dpage/pgadmin4</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"5555:80"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">pg_admin:/var/lib/pgadmin</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">PGADMIN_DEFAULT_EMAIL:</span> <span class="hljs-string">sachin.maharjan@dishhome.com.np</span>
      <span class="hljs-attr">PGADMIN_DEFAULT_PASSWORD:</span> <span class="hljs-string">password</span>

  <span class="hljs-attr">web:</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">csharp</span>
    <span class="hljs-attr">build:</span>
      <span class="hljs-attr">context:</span> <span class="hljs-string">.</span>
      <span class="hljs-attr">target:</span> <span class="hljs-string">debug</span>
    <span class="hljs-attr">ports:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">"5000:80"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./src:/src/</span>
    <span class="hljs-attr">depends_on:</span>
     <span class="hljs-bullet">-</span> <span class="hljs-string">db</span>

<span class="hljs-attr">volumes:</span>
  <span class="hljs-attr">postgres:</span>
  <span class="hljs-attr">pg_admin:</span>
</code></pre>
<p>Save and close the docker-compose.yml file. Add the <code>.dockerignore</code> file and paste the following code.</p>
<pre><code class="lang-bash">**/bin/
**/obj/
</code></pre>
<p>The sampleapp directory structure should now look like</p>
<pre><code class="lang-bash">├── samplefile
│ ├── src/
│ ├── Dockerfile
│ ├── .dockerignore
│ ├── docker-compose.yml
</code></pre>
<p>The <code>.dockerignore</code> the file is used in a Docker build context to specify files or directories that should be excluded from the build context. This helps to reduce the size of the build context and improve the build time by excluding files and directories that are not necessary for the build. Any files or directories listed in the .dockerignore file will not be included in the build context that is sent to the Docker daemon for building the image.</p>
<p>The <code>docker-compose.yml</code> the file describes a multi-container application. In our <code>docker-compose.yml</code> file, we have three services <code>db</code>, <code>pgadmin</code> and <code>web</code>.</p>
<ul>
<li><p>'db' is a PostgreSQL database service, which uses the official PostgreSQL image. It will be exposed on port 5432 and the data will be persisted in a Docker volume named 'postgres'. The environment variables 'POSTGRES_PASSWORD' and 'POSTGRES_USER' are set to 'password' and 'sachin' respectively.</p>
</li>
<li><p>'pg_admin' is a web-based database administration tool, using the image 'dpage/pgadmin4'. It will be exposed on port 5555 and the data will be persisted in a Docker volume named 'pg_admin'. The environment variables 'PGADMIN_DEFAULT_EMAIL' and 'PGADMIN_DEFAULT_PASSWORD' are set to '<a target="_blank" href="mailto:sachin.maharjan@dishhome.com.np"><strong>sachin.maharjan@dishhome.com.np</strong></a>' and 'password' respectively.</p>
</li>
<li><p>'web' is a .NET Core web application service. The service is built from the current directory and the build context is set to the 'debug' target. The service will be exposed on port 5000 and the source code will be mounted as a volume in the container at the '/src/' directory. The 'depends_on' key ensures that the 'db' service is started before the 'web' service.</p>
</li>
<li><p>The 'volumes' section at the bottom defines two named volumes: 'postgres' and 'pg_admin'.</p>
</li>
</ul>
<h3 id="heading-database-connection">Database Connection</h3>
<p>Let's add the package to allow the app to talk to a database and update the source files. On your local machine, open a terminal, change the directory to the src directory and run the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /path/to/dotnet-docker/src
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
</code></pre>
<p>In the <code>src</code> directory, create a <code>Models</code> folder. Inside the <code>Models</code> folder create a file named <code>Student.cs</code> and add the following code to <code>Student.cs</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Collections.Generic;
<span class="hljs-keyword">namespace</span> <span class="hljs-title">sampleapp.Models</span>
{
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Student</span>
  {
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> ID { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> LastName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> FirstMidName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> DateTime EnrollmentDate { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
  }
}
</code></pre>
<p>Save and close the <code>Student.cs</code> file.</p>
<p>In the <code>src</code> directory, create a <code>Data</code> folder. Inside the <code>Data</code> folder create a file named <code>SchoolContext.cs</code> and add the following code to <code>SchoolContext.cs</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;
<span class="hljs-keyword">namespace</span> <span class="hljs-title">sampleapp.Data</span>
{
   <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SchoolContext</span> : <span class="hljs-title">DbContext</span>
   {
      <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SchoolContext</span>(<span class="hljs-params">DbContextOptions&lt;SchoolContext&gt; options</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">options</span>)</span> { }
      <span class="hljs-keyword">public</span> DbSet&lt;Models.Student&gt;? Students { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
   }
}
</code></pre>
<p>Save and close the <code>SchoolContext.cs</code> file.</p>
<p>In the <code>Program.cs</code> file located in the <code>src</code> directory, replace the contents with the following code:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.EntityFrameworkCore;
<span class="hljs-keyword">using</span> sampleapp.Data;

<span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);

<span class="hljs-comment">// Add services to the container.</span>
builder.Services.AddControllersWithViews();
builder.Services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;
   options.UseNpgsql(builder.Configuration.GetConnectionString(<span class="hljs-string">"DefaultConnection"</span>)));
<span class="hljs-keyword">var</span> app = builder.Build();

<span class="hljs-comment">// Configure the HTTP request pipeline.</span>
<span class="hljs-keyword">if</span> (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler(<span class="hljs-string">"/Home/Error"</span>);
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
    name: <span class="hljs-string">"default"</span>,
    pattern: <span class="hljs-string">"{controller=Home}/{action=Index}/{id?}"</span>);

<span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> scope = app.Services.CreateScope())
{
    <span class="hljs-keyword">var</span> services = scope.ServiceProvider;

    <span class="hljs-keyword">var</span> context = services.GetRequiredService&lt;ApplicationDbContext&gt;();
    <span class="hljs-keyword">if</span> (context.Database.GetPendingMigrations().Any())
    {
        context.Database.Migrate();
    }
}
app.Run();
</code></pre>
<p>Save and close the <code>Program.cs</code> file.</p>
<p>In the <code>appsettings.json</code> file located in the <code>src</code> directory, replace the contents with the following code:</p>
<pre><code class="lang-bash">{
   <span class="hljs-string">"Logging"</span>: {
       <span class="hljs-string">"LogLevel"</span>: {
           <span class="hljs-string">"Default"</span>: <span class="hljs-string">"Information"</span>,
           <span class="hljs-string">"Microsoft"</span>: <span class="hljs-string">"Warning"</span>,
           <span class="hljs-string">"Microsoft.Hosting.Lifetime"</span>: <span class="hljs-string">"Information"</span>
       }
   },
   <span class="hljs-string">"AllowedHosts"</span>: <span class="hljs-string">"*"</span>,
   <span class="hljs-string">"ConnectionStrings"</span>: {
       <span class="hljs-string">"SchoolContext"</span>: <span class="hljs-string">"Host=db;Database=my_db;Username=sachin;Password=password"</span>
   }
}
</code></pre>
<p>Save and close the <code>appsettings.json</code> file.</p>
<p>In the <code>Index.cshtml</code> file located in the <code>src\Pages</code> directory, replace the contents with the following code:</p>
<pre><code class="lang-bash">
@{
    ViewData[<span class="hljs-string">"Title"</span>] = <span class="hljs-string">"Home page"</span>;
}

&lt;div class=<span class="hljs-string">"text-center"</span>&gt;
    &lt;h1 class=<span class="hljs-string">"display-4"</span>&gt;Welcome&lt;/h1&gt;
    &lt;p&gt;Learn about &lt;a href=<span class="hljs-string">"https://docs.microsoft.com/aspnet/core"</span>&gt;building Web apps with ASP.NET Core&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

&lt;div class=<span class="hljs-string">"row mb-auto"</span>&gt;
    &lt;p&gt;Student Name is @ViewBag.Student&lt;/p&gt;
&lt;/div&gt;
</code></pre>
<p>Save and close the <code>Index.cshtml</code> file.</p>
<p>In the <code>Index.cshtml.cs</code> file located in the <code>src\Pages</code> directory, replace the contents with the following code:</p>
<pre><code class="lang-bash">using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using sampleapp.Models;

namespace testapp.Controllers;

public class HomeController : Controller
{
    private <span class="hljs-built_in">readonly</span> ILogger&lt;HomeController&gt; _logger;
    private <span class="hljs-built_in">readonly</span> SchoolDbContext _db;
    public HomeController(ILogger&lt;HomeController&gt; logger, SchoolDbContext db)
    {
        _logger = logger;
        _db = db;
    }

    public IActionResult <span class="hljs-function"><span class="hljs-title">Index</span></span>()
    {
        var student = _context.Students?.Where(d=&gt;d.ID==1).FirstOrDefault();
            this.StudentName = $<span class="hljs-string">"{s?.FirstMidName} {s?.LastName}"</span>;
       ViewBag.Student = student;
        <span class="hljs-built_in">return</span> View();
    }

    public IActionResult <span class="hljs-function"><span class="hljs-title">Privacy</span></span>()
    {
        <span class="hljs-built_in">return</span> View();
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = <span class="hljs-literal">true</span>)]
    public IActionResult <span class="hljs-function"><span class="hljs-title">Error</span></span>()
    {
        <span class="hljs-built_in">return</span> View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}
</code></pre>
<p>Save and close the <code>Index.cshtml.cs</code> file.</p>
<p>Now, add migration command to create database and students table in a database named my_db.</p>
<pre><code class="lang-bash">dotnet-ef migrations add <span class="hljs-string">"InitalMigration"</span>
</code></pre>
<p>Note: you need to install dotnet-ef utility tool, for this you can install this using</p>
<p><code>donet tools install --global dotnet-ef</code></p>
<p>Now, up the all container using docker-compose up command. cd to sampleapp directory and run the following command.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> path to sampleapp
docker-compose up --build
</code></pre>
<p>If every thing is ok then all three containers web, database and pgadmin will start. Now, go to browser and enter url localhost:5555. you will see the login page of pg admin.</p>
<p><img src="https://www.pgadmin.org/static/docs/pgadmin4-6.18-docs/_images/oauth2_login.png" alt class="image--center mx-auto" /></p>
<p>Now, Login into pgadmin using email and password setup in <code>docker-compose.yml</code> file. After that, you will redirect to the home page.</p>
<p><img src="https://www.pgadmin.org/static/docs/pgadmin4-6.15-docs/_images/welcome.png" alt class="image--center mx-auto" /></p>
<p>Now right-click on the server and click on to register server option. Then a dialog box will open. In that section, you have to provide the hostname as <code>db</code> port name 5432 and username as sachin and password as password. All credentials are already defined in <code>docker-compose.yml the</code> file.</p>
<p>Now, Open the server menu you will see the database name my_db. Now open that my_db menu you will see the schema section. Under the schema section, you will see tables. Now add a row in the table named students.</p>
<p>so, If you open a browser and enter localhost:5000 you will see the home page with the first name and last name that you have inserted in the database.</p>
<h3 id="heading-enabling-debugging-in-vs-code">Enabling Debugging In VS Code</h3>
<p>For enabling debugging in vs code, first, we need the following extensions in vs code</p>
<ol>
<li><p>VS Code Extension for Docker</p>
</li>
<li><p>VS Code Launch configuration</p>
</li>
<li><p>C# extension for VS Code</p>
</li>
</ol>
<p>Click on to debug button on the right of the visual studio code. Then You will have the option to create a launch.json file. Click on it to create a launch.json.</p>
<p>Then it will create .vscode under sampleapp directory. when we open <code>.vscode</code> directory we will see the launch.json file. Open the file and paste the code below:</p>
<pre><code class="lang-bash">{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    <span class="hljs-string">"version"</span>: <span class="hljs-string">"0.2.0"</span>,
    <span class="hljs-string">"configurations"</span>: [
        {
            <span class="hljs-string">"name"</span>: <span class="hljs-string">".NET Core Docker Attach"</span>,
            <span class="hljs-string">"type"</span>: <span class="hljs-string">"coreclr"</span>,
            <span class="hljs-string">"request"</span>: <span class="hljs-string">"attach"</span>,
            <span class="hljs-string">"processId"</span>: <span class="hljs-string">"<span class="hljs-variable">${command:pickRemoteProcess}</span>"</span>,
            <span class="hljs-string">"pipeTransport"</span>: {
                <span class="hljs-string">"pipeProgram"</span>: <span class="hljs-string">"docker"</span>,
                <span class="hljs-string">"pipeArgs"</span>: [ <span class="hljs-string">"exec"</span>, <span class="hljs-string">"-i"</span>, <span class="hljs-string">"csharp"</span> ],
                <span class="hljs-string">"debuggerPath"</span>: <span class="hljs-string">"/root/vsdbg/vsdbg"</span>,
                <span class="hljs-string">"pipeCwd"</span>: <span class="hljs-string">"<span class="hljs-variable">${workspaceRoot}</span>"</span>,
                <span class="hljs-string">"quoteArgs"</span>: <span class="hljs-literal">false</span>
            },
            <span class="hljs-string">"sourceFileMap"</span>: {
                <span class="hljs-string">"/src"</span>: <span class="hljs-string">"<span class="hljs-variable">${workspaceRoot}</span>/src/"</span>
            }
        },

    ]
}
</code></pre>
<p>Now, if you put breakpoints in any c# code and hit the green run button on debug section. Then execution stops at that breakpoint. But you have to choose the correct process during the prompt which pops out while you click the green run button.</p>
<p><img src="https://code.visualstudio.com/assets/docs/editor/debugging/server-ready.gif" alt class="image--center mx-auto" /></p>
<p>The above animation is for node.js, I have kept it just to simulate how it is done.</p>
<p>That is, it! I hope you found this helpful. If you have any questions or are confused about anything, you can reach out to me or you can check out the sample project on <a target="_blank" href="https://github.com/lujamaharjan/DotnetDocker">GitHub</a>.</p>
<p>Thank you!</p>
<p>Happy Coding :)</p>
]]></content:encoded></item></channel></rss>