European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core Hosting :: Advancements With Rate Limiting In .NET Core API

clock August 12, 2022 08:06 by author Peter

This is a series of two articles that will help you to learn about rate limiting and how can it be applied in a microservice or .net core API.

It will cover the following topics:
    What is Rate limiting? (Covered in the last article)
    Why do we use Rate limiting? (Covered in the last article)
    Real-world use-case of Rate limiting (Covered in the last article)
    Hands-on Lab – Create a WebAPI project and execute the API using swagger (Covered in the last article)
    Hands-on Lab – Implement Rate limiting using the AspNetCoreRateLimit Nuget Package (Covered in the last article)
    Difference between Rate Limiting and Throttling
    Hands-on Lab – Implement Rate limiting using a Custom Middleware

Difference between Rate Limiting and Throttling
    Rate-Limiting refers to the broader concept of restricting the request traffic to an API endpoint at any point in time.
    Throttling is a particular process of applying rate-limiting to an API endpoint.
    There are other ways an API endpoint can apply rate-limiting. One such way is the use of Request Queues. This process queues the incoming requests. It then serves them to the API endpoint at a rate that the API can process gracefully.
    However, in Throttling, the API endpoint presents the consumer with a status code to indicate the restriction to send any more requests within the specific time window. The client application can then retry after the time window passes

Hands-on Lab – Implement Rate limiting using a Custom Middleware

Steps to be followed:
    In the existing asp.net core API application created in the last article, let’s use an attribute to decorate the endpoint that we want to rate limit.
    Add an attribute class named LimitRequests. This attribute applies only to methods. The two properties in the attribute indicate the max requests allowed within a specific time window. The attribute approach gives us the flexibility to apply different rate-limiting configurations for different endpoints within the same API.

Let’s apply the LimitRequests decorator to our endpoint and configure it to allow a maximum of two requests for a window of 50 seconds. A third request within 50 seconds would not be allowed.

Now, implement a middleware using a distributed cache to store NumberOfRequestsCompletedSuccessfully and LastSuccessfulResponseTime. Using the values of the above parameter from the distributed cache and matching it with the attribute on API, return the valid response or HTTPResponse with HTTPStatusCode - 429.

Execute the application (Press F5) and execute the API from swagger for the first and second time. Look to the below screenshot:


Execute the API from swagger for the third time, and as you can see the below screenshot, the quota for API calls for that particular API has been exceeded.

This is how we implement rate limiting using Custom Middleware, along with the difference between throttling and rate limiting. In the series of two articles, we have covered both approaches to implementing rate limiting on .NET Core API. I've attached the source for your reference. I hope you see you again in the next article.

Happy learning!

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: How To Upload Images In A Rich Text Editor?

clock August 8, 2022 07:25 by author Peter

In this article, I've used a web API for supporting databases and uploading images in a rich text editor.

What is a rich text editor?
The TinyMCE is a rich text editor that allows users to create user-formatted content within a user-friendly interface. The TinyMCE library is used for implementing a rich text editor in a project.

The TinyMCE rich text editor output is created in HTML. It includes tables, lists, images, text, and other elements, depending on your configuration. Users have complete control over the TinyMCE rich text editor, and we can extend its plugins, customizations, and functionality.
How to implement the rich text editor in a project

Step 1
To download the TinyMCE text editor from the TinyMCE official website.

Extract the TinyMCE folder and copy the TinyMCE folder under the js folder. Then, paste it into the js folder of the www root folder.

 

Step 2
Add the library into the layout file.
<script src="~/js/tinymce/tinymce.min.js" referrerpolicy="original"></script>

Step 3
Create a ViewEditor class from the ViewModels folder. In a class, we make properties.
namespace richtexteditorAPP.ViewModels
{
    public class ViewEditor
    {
        public Guid id { get; set; }
        public string title { get; set; }
        public string message { get; set; }
        public IFormFile editorimage { get; set; }
    }
}


C#

Step 4
Create a HttpHelper class from the logic folder. In this class, we create a PostData function to insert data into the database. In this function, we convert string data into JSON format and stored the response in the response message variable then return the result.
using Newtonsoft.Json;

namespace richtexteditorAPP.Logics
{
    public class HttpHelper
    {
        private readonly HttpClient _httpClient;
        public HttpHelper(HttpClient httpclient)
        {
            this._httpClient = httpclient;
        }
        public bool POSTData(object data, string url)
        {
            using (var content = new StringContent(JsonConvert.SerializeObject(data), System.Text.Encoding.UTF8, "application/json"))
            {
                HttpResponseMessage result = _httpClient.PostAsync(url, content).Result;
                if (result.IsSuccessStatusCode)
                    return true;
                string returnValue = result.Content.ReadAsStringAsync().Result;
                throw new Exception($"Failed to POST data: ({result.StatusCode}): {returnValue}");
            }
        }
    }
}


Step 5
Create a controller from the controller folder and in a controller, we call the Web API to upload an image. Here we create the HttpPost Add message method for calling the Web API Post method.

The TinyMceUpload function helps to post an image into the editor. The upload to the server method helps to store images in the database.
using Microsoft.AspNetCore.Mvc;
using richtexteditorAPP.Logics;
using richtexteditorAPP.Models;
using richtexteditorAPP.ViewModels;
using System.Text.Json;

namespace richtexteditorAPP.Controllers
{
    public class Editor : Controller
    {
        private readonly HttpClient httpClient;
        private readonly HttpHelper httphelper;
        public Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnviroment { get; set; }
        public richtexteditorAPP.Models.Editor message { get; set; }
        public Editor(HttpClient _httpClient, HttpHelper _httphelper, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnviroment)
        {
            this.httpClient = _httpClient;
            this.httphelper = _httphelper;
            this.hostingEnviroment = hostingEnviroment;
        }

        public IActionResult AddMessage()
        {
            return View();
        }
        public IActionResult TinyMceUpload(IFormFile file)
        {
            var location = UploadImageToServer(file);
            return Json(new { location });

        }

        public string UploadImageToServer(IFormFile file)
        {
            var uniqueFileName = "";
            var fullFilePath = "";
            if (file != null)
            {
                var uploadfilepath = Path.Combine(hostingEnviroment.WebRootPath, "Images");
                uniqueFileName = Guid.NewGuid() + Path.GetExtension(file.FileName);
                fullFilePath = Path.Combine(uploadfilepath, uniqueFileName);
                file.CopyTo(new FileStream(fullFilePath, FileMode.Create));
            }
            return "/Images/" + uniqueFileName;
        }

        [HttpPost]
        public IActionResult AddMessage(ViewEditor p)
        {
            if (httphelper.POSTData(p, "https://localhost:7106/api/Editor"))
            {
                return RedirectToAction("Index");

            }
            return View();
        }
        public List<richtexteditorAPP.Models.Editor> Data { get; set; }
         public async Task<IActionResult> Index()
        {
            HttpResponseMessage responseMessage = httpClient.GetAsync("https://localhost:7106/api/Editor").Result;
            if (responseMessage.IsSuccessStatusCode)
            {
                var res = await responseMessage.Content.ReadAsStreamAsync();
                Data = await JsonSerializer.DeserializeAsync<List<richtexteditorAPP.Models.Editor>>(res);
            }
            return View(Data);
        }
    }
}


