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 :: How To Post Data In ASP.NET Using AJAX Without JSON Form Serializer?

clock February 7, 2022 06:56 by author Peter

This article demonstrates how to send form data from the ASP.net web application using the Ajax post method without the form serialization.

We have already created the project in the previous part so we will use the same project, same view Model, and same form layout; however only send the data to the controller without the form serialization. So if you are new to this article you can refer to the previous article for detail and can follow up to step 6 to create the project.

This article is an extension of the previous part, hence here we will use the previous solution and start directly by adding the Action Method in the Home controller.

Step 1 – Add Action Method in Home Controller
Add Action Method named as CreateStudent1 in Home Controller which we will use to create a view for Student Form submission without form serialization.

Below is the code for the CreateStudent1 Action Method.
public IActionResult CreateStudent1() {
    return View();
}

Step 2 – Add View
Right-click on the CreateStudent1 IActionResult method and add View for it as depicted below.



Select the Razor page and click on add.



CreateStudent1.cshtml code.
<h4>Add Student Deatils using Ajax Post without Form Serialization</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form id="studenteForm" novalidate class="needs-validation">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" id="name" required />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Email" class="control-label"></label>
                <input asp-for="Email" type="email" class="form-control" id="email" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Phone" class="control-label"></label>
                <input asp-for="Phone" class="form-control" id="phone" />
                <span asp-validation-for="Phone" class="text-danger"></span>
            </div>
            <div class="form-group">
                <button type="button" class="btn btn-primary" onclick="submitStudent()">Add </button>
            </div>
        </form>
    </div>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Then, we will use the below JavaScript on the form submission button click event using Ajax in CreateStudent.cshtml page. Here we will not use a form serializer. In the previous part, we have used a form serializer.
<script type="text/javascript">
    function submitStudent() {
//below we are binding the input data (json format) in a variable inorder to post it.
        var data = {
            Name: $("#name").val(),
            Email: $("#email").val(),
            Phone: $("#phone").val()
        }
        console.log(data);
        $.ajax({
            type: 'POST',
            url: '/Home/AddStudent',
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(data),
            success: function (result) {
                alert('Successfully received Data ');
                console.log(result);
            },
            error: function () {
                alert('Failed to receive the Data');
                console.log('Failed ');
            }
        })
    }
</script>

You can find complete CreateStudent.cshtml code below:
@model Sample.ASPDotNETCore.Models.StudentModel

@{
    ViewData["Title"] = "CreateStudent1";
}

<script type="text/javascript">
    function submitStudent() {
        var data = {
            Name: $("#name").val(),
            Email: $("#email").val(),
            Phone: $("#phone").val()
        }
        console.log(data);
        $.ajax({
            type: 'POST',
            url: '/Home/AddStudent',
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(data),
            success: function (result) {
                alert('Successfully received Data ');
                console.log(result);
            },
            error: function () {
                alert('Failed to receive the Data');
                console.log('Failed ');
            }
        })
    }
</script>

<h4>Add Student Deatils using Ajax Post without Form Serialization</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form id="studenteForm" novalidate class="needs-validation">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" id="name" required />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Email" class="control-label"></label>
                <input asp-for="Email" type="email" class="form-control" id="email" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Phone" class="control-label"></label>
                <input asp-for="Phone" class="form-control" id="phone" />
                <span asp-validation-for="Phone" class="text-danger"></span>
            </div>
            <div class="form-group">
                <button type="button" class="btn btn-primary" onclick="submitStudent()">Add </button>
            </div>
        </form>
    </div>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Step 3 - Add post method in Home Controller for Submit button click Event
Then we will write the Post method in HomeController for the Form Submit event. Below is the code of the HTTP post method in HomeController with Model validation.

[HttpPost]
public async Task < IActionResult > AddStudent([FromBody] StudentModel student) {
    if (!ModelState.IsValid) return BadRequest("Enter required fields");
    //Insert code;
    return this.Ok($ "Form Data received!");
}

Now, it’s time to build and run the project. Fill in the Student Form data and test it.

Below is the home page design:


Design of created Student page for data submission.

When the user clicks on Submit button, data will be sent to the controller like below.


 

Hence, we have submitted the form data to the controller from the Student Details form.

To recapitulate, in this article we have learned to submit the data using Ajax in the ASP.NET Core application without JSON form serializer. This is how we can send the form data using these different methods that we have learned in this article series.

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 :: Guards In .NET

clock February 4, 2022 06:05 by author Peter

What are Guards?
Guard, is a check of integrity preconditions used to avoid errors during execution. The main purpose and use of this is to avoid unnecessary nested branching conditions and give meaningful errors and hence to simplify the code.

In simple language we can say that the code that validates your method's input is called a Guard clause. It makes your code more understandable and it protects you from bugs and unexpected behaviors.

The if block act as a guard clause by protecting the GetStudent method against any null _student arguments. But the main drawback is even though we have null check over here but to reuse this across the code we need to have multiple null checks in order to escape the crash or unexpected behavior.
public Students GetStudents(StudentModel _students) {
    if (_strudents != null) {
        // Write the code.
    } else {
        Console.WriteLine("Student model do not contain any data");
    }
}


How to handle guard clauses exceptions?
"Guard clauses exceptions should never be caught."

This means that most of the time, we should let the caller hit those exceptions as most of the time, guard clauses will guard against scenarios that should never happen like null arguments. We all must have encountered the time when the bug is caused because of the null reference exception. So should we catch a bug and take the chance of never discover it? The answer is No! Instead, we should let the application fail immediately so that we can discover the bug before deploying it to production during the development process.

But what if we have preconditions that don't rely on bugs? What if we have preconditions that could occur sometimes like business logic preconditions? The solution is to expose your guard clauses!

How to use Guard clause?
We can write our own defensive code to use the guards or one library which is simple to understand and solves this problem is Dawn.Guard library.

The below example is one step solution of getting rid of nested if conditions. So let's say if the condition is not fulfilled the code will throw exception so that the developer can get to know the error and can fix it. This library is not limited to null check. There are guards like Equality guards, Boolean guards, Comparison guards, etc. which makes our task easy when it comes to validation conditions.
public Students GetStudentsData(StudentsModel _students) {
    _students = Guard.Argument(_students, nameof(_students)).NotNull().Value;
    //This will let the user know if the _student is null before navigating to next step.
}


Let's take an example and explore more. Suppose we want to check if the Student's name is not null and length should not exceed more than 25 characters.