Step 6
Create a form with one input text and one text area, and add a script section at the end of the form.
<h2 style="margin-left:250px;">Add Message</h2>
<div class="container col-md-8">
<form enctype="multipart/form-data" method="post">
    <div class="mb-3">
    <label class="form-label">Title</label>
    <input type="text" name="title" id="title" class="form-control" >
   </div>
  <div class="mb-3">
    <label class="form-label">Message</label>
    <textarea name="message" id="message" class="form-control"></textarea>
  </div>
  <div class="btn-group" style="margin-top:20px;">
  <button type="submit" class="btn btn-primary">Post</button>
  </div>
</form>
</div>
@section Scripts{
    <script>
tinymce.init({
    selector: 'textarea#message',
    plugins: [
      'advlist', 'autolink', 'link', 'image', 'lists', 'charmap', 'preview', 'anchor', 'pagebreak',
      'searchreplace', 'wordcount', 'visualblocks', 'visualchars', 'code', 'fullscreen', 'insertdatetime',
      'media', 'table', 'emoticons', 'template', 'help'
    ],
    toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | ' +
      'bullist numlist outdent indent | link image | print preview media fullscreen | ' +
      'forecolor backcolor emoticons | help',
    menu: {
      favs: { title: 'My Favorites', items: 'code visualaid | searchreplace | emoticons' }
    },
    menubar: 'favs file edit view insert format tools table help',
    content_css: 'css/content.css',
    images_upload_url: '/Editor/TinyMceUpload'
   });

</script>
}

In the script section, we call the TinyMCE text editor and also add plugins.


Output


The better advantage of a rich text editor is it allows to manipulate the text, images, list, tables, and others. It's easy to change the size of the image.

It's easy to set the alignment of items.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core Hosting :: Filtering In Datagridview In Vb.Net And Also In C#

clock August 3, 2022 10:04 by author Peter

In this article we will learn about how to filter data in datagridview. We can better understand this with an example.

Step 1
Create Windows Form with Textbox and DataGridView.

Step 2
In coding view, code as per the following code. Here, I give both code c# and vb.Net. You can choose as per your requirement(s).

Code as per Vb.Net
Imports System.Data.SqlClient

Public Class Form14
    Dim libconn As SqlConnection
    Dim daMain As SqlDataAdapter
    Dim dtMain As New DataSet
    Dim strQuery As String = ""
    Dim strConnectionString As String
    Dim otable As DataTable = New DataTable()

    Private Sub Form14_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        load_data()
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.AllowUserToDeleteRows = False
    End Sub

    Private Sub load_data()
        Connetion()
        daMain = New SqlDataAdapter("Select * From Employee", libconn)
        dtMain.Clear()
        daMain.Fill(dtMain)
        DataGridView1.DataSource = dtMain.Tables(0)
        libconn.Close()
        DataGridView1.ClearSelection()
        TextBox1.Text = ""
        otable = GetOriginalDataTable()
    End Sub

    Public Function Connetion()
        strConnectionString = "Data Source=UDAY-LAPTOP;Initial Catalog=sqldemo;Integrated Security=true"
        libconn = New SqlConnection
        libconn.ConnectionString = strConnectionString
        If libconn.State <> ConnectionState.Open Then
            Try
                libconn.Open()
            Catch conn_error As SqlException
                MsgBox(conn_error.Message)
                Connetion = False
            End Try
        End If
        Connetion = True
    End Function

    Private Function GetOriginalDataTable() As DataTable
        Dim dtable As DataTable = New DataTable()
        For Each col As DataGridViewColumn In DataGridView1.Columns
            dtable.Columns.Add(col.Name)
        Next
        For Each row As DataGridViewRow In DataGridView1.Rows

            Dim dRow As DataRow = dtable.NewRow()
            Dim flag As Integer = -1
            For Each cell As DataGridViewCell In row.Cells
                dRow(cell.ColumnIndex) = cell.Value
            Next
            dtable.Rows.Add(dRow)
        Next
        Return dtable
    End Function

    Private Function SearchGrid()
        Dim dtable As DataTable = New DataTable()
        If TextBox1.Text.Length > 0 And DataGridView1.RowCount = 0 Then
            DataGridView1.DataSource = otable
        End If
        If TextBox1.Text.Length = 0 Then
            DataGridView1.DataSource = Nothing
            DataGridView1.DataSource = otable
        Else
            For Each col As DataGridViewColumn In DataGridView1.Columns
                dtable.Columns.Add(col.Name)
            Next
            For Each row As DataGridViewRow In DataGridView1.Rows
                Dim dRow As DataRow = dtable.NewRow()
                Dim flag As Integer = -1
                For Each cell As DataGridViewCell In row.Cells
                    dRow(cell.ColumnIndex) = cell.Value
                    Dim str As String = cell.Value.ToString().ToLower()
                    Dim str1 As String = TextBox1.Text.ToLower()
                    If str.Contains(str1.ToString()) = True Then
                        flag = 1
                    End If
                Next
                If flag = 1 Then
                    dtable.Rows.Add(dRow)
                End If
            Next
            DataGridView1.DataSource = Nothing
            DataGridView1.DataSource = dtable
        End If
        SearchGrid = True
    End Function

    Private Function HighlightGrid()
        If TextBox1.Text.Length = 0 Then
            For n As Integer = 0 To (DataGridView1.Rows.Count) - 1
                For m As Integer = 0 To (DataGridView1.Rows(n).Cells.Count) - 1
                    DataGridView1.Rows(n).Cells(m).Style.BackColor = SystemColors.Control
                Next
            Next
        Else
            For n As Integer = 0 To (DataGridView1.Rows.Count) - 1
                For m As Integer = 0 To (DataGridView1.Rows(n).Cells.Count) - 1
                    Dim str As String = DataGridView1.Rows(n).Cells(m).Value.ToString().ToLower()
                    Dim str1 As String = TextBox1.Text.ToLower()
                    If str.Contains(str1.ToString()) = True Then
                        DataGridView1.Rows(n).Cells(m).Style.BackColor = Color.Yellow
                    Else
                        DataGridView1.Rows(n).Cells(m).Style.BackColor = SystemColors.Control
                    End If
                Next
            Next
        End If
        HighlightGrid = True
    End Function

    Private Sub TextBox1_KeyUp(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyUp
        If e.KeyCode = Keys.Back Then
            DataGridView1.DataSource = otable
            SearchGrid()
            HighlightGrid()
            DataGridView1.ClearSelection()
        End If
    End Sub

    Private Sub TextBox1_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBox1.TextChanged
        SearchGrid()
        HighlightGrid()
        DataGridView1.ClearSelection()
    End Sub

End Class


ASP.NET (C#)
Code as per C#
using System.Data.SqlClient;

public class Form14
{
    private SqlConnection libconn;
    private SqlDataAdapter daMain;
    private DataSet dtMain = new DataSet();
    private string strQuery = "";
    private string strConnectionString;
    private DataTable otable = new DataTable();

    private void Form14_Load(System.Object sender, System.EventArgs e)
    {
        load_data();
        DataGridView1.AllowUserToAddRows = false;
        DataGridView1.AllowUserToDeleteRows = false;
    }

    private void load_data()
    {
        Connetion();
        daMain = new SqlDataAdapter("Select * From Employee", libconn);
        dtMain.Clear();
        daMain.Fill(dtMain);
        DataGridView1.DataSource = dtMain.Tables(0);
        libconn.Close();
        DataGridView1.ClearSelection();
        TextBox1.Text = "";
        otable = GetOriginalDataTable();
    }

    public void Connetion()
    {
        strConnectionString = "Data Source=UDAY-LAPTOP;Initial Catalog=sqldemo;Integrated Security=true";
        libconn = new SqlConnection();
        libconn.ConnectionString = strConnectionString;
        if (libconn.State != ConnectionState.Open)
        {
            try
            {
                libconn.Open();
            }
            catch (SqlException conn_error)
            {
                Interaction.MsgBox(conn_error.Message);
                Connetion = false;
            }
        }
        Connetion = true;
    }

    private DataTable GetOriginalDataTable()
    {
        DataTable dtable = new DataTable();
        foreach (DataGridViewColumn col in DataGridView1.Columns)
            dtable.Columns.Add(col.Name);
        foreach (DataGridViewRow row in DataGridView1.Rows)
        {
            DataRow dRow = dtable.NewRow();
            int flag = -1;
            foreach (DataGridViewCell cell in row.Cells)
                dRow(cell.ColumnIndex) = cell.Value;
            dtable.Rows.Add(dRow);
        }
        return dtable;
    }

    private void SearchGrid()
    {
        DataTable dtable = new DataTable();
        if (TextBox1.Text.Length > 0 & DataGridView1.RowCount == 0)
            DataGridView1.DataSource = otable;
        if (TextBox1.Text.Length == 0)
        {
            DataGridView1.DataSource = null;
            DataGridView1.DataSource = otable;
        }
        else
        {
            foreach (DataGridViewColumn col in DataGridView1.Columns)
                dtable.Columns.Add(col.Name);
            foreach (DataGridViewRow row in DataGridView1.Rows)
            {
                DataRow dRow = dtable.NewRow();
                int flag = -1;
                foreach (DataGridViewCell cell in row.Cells)
                {
                    dRow(cell.ColumnIndex) = cell.Value;
                    string str = cell.Value.ToString().ToLower();
                    string str1 = TextBox1.Text.ToLower();
                    if (str.Contains(str1.ToString()) == true)
                        flag = 1;
                }
                if (flag == 1)
                    dtable.Rows.Add(dRow);
            }
            DataGridView1.DataSource = null;
            DataGridView1.DataSource = dtable;
        }
        SearchGrid = true;
    }

    private void HighlightGrid()
    {
        if (TextBox1.Text.Length == 0)
        {
            for (int n = 0; n <= (DataGridView1.Rows.Count) - 1; n++)
            {
                for (int m = 0; m <= (DataGridView1.Rows(n).Cells.Count) - 1; m++)
                    DataGridView1.Rows(n).Cells(m).Style.BackColor = SystemColors.Control;
            }
        }
        else
            for (int n = 0; n <= (DataGridView1.Rows.Count) - 1; n++)
            {
                for (int m = 0; m <= (DataGridView1.Rows(n).Cells.Count) - 1; m++)
                {
                    string str = DataGridView1.Rows(n).Cells(m).Value.ToString().ToLower();
                    string str1 = TextBox1.Text.ToLower();
                    if (str.Contains(str1.ToString()) == true)
                        DataGridView1.Rows(n).Cells(m).Style.BackColor = Color.Yellow;
                    else
                        DataGridView1.Rows(n).Cells(m).Style.BackColor = SystemColors.Control;
                }
            }
        HighlightGrid = true;
    }

    private void TextBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Back)
        {
            DataGridView1.DataSource = otable;
            SearchGrid();
            HighlightGrid();
            DataGridView1.ClearSelection();
        }
    }

    private void TextBox1_TextChanged(System.Object sender, System.EventArgs e)
    {
        SearchGrid();
        HighlightGrid();
        DataGridView1.ClearSelection();
    }
}


Output 1
When you run the application, by default all data will be loaded in datagridview as per the following:


Final Output
In Textbox, when I type IT, the following records will be filtered:

Final Output
In Textbox, when I type IT, the following records will be filtered:

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core Hosting :: Creating Dynamic Checkbox Using C# In ASP.NET Web Forms

clock July 29, 2022 10:25 by author Peter

Creating dynamic elements means that user can generate checkbox on demand based on their input. In this short tutorial, we will learn how to create various functions to generate the checkbox.

We will mainly use 3 types of object: Checkbox list, text box, label, and button. All the related objects will be run at server.
First Scenario: User inputs number of checkbox that needs to be generated

In the ASP.NET web forms structure, we have two main parts: the front end part which house our HTML, CSS, and JS, and also the back end part which run our code in server. There are several web structures such as Single Page Application, MVP, etc. However, we first will use the traditional web forms (1 interface, 1 code behind) to keep our learning simple.

1. Accepting Input
To accept user input, we need a textbox object. Because the textbox will be load together with the page load, then we can directly write our object in the interface (.aspx) or using the drag and drop toolbox (to activate it you can use Ctrl+Alt+X)

Inside the asp:Content insert the textbox object. An object needs ID. We also tell our aspx that this textbox will be runat=”server”. Thus, we can gain control over it from our C# code. We also tell the aspx that our textbox has the AutoPostBack behavior which means that whenever the content is changed, the page will undergo a PostBack or “Reload”.

<p>Enter Number of Checkbox:<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="true"></asp:TextBox><asp:Panel ID="PnlControl" runat="server">