Code without using Dawn.Guards Library
public Student(string studentName) {
    if (studentName == null) throw new ArgumentNullException(nameof(studentName), "studentName cannot be null.");
    if (studentName.Length > 25) throw new ArgumentException("studentName cannot exceed more than 25 characters.", nameof(studentName));
}


That if expression is a Guard Clause. However, we can do better than that, since repeating this code over and over in all of our methods is a bad practice.

Code using Guards(Dawn.Guards library)
Guard needs to know the argument's value to test it against preconditions and its name to include in a potential exception. There are three ways to initialize a guarded argument,
// First, by specifying the argument value and name separately.
Guard.Argument(arg, nameof(arg));
// Second, omitting the optional argument name.
Guard.Argument(arg);
// Third, creating a MemberExpression via a lambda expression.
Guard.Argument(() => arg);

  • The first sample initializes a guarded argument by specifying both the argument's value and name.
  • The second sample does not specify the argument name. This is allowed but not recommended since the argument name proves a valuable piece of information when you try to identify the cause of an error from logs or crash dumps.
  • The third sample initializes a MemberExpression that provides both the argument's value and name. Although compiling an expression tree is an expensive operation, it is a convenient alternative that can be used in applications that are not performance-critical.


With Guard, if you want to guard an argument against null or max length, you just write NotNull and MaxLength and that's it.
public Student(string StudentName) {
    Guard.Argument(StudentName, nameof(StudentName)).NotNull().MaxLength(25);
}


If the argument is passed null, you'll get an ArgumentNullException thrown with the correct parameter name and a clear error message out of the box. Similarly, it will throw an exception if the criteria for max length is not met. By pulling out all of the validation checks from throughout the method we can remove a number of nested conditionals. This definitely improves the readability of the code and makes the code easier to maintain in the future.

The above example illustrates the use of the Dawn.Guard library. We can extend the guard class to handle our own custom exceptions as well.

Exception Messages
Guard creates a meaningful exception message that contains the argument name and a description specific to the validation when a precondition can't be satisfied. Additionally, every validation in Guard accepts an optional parameter letting the user specify a custom error message.
// Throws an ArgumentException if the arg is not null.
Guard.Argument(() => arg).Null(a => "The argument must be null but it is: " + a);
// Throws an ArgumentNullException if the arg is null.
Guard.Argument(() => arg).NotNull("The argument cannot be null.");


In this article, we have seen how guards clause can help us to discover the bugs before deploying in production and to make our code more readable. We have also learned about Dawn.Guard library and how to use it.

That's all from my side. Happy coding!

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 Use Dependency Injection In .NET Core?

clock January 28, 2022 05:41 by author Peter

Have you ever had to alter a lot of code due to a new straightforward requirement? Have you ever had a difficult time attempting to refactor an application? If you replied yes to any of the above questions, perhaps your codebase mourns from dependency. It's a specific challenge of the code of an application when its components are too coupled. In other words, when a component depends on another one in a too-tight way. The major effect of component dependency is the maintenance hardship of the code, which, of course, signifies a more heightened cost.

What is Dependency Injection?
In software engineering, there is a term design pattern that could facilitate solving the problem by reusing the solution that is already found, In which Dependency Injection(DI) is one of the good design patterns in which a technique, “an object achieves other objects that it depends on, called dependencies”. The “injection” does mean the passing of a dependency “a service” into the client that uses it. The service is made part of the client's state. It actually helps us to create a loosely coupled application.

DI is one of the most common practices that assist you to create better maintainable code. The main advantage is the application which is going to be created is loosely coupled and has provided superb maintainability, reusability, and testability as well. It is loosely coupled due to dependency required by the class being injected from the external world rather than made themselves directly win in code.

.Net Core also provides you facility with ample support to DI, but it may not always be obvious how to use it. In this article, I want to explain various DI concepts and introduce you to support provided by .Net Core.

Use DI in .Net Core
.NET Core provided a built-in IoC Container that facilitates DI management. The IoC Container is responsible for helping automatic DI. It includes:

  • Registration: The IoC Container ought to know which type of object to make for a specific dependency so, it delivers a way to map a type to a class so that it can make the correct dependency instance.
  • Resolution: The IoC Container helps to resolve a dependency by making an object and injecting it into the requesting class. We do not have to instantiate objects manually to handle dependencies.
  • Disposition: The IoC Container manages the lifetime of the dependencies.

The IoC Container implements the 'IServiceProvider' interface. If you want to create your own IoC Container, you must implement this interface. In .NET Core, the dependencies managed by the container are called services. We have 2 types of services:

  • Framework services: are part of the .NET Core framework
  • e.g IApplicationBuilder, IConfiguration, ILoggerFactory, etc.
  • Application services: we create in our application while IoC doesn't know them, we need to register them explicitly.


Framework Services (Example)

The Startup class in an ASP.NET application uses Dependency Injection much:

 

 

The above example shows that the Startup() constructor needs a configuration parameter implementing the IConfiguration type. While IConfiguration is one of the framework service types, IoC Container knows how to make an instance of it and inject it into the Startup class using the Constructor Injection technique. The same is used in the Configure() method. Here the thing which we have to Keep in mind is that only the below mention framework service types can be injected in the Startup() constructor and the Configure() method of a standard ASP.NET application:

    IWebHostEnvironment
    IHostEnvironment
    IConfiguration

 These are certain cases for framework services because we don't need to register them.
Register Framework Services

ConfigureServices() method of the Startup class is used for registering of services, It has an IServiceCollection parameter illustrating the list of services our application depends on. The collection portrayed by this parameter allows us to register a service in the IoC Container. Following example illustrate it:

In the above illustration, we are registering a dependency for handling authentication for our application. In this particular case, are using the extension method AddAuthentication(). The framework provides extension methods to register and configure dependencies for the common services.

Application Services (Example)
For explaining this we have to create some practical scenario, we want to fetch all the students from the database and display them in the UI layer. So for this, we have to create a service (API) that will be called by the UI layer. Then, in API, we require to create one 'GET' method that will call the repository, and the repository will get a list from the database. For the purpose to call this repository, we have to create an instance of the repo in API's GET method, which means, it is mandatory to create an instance of repository for API.

So the dependency of API is the instance of the repository. So, let’s get practical and see code how we can inject this dependency into our API.

The Student Model class has 2 properties.

public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }
}

The Student Repository Interface.

public interface IStudentRepository
{
    List<Student> GetStudents();
}

The implementation class of above interface having dummy data.