ASP.NET (C#)

or

Searching the textbox object using toolbox (Ctrl+Alt+X)

The interface design after drag and drops

We also need to put a Panel Control as a place to render our generated CheckBoxList.

2. Processing Input: (1) Page_Load and PostBack
After we set up the textbox, now user can input the number. As long as there are any changes to the textbox, our code will request a postback. And nothing happens!

In order to do something after the user input the number, we need to create a function that generates our checkboxlist every time the page is loaded.
As a rule of thumbs, Dynamically generated object needs to be regenerated every postback.
protected void Page_Load(object sender, EventArgs e) {
    if (Page.IsPostBack) {
        RecreateControls(TextBox1.Text);
    }
}

A void can be translated as “a function”, hence the code above is a function that runs every time the page is load due to user action such as postback request.

Inside this pageload function, we are going to check whether the page is postback or not by using the isPostBack method. Page is our object here. The isPostBack method is a boolean method that will return true or false value. If it is true, then we create the execute the function that will recreate our dynamic object, in this case our checkboxlist.

The reason why we need to check whether the page is postback or not is because we only want to generate the dynamic object (checkboxlist) only after the user changes any value in the input textbox. Therefore, when the user loads the page for the first time, our user only can see the default object that we have in the aspx interface (our HTML).

3. Processing Input: (2) Recreate dynamic objects

In order to create or recreate our dynamically generate checkbox, we will utilize checkboxlist as our object. Because we want to generate it dynamically, we cannot do the drag and drop method. Therefore inside the function that we already call in the page load, we need to manually instruct how to generate the checkbox inside our checkboxlist.
RecreateControls(TextBox1.Text);

This function will be able to accept a string input from our textbox by calling the .Text method.

Overview: Recreate checkbox list Object
The first step we need to do is to create and define a new object using CheckBoxList class. We give our new CheckBoxList variable name as genCBL and an ID of genCBL. Both things do not need necessarily to be the same. The variable names are used internally in the backend code, while the ID is the global identifier of our chechboxlist in the ASPX.
CheckBoxList genCBL = new CheckBoxList {ID = "genCBL"};

Same as textbox, every object needs to have its own properties and related behavior. In this case, we set the AutoPostBack behavior to be true.
genCBL.AutoPostBack = true;

Because Checkbox List is a collection of individual checkboxes, thus to produce the checkbox dynamically, we need to DataSource property. DataSource can accept list-type data. So we need to create a function that can supply a sorted list of keys and values.

Flowchart of Generating the Data Source (list) for CheckBoxList

    Convert Numerical String to Int: Convert.ToInt32(int)
    Convert Int to String: .ToString()


We named the function above as addCB and return the value as SortedList<TKey: int, TValue: string>. Now, we instruct our CheckBoxList generator to take this value. The databind method forces our control to read the datasource (More about databinding).
genCBL.DataValueField = "Key";
genCBL.DataTextField = "Value";
genCBL.DataSource = addCB(inputNumCB);
//keep selected item
genCBL.DataBind();

After we attributed all the neccessary properties and behaviour, then we instruct the PanelControl to render it inside.
PnlControl.Controls.Add(genCBL);

4. Result: After the first PostBack

HTML output after running the code

HTML source from the rendered ASPX

Code Overview
protected void Page_Load(object sender, EventArgs e) {
    if (Page.IsPostBack) {
        RecreateControls(TextBox1.Text);
    }
}
private SortedList < int, string > addCB(string inputNumCB) {
    SortedList < int, string > addCB_data = new SortedList < int, string > ();
    for (int index = 0; index < Convert.ToInt32(inputNumCB); index++) addCB_data.Add(index, "CheckBox -" + index.ToString());
    return addCB_data;
}
private void RecreateControls(string inputNumCB) {
    CheckBoxList genCBL = new CheckBoxList {
        ID = "genCBL"
    };
    genCBL.AutoPostBack = true;
    genCBL.DataTextField = "Value";
    genCBL.DataValueField = "Key";
    genCBL.DataSource = addCB(inputNumCB);
    genCBL.DataBind();
    PnlControl.Controls.Add(genCBL);
}


Second Scenario: Shows selected checkbox after user click

In this scenario, we want to know which checkbox is already clicked or selected by the user. Thus, we need a way to check whether each checkbox is selected, then we show the results. We will utilize label object to show the results. We also set the label to runat server, so we can manipulate it from code behind.
<p>Enter Number of Checkbox:
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="true"></asp:TextBox>
<asp:Label ID="Label1" runat="server" Text="Active: "></asp:Label>

We want that each time user does something with our previous CheckBoxList the results will auto-update. We can create new handler to implement this scheme by calling the .SelectedIndexChange method. Inside the Recreate CheckBoxList function instruct our object to recognize new handler, in this case, I name it genCBL_SelectedIndexChange.
genCBL.SelectedIndexChanged += new EventHandler(genCBL_SelectedIndexChanged);

After adding the new handler, we need to declare our handling function or what it needs to do when the CBL change.


Create function to update the Label based on CBL changed (user click)

Flowchart of the SelectedIndexChanged handler


Already selected checkbox will be showed on the label’s text
Third Scenario: Adding default selected/checked checkbox

The last scenario will be involved cases like default preferences from previous data or when you want to make it stays selected despite its changes. Therefore, we need input or a previous state that can tell our function to auto-select the checkbox. To facilitate this, we can extract value from the database or provide another textbox as an input method.
<asp:TextBox ID="TextBox2" runat="server" AutoPostBack="true" Font-Italic="True"></asp:TextBox>

Adding new input for taking default selected textbox
After that, we can insert new instructions in our previous updateCBL function. We want to check whether each checkbox is a member of the supplied default value. If true, then we make the checkbox status to be selected and add the textfield to our label.


If the index is the same as any default value, then make it selected. The problem now is how to check whether the current index checkbox is contained within any default value. Thus, we need a function that returns a boolean value.


A function that takes our index as a parameter and checks whether it “exists” within the default value
This function mainly utilizes two major tools: Parser and Array. First, we extract the string text from our textbox. Then, we split the string by the comma separator. Therefore, we need to make sure that the user also understands what kind of format they should input. After splitting, we try to parse the string number into an int and if it succeeds, we put it in the list. We change the list into an array type so that we can easily use the .Exist method to compare the int from parameter and the int on the default array. We then return it as true or false.

Flowchart for the default checkbox function
After that don’t forget to make this function runs when the textbox change. We can create a new handler to find our CheckBoxList by its ID then do update on it.
<asp:TextBox ID="TextBox2" runat="server" AutoPostBack="true" Font-Italic="True" OnTextChanged="TextBox2_TextChanged"></asp:TextBox>

Updating whenever the checkbox is clicked, or the text box value changes


Final Rendered Result on browser


In this tutorial, we successfully create a dynamic checkbox using three different scenarios. We utilize several C# tools such as array, parser, covert, etc. We also learn how to generate objects and what kind of properties or behavior we can attribute to them. In the future, this simple tutorial can become a starting point for coding web app using C# and also a nice and simple gateway to understanding relating structure and functionality around the C# web forms. Thank you and enjoy learning!

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core Hosting :: ASP.NET Core 6.0 Middleware

clock July 26, 2022 08:00 by author Peter

Middleware is a component that is assembled into an application pipeline to handle requests and responses. Middleware is linked one after the other, so each gets to choose whether to pass the request to the next middleware and work before and after the next component in the pipeline.

Middleware:
    Sits between the requestor and the target.
    Can directly modify the response.
    Can log things.
    Can use the data within the request to generate the response.

Take look at the diagram below:

ASP.NET 6.0 implements a pipeline consisting of a series of middleware classes.

  • Requests filter down the pipeline until they reach a point where the middleware class creates a response.
  • Responses filter back through the middleware in reverse order until they reach the requestor.

Middleware is a great place to do the following:
    Authorization
    Authentication
    Diagnostics
    Error handling and logging

Each middleware consists of a request delegate. This is a specific kind of object in .NET that can pass execution control to the next object. Let us create a simple Web API project. For this tutorial I’m using the tools below:
    Visual Studio Community Edition 2022 (64-bit) – Preview (Version 17.3.0 Preview 4.0)
    .NET 6.0
    Minimal Web API
    Swagger

Please find the program.cs file part of the minimal API:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI();
}
//I have commented out the below codes as we are going to check Use(), Map() and Run()
/* var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateTime.Now.AddDays(index),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast"); */
app.Run();
/*internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

} */


If we run this project, you should get the below output.

Now let's create simple middleware that will return “Hello Readers!” as response. In Program.cs, we add a new middleware using Run() method like below. We normally call it inline middleware.
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.Run(async context => {
        await context.Response.WriteAsync("Hello Readers!");
    });
    app.UseSwagger();
    app.UseSwaggerUI();
}


Run the application. You should get the below output:

While going through each line of code in Program.cs, generally we identify which parts of the code are considered middleware by looking at the methods used to add them to the pipeline. Those methods are Run(), Use() and Map().

Let's look at each method to understand the usage and differences between them.
Run()

This method only receives only context parameter and doesn’t know about the next middleware. These delegates are usually known as terminal delegates because they terminate or end the middleware pipeline.

Let us add another delegate as below and see how it behaves:
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.Run(async context => {
        await context.Response.WriteAsync("Hello Readers!");
    });
    app.Run(async context => {
        await context.Response.WriteAsync("We are learning Middlware!");
    });
    app.UseSwagger();
    app.UseSwaggerUI();
}


Go head and run the application. You should get the below output:

The second delegate didn’t invoke here because the first one terminated the pipeline.
Use()

The whole idea behind middleware is to link one after another. Let us take a look at the Use() method, which helps us to chain the delegates one after the other.

This method will accept two parameters, context and next. Let us create a inline middleware using the Use() method:
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.Use(async (context, next) => {
        await context.Response.WriteAsync($ "Before Request {Environment.NewLine}");
        await next();
        await context.Response.WriteAsync($ "After Request {Environment.NewLine}");
    });
    app.Run(async context => {
        await context.Response.WriteAsync($ "Hello Readers!{Environment.NewLine}");
    });
    app.UseSwagger();
    app.UseSwaggerUI();
}


The output is given below:

This will show us that the middleware has been changed, one after another. Here, the await next() triggered the next middleware, which was implemented using the method Run().

Notes:
    Don’t call next.invoke after the response has been sent to client.
    Writing to the response body after calling next may cause a protocol violation.
    Writing to the response body after calling next may cause the body format

Map()
Map extensions are used for branching the pipeline. Map extensions branch the request pipeline based on matching the given request path. If the request path starts with the given path, the branch is executed.

Let us see two middleware, as below:
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.Map("/BranchOne", MapBranchOne);
app.Map("/BranchTwo", MapBranchTwo);
app.Run();
static void MapBranchOne(IApplicationBuilder app) {
    app.Run(async context => {
        await context.Response.WriteAsync("You are on Branch One!");
    });
}
static void MapBranchTwo(IApplicationBuilder app) {
    app.Run(async context => {
        await context.Response.WriteAsync("You are on Branch Two!");
    });
}


The output should be as below:
http://localhost:1233/branchone

http://localhost:1234/branchtwo


We have covered the basics of middleware. In the upcoming tutorial, I will be covering custom middleware. Thank you for reading my article. Please leave your comments in the comment box below.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



ASP.NET Core Hosting - HostForLIFE :: Testing The Exception Thrown In NUnit C#

clock July 25, 2022 10:11 by author Peter

In this article, we will learn how to test the exception thrown by the test code using NUnit in .Net. While doing Unit testing, we write test cases for every possible positive as well as the negative scenario. In several test cases, there might be a situation or condition which throws an exception. In order to test those scenarios, we have to use Asset.Throws method. Asset.Throws attempts to invoke a code snippet represented as a delegate in order to verify that it throws a particular exception.

For demonstration, I already created a sample application “BankingApp” which is basically a .Net Core Class Library project.

A Test project named “BankingApp.Test” is also added to the Solution. I am using NUnit for writing the Unit Test case. In the Account.cs class, I have a parameterized constructor and two methods in which one is for adding the amount i.e. depositAmount() method, and another for checking the balance amount (i.e. checkBalanceAmount() method). In case the amount to be deposited is either zero or less than that, an exception (ArgumentException) will be thrown.

In AccountTest.cs file, I have written a test case in which the amount to be deposited is “-100” i.e. less than zero.

Now, let’s run the test case from the Test Explorer.

On running the test case, an Argument exception with a message i.e., “Amount to be deposit must be greater than zero” is thrown.

Let’s use the Assert.Throws() method and pass method as a delegate which is throwing the exception. In our case, it is depositAmount(). Assert.Throws require the exact type of exception which can be thrown. It returns the exception as well. With StringAssert.Contains() method, we can verify the expected exception text with the actual exception text.

Now run the test case. You can see that our test case is passed. In this example, we verified that on passing the deposit amount 0 or less than zero, an exception is properly thrown to the user.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core Hosting :: Feature Flags In ASP.NET Core

clock July 19, 2022 08:17 by author Peter

Feature flags allow toggling multiple features of an application without having to redeploy the application. One or more feature flags can be defined declaratively as part of the application’s config file that can control feature availability. Feature flag is part of a broader concept of feature management. Feature management provides additional functionality like filtering feature availability based on user groups, devices etc., caching feature flags and managing their states. In this article, we will focus on implementing feature flags using ASP.NET Core feature management package.

Setup
Consider you have a simple ASP.NET 6 MVC application for creating a todo list. To keep this article focused on the subject, I will omit the steps for creating such application. Typically, the application would be capable of adding new todo items to a list of todos and displaying them on the screen.

To work with ASP.NET Core feature management, add Microsoft.FeatureManagement.AspNetCore nuget package to the application. Add the feature management service to the application inside Program.cs
using Microsoft.FeatureManagement;

namespace FeatureFlagDemo;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        // Add services to the container.
        ...
        builder.Services.AddFeatureManagement();
        ...
        var app = builder.Build();
        ...
    }
}


Adding feature flags to the configuration
We will expose two feature flags – one for enabling edit of the todo item and another for enabling delete of the todo item. Add the feature flags to the appsettings.json file under FeatureManagement section as follows
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "FeatureManagement": {
    "Edit": false,
    "Delete": false
  },
  "AllowedHosts": "*"
}


Note both the features are disabled in the configuration file.

FeatureGate attribute
To enable the feature flags at controller or action level, we can use the FeatureGate attribute as shown below.
[HttpGet]
[FeatureGate("Edit")]
public ActionResult Edit(int id)
{
    ...
}

[HttpPost]
[FeatureGate("Edit")]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, TodoItem todoItem)
{
    ...
}


Applying the attribute for all actions related to the Edit feature will ensure that the actions are available only when the Edit feature flag is enabled.