public class StudentRepository : IStudentRepository
{
    public List<Student> GetStudents()
    {
        List<Student> students = new List<Student>();

        Student student = new Student() { StudentId = 1, Name = "Student1" };
        students.Add(student);

        student = new Student() { StudentId = 2, Name = "Student2" };
        students.Add(student);

        return students;
    }
}

Then we have to create a Controller(API) for calling this repo, and inject this interface into this.

public class StudentController : Microsoft.AspNetCore.Mvc.Controller
{
    private IStudentRepository studentRepository { get; set; }
    public StudentController(IStudentRepository _studentRepository)
    {
        studentRepository = _studentRepository;
    }

    [HttpGet]
    public async Task<IActionResult> Get()
    {
        List<Student> categories = studentRepository.GetStudents();
        return Ok(categories);
    }
}

In the last, we have to register it in Startup class. Also mention which type of instance want to inject - (the lifetime) of our instance.
public void ConfigureServices(IServiceCollection services)
{
    // its lifetime so get only one
    services.AddSingleton<IStudentRepository, StudentRepository>();
    //services.AddTransient<IStudentRepository, StudentRepository>();
    //services.AddScoped<IStudentRepository, StudentRepository>();
    //services.AddControllersWithViews();
}


What is the lifetime?

Transient
    Makes an instance each time.
    Never shared.
    Used for lightweight stateless services.

Singleton
    Creates only single instance.
    Shared among all components that demand it.

Scoped

    Creates an instance once per scope.
    Created on every request to the application.




Finally, we got the above result from our API. Hopefully, it has been helpful to you to understand the concept of DI.

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 Resolve Issue Of Test Project Not Running The Unit Tests After Upgrade To .NET 6?

clock January 25, 2022 07:36 by author Peter

I was upgrading the .NET Core 3.1 project to .NET 6 and faced issues running test cases in my test projects. I had several projects and test projects for each project; all were working fine after the upgrade. However, I got an issue with only two test projects after the upgrade. So here in this article, I am going to share the issue and the solution to how I fixed it.

Even though there was no single error after the upgrade, the solution was cleaned and built successfully I was not able to run unit tests of two projects.

Once, the upgrade is completed I was testing the solution where I got an error: “unexpected error detected. Check the Tests output Pane for details.”

Two of my test projects didn’t run the test cases, it was about to start and took some time to run the test but got stopped after a few minutes. This is the scenario of the Test project using xunit framework for unit tests.

The below image shows the error that I got while testing.

When I checked the Output pane the exact error was

“Starting test discovery for requested test run

========== Starting test discovery ==========

Microsoft.VisualStudio.TestPlatform.ObjectModel.TestPlatformException: Failed to negotiate protocol, waiting for response timed out after 90 seconds. This may occur due to machine slowness, please set environment variable VSTEST_CONNECTION_TIMEOUT to increase timeout.

at Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TestRequestSender.CheckVersionWithTestHost()

at Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.ProxyOperationManager.SetupChannel(IEnumerable`1 sources, String runSettings)

at Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.ProxyDiscoveryManager.DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEventsHandler2 eventHandler)

========== Test discovery aborted: 0 Tests found in 1.5 min ==========

========== Starting test run ==========

Failed to negotiate protocol, waiting for response timed out after 90 seconds. This may occur due to machine slowness, please set environment variable VSTEST_CONNECTION_TIMEOUT to increase timeout.

Failed to negotiate protocol, waiting for response timed out after 90 seconds. This may occur due to machine slowness, please set environment variable VSTEST_CONNECTION_TIMEOUT to increase timeout.

========== Test run aborted: 0 Tests (0 Passed, 0 Failed, 0 Skipped) run in < 1 ms ==========”
Solution

Then I researched, spent several hours surfing various sites, forums and couldn’t get the solution for this. Later on, I checked and compared the project file of working test project after upgrade to .NET 6 and the project having issue after upgrade where I found some differences in the .csproj file.

Differences are listed below:

    Additionally, there was no Microsoft.NET.Test.Sdk in the .csproj file.
    Project which is having issue has different version of xunit and xunit.runner.visualstudio than the working project.

I updated the project file (csproj) manually and made it same as a working project, then cleaned and built the project. After that the test project worked perfectly.

Updated part of the project.csproj file is highlighted below.

Alternatively, you can add “Microsoft.NET.Test.Sdk” from the NuGet package manager or Package Manager console as well. I made changes to xunit and xunit.runner.visualstudio to make uniformity of version with all test projects.

Note that: some cases only adding the below line in ItemGroup may resolve the issue. In my case only adding the below package reference resolved the problem. However, to maintain the same version of xunit and xunit.runner.visualstudio, I kept the same version of those across all test projects.

<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />

Test Project’s project file(.csproj file) in details

    TargetFramework specifies the target framework of your project.
    IsPackable has nothing to do. Unit test projects cannot be packed so it is redundant. If you wish you can remove it. However, when you create the test projects in .Net 6, it comes by default.
    Packages xunit.runner.visualstudio and Microsoft.NET.Test.Sdk are mandatory to run the test project using visual studio as well as with command dotnet test.

In my case, Microsoft.NET.Test.Sdk was missing which plays a vital role to run the unit test that’s why I was not able to run tests.

I hope, this helps you to upgrade your test project to .NET 6 and resolve the issue if you encounter it after the upgrade.

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 :: Working With Async/Await/Task Keywords In Depth

clock January 13, 2022 06:43 by author Peter

Modern systems are becoming more powerful with multiple processors. Similarly,  modern server application development  has also improved to leverage the host CPU power for processing multiple requests in parallel to achieve more scalability.

Earlier we had many limitations on asynchronous calls and not utilizing the complete CPU cores. The Task Parallel Library (TPL) that was introduced in the .NET Framework 4 made rapid changes to our asynchronous development and utilization of infrastructure.

Still, most of the developers are not very familiar with understanding these keywords and make regular mistakes during usage. Here, we will concentrate more on understanding how these keywords work with asynchronous calls. At the end we will see some of the recommendations needed for regular usage.

Every .NET/.NET Core application is associated with a thread pool and is a collection of threads that effectively executes asynchronous calls of an application. These threads on the thread pool are known as Worker threads.

Threadpool will work as a software-level thread management system for the .NET runtime. It is a queuing mechanism for all application requests.

When the application is initiated, the .NET runtime will spawn the worker threads and keep them in the thread pool queue as available threads. Once any request comes, the runtime will pick one worker thread from this queue and assign this incoming request to it and it will be retained to the queue once this request process is completed. The number of threads the runtime will spawn depends on how many logical processors are available on the host system by default. If needed we can increase the minimum worker threads to spawn by using the below statement at the startup of the application.

ThreadPool.SetMinThreads(100, 100);

The first parameter is the number of worker threads that need to be created and the second parameter defines the completion port thread count. Please find my other article on completion ports in detail here.

Let us understand Async, Await and Task keywords in detail here with the following example code block.
public async Task<decimal> TotalGiftBudget()
{
  decimal totalBudgetAmount = 0;
  decimal percentageAmount = GetGiftPercentage();
  List<Employee> lstEmployees = new List<Employee>();
  //Fetch all active employees from Hyderabad Branch
  List<Employee> lstHyd = await GetHyderabadEmployeesListAsync();
  lstEmployees.AddRange(lstHyd);
  //Fetch all active employees from Banglore Branch
  List<Employee> lstBglre = await GetBangloreEmployeesListAsync();
  lstEmployees.AddRange(lstBglre);
  foreach(var emp in lstEmployees)
  {
    totalBudgetAmount += (emp.Salary * percentageAmount) / 100.0m;
  }
  return totalBudgetAmount;
}

Let say a company decided to pay a Christmas gift to all their employees with a certain percentage of their monthly salary. Before announcing to the employees they want to check the budget for this bonus amount. This asynchronous method will give this information by fetching all the employees from their Hyderabad and Bangalore branches asynchronously and calculating the expected gift amount based on each employee's salary.

When this method is called, the following actions will happen at the runtime.

When runtime finds the async keyword, it will allocate some memory on the RAM to store the state information of the method.

Next, Runtime will divide this method into three parts as follows

Once it executes or processes part-1 and founds asynchronous statement to get employees from the Hyderabad branch, then immediately creates an I/O thread and returns the Task object which points to its IOCP and the current worker thread will be retained to the available worker threads queue i.e., thread pool so that runtime will utilize this worker thread to serve other requests.

Once the Hyderabad list is ready (for example, it might get from an external API) our completion port will keep this in its queue. The await keyword is used so that the runtime will keep getting the status of the I/O process using the GetQueuedCompletionStatus function and once it is ready, a new available worker thread will be allocated to continue the rest of the actions. This new worker thread will fetch the state machine information from the RAM and continue the remaining process of the method.

In our case, once the list of Hyderabad is available and added to the listEmployee list and again runtime found another asynchronous statement and repeat the same as above. Once we get the Bangalore list too, there is no other asynchronous statement and this time runtime will complete the next actions to calculate the total gift amount and returns successfully.

Here the point of interest is until we get the list of employees from Hyderabad and Bangalore the worker thread is retained and utilized to serve other requests. In the case of a synchronous call, the worker thread will be blocked until it returns the budget amount. Here is the advantage of these asynchronous calls using async/await keywords to improve the performance of the application and to make it more scalable.

Recommendations

If possible avoid the Async keyword and use only Task. When we use Async, some memory will be allocated to the Ram and it will impact the performance. For example, the below code doesn’t need any async and await.
publc Task<int> GetSum(int a, int b)
{
    int c = a + b;
   return c;
}


In case, if we have a method non-async and we need to call an async method. The following statements are very BAD and they will block the thread and it will lead to perf issues.
Task.Result; //bad
Task.Wait(); //bad
Task.GetAwaiter().GetResult(); //bad

Instead, we can write like below

Public string Getsomething()
{
   var task1 = Do1Async();
   var task2 = Do2Async();

   Task.WaitAll(new[] {task1, task2});
  //or
   Task.WhenAll(new[] {task1, task2});
}
Public async Task<string> do1Async()
{}
Public async Task<string> do2Async()
{}


Hope this article is helpful to you in understanding the best usage of Async, Await and Task keywords in an asynchronous world.

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 :: JWT Authentication In Microservices

clock January 3, 2022 06:16 by author Peter

As with any Web Service, the microservices need to be protected from unauthorized access. So how do you protect each of your services? How does one share the token that is received from the Auth service? Exposing your microservices directly to the client and allowing them to directly communicate with all your services would have its own problems, so in this example, we will also add a layer of API Gateway which would be the single point of contact for all your clients.

The Gateways, in addition to providing a single point of access, also adds a security layer over your microservices. It could also support load balancing and reducing round trips when the client requires calls to multiple microservices. With regard to authentication, the gateway could pass the authentication token to the downstream paths. In this example, we would be using Ocelot for building our gateway.

The Working
The typical authentication process could be outlined as shown in the diagram below.

The authentication request from the client is redirected to the dedicated Auth service. This service would be responsible for validating the user and granting the authentication token. The authentication token is then returned back to the client via the gateway. In each of the subsequent requests, the client would pass the Authentication token along with the request. The API Gateway would be processed the incoming request, and if the downstream service requires an authenticated path, would pass the received token along.

We could also add BFF and other layers in the architecture, but for this article, we will keep it to a bare minimum. Let us now get our hands dirty and start building our sample application which would comprise of an API Gateway, two microservices - an auth service, and a User Service. For the sake of example, we will use Postman as our client and use Minimal API for building our services.

Auth Service

As mentioned earlier, the Auth Service would be responsible for authenticating the User and generating the Auth token. We will begin by defining our Token Service and registering it.
internal interface ITokenService
{
    string BuildToken(string key, string issuer, IEnumerable<string> audience, string userName);
}
internal class TokenService : ITokenService
{
    private TimeSpan ExpiryDuration = new TimeSpan(0, 30, 0);
    public string BuildToken(string key, string issuer, IEnumerable<string> audience, string userName)
    {
        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.UniqueName, userName),
        };

        claims.AddRange(audience.Select(aud => new Claim(JwtRegisteredClaimNames.Aud, aud)));

        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
        var tokenDescriptor = new JwtSecurityToken(issuer, issuer, claims,
            expires: DateTime.Now.Add(ExpiryDuration), signingCredentials: credentials);
        return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
    }
}

We will go ahead and register it so that we could use it with DI.
builder.Services.AddSingleton<ITokenService>(new TokenService());

We will keep the Validate endpoint simple for sake of the example and hardcode our user credentials, but this could be easily replaced with your repositories later.
app.MapPost("/validate", [AllowAnonymous] (UserValidationRequestModel request, HttpContext http, ITokenService tokenService) =>
{
    if (request is UserValidationRequestModel { UserName: "john.doe", Password: "123456" })
    {
        var token = tokenService.BuildToken(builder.Configuration["Jwt:Key"],
                                            builder.Configuration["Jwt:Issuer"],
                                            new[]
                                            {
                                                        builder.Configuration["Jwt:Aud1"],
                                                        builder.Configuration["Jwt:Aud2"]
                                                    },
                                            request.UserName);
        return new
        {
            Token = token,
            IsAuthenticated = true,
        };
    }
    return new
    {
        Token = string.Empty,
        IsAuthenticated = false
    };
})
.WithName("Validate");


Where UserValidationRequestModel is defined as
internal record UserValidationRequestModel([Required]string UserName, [Required] string Password);

The AuthService, as you could understand from the code above, exposes a single endpoint - validate which would generate an auth token if the username/password supplied are "john.doe" and "123456". The generated and subsequently returned auth token would be then used by the succeeding requests by the client for accessing authorized routes.

API Gateway
As mentioned earlier, we would be using Ocelot for building our API Gateway. The role of Gateway as far as Authentication is concerned would be to detect if the requested downstream path requires authentication and if so, pass the authorization token which was passed in the upstream request. Let us configure the routing configuration for our sample Gateway.
{
  "Routes": [
    {
      "DownstreamPathTemplate": "/GetUsers",
      "DownstreamSchema": "https",
      "DownstreamHttpMethod": "GET",
      "RouteIsCaseSensitive": false,
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": "7163"
        }
      ],
      "UpstreamPathTemplate": "/user/getusers",
      "UpstreamHttpMethod": [ "Get" ],
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "GatewayAuthenticationKey",
        "AllowedScopes": []
      }
    },
    {
      "DownstreamPathTemplate": "/validate",
      "DownstreamSchema": "https",
      "DownstreamHttpMethod": "POST",
      "RouteIsCaseSensitive": false,
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": "7075"
        }
      ],
      "UpstreamPathTemplate": "/user/validate",
      "UpstreamHttpMethod": [ "Post" ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "https://localhost:7254"
  }
}


As you can observe in the configuration, there are two routes that are exposed in the API Gateway. The /validate route doesn't require any authentication, while the /GetUsers route requires authentication. When ocelot runs, it would check the routes AuthenticationOptions and if it exists, reads the AuthenticationProviderKey. This denotes the authentication key (scheme), which needs to be registered with the authentication services at the startup.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer("GatewayAuthenticationKey", option =>
    {
        option.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Aud"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });
builder.Configuration.AddJsonFile("ocelot.json");
builder.Services.AddOcelot(builder.Configuration);


Ocelot requires you to register the Authentication Service be registered with a name/key. Ocelot would use this key to recognize the service to use when encountered  AuthenticationProviderKey in the route declaration. If the route requires authentication, Ocelot would execute the authentication middleware registered for the provider.

UserService
The last step in this demo code would be to set up a mock User Service, a microservice that would be responsible for handling user details. We will expose a single endpoint the UserService, which would return a set of Usernames.

app.MapGet("/GetUsers", [Authorize]() =>
{
    return new[]
    {
        "John.Doe",
        "Jane.Doe",
        "Jewel.Doe",
        "Jayden.Doe",
    };
}).WithName("GetUsers");


Do not forget to register the authentication services as usual.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(option =>
    {
        option.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Aud"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });


That would be what we all require in the microservice end of our demo code to test our Authentication sample.

Client
As mentioned earlier, we will be using Postman to test our sample set of services. So fire up your Postman, and first send the request to validate the user and get the auth token. Remember to use the Gateway instead of using the microservice directly.

As you can observe, we have retrieved the Auth Token from the Auth Service (via the gateway of course). We will now use the auth token to authenticate our request to access the protected route in the User Service.


It could be observed that the request was a success and then User Service has returned the required results.

In this article, we addressed how to authenticate the different individual services in the microservice architecture. We also used the wonderful Ocelot library for building API Gateways. The services and the gateways are loosely coupled with each other, while the client is having a single point of contact in the gateway.

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 :: Non-Nullable Property Must Contain A Non-Null Value

clock December 21, 2021 06:51 by author Peter

Recently, I was getting this warning for most of the properties which are not specified as nullable. I was not happy with this warning, though I was able to run my .NET 6 application smoothly.

Exact Error:
    Non-nullable property ‘propername’ must contain a non-nullvalue when exiting constructor. Consider declaring the property as nullable

Non-nullable property must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

After carefully observing this error message, it makes sense for those properties. In order to minimize the likelihood that our code causes the runtime to throw System.NullReferenceException, we need to resolve this warning.

Therefore, the compiler is giving warning in the solution that the default assignment of your properties (which is null) doesn’t match its state type (which is non-null string

https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references

We can resolve this error in 3 ways.

Solution 1

We can simply make the properties nullable, as shown below:
public class AppSetting {
    public string? ReferenceKey { get; set; }
    public string? Value { get; set; }
    public string? Description { get; set; }
}

Solution 2
We can assign a default value to those properties as shown below:
public class AppSetting {
    public string ReferenceKey { get; set; } = “Default Key”
    public string? Value { get; set; } = “Default Value”
    public string? Description { get; set; } = “Default Description”
}

Alternatively, you can give a reasonable default value for non-nullable strings as string.empty.

Solution 3
You can disable this warning from project level. You can disable by removing the below line from project file csproj or setting.

<Nullable>enable</Nullable>

Reference: https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#nullable-contexts

These are three ways you can overcome the above warning.

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 :: Custom Controls In C#

clock December 20, 2021 08:14 by author Peter

Custom controls are control that are created by user when Windows Forms controls do not fulfill their application requirements. Simple custom controls can be created by inheriting the Control class, UserControl class, or any Windows Forms controls. The developer should write the code for the custom control in the OnPaint event of the control. After writing the code, it should be saved with the .cs extension. The code can be complied into an assembly and saved into the application’s directly by executing the following command:

Syntax
csc /t:library/out:<path to your application;s directory>/<name of the assembly that contains the custom control class> /r:System.dll
/r: System.Windows.Form.dll /r: System.Drawing.dll <name of the custom control class file>

Where,
    /t:library, Instructs the compiler that the assembly that is being created is a library and it is cannot be executed.
    /out : Specifies the name and path of the assembly file that contains the custom control.
    /r: Specifies the names of all the assemblies that are used by the code.

Control Class

The Control class includes functionalities to handle user input, define position and size of controls, and so on. The control class can be inherited by other classes to display information to the user. The properties of Control class.

    Bounds
    Specifies or retrieves the size and location of the specified control with respect to its parent control.
    CanFocus
    Retrieves a value that indicates whether the specified control can receive focus.
    CanSelect
    Retrieves a value that indicates whether the specified control can be selected.
    Created
    Retrieved a value that indicates whether the specified the specified control has been created.
    Dock
    Specifies or retrieves the control borders, which are docked to its parent control. It also identifies the way a control is resized with its parent.
    Left
    Retrieves the distance between the left edge of specified control and the left edge of the container’s client area.
    Right
    Retrieves the distance between the right edge of specified control and the left edge of the container’s client area.
    TabIndex
    Specifies or retrieves the tab order of the specified control within a container.

Table below the list of methods of control class.

Method Description
Contains specifies control is a child of the control
CreateControl Forcibly creates a control along with its handle and child controls.
CreateGraphics Creates a graphic for the specified control.
GetNextControl It retrieves the next control according to the specified tab order of child controls.
GetPreferredSize It retrieves the size of the rectangular area.
Hide Hides the specified control from the user.

Below are the lists of events of Control class.

Event Description
ControlAdded Occurs when a new control is added to a collection of controls.
ControlRemoved Occurs when a specified control is removed from a collection of controls.
Validated Occurs when the validation process of the specified control is complete.

Code below creates a rectangular custom control and changes its appearance when the control is validated.

public partial class CustomControl: Control {
    Graphics graphics;
    protected override void OnPaint(PaintEventArgs pe) {
        this.Bounds = new Rectangle(15, 15, 30, 15);
        if (this.CanFocus) {
            this.Focus();
        }
        this.Dock = DockStyle.None;
        graphics = this.CreateGraphics();
        graphics.FillRectangle / (Brushes.CornflowerBlue, ClientRectangle);
    }
    protected override void OnValidated(EventsArgs e) {
        graphics.FillRectangle(Brushes.MediumOrchid, ClientRectangle);
        graphics.DrawRectangle(new Pen(Color.Black, ClientRectangle);
    }
}

In this code, the custom control is created by inheriting the Control class. When the OnPaint() method is invoked, the Bounds property is used to set a rectangular region. This is done by invoking the constructor of the Rectangular class, which takes the x and y coordinates, width and height as the parameters. The CanFocus property is used to check whether the control can receive focus. By default, it returns true and the focus() method is used to focus the control. The dock style for the control is set to None, which means that control cannot be dragged to some other location on the form. The graphics object Brush, is used to create the custom control within the specified rectangular bounds. When the validations are successfully made to the control, the OnValidated() method is invoked. This event changes the appearance of the control by changing its back color and border color.

The following code demonstrates how to override the Text and BackColor properties of the Control class. This is useful in setting the default values of the properties when the custom control appears on the form.

The Text property of the Control class is overridden. The BackColor property is also overridden to set the default color as dark blue. When the custom control is added to the form, the control appears with dark blue as the background color and customLabel as the default text. This text and background color appear on the label due to the Invalidate() method, which in turn, calls the OnPaint() method. This method redraws the control within the given client area along with the specified text and background color.
UserControl Class

The UserControl class allows the user to create controls that can be used in many places within an application of across multiple applications.


Table shows the properties of UserControl class

Property Description
AutoSizeMode Specifies or retrieves the way a control will resize itself.
AutoValidate Specifies or retrieved the way a control performs validation when the focus is switched to another control
HorizontalScroll Retrieves the characteristics of the horizontal scroll bar.
VerticalScroll Retrieves the characteristics of the vertical scroll bar.

Table below the methods of UserControl class.

Method Description
PerformAutoScale Performs automatic scaling of the specified container control and its child controls.
ScrollControlView Scrolls the specified control into view.

Table shows the events of UserControl class.

Event Description
AutoValidateChanged It occurs when the value of AutoValidate property is changed.
Load Before the specified control becomes visible for the first time.

Code below shows how to create custom scroll bars using the UserControl class.

public partial class ScrollControl: UserControl {
    protected override void OnPaint(PaintEventArgs e) {
        this,
        VerticalScroll,
        Visible = true;
        this.HorizontalScroll.Visible = true;
        this.PerformAutoScale();
    }
    private void ScrollControl_Load(object sender, EventArgs e) {
        this.VericalScroll.Minimum = 0;
        this.VerticalScroll.Maximum = 100;
        this.HorizontalScroll.Minimum = 0;
        this.HorizontalScrollMaximum = 60;
    }
}


The OnPaint() method is invoked to set the vertical and horizontal scroll bars. This is done using the VerticalScroll and HorizontalScroll properties of the UserControl class. The PerformAutoScale() method automatically scales the control and its container control. When the created custom control is loaded, the Load event is raised. When this event is raised, the Minimum and Maximum properties sets the minimum and maximum limits for both the scroll bars.
Control Type Recommendations

Windows Forms provide the user with a variety of options while working with controls. The user can either use the Windows Forms controls or create a new control. But, sometimes, the user might get confused about the type of control to be used in the application. The difference between various types of controls from which the user can inherit are listed as follows:

Inheriting Windows Forms Controls
Inheriting Windows Forms controls allows the user to implement the functionalities of the inherited control. The user can also extend the functionalities of the inherited control. The user can inherit from the Windows Forms control if the inheriting control fulfills most of the application’s requirements.

Inheriting the Control Class

The user can inherit from the Control class while customizing the appearance of the control. Also, inheriting the control class allows the user to implement the functionalities that are not provided by the standard controls.

Inheriting the UserControl Class
When the user wants to combine the functionalities of several Windows Forms controls, a user can create a composite control by inheriting the UserControl class.

Property- Changed Events

Windows Forms allows the user to send notifications when the value of the property is changed. The user can send notifications by defining an event and then a method that raises the event. The event name is the name of the property by appending the word, Changed, to the name of the property. For example, if the name of the property is BackColor, the user can define an event named BackColorChanged and the event-handler method named OnBackColorChanged.

Event handlers can be created to respond to property- change events. This allows developers to define various actions that can take place when a property of the control is changed.

Code below creates a custom TextBox control and raises an event when a value in the control is changed

public partial class TxtPrincipal: TextBox {
    int years;
    float rate;
    double principal;
    double interest;
    protected override void OnTextChanged(EventArgs e) {
        years = 10;
        rate = 8.5 F;
        principal = 0;
        interest = 0;
        try {
            principal = Convert.ToDouble(this.Text);
            interest = (principal * years * rate) / 100;
            this.Parent.Text = ”Interest is: ”+interest.ToString();
        } catch (Exception ex) {
            MessageBox.Show(“Enter the numeric value only.”, ”ABCDBank”, MessageBoxButtons.OK, MessageBoxIcon.Error);
            this.Focus();
        }
    }
}

In this code, a custom textbox namely, TxtPrincipal is created. The OnTextChanged event is overridden and is raised when the value in the control is changed. The code calculated the interest using the values specified in the control.

User-defined controls can be created by inheriting the control class. UserControl class, or any windows forms existing control’s class. The HorizontalScroll and VerticalScroll properties of the UserControl class can be used to define custom scroll bars. The GetImage() method of the ToolBoxBitmapAttribute class retrieves the image icon associated with the custom control. Composite controls are user controls that are created using one or more Windows Forns controls. Property-changed events allows the user to send notification whenever the value of the property is changed.

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 :: The Downsides Of Using The Repository Pattern

clock December 13, 2021 06:46 by author Peter

The Repository Pattern is one of the most popular design patterns used for abstracting the data persistence in the database or retrieving from the database. The fundamental objective of the Repository Pattern is to help you decouple the data access and business logic layers of an application.

In this article, we’ll discuss the Repository Pattern. We'll learn why it is considered an anti-pattern and when we can use it in applications. Also, we'll illustrate its implementation with code examples in C#.

Let’s start.

Pre-requisites

You’ll need the following tools to deal with code examples,

    Visual Studio 2019 Community Edition (download)
    SQL Server 2019 Developer Edition (download)
    Entity Developer (download)

The Community Edition of Visual Studio 2019 and the Developer Edition of SQL Server 2019 are free editions. Entity Developer offers a fully functional 30-days Free Trial which we’ll use in our scenarios.
What is a Repository Pattern and Why We Should Care?

A Repository Pattern is a design pattern used to decouple the application's business logic and data access layers.

It was first introduced as part of Domain-Driven Design in 2004. Since then, it has become very popular. Now, it is the design pattern of choice for abstracting calls from the application to the underlying database.
But why is Repository Pattern so essential?

A repository, in essence, acts as a bridge between your application's domain and data mapping layers. When used correctly, it improves testability, code extensibility, and maintenance. With the Repository design pattern applied, the business logic layer of the application does not need to understand how data persistence works beneath the surface.

In other words, a repository abstracts the data storage and retrieval mechanism from the application.

This isolation enables the developers to focus on the business logic components rather than write boilerplate code to perform CRUD operations against databases. It also helps in unit testing the application's code since the business logic code is abstracted from the data access logic. You can change the data access code without impacting the work of the application works.

Assume that you introduce new database objects (tables, stored procedures, etc.). You can create a corresponding entity class in your application and write a few lines of data mapping code. You might (though, rarely) also need to change the database type altogether (from Oracle to SQL Server, PostgreSQL, etc.).

By leveraging the Repository Pattern, you can build and test the data access logic and the business logic of an application separately. It helps you to adhere to the Don't Repeat Yourself (DRY) principle since you don't need to repeat the code for performing CRUD operations.

In that case, you would need to change your data access code – update the repository classes. You might also want to change a few lines of code in the application, but that would be minimal.

What is an Anti-Pattern?
An anti-pattern is usually an ineffective solution to a problem. Anti-patterns are ineffective programming techniques that create issues rather than solve them and emerge due to over-engineering, incorrect application of design patterns, not following recommended practices, etc. On the other hand, anti-patterns are recurring solutions to common software application problems. Some common examples are spaghetti code, dead code, God object, etc.

The objective observation of functional and non-functional requirements will help you choose correct application patterns, frameworks, and platforms. You might not select a design pattern simply because you saw someone else use it or because someone told you there was no harm in using it. But an anti-pattern can help you determine the appropriate pattern you can use for your problem statement and available solutions.
An Extra Layer of Abstraction

One of the biggest downsides of the Repository Pattern is adding an extra layer of abstraction which eventually can become overkill for your application. Besides, you would typically need to create a repository for each entity in your application.

Things deteriorate as you include additional methods and complex search capabilities in your repository. You'll wind up with a repository that closely matches the permanent storage layer in use underneath. As an example, you might need methods such as FindProductById, FindCustomerById, etc. Such methods are present in the mature ORM frameworks. It implies that you are creating an abstraction on top of another abstraction for no good reason.
Downsides of a Generic Repository

In an application, the domain model and the persistence model have separate roles. The domain model’s behavior deals with real-world issues and solutions. The persistence model serves to represent how the application's data is saved in the data storage.

The Repository Pattern should encapsulate the persistence logic and conceal the underlying implementations of the data storage ways. The operations in repositories should be expressive rather than generic.

For instance, you cannot have a Generic Repository containing operations that you may use in any situation. As a result of this needless abstraction, the generic repository design becomes an anti-pattern.

A Generic Repository does not provide a meaningful contract. Therefore, you need to create a specific repository that extends the Generic Repository and offers a precise set of operations relevant to that particular entity.
Create a new ASP.NET Core Web API Project

Earlier, we mentioned the necessary tools to proceed to the practical scenarios. The time has come to use those tools.

First, we need to create a new ASP.NET Core Web API project,

    Open Visual Studio 2019.
    Click Create a new project.
    Select ASP.NET Core Web Application and click Next.
    Specify the project name and location to store that project in your system. Optionally, checkmark the Place solution and project in the same directory checkbox.
    Click Create.
    In the Create a new ASP.NET Core Web Application window, select API as the project template.
    Select ASP.NET Core 3.1 or later as the version.
    Disable the Configure for HTTPS and Enable Docker Support options (uncheck them).
    Since we won’t use authentication in this example, specify authentication as No Authentication.
    Click Create to finish the process.

We’ll use this project in this article.
A Generic Repository is an Anti-Pattern

You can take advantage of the Entity Developer tool to generate the Entity Data Model and repository classes. Using this tool simplifies the tasks significantly.

Select the project that we have created earlier. Specify Repository and Unit of Work as the code generation template when creating the Entity Data Model:

This would generate the Irepository and IProductRepository interfaces, and the EntityFrameworkRepository (the generic repository) and ProductRepository classes. It would also generate the entity classes and the unit of work classesandinterfaces.

The Generic Repository generated by Entity Developer would look like below:

public partial class EntityFrameworkRepository < T > : IRepository < T > where T: class {
    private DbContext context;
    protected DbSet < T > objectSet;
    public EntityFrameworkRepository(DbContext context) {
        if (context == null) {
            throw new ArgumentNullException("context");
        }
        this.context = context;
        this.objectSet = context.Set < T > ();
    }
    public virtual void Add(T entity) {
        if (entity == null) {
            throw new ArgumentNullException("entity");
        }
        objectSet.Add(entity);
    }
    public virtual void Remove(T entity) {
        if (entity == null) {
            throw new ArgumentNullException("entity");
        }
        objectSet.Remove(entity);
    }
    public DbContext Context {
        get {
            return context;
        }
    }
}

The code generator will generate the IRepositoryinterface as well:
public partial interface IRepository < T > {
    void Add(T entity);
    void Remove(T entity);
}

You can register an instance of the EntityFrameworkRepositoryclass as a scoped service to use it in the controller classes or elsewhere in the application.

public void ConfigureServices(IServiceCollection services) {
    services.AddScoped < IRepository < Product >> (x => {
        return new EntityFrameworkRepository < Product > (new DataModel());
    });
    services.AddControllers();
}

Now, you can use the dependency injection in your controllers to retrieve this instance.

The Generic Repository works fine as long as you perform simple CRUD operations. If you need specific methods, such as GetAllExpiredProducts, you’ll have to write a custom code in the ProductRepositoryclass. The generated class would look as follows:

public partial class ProductRepository {}

Here you have to write your own implementation of the GetAllExpiredProducts.

So, besides the generic repository that you can use in simple cases only, you'll always need specific repository classes for each entity class in your application to address such issues.

Use the Repository Pattern for applications that don’t perform complex operations.
Summary

In this article, we've discussed the pros, cons, and some common pitfalls you may face when using the Repository Pattern. Hope this information will be helpful in your further work.

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 :: Deserialize JSON Format In An ASP.NET GridView Using System.Text.Json Library

clock December 7, 2021 08:03 by author Peter

JSON is an open standard file format and data interchange format that uses human-readable text to store and transmit data objects consisting of attribute-value pairs and arrays.

About System.Text.Json
System.Text.Json library provides high-performance and low-allocating types that serialize objects to JavaScript Object Notation (JSON) text and deserialize JSON text to objects, with UTF-8 support built-in. Also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM), that is read-only, for random access of the JSON elements within a structured view of the data.

Now, let's install and use JSON library in the ASP.NET website.

Install System.Text.Json library from NuGet
To install library, go to "Microsoft Visual Studio 2022" => "Tools" menu => "NuGet Package Manager" => "Manage NuGet Packages for solution", search for "System.Text.Json" and click "Install" as in below picture.

What is JSON Deserialization?
Deserialization is the process of parsing a string into an object of a specific type. The JsonSerializer.Deserialize() method converts a JSON string into an object of the type specified by a generic type parameter.

Below is the JSON format that will be used as an example:
string JsonString = @"{
        ""Version"": 1,
        ""Key"": ""314929"",
        ""Type"": ""City"",
        ""Rank"": 30,
        ""LocalizedName"": ""Stockholm"",
        ""EnglishName"": ""Stockholm"",
        ""PrimaryPostalCode"": """",
        ""Region"": {
            ""ID"": ""EUR"",
            ""LocalizedName"": ""Europe"",
            ""EnglishName"": ""Europe""
        },
        ""Country"": {
            ""ID"": ""SE"",
            ""LocalizedName"": ""Sweden"",
            ""EnglishName"": ""Sweden""
        },
        ""TimeZone"": {
            ""Code"": ""CET"",
            ""Name"": ""Europe/Stockholm"",
            ""GmtOffset"": 1.0,
            ""IsDaylightSaving"": false,
            ""NextOffsetChange"": ""2022-03-27T01:00:00Z""
        },
        ""DataSets"": [
            ""AirQualityCurrentConditions"",
            ""AirQualityForecasts"",
            ""Alerts"",
            ""DailyPollenForecast"",
            ""ForecastConfidence"",
            ""FutureRadar"",
            ""MinuteCast"",
            ""Radar""
        ]
 }";

And here are Class Properties for converting JSON string,

public class Cities {
    public int Version {
        get;
        set;
    }
    public string Key {
        get;
        set;
    }
    public string Type {
        get;
        set;
    }
    public string EnglishName {
        get;
        set;
    }
    public Region Region {
        get;
        set;
    }
    public Country Country {
        get;
        set;
    }
    public TimeZone TimeZone {
        get;
        set;
    }
    public string[] DataSets {
        get;
        set;
    }
}
public class Region {
    public string ID {
        get;
        set;
    }
    public string LocalizedName {
        get;
        set;
    }
    public string EnglishName {
        get;
        set;
    }
}
public class Country {
    public string ID {
        get;
        set;
    }
    public string LocalizedName {
        get;
        set;
    }
    public string EnglishName {
        get;
        set;
    }
}
public class TimeZone {
    public string Code {
        get;
        set;
    }
    public string Name {
        get;
        set;
    }
    public float GmtOffset {
        get;
        set;
    }
}

Now, the following is JsonSerializer.Deserialize() method to convert JSON string, which will be added to a datatable to use it in the GridView.

Cities cities = JsonSerializer.Deserialize<Cities>(JsonString);
int Version = cities.Version;
string Key = cities.Key;
string Type = cities.Type;
string City = cities.EnglishName;
string Region = cities.Region.EnglishName;
string Country = cities.Country.EnglishName;
string TimeZone = cities.TimeZone.Name;
string Alerts = cities.DataSets[2];

DataTable dt = new DataTable();
dt.Columns.Add("Version", typeof(string));
dt.Columns.Add("Key", typeof(string));
dt.Columns.Add("Type", typeof(string));
dt.Columns.Add("City", typeof(string));
dt.Columns.Add("Region", typeof(string));
dt.Columns.Add("Country", typeof(string));
dt.Columns.Add("TimeZone", typeof(string));
dt.Columns.Add("Alerts", typeof(string));

DataRow row;
row = dt.NewRow();
row["Version"] = Version;
row["Key"] = Key;
row["Type"] = Type;
row["City"] = City;
row["Region"] = Region;
row["Country"] = Country;
row["TimeZone"] = TimeZone;
row["Alerts"] = Alerts;
dt.Rows.Add(row);

GridView1.DataSource = dt;
GridView1.DataBind();

After running ASP.NET website, the following image is the result of JSON deserialization process.

In this article, System.Text.Json library was introduced, we saw how to install it and use it in an ASP.NET website. Also we discussed the steps to deserialize JSON string in an ASP.NET GridView. In conclusion, this was a demonstration of the concept of JSON deserialization and how System.Text.Json library helps achieve this process.

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