Add similar code for handling Delete feature.
[HttpGet]
[FeatureGate("Delete")]
public ActionResult Delete(int id)
{
    ...
}

[HttpPost]
[FeatureGate("Delete")]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, TodoItem todoItem)
{
    ...
}


Note: Part of code is omitted for brevity and to remain focused on the topic. In production scenarios, consider appropriate measures for implementing the feature including security, performance etc.
<feature> tag helper

The <feature> tag can be used to conditionally render text on razor views depending upon the state of feature flags. Import the feature management tag helpers inside the _ViewImports.cshtml file.
@using FeatureFlagDemo
@using FeatureFlagDemo.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore


Inside razor view, use the <feature> tag as follows to conditionally render Edit and Delete options based on the state of their respective feature flags.
<feature name="Edit"><a asp-action="Edit" asp-route-id="@item.Id">Edit</a></feature>
<feature name="Delete"><a asp-action="Delete" asp-route-id="@item.Id">Delete</a></feature>


Toggling feature flags and testing
Initially both the feature flags are disabled. Upon running the application, none of the Actions (Edit / Delete) are visible on the razor view.

Enable Edit feature by toggling the Edit feature flag in the appsettings.json file
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "FeatureManagement": {
    "Edit": true,
    "Delete": false
  },
  "AllowedHosts": "*"
}


Refresh the page and you should be able to see Edit feature enabled. Upon clicking edit link you can also confirm that the actions related to edit feature are being executed as per the implementation.

Enable Delete feature by toggling the Delete feature flag in the appsettings.json file
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "FeatureManagement": {
    "Edit": true,
    "Delete": true
  },
  "AllowedHosts": "*"
}


Refresh the page and you should be able to see Delete feature enabled. Upon clicking delete link you can also confirm that the actions related to delete feature are being executed as per the implementation.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: Label Control In ASP.NET

clock July 15, 2022 08:39 by author Peter

In this article, you will learn how to use Label in ASP.NET Framework and how Label works.

What are Label Controls

    The label control is used to display text on a website.
    It is primarily used to generate captions for other controls such as textboxes.
    Labels typically assist the user in entering data into text boxes by providing written instructions.
    Labels are controls on the server-side.
    The Label class can be found in the System.Web.UI.WebControls namespace.

Adding Label Control
    To create a label, we can either write code or use Visual Studio's drag and drop feature.
    This is a server-side control, and asp provides its own tag for label creation.

The following is an example and syntax to add label control.
<asp:Label_ID="LabelNew" runat="'server" Text="Label_Control"></asp:Label>
here Runat='Server' Indicates the accessibility of the control at Serverside

Properties of Label Control
Label Control has its own properties that will be used to improve it. (Syntax for each label control property is given in ASP.NET code)

AccessKey

Accesskey is used to add the keyboard shortcut for the label.
<asp:webcontrol id="id" AccessKey="accessKey" runat="server" />

Tablndex
It determines the webserver's tab control index.
<asp:TextBox ID="txtName" runat="server" TabIndex="0"></asp:TextBox>

BackColor
This property is used to change the look and make it with different colours.
<asp:webcontrol id="id" BackColor="color" runat="server" />

BorderColor
We can use this property to change the colour of the label border.
<asp:webcontrol id="id" BorderColor="color" runat="server" />

BorderWidth
This property will allow us to specify the width of the label border.
<asp:webcontrol id="id" BorderWidth="length" runat="server" />

Font
This property will allow us to specify the width of the label border.
<asp:webcontrol id="id" font-subproperty="value" runat="server" />

Forecolor
It's used to change the colour of the label text.
<asp:webcontrol id="id" ForeColor="color" runat="server" />

Text
This property makes use of text that must be displayed for the label.
<asp:HyperLink Text="string" runat="server" />

ToolTip
It specifies the text that will be displayed when we move the mouse over a label.
<asp:webcontrol id="id" ToolTip="string" runat="server" />

Visible
It will allow us to customise the control's visibility on the web form.
<asp:webcontrol id="id" Visible="True|False" runat="server" />

Height
It allows us to customise the height of the label control.
<asp:Image ID="Image1" runat="server" Height="value" />

Width
It allows us to adjust the width of the label control.
<asp:Image ID="Image1" runat="server"  Width="value" />

BorderStyle
The border of the label control can be designed to meet the needs of the application.
<asp:webcontrol id="id" BorderStyle="style" runat="server" />

CssClass
It gives us the CSS class of the label control.
<asp:webcontrol id="id" CssClass="style" runat="server" />

Events for Label Controls
DataBinding

When the server control binds to a data source, this is referred to as data binding.

Disposed
When an ASP.NET page is requested, a server control is released from memory, which is the final stage of the server control lifecycle.

Init
Occurs during the initialization of the server control, which is the first step in its lifecycle.

Load
When the server control is loaded into the Page object, this event occurs.

PreRender
This occurs after the Control object has been loaded but before rendering.

Unload
This happens when the server control is loaded from memory.

Methods for Label Control
DataBind()
Binds a data source to the server control that was invoked and all of its child controls.

Dispose()
Allows a server control to perform final cleanup before releasing it from memory.

Equals(Object)
Checks whether the specified object is the same as the current object.

Focus()
Sets a control's input focus.

OnLoad(EventArgs)
The Load event is raised.

ToString()
This method returns a string that represents the current object.

Conclusion
Here, we have learned how label works in ASP.NET Framework and how label controls are useful for us to use.

If you have any queries/suggestions on the article, please leave your questions and thoughts in the comment section below. Follow C# Corner to learn more new and amazing things about ASP.NET or to explore more technologies.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: Complete Signup-Login System Using Dependency

clock July 12, 2022 08:50 by author Peter

There are various methods available to create a login system but here I'm introducing a way to design complete signup and login system using dependencies in asp.net core with SQL database.

What is a dependency?
The term dependency means to depend on anyone else which means if an object is dependent on other objects that is called a dependency. Dependency is a relationship between a component or class that can be thought of as a uses relationship generally the parameterized constructor that provides an object for a needed class. If you have more than one class that class is dependent on each other that is dependency. The dependency is injected into a parameterized constructor.

Step 1
Create a database from MSSQL.
create database dependencylogin
use dependencylogin;
create table users(id int primary key, Name varchar(50), Email varchar(50), Password varchar(50));
select * from users


Step 2
Create a table from the database and id is the primary key as well as identity with autoincrement.

Step 3
Open visual studio 2022 and click create a new project.


Step 4
Select ASP.Net core web App project and click on the Next button.


Step 5
Write the name of the project and click on the Next button.

Step 6
Click on the Create button for creating a project.

Step 7
Now my project is ready for use.

Step 8
Here create a new folder on solution explorer. Right-click on the project name in solution explorer and select Add option then select the new folder option then write the name of the folder.


Write the folder name as Models.

Step 9
In Models, folder right-click to choose to Add option and move to the class option, create a class with the class name as a connection.


 

Step 10
To make a property connection string name then create a constructor and pass the connection string.
namespace signuploginproject.Models
{
    public class connection
    {
        public string ConnectionString { get; set; }
        public connection()
        {
            this.ConnectionString = @"Data Source=LAPTOP-2L6RE54T;Initial Catalog=dependencylogin;Integrated Security=True";

        }
    }
}


Step 11
To install the System.Data.SqlClient package from NuGet Package Manager.


Step 12
Similar to creating another class on the Models folder the class name is DAL. Make a connection class object and pass  under the constructor.
using System.Data.SqlClient;
namespace signuploginproject.Models
{
    public class DAL
    {
        connection conn;
        public DAL(connection conn)
        {
            this.conn = conn;

        }
        public string GetValue(string query)
        {
            SqlConnection sqlconnection = new SqlConnection(conn.ConnectionString);
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = sqlconnection;
            cmd.CommandText = query;
            sqlconnection.Open();
            var res = cmd.ExecuteScalar();
            sqlconnection.Close();
            return res.ToString();
        }
        public void SetValue(string query)
        {
            SqlConnection sqlconnection = new SqlConnection(conn.ConnectionString);
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = sqlconnection;
            cmd.CommandText = query;
            sqlconnection.Open();
            cmd.ExecuteNonQuery();
            sqlconnection.Close();

        }
    }
}


Step 13
Similarly create one more class on the Models folder. The class name is Logics. Here create a DAL class object and pass a Logics class constructor. A Logic class makes two different functions for login and signup.
namespace signuploginproject.Models
{
    public class Logics
    {
        DAL DL;
        public Logics(DAL dl)
        {
            DL = dl;
        }
        public bool Login(string email, string password)
        {
            string query = $"select password from users where email='{email}'";
            var res = DL.GetValue(query);
            return res == password;
        }
        public string submitdata(string name, string email, string password)
        {
            string query = $"insert into users (name,email,password) values ('{name}','{email}','{password}')";
            DL.SetValue(query);
            return "Data submitted";

        }
    }
}

Step 14
Design an Index page for the Login page.
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}
<div class="container" style="width:30%">
  <center>
    <h2>Login</h2>
  </center>
  <form method="post">
    <div class="mb-3">
      <label class="form-label">Email</label>
      <input type="email" name="email" class="form-control">
    </div>
    <div class="mb-3">
      <label class="form-label">Password</label>
      <input type="password" name="password" class="form-control">
    </div>
    <div class="btn-group" style="margin-top:15px;">
      <button type="submit" class="btn btn-success">Submit</button>
    </div>
  </form>
  <center>
    <p>if you don't have an account to click <a href="/Signup"> Signup</a>
    </p>
  </center>
</div>


Login page


Step 15
Write a code on the Index model page.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using signuploginproject.Models;
namespace signuploginproject.Pages {
    public class IndexModel: PageModel {
        private readonly ILogger < IndexModel > _logger;
        public IndexModel(ILogger < IndexModel > logger, Logics logic) {
            _logger = logger;
            this.logi = logic;
        }
        public void OnGet() {}
        Logics logi;
        public IActionResult OnPost(string email, string password) {
            bool res = logi.Login(email, password);
            if (res == true) {
                return Redirect("/dashboard");
            } else {
                return Redirect("/error");
            }
        }
    }
}

Step 16
Create a new razor page for signup and design a signup form.
@page
@model signuploginproject.Pages.signupModel
@{
}
<div class="container" style="width:30%">
  <center>
    <h2>Signup</h2>
  </center>
  <form method="post">
    <div class="mb-3">
      <label class="form-label">Name</label>
      <input type="text" name="name" class="form-control">
    </div>
    <div class="mb-3">
      <label class="form-label">Email</label>
      <input type="email" name="email" class="form-control">
    </div>
    <div class="mb-3">
      <label class="form-label">Password</label>
      <input type="password" name="password" class="form-control">
    </div>
    <div class="btn-group" style="margin-top:15px;">
      <button type="submit" class="btn btn-success">Submit</button>
    </div>
  </form>
  <center>
    <p>Have an account to click <a href="/Index"> Login</a>
    </p>
  </center>
</div>


Signup Page


Step 17
Write code on the signup model page.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using signuploginproject.Models;
namespace signuploginproject.Pages {
    public class signupModel: PageModel {
        public signupModel(Logics logic) {
            this.logi = logic;
        }
        public void OnGet() {}
        Logics logi;
        public IActionResult OnPost(string name, string email, string password) {
            var rees = logi.submitdata(name, email, password);
            return Redirect("/index");
        }
    }
}

Step 18
Create a new razor page for the dashboard page and write the code.
@page
@model signuploginproject.Pages.dashboardModel
@{
}
<h1>Dashboard</h1>


Dashboard Page


Step 19
Add the services to the program.cs file for providing a class object when needed. To click on the program.cs file and write the code on container services.


To build and execute the project.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core Hosting :: Custome JWT Token And ASP.NET Core Web API

clock July 11, 2022 08:34 by author Peter

In this article, I am explaining how to implement custom JWT token authentication in ASP.NET Core 3.1 API. For this, I have created the demo application which has two controllers “AthenticateController” and “UserController”.

AthenticateController has one endpoint “AuthenticateUser”, which will authenticate the user based on the user id and password and if user is valid then it will generate the JWT Token.

UserController has two endpoints “GetUsers” and “GetUserById”.

GetUsers
I have implemented Authorization filter to secure the endpoint and this endpoint accepts HTTP GET requests and returns a list of all the users in the application if the HTTP Authorization header contains a valid JWT token. If there is no auth token or the token is invalid, then a 401 Unauthorized response is returned.

Similarly, GetUserById returns user details by id if the HTTP Authorization header contains a valid JWT token.

Project Architecture

Below is the project Architecture,


Follow below steps for project set up and generate JWT token:

Step 1
Create the ASP.NET Core 3.1 Web API Application. I am giving application name as “JWTTokenPOC”

Step 2
Install “Microsoft.AspNetCore.Authentication.JwtBearer” using NuGet Package manager. I have installed 3.1.26 version.

Step 3
Create new folder “Entities” inside the solution and create an entity class “User”
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json.Serialization;
namespace JWTTokenPOC.Entities {
    public class User {
        public int Id {
            get;
            set;
        }
        public string FirstName {
            get;
            set;
        }
        public string LastName {
            get;
            set;
        }
        public string Username {
            get;
            set;
        }
        [JsonIgnore]
        public string Password {
            get;
            set;
        }
    }
}


Step 4
Create new folder Models inside the solution and create two models AuthenticateRequest and AuthenticateResponse.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace JWTTokenPOC.Models {
    public class AuthenticateRequest {
        [Required]
        public string UserName {
            get;
            set;
        }
        [Required]
        public string Password {
            get;
            set;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JWTTokenPOC.Entities;
namespace JWTTokenPOC.Models {
    public class AuthenticateResponse {
        public int Id {
            get;
            set;
        }
        public string FirstName {
            get;
            set;
        }
        public string LastName {
            get;
            set;
        }
        public string Username {
            get;
            set;
        }
        public string Token {
            get;
            set;
        }
        public AuthenticateResponse(User user, string token) {
            Id = user.Id;
            FirstName = user.FirstName;
            LastName = user.LastName;
            Username = user.Username;
            Token = token;
        }
    }
}


Step 5
Create new folder “Helper” inside the solution and create two helper classes “AppSettings” and “AuthorizeAttribute” in that folder.
namespace JWTTokenPOC.Helper {
    public class AppSettings {
        public string Key {
            get;
            set;
        }
        public string Issuer {
            get;
            set;
        }
    }
}
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using JWTTokenPOC.Entities;
namespace JWTTokenPOC.Helper {
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthorizeAttribute: Attribute, IAuthorizationFilter {
        public void OnAuthorization(AuthorizationFilterContext context) {
            var user = context.HttpContext.Items["User"];
            if (user == null) {
                // user not logged in
                context.Result = new JsonResult(new {
                    message = "Unauthorized"
                }) {
                    StatusCode = StatusCodes.Status401Unauthorized
                };
            }
        }
    }
}


Step 6
Add below appsetting in appsettings.json file.
"AppSettings": {
    "Key": "986ghgrgtru989ASdsaerew13434545435",
    "Issuer": "atul1234"
}

Step 7
Create new folder “Service” inside the solution and create two service classes “AuthenticationService” and “UserService” in that folder.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JWTTokenPOC.Entities;
namespace JWTTokenPOC.Service {
    public interface IUserService {
        User GetById(int id);
        IEnumerable < User > GetAll();
    }
    public class UserService: IUserService {
        // List of user
        private List < User > _users = new List < User > {
            new User {
                Id = 1, FirstName = "mytest", LastName = "User", Username = "mytestuser", Password = "test123"
            },
            new User {
                Id = 2, FirstName = "mytest2", LastName = "User2", Username = "test", Password = "test"
            }
        };
        public IEnumerable < User > GetAll() {
            return _users;
        }
        public User GetById(int id) {
            return _users.FirstOrDefault(x => x.Id == id);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.Extensions.Options;
using System.Text;
using JWTTokenPOC.Entities;
using JWTTokenPOC.Helper;
using JWTTokenPOC.Models;
namespace JWTTokenPOC.Service {
    public interface IAuthenticationService {
        AuthenticateResponse Authenticate(AuthenticateRequest model);
    }
    public class AuthenticationService: IAuthenticationService {
        // here I have  hardcoded user for simplicity
        private List < User > _users = new List < User > {
            new User {
                Id = 1, FirstName = "mytest", LastName = "User", Username = "mytestuser", Password = "test123"
            }
        };
        private readonly AppSettings _appSettings;
        public AuthenticationService(IOptions < AppSettings > appSettings) {
            _appSettings = appSettings.Value;
        }
        public AuthenticateResponse Authenticate(AuthenticateRequest model) {
            var user = _users.SingleOrDefault(x => x.Username == model.UserName && x.Password == model.Password);
            // return null if user not found
            if (user == null) return null;
            // authentication successful so generate jwt token
            var token = generateJwtToken(user);
            // Returns User details and Jwt token in HttpResponse which will be user to authenticate the user.
            return new AuthenticateResponse(user, token);
        }
        //Generate Jwt Token
        private string generateJwtToken(User user) {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Key));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            // Here you  can fill claim information from database for the users as well
            var claims = new [] {
                new Claim("id", user.Id.ToString()),
                    new Claim(JwtRegisteredClaimNames.Sub, "atul"),
                    new Claim(JwtRegisteredClaimNames.Email, ""),
                    new Claim("Role", "Admin"),
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            };
            var token = new JwtSecurityToken(_appSettings.Issuer, _appSettings.Issuer, claims, expires: DateTime.Now.AddHours(24), signingCredentials: credentials);
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
}


Step 8
Now inside Helper folder create a JwtMiddleware class. This class will be used to validate the token and it will be registered as middleware.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using JWTTokenPOC.Service;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
namespace JWTTokenPOC.Helper {
    public class JwtMiddleware {
        private readonly RequestDelegate _next;
        private readonly AppSettings _appSettings;
        public JwtMiddleware(RequestDelegate next, IOptions < AppSettings > appSettings) {
            _next = next;
            _appSettings = appSettings.Value;
        }
        public async Task Invoke(HttpContext context, IUserService userService) {
            var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
            if (token != null)
                //Validate the token
                attachUserToContext(context, userService, token);
            await _next(context);
        }
        private void attachUserToContext(HttpContext context, IUserService userService, string token) {
            try {
                var tokenHandler = new JwtSecurityTokenHandler();
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Key));
                tokenHandler.ValidateToken(token, new TokenValidationParameters {
                    ValidateIssuerSigningKey = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        IssuerSigningKey = key,
                        ValidIssuer = _appSettings.Issuer,
                        ValidAudience = _appSettings.Issuer,
                        // set clockskew to zero so tokens expire exactly at token expiration time.
                        ClockSkew = TimeSpan.Zero
                }, out SecurityToken validatedToken);
                var jwtToken = (JwtSecurityToken) validatedToken;
                var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);
                // attach user to context on successful jwt validation
                context.Items["User"] = userService.GetById(userId);
            } catch (Exception) {
                // do nothing if jwt validation fails
                // user is not attached to context so request won't have access to secure routes
            }
        }
    }
}

Step 9
Now open the statrtup.cs file. In the ConfigureServices method, add CORS policy and add the services as below.
public void ConfigureServices(IServiceCollection services) {
    services.AddCors();
    services.AddControllers();
    // configure to get Appsetting section from appsetting.json
    services.Configure < AppSettings > (Configuration.GetSection("AppSettings"));
    services.AddScoped < IUserService, UserService > ();
    services.AddScoped < IAuthenticationService, AuthenticationService > ();
}

Step 10
In the Configure method, set CORS policy and register the JWT middleware as below.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    app.UseRouting();
    // set global cors policy
    app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    // Custom jwt auth middleware to authenticate the token
    app.UseMiddleware < JwtMiddleware > ();
    app.UseEndpoints(endpoints => {
        endpoints.MapControllers();
    });
}


Step 11
Now build and run the application.

Step 12
Open Postman tool and generate the JWT token as below:

    Click on the New icon as shown in the below image and create a New Http Request. I have given Http Request name as “AuthToken”.
    Change the http request method to "GET" with the dropdown selector on the left of the URL input field.
    In the URL field enter the address to the route of your local API http://localhost:60119/Authenticate/authenticate.
    Select the "Body" tab below the URL field, change the body type radio button to "raw", and change the format dropdown selector to "JSON (application/json)".
    Enter a JSON object containing the test username and password in the "Body" text
    {
        "username": "mytestuser",
        "password": "test123"
    }


Click the "Send" button, you should receive a "200 OK" response with the user details including a JWT token in the response body, make a copy of the token value because we'll be using it in the next step to make an authenticated request.


 

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in