European ASP.NET MVC 4 and MVC 5 Hosting

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

ASP.NET MVC Hosting - HostForLIFE.eu :: CRUD Functions in an MVC.NET Core Project

clock September 9, 2026 11:45 by author Peter

CRUD stands for Create, Read, Update, and Delete. These four operations form the foundation of many data-driven web applications. In this article, we will build a simple ASP.NET Core MVC application that performs CRUD operations for a Students entity. We will create the project, define the model, configure the application, create a controller, and test the CRUD endpoints.

The example uses an in-memory collection to keep the implementation simple and focused on understanding the CRUD flow. A SQL Server or another database can be introduced later when persistent data storage is required.

Prerequisites
Before we begin, ensure you have the following:

  • Visual Studio 2022 or later.
  • .NET SDK.
  • Basic knowledge of C# and ASP.NET Core MVC.
  • Basic understanding of HTTP methods such as GET, POST, PUT, and DELETE.

Step 1: Setting Up the ASP.NET Core Project

  • Open Visual Studio.
  • Select Create a new project.
  • Search for ASP.NET Core Web API.
  • Select the ASP.NET Core Web API template and click Next.
  • Configure the project name and location.
  • Select the required .NET version.
  • Keep the default OpenAPI support enabled if you want to test the API through Swagger.
  • Click Create.

For this example, the project is named:
CRUDOperationAPI

Although the original example refers to an MVC project, the supplied StudentsController inherits from ControllerBase and uses [ApiController], which makes it an ASP.NET Core Web API controller. Therefore, this implementation follows the Web API approach.

Step 2: Configure the Project

For a basic CRUD API, the default project configuration is sufficient.

A typical Program.cs file looks like this:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();


Here:

  • AddControllers() registers controller support.
  • AddEndpointsApiExplorer() enables API endpoint discovery.
  • AddSwaggerGen() generates OpenAPI documentation.
  • UseSwagger() and UseSwaggerUI() provide a browser-based interface for testing the API.
  • MapControllers() maps controller routes.

Step 3: Create the Student Model
Create a Models folder in the project.
Inside the folder, create a Students.cs class:
namespace CRUDOperationAPI.Models
{
    public class Students
    {
        public int Id { get; set; }

        public string Name { get; set; } = string.Empty;

        public int Age { get; set; }

        public string Address { get; set; } = string.Empty;
    }
}

This class represents the data that our CRUD API will manage.

The properties are:

Property

Description

Id

Unique identifier for the student

Name

Student's name

Age

Student's age

Address

Student's address

Step 4: Create the Students Controller
Create a StudentsController.cs file inside the Controllers folder.

The controller will expose endpoints for all four CRUD operations.
using CRUDOperationAPI.Models;
using Microsoft.AspNetCore.Mvc;

namespace CRUDOperationAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StudentsController : ControllerBase
    {
        private static readonly List<Students> students = new()
        {
            new Students
            {
                Id = 1,
                Name = "Capt. Peter",
                Age = 24,
                Address = "London"
            },
            new Students
            {
                Id = 2,
                Name = "Capt. Scott",
                Age = 24,
                Address = "Leeds"
            }
        };

        [HttpGet]
        public ActionResult<List<Students>> GetAllStudents()
        {
            return Ok(students);
        }

        [HttpGet("{id}")]
        public ActionResult<Students> GetStudentById(int id)
        {
            var student = students.FirstOrDefault(s => s.Id == id);

            if (student == null)
            {
                return NotFound();
            }

            return Ok(student);
        }

        [HttpPost]
        public ActionResult<Students> CreateStudent([FromBody] Students student)
        {
            student.Id = students.Count == 0
                ? 1
                : students.Max(s => s.Id) + 1;

            students.Add(student);

            return CreatedAtAction(
                nameof(GetStudentById),
                new { id = student.Id },
                student);
        }

        [HttpPut("{id}")]
        public ActionResult UpdateStudent(
            int id,
            [FromBody] Students updatedStudent)
        {
            var student = students.FirstOrDefault(s => s.Id == id);

            if (student == null)
            {
                return NotFound();
            }

            student.Name = updatedStudent.Name;
            student.Age = updatedStudent.Age;
            student.Address = updatedStudent.Address;

            return NoContent();
        }

        [HttpDelete("{id}")]
        public ActionResult DeleteStudent(int id)
        {
            var student = students.FirstOrDefault(s => s.Id == id);

            if (student == null)
            {
                return NotFound();
            }

            students.Remove(student);

            return NoContent();
        }
    }
}


The controller uses a static List<Students> as temporary storage. This means the data exists only while the application is running.

Step 5: Understand the CRUD Endpoints

The controller exposes five HTTP endpoints.

HTTP Method

Endpoint

Operation

GET

/api/students

Get all students

GET

/api/students/{id}

Get a student by ID

POST

/api/students

Create a student

PUT

/api/students/{id}

Update a student

DELETE

/api/students/{id}

Delete a student

These endpoints represent the standard CRUD workflow.

Step 6: Test the Read Operation
Run the application using F5 or the Start button in Visual Studio. If Swagger is enabled, the application will open the Swagger interface.

Expand:
GET /api/Students

Click Try it out, followed by Execute.

The response will contain the existing students:
[
  {
    "id": 1,
    "name": "Capt. Tim",
    "age": 24,
    "address": "Liverpool"
  },
  {
    "id": 2,
    "name": "Capt. Scott",
    "age": 24,
    "address": "Leeds"
  }
]

This demonstrates the Read operation.

Step 7: Get a Student by ID

To retrieve a specific student, use:
GET /api/Students/1

The API searches the collection for a matching ID.
var student = students.FirstOrDefault(s => s.Id == id);

if (student == null)
{
    return NotFound();
}

return Ok(student);


For ID 1, the response is:
{
  "id": 1,
  "name": "Capt. Tim",
  "age": 24,
  "address": "Liverpool"
}


If the requested student does not exist, the API returns an HTTP 404 Not Found response.

Step 8: Create a New Student
To create a student, use:
POST /api/Students

Send the following JSON request body:
{
  "name": "David",
  "age": 22,
  "address": "London"
}


The controller assigns a new ID and adds the student to the collection.
student.Id = students.Count == 0
    ? 1
    : students.Max(s => s.Id) + 1;

students.Add(student);


The API returns 201 Created along with the newly created resource.

Example response:
{
  "id": 3,
  "name": "David",
  "age": 22,
  "address": "London"
}

This demonstrates the Create operation.

Step 9: Update a Student

To update an existing student, use:
PUT /api/Students/3

Send the updated data:
{
  "name": "Peter",
  "age": 23,
  "address": "London"
}

The controller finds the student and updates its properties.
student.Name = updatedStudent.Name;
student.Age = updatedStudent.Age;
student.Address = updatedStudent.Address;

If the operation succeeds, the API returns:
204 No Content

This demonstrates the Update operation.

Step 10: Delete a Student

To delete a student, use:
DELETE /api/Students/3

The controller finds the student and removes it from the collection.
students.Remove(student);

If the deletion succeeds, the API returns:
204 No Content

If the student does not exist, the API returns:
404 Not Found

This demonstrates the Delete operation.

Step 11: Validate the CRUD Flow

The complete CRUD flow can now be tested as follows:
Create
  |
  v
POST /api/Students
  |
  v
Read
  |
  v
GET /api/Students
  |
  v
Update
  |
  v
PUT /api/Students/{id}
  |
  v
Read Updated Data
  |
  v
GET /api/Students/{id}
  |
  v
Delete
  |
  v
DELETE /api/Students/{id}


This provides a simple end-to-end test of the API.

Step 12: Customize the Controller

You may want to customize the controller logic according to your application's requirements.

For example, validation can be added before creating a student:
[HttpPost]
public ActionResult<Students> CreateStudent([FromBody] Students student)
{
    if (string.IsNullOrWhiteSpace(student.Name))
    {
        return BadRequest("Student name is required.");
    }

    if (student.Age <= 0)
    {
        return BadRequest("Age must be greater than zero.");
    }

    student.Id = students.Count == 0
        ? 1
        : students.Max(s => s.Id) + 1;

    students.Add(student);

    return CreatedAtAction(
        nameof(GetStudentById),
        new { id = student.Id },
        student);
}


This prevents invalid data from being added to the collection.

For a production application, validation would generally be implemented using model validation attributes or a dedicated validation approach rather than keeping all validation logic directly inside controller actions.
Step 13: Move from In-Memory Data to SQL Server

The example uses an in-memory list so that the CRUD concepts can be demonstrated without introducing database configuration.

For a real application, the data would normally be stored in a database such as SQL Server.

A common architecture would be:

Client
   |
   v
ASP.NET Core Controller
   |
   v
Service Layer
   |
   v
Repository / Data Access
   |
   v
SQL Server

Entity Framework Core can be used to connect the ASP.NET Core application to SQL Server.

For example, the required packages can be installed using the .NET CLI:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools


The exact package versions should match the .NET and Entity Framework Core versions used by the project.

Once a database is introduced, the static list can be replaced with an DbContext and database queries.

Why the Original Package Configuration Needs Attention?

The original implementation listed packages such as:
Microsoft.ASPNetCore
Microsoft.SqlServer
Microsoft.Data.SqlClient


These are not the appropriate set of packages for the MVC/API CRUD implementation shown in the article.

If SQL Server is being used with Entity Framework Core, the application should use the appropriate Entity Framework Core SQL Server provider, such as:
Microsoft.EntityFrameworkCore.SqlServer

Microsoft.Data.SqlClient is the SQL Server ADO.NET provider and is useful when directly working with SQL Server through ADO.NET, but it does not replace the Entity Framework Core SQL Server provider.
MVC Views vs Web API Controllers

There is an important distinction between the two approaches.

An ASP.NET Core MVC application commonly uses:
Controller
    |
    v
Razor Views
    |
    v
HTML UI

A Web API application commonly uses:
Client
    |
    v
API Controller
    |
    v
JSON Response


The supplied StudentsController uses:
[ApiController]
public class StudentsController : ControllerBase


Therefore, it is a Web API controller rather than an MVC controller that returns Razor Views.
If the goal is to create an MVC application with Create, Edit, Details, and Delete pages, the controller would instead work with Razor Views and a database context.

Common Mistakes to Avoid
Mixing MVC and Web API Terminology

An MVC controller and an API controller serve different purposes. Make sure the project template, controller base class, routes, and expected output match the application's architecture.

Assuming In-Memory Data Is Persistent
The static list is only temporary storage. Restarting the application resets the data.

Not Validating Input
APIs should validate incoming data before storing or processing it.

Exposing Internal Exception Details
Production APIs should avoid returning sensitive exception information directly to clients.

Using Manual ID Generation in Production
The example generates IDs from the current collection because it uses an in-memory list. A database should normally be responsible for generating unique primary keys.

Conclusion
CRUD operations are fundamental to most data-driven applications. ASP.NET Core provides a straightforward way to implement Create, Read, Update, and Delete operations through HTTP endpoints. In this example, we created a students model and implemented GET, POST, PUT, and DELETE operations using an ASP.NET Core Web API controller. We also tested the endpoints and reviewed how the same application can be extended with SQL Server and Entity Framework Core for persistent data storage.

The example is intentionally simple so that the CRUD workflow is easy to understand. In a production application, the next steps would typically include database persistence, model validation, authentication and authorization, service and repository layers, logging, error handling, and automated testing.



ASP.NET MVC Hosting - HostForLIFE.eu :: URL Creation Fundamentals In MVC

clock September 2, 2026 11:41 by author Peter

Let's start with MVC foundations. There are two ways to create a URL in the MVC framework: ActionLink and Raw HTML. In this tutorial, we will examine several methods of building URLs in MVC as well as other essential ideas of MVC.

Question - Which approach is best for URL creation?
Answer
Action LInk in the background queries the routing engine whenever the URL associated with the given controllers ACTION. Sometimes we do have Custom URLs associated with an action, and we require to change that URL in future. For this scenario actionLink will pick up the latest URL, you don't need to make any changes.

On the other hand, if you are using raw HTML, you need to update your links when URLs changed.

As a good programmer, we should always avoid changing URLs as URLs are the public contract of your app and can be referenced by other apps, and many times users bookmark the URLs. If you change them, all these bookmarks and references will be broken.

In the end, the decision is up to the programmer's choice, no hard and fast rule here.

Again, the simplest way is using raw HTML

1: Raw HTML
Example,
<a href = "Courses/Index"> View Course</a>

2: ActionLink
Below is the example of using ActionLink for URL creation.
@HTML.ActionLink("View Courses","Index","Courses")

If the targeted action needs a parameter we can make use of an anonymous object to pass the parameter values.
@HTML.ActionLink("View Courses","Index","Courses", new {id = 1})

This will generate a link as - courses/index/1

This method doesn't generate the link for a reason, we need to pass another argument to ActionLink. This argument can be null or an anonymous object to render any additional HTML attribute.
@HTML.ActionLink("View Courses","Index","Courses", new {id = 1}, null)

Type Helper Method
ViewResult View()
PartialViewResult PartialView()
RedirectResult Redirect()
ContentResult Content()
JsonResult Json()
RedirectToRouteResult RedirectToAction()
FileResult File()
HttpNotFoundResult HttpNotFound()
EmptyResult  

Passing Data to views in MVC
We should avoid passing data using ViewData and ViewBag as these methods are fragile and need a lot of casting which makes code ugly. Instead, we can pass model or viewModel directly to view.
return View(Course);

Razor Views
@if(condition)
{
    // c# or HTML code
}

@foreach(...)
{
}

We can render a class or any attribute conditionally as follows,
@{
    var className=Model.Movies.Count >3 ? "Popular" : null;
}
<h2 class = "@className">...</h2>


Partial View
@Html.Partial("_NavBar")

Types of Routing in MVC
1. Convention based Routing
Here we can specify the routing in RouteConfig.cs file and mention the Controller, action which needs to be invoked using mapRoute method of routes collection.

2. Attribute based Routing
Here we can apply route by decorating the action method with the Route keyword followed by the path.

Authentication in MVC
Use [authorize] keyword. Apply it to action, controller or globally (in FilterConfig.cs)
Enabling Social Login in MVC

Step 1
Enable SSL: Select project, press F4, set SSL enabled to true.

Step 2

Copy SSL URL, select the project, go to properties, in the Web tab, set startup URL.

Step 3
Apply RequireSSL filter globally in FilterConfig.cs file.

Step 4

Register your app with external authentication providers to get secret key/secret. In AppStart.cs/Startup.Auth.cs, add corresponding providers and your key/secret.

Summary
In this article, we explored different ways of URL creation in MVC and different fundamental concepts of MVC. I hope you liked the article. Until Next Time - Happy Learning.



ASP.NET MVC Hosting - HostForLIFE.eu :: Areas in ASP.NET MVC

clock August 28, 2026 13:51 by author Peter

The Model, View, and Controller folders are automatically generated when we start a new MVC project.

This structure is typical for small applications, however the single Model, View, and Controller may get cumbersome as your program expands and becomes more sophisticated. so that we may use regions to manage a complicated MVC application. We can build more maintainable code for an application that is neatly divided into modules by using areas.

Thus, start by creating a new, empty MVC project.

Next, choose the region by performing a right-click on Solution Explorer and selecting Add.

Provide a name.

Now add a second Employee area. In your Solution Explorer show your Model, View and Controller in a different student and employee area.

Now add a Home Controller and in the Index action add an Index View for both the student and employee area.

Now run the project. (Ctrl+F5).

For the Teacher area the follwing is the URL localhost/Teachers/Home/Index.

Here Teachers is the area name, Home is the controller and Index is the Action name.

For the Teacher area the follwing is the URL localhost/Students/Home/Index. Here Students is the area name, Home is the controller and Index is the Action name.



ASP.NET MVC Hosting - HostForLIFE.eu :: URL Routing Of ASP.NET MVC And ASP.NET Web Forms

clock August 18, 2026 13:47 by author Peter

Important Points Regarding ASP.NET MVC
The program ASP.NET MVC is open-source. The ASP.NET MVC is a web application framework developed by Microsoft, which implements the model–view–controller pattern. Partial Views in ASP.NET MVC allow for code reuse. Views and logic are stored independently in ASP.NET MVC. Razor is the default syntax used by ASP.NET MVC.HTML aids are available in ASP.NET MVC.ASP.NET MVC adheres to the MVC (approach, View, Controller) pattern-based development approach and is lightweight. View state is not supported by ASP.NET MVC.



Key Notes To ASP.NET Web Form
ASP.NET Web Form is not Open Source.ASP.NET Web Form follows a traditional event-driven development model.ASP.NET Web Form has server controls.ASP.NET Web Form supports view state for state management at client side.ASP.NET Web Form follows Web Forms Syntax.In ASP.NET Web Form, Web Forms(ASPX) i.e. views are tightly coupled to Code behind(ASPX.CS) i.e. logic. ASP.NET Web Form has User Controls for code re-usability.

Url Path Note Of ASP.NET MVC
ASP.NET MVC has route-based URLs which means URLs are divided into controllers and actions and moreover it is based on controller not on physical files.

Url Path Note Of ASP.NET Web Form
ASP.NET Web Form has file-based URLs means file name exist in the URLs must have its physical existence.

Description
Here I built one ASP.NET MVC and ASP.NET web form application.That will show you what the URL Path Concept Between ASP.NET MVC and ASP.NET Web Forms.
 
Steps to be followed For ASP.NET MVC

Step 1
Create a Mvc Project named "MvcWeb".

Step 2
Create class file in Models Folder named "Student.cs".

Code Ref
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.ComponentModel.DataAnnotations;  
      
    namespace MvcWeb.Models  
    {  
        public class Student  
        {  
            [Display(Name = "Name")]  
            public string StudentName { get; set; }  
        }  
    } 

Code Description
Add one variable or entity named "StudentName". To display the result in the page associate with label htmlhelper.
public string StudentName { get; set; } 

We can control the display of data in a view using display attributes that are found in System.ComponentModel.DataAnnotations namespace.
    [Display(Name = "Name")]  

Step 3

Create a controller class file named "HomeController.cs".

Code Ref
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
    using MvcWeb.Models;  
      
    namespace MvcWeb.Controllers  
    {  
        public class HomeController : Controller  
        {  
            //  
            // GET: /Home/  
      
            public ActionResult HFL()  
            {  
                return View();  
            }  
      
        }  
    } 

Code Description
Here I created one controller action method named "HFL()". Add the namespace reference on Model class that is,
    using MvcWeb.Models;  

Step 4
Create one view named "HFL.cshtml" in Views/Home Folder as the same name in controller action method.

Code Ref
    @model MvcWeb.Models.Student  
    @{  
        ViewBag.Title = "Satyaprakash";  
    }  
    <h2 style="background-color: Yellow; color: Blue; text-align: center; font-style: oblique">  
        Satyaprakash's Mvc Path Concept</h2>  
    <fieldset>  
        <legend style="font-family: Arial Black; color: blue">Student Name</legend>  
        @Html.LabelFor(m => m.StudentName, "Satyaprakash Samantaray")  
    </fieldset>  
      
      
    <footer>    
          <p style="background-color: Yellow; font-weight: bold; color:blue; text-align: center; font-style: oblique">© @DateTime.Now.ToLocalTime()</p> @*Add Date Time*@    
    </footer> 


Code Description
Here I added namespace in view to access properties of student model class file. 
    @model MvcWeb.Models.Student 

LabelFor helper method is a strongly typed extension method. It generates a html label element for the model object property specified using a lambda expression. LabelFor() method Signature: MvcHtmlString LabelFor(<Expression<Func<TModel,TValue>> expression) .
    @Html.LabelFor(m => m.StudentName, "Peter") 

We have specified the StudentName property of Student model using lambda expression in the LabelFor() method. So, it generates <label> and sets label text to the same as StudentName property name. Here labelfor htmlhelper will show the name "Satyaprakash Samantaray". 
 
Step 5
Set as start page In mvc.

Go to this file path "MvcWeb\App_Start\RouteConfig.cs". Open the file called "RouteConfig.cs".

Code Ref
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
    using System.Web.Routing;  
      
    namespace MvcWeb  
    {  
        public class RouteConfig  
        {  
            public static void RegisterRoutes(RouteCollection routes)  
            {  
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
      
                routes.MapRoute(  
                    name: "Default",  
                    url: "{controller}/{action}/{id}",  
                    defaults: new { controller = "Home", action = "HFL", id = UrlParameter.Optional }  
                );  
            }  
        }  
    } 


Code Description
So here I set start page :
    defaults: new { controller = "Home", action = "HFL", id = UrlParameter.Optional } 

 At page load time the controller Home and action method name HFL of home controller will be loaded.

OUTPUT OF MVC URL
http://localhost:1064/home/HFL

Steps to be followed For ASP.NET Webform

Step1
Create a ASP.NET Webform Project named "AspxWeb".

Step2
Create a new folder named "Home".

Step3
Then add webform named "HFL.aspx".

Code ref of HFL.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HFL.aspx.cs" Inherits="AspxWeb.Home.HFL" %>  
      
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    <html xmlns="http://www.w3.org/1999/xhtml">  
    <head runat="server">  
        <title>Satyaprakash</title>  
    </head>  
    <body>  
        <form id="form1" runat="server">  
        <div>  
            <h2 style="background-color: Yellow; color: Blue; text-align: center; font-style: oblique">  
                Peter's Webform Path Concept</h2>  
            <fieldset>  
                <legend style="font-family: Arial Black; color: blue">Student Name</legend>  
                <asp:Label ID="Peterlbl" runat="server" Text="Label"></asp:Label>  
            </fieldset>  
        </div>  
        </form>  
    </body>  
    <footer>      
            <p style="background-color: Yellow; font-weight: bold; color:blue; text-align: center; font-style: oblique">©<script>document.write(new Date().toDateString()); </script></p>      
        </footer>  
    </html> 

Code Description
Here I added label server control named "Peterlbl" .
    <asp:Label ID="
Peterlbl" runat="server" Text="Label"></asp:Label> 

Code ref of HFL.aspx.cs
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.UI;  
    using System.Web.UI.WebControls;  
      
    namespace AspxWeb.Home  
    {  
        public partial class HFL : System.Web.UI.Page  
        {  
            protected void Page_Load(object sender, EventArgs e)  
            {  
                Satyalbl.Text = "Peter";  
            }  
        }  
    } 


Code Description

In the page_load() event I added label control id with associate result which will show in webpage during load time.

Step4
Set start page follow below image .

Here the Home is the name of the folder and HFL.aspx name of the webform inside the Home folder.

Notes
In MVC , URL is mapped to a controller action method. Where as in web forms application, the URL is mapped to a physical file.

Module Summary

  • What is ASP.NET MVC.
  • What is ASP.NET Webform.
  • The url path concept between ASP.NET MVC and ASP.NET Web Forms.
  • Set start page in ASP.NET MVC and ASP.NET Web Forms.


ASP.NET MVC Hosting - HostForLIFE.eu :: Consuming WCF Service in MVC Application Using Entity Framework

clock August 13, 2026 14:15 by author Peter

This article includes a step by step tutorial to learn WCF using MVC in Visual Studio. We are also using the Entity Framework (.edmx model) for database operations. This scenario targets the user of Entity Framework Model's first approach that consumes WCF service which is consumed in MVC applications for CRUD operations.

Note :
Make sure that Entity Framework is already installed with Visual Studio. Otherwise, install it using NuGet Packages.
Create a table in your database with the name of "UserDetail", as the following.

Step 1. Crate a blank solution
Open Visual Studio.
File - New - Project…
Select "Other project Type" in the left pane and choose "Blank Solution."
Type the name of the Solution "MvcWcfEF";

Step 2. Creating an WCF Application
Right click on the MvcWcfEF solution in Solution Explorer and go to Add  New Project.

Select WCF Service Application Library and type the name as WcfServiceApp.
Click on OK.

Step 3. Creating a service for CRUD operation
Right click on the WcfServiceApp project and select Add - New Item.
Choose Web option from left pane and select "WCF Service".
Type the name as "MyService.svc" and click on Add button.

Step 4. Creating an Entity Framework Model
Right click on the WcfServiceApp project and select Add - New Item.
Choose Data option from left pane and select "ADO.NET Entity data model".
Type the name as "EntityModel.edmx" and click on Add button, same as in the following images.

 

Select your database and type the name of connection settings in web.config as "TestDBEntities".

Step 5. Write a service for CRUD operation
Open MyService.csv page from WcfService application and write the following code:
        using System;  
        using System.Collections.Generic;  
        using System.Data;  
        using System.Linq;  
        using System.Runtime.Serialization;  
        using System.ServiceModel;  
        using System.Text;  
          
        namespace WcfServiceApp  
        {  
            // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "MyService" in code, svc and config file together.  
            // NOTE: In order to launch WCF Test Client for testing this service, please select MyService.svc or MyService.svc.cs at the Solution Explorer and start debugging.  
            public class MyService : IMyService  
            {  
                public void DoWork()  
                {  
                }  
          
                public List<UserDetail> GetAllUser()  
                {  
                    List<UserDetail> userlst = new List<UserDetail>();  
                    TestDBEntities tstDb = new TestDBEntities();  
                    var lstUsr = from k in tstDb.UserDetails select k;  
                    foreach (var item in lstUsr)  
                    {  
                        UserDetail usr = new UserDetail();  
                        usr.Id = item.Id;  
                        usr.Name = item.Name;  
                        usr.Email = item.Email;  
                        userlst.Add(usr);  
          
                    }  
          
                    return userlst;  
                }  
          
          
          
                public UserDetail GetAllUserById(int id)  
                {  
          
                    TestDBEntities tstDb = new TestDBEntities();  
                    var lstUsr = from k in tstDb.UserDetails where k.Id==id select k;  
                    UserDetail usr = new UserDetail();  
                    foreach (var item in lstUsr)  
                    {  
          
                        usr.Id = item.Id;  
                        usr.Name = item.Name;  
                        usr.Email = item.Email;  
          
          
                    }  
          
                    return usr;  
                }  
          
                public int DeleteUserById(int Id)  
                {  
          
                    TestDBEntities tstDb = new TestDBEntities();  
                    UserDetail usrdtl = new UserDetail();  
                    usrdtl.Id = Id;  
                    tstDb.Entry(usrdtl).State = EntityState.Deleted;  
                    int Retval = tstDb.SaveChanges();  
                    return Retval;  
                }  
          
                public int AddUser(string Name, string Email)  
                {  
                    TestDBEntities tstDb = new TestDBEntities();  
                    UserDetail usrdtl = new UserDetail();  
                    usrdtl.Name = Name;  
                    usrdtl.Email = Email;  
                    tstDb.UserDetails.Add(usrdtl);  
                    int Retval = tstDb.SaveChanges();  
                    return Retval;  
                }  
              public int UpdateUser(int Id,string Name, string Email)  
                {  
                    TestDBEntities tstDb = new TestDBEntities();  
                    UserDetail usrdtl = new UserDetail();  
                    usrdtl.Id = Id;  
                    usrdtl.Name = Name;  
                    usrdtl.Email = Email;  
                    tstDb.Entry(usrdtl).State = EntityState.Modified;  
                     
                    int Retval = tstDb.SaveChanges();  
                    return Retval;  
                }  
                 
            }  
        }  


Now, Open IMyService and write the "ServiceContract" and "DatatContract", as follows.
using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Runtime.Serialization;  
    using System.ServiceModel;  
    using System.Text;  
      
    namespace WcfServiceApp  
    {  
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IMyService" in both code and config file together.  
        [ServiceContract]  
        public interface IMyService  
        {  
            [OperationContract]  
           List<UserDetail> GetAllUser();  
            [OperationContract]  
            int AddUser(string Name, string Email);  
            [OperationContract]  
            UserDetail GetAllUserById(int id);  
      
            [OperationContract]  
            int UpdateUser(int Id, string Name, string Email);  
      
            [OperationContract]  
            int DeleteUserById(int Id);  
        }  
      
      
        [DataContract]  
        public class UserDetails  
        {  
            [DataMember]  
            public int Id { get; set; }  
            [DataMember]  
            public string Name { get; set; }  
            [DataMember]  
            public string Email { get; set; }  
          
          
        }  
    }  

Service has been completed. Now, build the service.

  • Press F5 to run the Service.
  • Copy the Service URL, as shown in following image (localhost:1034/MyService.svc), for creating the reference.

Step 6. Creating an MVC Application

  • Now, right click on the "MvcWcfEF " solution in Solution Explorer, again.
  • Select e New  Project…
  • Select ASP.NET MVC3/4 Web Application.
  • Enter the name of application as "MvcApp".
  • Click on OK.

Adding a Project Priority and setting the reference

  • Right click on the MvcApp and click on add service reference as in he image below.
  • Paste the Copied Service URL in the given address and press Go button.
  • All the services will display, as in the folowing picture. Just give the Namespace as "ServiceRefernce1" and click on OK button.

Since WCF service application and MVC application both are in the same solution, we have to build the Service first and then the MVC application in order to consume the service in MVC application. Do the following for that,
Right Click on the MvcWcfEF Solution in Solution Explorer and click on properties.
Check the "Multiple Startup Project " and set the application priority for WCF and MVC application (WCF service should be first and MVC afterwards), as in the following image.

Create a Model

Right click on Model folder and click on Class. Write the class name as "User" and create the following properties.

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
      
    namespace MvcApp.Models  
    {  
        public class User  
        {  
      
             
                public int Id { get; set; }  
                 
                public string Name { get; set; }  
                 
                public string Email { get; set; }  
      
        }  
    }  

Create a Controller

Right click on the Controller folder and click on add controller. Give the name of controller as "HomeController" and write the following action for CRUD operation.
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
    using MvcApp.Models;  
      
      
    namespace MvcApp.Controllers  
    {  
        public class HomeController : Controller  
        {  
            //  
            // GET: /Home/  
            ServiceReference1.MyServiceClient ur = new ServiceReference1.MyServiceClient();  
            public ActionResult Index()  
            {  
                List<User> lstRecord = new List<User>();  
                 
                var lst = ur.GetAllUser();  
      
                foreach (var item in lst)  
                {  
                    User usr = new User();  
                    usr.Id = item.Id;  
                    usr.Name = item.Name;  
                    usr.Email = item.Email;  
                    lstRecord.Add(usr);  
                  
                }  
      
      
                return View(lstRecord);  
            }  
      
      
            public ActionResult Add()  
            {  
      
                return View();  
            }  
            [HttpPost]  
            public ActionResult Add(User mdl)  
            {  
      
                User usr= new User();  
                usr.Name=mdl.Name;  
                usr.Email=mdl.Email;  
                ur.AddUser(usr.Name,usr.Email);  
                return RedirectToAction("Index", "Home");  
                
            }  
            public ActionResult Delete(int id)  
            {  
                int retval = ur.DeleteUserById(id);  
                if (retval > 0)  
                {  
                    return RedirectToAction("Index", "Home");  
                }  
      
                return View();  
            }  
      
            public ActionResult Edit(int id)  
             {  
                var lst = ur.GetAllUserById(id);  
                  User usr = new User();  
                  usr.Id = lst.Id;  
                  usr.Name = lst.Name;  
                  usr.Email = lst.Email;  
                  return View(usr);  
      
            }  
            [HttpPost]  
            public ActionResult Edit(User mdl)  
            {  
                User usr = new User();  
                usr.Id = mdl.Id;  
                usr.Name = mdl.Name;  
                usr.Email = mdl.Email;  
      
      
                int Retval = ur.UpdateUser(usr.Id, usr.Name, usr.Email);  
                if (Retval > 0)  
                {  
                    return RedirectToAction("Index", "Home");  
                }  
                return View();  
            }  
        }  
    }  

Creating a View
Creating a view is very simple. Just right click on All action of the controller and click on Add View. The following is the code for all views (Index, Add, Edit). 
Index.cshtml
    @model IEnumerable<MvcApp.Models.User>  
      
    @{  
        ViewBag.Title = "Index";  
    }  
      
      
    @using (Html.BeginForm()){  
        <div>  
            <h2>User Details</h2>  
             @Html.ActionLink("Add User", "Add", "")  
        </div>  
        <div>  
             <table >  
                <tr style="background-color: #FFFACD; text-align:center">  
                    <th style="text-align:left">  
                        Name  
                    </th>  
                    <th style="text-align:left">  
                       Email  
                    </th>  
                    <th style="text-align:left">  
                        Manage  
                    </th>  
                </tr>  
      
                @{  
                    foreach (var item in Model)  
                    {  
                    <tr style="background-color: #FFFFF0">  
                        <td>  
                            @item.Name  
                        </td>  
                        <td>  
                            @item.Email  
                        </td>  
                         
                        <td>  
                            @Html.ActionLink("Edit", "Edit", new { id = @item.Id }) /@Html.ActionLink("Delete", "Delete", new {[email protected] })   
                             
                        </td>  
                         
                    </tr>  
                    }  
                }  
      
            </table>  
      
        </div>  
         
      
    }  


Add.cshtml
    @model MvcApp.Models.User  
      
    @{  
        ViewBag.Title = "Add";  
    }  
      
    <h2>Add New User</h2>  
      
    @using (Html.BeginForm()) {   
      
    <div style="text-align:center">  
      
        <table>  
            <tr>  
                <td>  
                    Name :   
                </td>  
                <td>   
                    @Html.TextBoxFor(m=>m.Name)  
                </td>  
            </tr>  
      
             <tr>  
                <td>  
                    Email :   
                </td>  
                <td>   
                    @Html.TextBoxFor(m=>m.Email)  
                </td>  
            </tr>  
             <tr>  
                <td>  
                    Email :   
                </td>  
                <td>   
                   <input type="submit" value="Submit" />  
                </td>  
            </tr>  
        </table>  
      
    </div>    
    }  


Edit.cshtml
    @model MvcApp.Models.User  
      
    @{  
        ViewBag.Title = "Edit";  
    }  
      
    <h2>Edit User</h2>  
      
    @using (Html.BeginForm()) {   
      
    <div style="text-align:center">  
      
        <table>  
            <tr>  
                <td>  
                    Name :   
                </td>  
                <td>   
                    @Html.TextBoxFor(m=>m.Name)  
                </td>  
            </tr>  
      
             <tr>  
                <td>  
                    Email :   
                </td>  
                <td>   
                    @Html.TextBoxFor(m=>m.Email)  
                </td>  
            </tr>  
             <tr>  
                <td>  
                       
                </td>  
                <td>   
                   <input type="submit" value="Update" />  
                </td>  
            </tr>  
        </table>  
      
    </div>  
    }  

Now, press F5 to run the Application



ASP.NET MVC Hosting - HostForLIFE.eu :: Different Ways Of Rendering Partial View In MVC

clock August 5, 2026 13:52 by author Peter

There are 5 different way of rendering a partial view.

  • Partial
  • Render partial
  • Action
  • Render action
  • JQuery load function

When to use a partial view?

  • To break up large markup files into smaller components.
  • To reduce the duplication of common markup content across markup files.
  • Partial views shouldn't be used to maintain common layout elements. Common layout elements should be specified in the _Layout.cshtml files.

Difference between RenderPartial and Partial
Partial
The partial method returns an MvcHtmlString object. Basically, it stringifies the HTML content in the location where it was specified.

RenderPartial
The RenderPartial method will not actually return any values or strings and instead, it will write the Partial View that is requested to the Response Stream through response.write internally.
 
Difference between RenderAction and Action
RenderAction

The RenderAction method renders the result directly to the response which means it is more efficient if the action returns a large amount of HTML.

Action
Action method returns a string with the result.
 
Let's see this via an example. 

Step 1
Open Visual Studio 2015 or an IDE of your choice and create a new project.

Step 2
Choose web application project and give an appropriate name to your project.

Step 3
Select empty template, check on MVC checkbox below, and click OK.

Step 4
Right click on the Models folder and add a database model. Add Entity Framework now. For that, right-click on Models folder, select Add, then select "New Item".

You will get a window; from there, select Data from the left panel and choose ADO.NET Entity Data Model, give it the name EmployeeModel (this name is not mandatory, you can give any name) and click "Add".

After you click on "Add a window", the wizard will open. Choose EF Designer from the database and click "Next".

After clicking on "Next", a window will appear. Choose "New Connection". Another window will appear. Add your server name - if it is local, then enter dot (.). Choose your database and click "OK".

The connection will be added. If you wish, save the connection name as you want. You can change the name of your connection below. It will save the connection in the web config. Now, click "Next"

After clicking on NEXT, another window will appear. Choose the database table name as shown in the below screenshot and click "Finish".


Entity Framework gets added and the respective class gets generated under the Models folder.

Step 5
Right click on controllers folder add a controller.

A window will appear. Choose MVC5 Controller-Empty and click "Add".

After clicking on "Add", another window will appear with DefaultController. Change the name to HomeController and click "Add". The HomeController will be added under the Controllers folder. Don’t change the Controller suffix for all controllers, change only the highlight, and instead of Default, just change Home;

Complete code for Home Controller
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
    using MvcPartialView_Demo.Models;  
       
    namespace MvcPartialView_Demo.Controllers  
    {  
        public class HomeController : Controller  
        {  
            private readonly EmployeeContext _dbContext=new EmployeeContext();  
       
            public ActionResult Index()  
            {  
                var employee = _dbContext.Employees.ToList();  
                return View(employee);  
            }  
       
            public PartialViewResult Employee()  
            {  
                return PartialView("_employee");  
            }  
        }  
    }  

Step 6

Right-click on Index method in HomeController. The "Add View" window will appear with default index name checked (use a Layout page), and click on "Add.


Html.Partial
    @{  
        ViewBag.Title = "Index";  
    }  
       
    <h3>List of Employee</h3>  
    @Html.Partial("_employee")  


Html.RenderPartial
    @{  
        ViewBag.Title = "Index";  
    }  
       
    <h3>List of Employee</h3>  
    @{  
        Html.RenderPartial("_employee");  
    }  


Html.Action
    @{  
        ViewBag.Title = "Index";  
    }  
       
    <h3>List of Employee</h3>  
    @{  
        @Html.Action("Employee")  
    }  

Html.RenderAction
    @{  
        ViewBag.Title = "Index";  
    }  
       
    <h3>List of Employee</h3>  
    @{  
        Html.RenderAction("Employee");  
    }  


JQuery load function 
    @{  
        ViewBag.Title = "Index";  
    }  
    <script src="~/Scripts/jquery-3.3.1.min.js"></script>  
    <h3>List of employee</h3>  
    <div id="partialView">  
    </div>  
    <script type="text/javascript">  
        $(document).ready(function() {  
            $("#partialView").load('@Url.Content("/Home/Employee")');  
        });  
    </script>  

Step 7
Right-click on the "Shared" folder index views folder add a view name it _employee checked on create as a partial view, and click on "Add".

Code for partial view
    @model IEnumerable<MvcPartialView_Demo.Models.Employee>  
       
    <table class="table table-bordered">  
        <thead>  
        <tr>  
            <th>@Html.DisplayNameFor(m=>m.Name)</th>  
            <th>@Html.DisplayNameFor(m=>m.Gender)</th>  
            <th>@Html.DisplayNameFor(m=>m.Age)</th>  
            <th>@Html.DisplayNameFor(m=>m.Position)</th>  
            <th>@Html.DisplayNameFor(m=>m.Office)</th>  
            <th>@Html.DisplayNameFor(m=>m.HireDate)</th>  
            <th>@Html.DisplayNameFor(m=>m.Salary)</th>  
        </tr>  
        </thead>  
        <tbody>  
        @foreach (var emp in Model)  
        {  
            <tr>  
                <td>@emp.Name</td>  
                <td>@emp.Gender</td>  
                <td>@emp.Age</td>  
                <td>@emp.Position</td>  
                <td>@emp.Office</td>  
                <td>  
                    @if (emp.HireDate != null)  
                    {  
                        @emp.HireDate.Value.ToString("dd/MM/yyyy")  
                    }  
                </td>  
                <td>@emp.Salary</td>  
            </tr>  
        }  
        </tbody>  
    </table>  

Step 8
Build and run your project by pressing CTRL+F5.



ASP.NET MVC Hosting - HostForLIFE.eu :: Onion Architecture In ASP.NET Core MVC

clock July 30, 2026 13:20 by author Peter

The Onion Architecture term was coined by Jeffrey Palermo in 2008. This architecture provides a better way to build applications for better testability, maintainability, and dependability on the infrastructures like databases and services. This architecture's main aim is to address the challenges faced with 3-tier architecture or n-tier architecture and to provide a solution for common problems, like coupling and separation of concerns. There are two types of coupling - tight coupling and loose coupling.

Tight Coupling
When a class is dependent on a concrete dependency, it is said to be tightly coupled to that class. A tightly coupled object is dependent on another object; that means changing one object in a tightly coupled application, often requires changes to a number of other objects. It is not difficult when an application is small but in an enterprise-level application, it is too difficult to make the changes.
 
Loose Coupling
It means two objects are independent and an object can use another object without being dependent on it. It is a design goal that seeks to reduce the interdependencies among components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.
 
Advantages of Onion Architecture
There are several advantages of the Onion Architecture, as listed below.

  • It provides better maintainability as all the codes depend on layers or the center.
  • It provides better testability as the unit test can be created for separate layers without an effect of other modules of the application.
  • It develops a loosely coupled application as the outer layer of the application always communicates with the inner layer via interfaces.
  • Any concrete implantation would be provided to the application at run time
  • Domain entities are core and center part. It can have access to both the database and UI layers.
  • The internal layers never depend on the external layer. The code that may have changed should be part of an external layer.

Why Onion Architecture
There are several traditional architectures, like 3-tier architecture and n-tier architecture, all having their own pros and cons. All these traditional architectures have some fundamental issues, such as - tight coupling and separation of concerns. The Model-View-Controller is the most commonly used web application architecture, these days. It solves the problem of separation of concern as there is a separation between UI, business logic, and data access logic. The View is used to design the user interface. The Model is used to pass the data between View and Controller on which the business logic performs any operations. The Controller is used to handle the web request by action methods and returns View accordingly. Hence, it solves the problem of separation of concern while the Controller is still used to database access logic. In essence, MVC solves the separation of concern issue but the tight coupling issue still remains.
 
On the other hand, Onion Architecture addresses both the separation of concern and tight coupling issues. The overall philosophy of the Onion Architecture is to keep the business logic, data access logic, and model in the middle of the application and push the dependencies as far outward as possible means all coupling towards to center.
 
Onion Architecture Layers
This architecture relies heavily on the Dependency Inversion Principle. The UI communicates to business logic through interfaces. It has four layers, as shown in figure 1.

  • Domain Entities Layer
  • Repository Layer
  • Service Layer
  • UI (Web/Unit Test) Layer

These layers are towards to center. The center part is the Domain entities that represent the business and behavior objects. These layers can vary but the domain entities layer is always part of the center. The other layer defines more behavior of an object. Let’s see each layer one by one.

Domain Entities Layer
It is the center part of the architecture. It holds all application domain objects. If an application is developed with the ORM entity framework then this layer holds POCO classes (Code First) or Edmx (Database First) with entities. These domain entities don't have any dependencies.
 
Repository Layer
The layer is intended to create an abstraction layer between the Domain entities layer and the Business Logic layer of an application. It is a data access pattern that prompts a more loosely coupled approach to data access. We create a generic repository, which queries the data source for the data, maps the data from the data source to a business entity, and persists changes in the business entity to the data source.
 
Service Layer
The layer holds interfaces which are used to communicate between the UI layer and repository layer. It holds business logic for an entity so it’s called the business logic layer as well.
 
UI Layer
It’s the most external layer. It could be the web application, Web API, or Unit Test project. This layer has an implementation of the Dependency Inversion Principle so that the application builds a loosely coupled application. It communicates to the internal layer via interfaces.

Onion Architecture Project Structure

To implement the Onion architecture, we develop an ASP.NET Core application. This application performs CRUD operations on entities. The application holds four projects as per figure 2. Each project represents a layer in onion architecture. 

There are four projects in which three are class library projects and one is a web application project. Let’s see each project mapping with onion architecture layers.

OA.Data
It is a class library project. It holds POCO classes along with configuration classes. It represents the Domain Entities layer of the onion architecture. These classes are used to create database tables. It’s a core and central part of the application.
 
OA.Repo
It is a second class library project. It holds a generic repository class with its interface implementation. It also holds a DbContext class. The Entity Framework Code First data access approach needs to create a data access context class that inherits from the DbContext class. This project represents the Repository layer of the onion architecture.
 
OA.Service
It is a third class library project. It holds business logic and interfaces. These interfaces communicate between UI and data access logic. As it communicates via interfaces,  it builds applications that are loosely coupled. This project represents the Service layer of the onion architecture.
 
OA.Web

It is an ASP.NET Core Web application in this sample but it could be a Unit Test or Web API project. It is the most external part of an application by which the end-user can interact with the application. It builds loosely coupled applications with in-built dependency injection in ASP.NET Core. It represents the UI layer of the onion architecture.

Implement Onion Architecture
To implement the Onion Architecture in the ASP.NET Core application, create four projects as described in the above section. These four projects represent four layers of the onion architecture. Let’s see each one by one.
 
Domain Entities Layer
The Entities Domain layer is a core and central part of the architecture. So first, we create "OA.Data" project to implement this layer. This project holds POCO class and fluent API configuration for this POCO classes.
 
There is an unsupported issue of EF Core 1.0.0-preview2-final with "NETStandard.Library": "1.6.0". Thus, we have changed the target framework to netstandard1.6 > netcoreapp1.0. We modify the project.json file of OA.Data project to implement the Entity Framework Core in this class library project. Thus, the code snippet, mentioned below, is used for the project.json file after modification.
    {  
      "dependencies": {  
        "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",  
        "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"  
      },  
      "frameworks": {  
        "netcoreapp1.0": {  
          "imports": [ "dotnet5.6", "portable-net45+win8" ]  
        }  
      },  
      "tools": {  
        "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"  
      },  
      "version": "1.0.0-*"  
    }  


This Application uses the Entity Framework Code First approach, so the project OA.Data contains entities that are required in the application's database. The OA.Data project holds three entities, one is the BaseEntity class that has common properties that will be inherited by each entity. The code snippet, mentioned below is the BaseEntity class.
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Threading.Tasks;  
      
    namespace OA.Data  
    {  
        public class BaseEntity  
        {  
            public Int64 Id { get; set; }  
            public DateTime AddedDate { get; set; }  
            public DateTime ModifiedDate { get; set; }  
            public string IPAddress { get; set; }  
        }  
    }  


There are two more entities, one is User and the another one is UserProfile. Both entities have a one to one relationship, as shown below. 

Now, we create an User entity, which is inherited from BaseEntity class. The code snippet, mentioned below is for the User entity.
    namespace OA.Data  
    {  
        public class User:BaseEntity  
        {  
            public string UserName { get; set; }  
            public string Email { get; set; }  
            public string Password { get; set; }  
            public virtual UserProfile UserProfile { get; set; }  
        }  
    }  

Now, we define the configuration for the User entity that will be used when the database table will be created by the entity. The following is a code snippet for the User mapping entity (UserMap.cs).
    using Microsoft.EntityFrameworkCore.Metadata.Builders;  
      
    namespace OA.Data  
    {  
        public class UserMap  
        {  
            public UserMap(EntityTypeBuilder<User> entityBuilder)  
            {  
                entityBuilder.HasKey(t => t.Id);  
                entityBuilder.Property(t => t.Email).IsRequired();  
                entityBuilder.Property(t => t.Password).IsRequired();  
                entityBuilder.Property(t => t.Email).IsRequired();  
                entityBuilder.HasOne(t => t.UserProfile).WithOne(u => u.User).HasForeignKey<UserProfile>(x => x.Id);  
            }  
        }  
    }  


Now, we create a UserProfile entity, which inherits from the BaseEntity class. The code snippet, mentioned below is for the UserProfile entity.
    namespace OA.Data  
    {  
        public class UserProfile:BaseEntity  
        {  
            public string FirstName { get; set; }  
            public string LastName { get; set; }  
            public string Address { get; set; }  
            public virtual User User { get; set; }  
        }  
    }  


Now, we define the configuration for the UserProfile entity that will be used when the database table will be created by the entity. The code snippet is mentioned below for the UserProfile mapping entity (UserProfileMap.cs).
    using Microsoft.EntityFrameworkCore.Metadata.Builders;  
      
    namespace OA.Data  
    {  
        public class UserProfileMap  
        {  
            public UserProfileMap(EntityTypeBuilder<UserProfile> entityBuilder)  
            {  
                entityBuilder.HasKey(t => t.Id);  
                entityBuilder.Property(t => t.FirstName).IsRequired();  
                entityBuilder.Property(t => t.LastName).IsRequired();  
                entityBuilder.Property(t => t.Address);    
            }  
        }  
    }  

Repository Layer
Now we create a second layer of the onion architecture which is a repository layer. To build this layer, we create one more class library project named OA.Repo. This project holds both repository and data, context classes.
 
The OA.Repo project contains DataContext. The ADO.NET Entity Framework Code First data access approach needs to create a data access context class that inherits from the DbContext class, so we create a context class ApplicationContext (ApplicationContext.cs).
 
In this class, we override the OnModelCreating() method. This method is called when the model for a context class (ApplicationContext) has been initialized, but before the model has been locked down and used to initialize the context such that the model can be further configured before it is locked down. The following is the code snippet for the context class.
    using Microsoft.EntityFrameworkCore;  
    using OA.Data;  
      
    namespace OA.Repo  
    {  
        public class ApplicationContext : DbContext  
        {  
            public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)  
            {  
            }  
            protected override void OnModelCreating(ModelBuilder modelBuilder)  
            {  
                base.OnModelCreating(modelBuilder);  
                new UserMap(modelBuilder.Entity<User>());  
                new UserProfileMap(modelBuilder.Entity<UserProfile>());  
            }  
        }  
    }  


The DbContext must have an instance of DbContextOptions in order to execute. We will use dependency injection, so we pass options via constructor dependency injection. ASP.NET Core is designed from the ground to support and leverage dependency injection. Thus, we create generic repository interface for the entity operations, so that we can develop loosely coupled application. The code snippet, mentioned below is for the IRepository interface.
    using OA.Data;  
    using System.Collections.Generic;  
      
    namespace OA.Repo  
    {  
        public interface IRepository<T> where T : BaseEntity  
        {  
            IEnumerable<T> GetAll();  
            T Get(long id);  
            void Insert(T entity);  
            void Update(T entity);  
            void Delete(T entity);  
            void Remove(T entity);  
            void SaveChanges();  
        }  
    }  


Now, let's create a repository class to perform database operations on the entity, which implements IRepository. This repository contains a parameterized constructor with a parameter as Context, so when we create an instance of the repository, we pass a context so that the entity has the same context. The code snippet is mentioned below for the Repository class under OA.Repo project.
    using Microsoft.EntityFrameworkCore;  
    using OA.Data;  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
      
    namespace OA.Repo  
    {  
        public class Repository<T> : IRepository<T> where T : BaseEntity  
        {  
            private readonly ApplicationContext context;  
            private DbSet<T> entities;  
            string errorMessage = string.Empty;  
      
            public Repository(ApplicationContext context)  
            {  
                this.context = context;  
                entities = context.Set<T>();  
            }  
            public IEnumerable<T> GetAll()  
            {  
                return entities.AsEnumerable();  
            }  
      
            public T Get(long id)  
            {  
                return entities.SingleOrDefault(s => s.Id == id);  
            }  
            public void Insert(T entity)  
            {  
                if (entity == null)  
                {  
                    throw new ArgumentNullException("entity");  
                }  
                entities.Add(entity);  
                context.SaveChanges();  
            }  
      
            public void Update(T entity)  
            {  
                if (entity == null)  
                {  
                    throw new ArgumentNullException("entity");  
                }  
                context.SaveChanges();  
            }  
      
            public void Delete(T entity)  
            {  
                if (entity == null)  
                {  
                    throw new ArgumentNullException("entity");  
                }  
                entities.Remove(entity);  
                context.SaveChanges();  
            }  
            public void Remove(T entity)  
            {  
                if (entity == null)  
                {  
                    throw new ArgumentNullException("entity");  
                }  
                entities.Remove(entity);              
            }  
      
            public void SaveChanges()  
            {  
                context.SaveChanges();  
            }  
        }  
    }  

We developed entity and context which are required to create a database but we will come back to this after creating the two more projects.
 
Service Layer
Now we create the third layer of the onion architecture which is a service layer. To build this layer, we create one more class library project named OA.Service. This project holds interfaces and classes which have an implementation of interfaces. This layer is intended to build loosely coupled applications. This layer communicates to both Web applications and repository projects.
 
We create an interface named IUserService. This interface holds all methods signature which accesses by external layer for the User entity. The following code snippet is for the same (IUserService.cs).
    using OA.Data;  
    using System.Collections.Generic;  
      
    namespace OA.Service  
    {  
        public  interface IUserService  
        {  
            IEnumerable<User> GetUsers();  
            User GetUser(long id);  
            void InsertUser(User user);  
            void UpdateUser(User user);  
            void DeleteUser(long id);  
        }  
    }  


Now, this IUserService interface implements on a class named UserService. This UserService class holds all the operations for User entity. The following code snippet is for the same(UserService.cs).
    using OA.Data;  
    using OA.Repo;  
    using System.Collections.Generic;  
      
    namespace OA.Service  
    {  
        public class UserService:IUserService  
        {  
            private IRepository<User> userRepository;  
            private IRepository<UserProfile> userProfileRepository;  
      
            public UserService(IRepository<User> userRepository, IRepository<UserProfile> userProfileRepository)  
            {  
                this.userRepository = userRepository;  
                this.userProfileRepository = userProfileRepository;  
            }  
      
            public IEnumerable<User> GetUsers()  
            {  
                return userRepository.GetAll();  
            }  
      
            public User GetUser(long id)  
            {  
                return userRepository.Get(id);  
            }  
      
            public void InsertUser(User user)  
            {  
                userRepository.Insert(user);  
            }  
            public void UpdateUser(User user)  
            {  
                userRepository.Update(user);  
            }  
      
            public void DeleteUser(long id)  
            {              
                UserProfile userProfile = userProfileRepository.Get(id);  
                userProfileRepository.Remove(userProfile);  
                User user = GetUser(id);  
                userRepository.Remove(user);  
                userRepository.SaveChanges();  
            }  
        }  
    }  

We create one more interface named IUserProfileService. This interface holds method signature which is accessed by the external layer for the UserProfile entity. The following code snippet is for the same (IUserProfileService.cs).
    using OA.Data;  
      
    namespace OA.Service  
    {  
        public interface IUserProfileService  
        {  
            UserProfile GetUserProfile(long id);  
        }  
    }  


Now, this IUserProfileService interface implements on a class named UserProfileService. This UserProfileService class holds the operation for UserProfile entity. The following code snippet is for the same(UserProfileService.cs).
    using OA.Data;  
    using OA.Repo;  
      
    namespace OA.Service  
    {  
        public class UserProfileService: IUserProfileService  
        {  
            private IRepository<UserProfile> userProfileRepository;  
      
            public UserProfileService(IRepository<UserProfile> userProfileRepository)  
            {             
                this.userProfileRepository = userProfileRepository;  
            }  
      
            public UserProfile GetUserProfile(long id)  
            {  
                return userProfileRepository.Get(id);  
            }  
        }  
    }  

UI Layer

Now, we create the external layer of the onion architecture which is a UI layer. The end-user interacts with the application by this layer. To build this layer, we create an ASP.NET Core MVC web application named OA.Web. This layer communicates with service layer projects. This project contains the user interface for both user and user profile entities database operations and the controller to do these operations.
 
As the concept of dependency injection is central to the ASP.NET Core application, we register context, repository, and service to the dependency injection during the application start up. Thus, we register these as a Service in the ConfigureServices method in the StartUp class as per the following code snippet.
    public void ConfigureServices(IServiceCollection services)  
          {             
              services.AddMvc();  
              services.AddDbContext<ApplicationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));  
              services.AddScoped(typeof(IRepository<>), typeof(Repository<>));  
              services.AddTransient<IUserService, UserService>();  
              services.AddTransient<IUserProfileService, UserProfileService>();  
          }  

Here, the DefaultConnection is connection string which defined in appsettings.json file as per following code snippet.

    {  
      "ConnectionStrings": {  
        "DefaultConnection": "Data Source=DESKTOP-RG33QHE;Initial Catalog=OADb;User ID=sa; Password=***"  
      },  
      "Logging": {  
        "IncludeScopes": false,  
        "LogLevel": {  
          "Default": "Debug",  
          "System": "Information",  
          "Microsoft": "Information"  
        }  
      }  
    }  

Now, we have configured settings to create a database, so we have time to create a database, using migration. We must choose the OA.Repo project in the Package Manager console during the performance of the steps, mentioned below.

  • Tools -> NuGet Package Manager -> Package Manager Console
  • Run PM> Add-Migration MyFirstMigration to scaffold a migration to create the initial set of tables for our model. If we receive an error stating the term `add-migration' is not recognized as the name of a cmdlet, then close and reopen Visual Studio.
  • Run PM> Update-Database to apply the new migration to the database. Because our database doesn't exist yet, it will be created for us before the migration is applied.

Create Application User Interface
Now, we proceed to the controller. We create a controller named UserController under the Controllers folder of the application. It has all ActionResult methods for the end-user interface of operations. We create both IUserService and IUserProfile interface instances; then we inject these in the controller's constructor to get its object. The following is a partial code snippet for the UserController in which service interfaces are injected, using constructor dependency injection.
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using Microsoft.AspNetCore.Mvc;  
    using OA.Service;  
    using OA.Web.Models;  
    using OA.Data;  
    using Microsoft.AspNetCore.Http;  
      
    namespace OA.Web.Controllers  
    {  
        public class UserController : Controller  
        {  
            private readonly IUserService userService;  
            private readonly IUserProfileService userProfileService;  
      
            public UserController(IUserService userService, IUserProfileService userProfileService)  
            {  
                this.userService = userService;  
                this.userProfileService = userProfileService;  
            }  
        }  
    }  


We can notice that Controller takes both IUserService and IUserProfileService as a constructor parameters. The ASP.NET Core dependency injection will take care of passing an instance of these services into UserController. The controller is developed to handle operations requests for both User and UserProfile entities. Now, let's develop the user interface for the User Listing, Add User, Edit User and Delete User. Let's see each one by one.
 
User List View
This is the first view when the application is accessed or the entry point of the application is executed. It shows the author listing as in Figure 4. The user data is displayed in a tabular format and on this view, it has linked to add a new user, edit a user and delete a user.
 
To pass data from controller to view, create named UserViewModel view model, as per the code snippet, mentioned below. This view model is also used for adding or editing a user.
    using Microsoft.AspNetCore.Mvc;  
    using System;  
    using System.ComponentModel.DataAnnotations;  
      
    namespace OA.Web.Models  
    {  
        public class UserViewModel  
        {  
            [HiddenInput]  
            public Int64 Id { get; set; }  
            [Display(Name = "First Name")]  
            public string FirstName { get; set; }  
            [Display(Name = "Last Name")]  
            public string LastName { get; set; }  
            public string Name { get; set; }  
            public string Address { get; set; }  
            [Display(Name = "User Name")]  
            public string UserName { get; set; }  
            public string Email { get; set; }  
            public string Password { get; set; }  
            [Display(Name = "Added Date")]  
            public DateTime AddedDate { get; set; }  
        }  
    }  

Now, we create action method, which returns an index view with the data. The code snippet of Index action method in UserController is mentioned below.
    [HttpGet]  
            public IActionResult Index()  
            {  
                List<UserViewModel> model = new List<UserViewModel>();  
                userService.GetUsers().ToList().ForEach(u =>  
                {  
                    UserProfile userProfile = userProfileService.GetUserProfile(u.Id);  
                    UserViewModel user = new UserViewModel  
                    {  
                        Id = u.Id,  
                        Name = $"{userProfile.FirstName} {userProfile.LastName}",  
                        Email = u.Email,  
                        Address = userProfile.Address  
                    };  
                    model.Add(user);  
                });  
      
                return View(model);  
            }  

Now, we create an index view, as per the code snippet, mentioned below under the User folder of views.
    @model IEnumerable<UserViewModel>  
    @using OA.Web.Models  
    @using OA.Web.Code  
      
    <div class="top-buffer"></div>  
    <div class="panel panel-primary">  
        <div class="panel-heading panel-head">Users</div>  
        <div class="panel-body">  
            <div class="btn-group">  
                <a id="createEditUserModal" data-toggle="modal" asp-action="AddUser" data-target="#modal-action-user" class="btn btn-primary">  
                    <i class="glyphicon glyphicon-plus"></i>  Add User  
                </a>  
            </div>  
            <div class="top-buffer"></div>  
            <table class="table table-bordered table-striped table-condensed">  
                <thead>  
                    <tr>  
                        <th>Name</th>  
                        <th>Email</th>  
                        <th>Address</th>  
                        <th>Action</th>  
                    </tr>  
                </thead>  
                <tbody>  
                    @foreach (var item in Model)  
                    {  
                        <tr>  
                            <td>@Html.DisplayFor(modelItem => item.Name)</td>  
                            <td>@Html.DisplayFor(modelItem => item.Email)</td>  
                            <td>@Html.DisplayFor(modelItem => item.Address)</td>  
                            <td>  
                                <a id="editUserModal" data-toggle="modal" asp-action="EditUser" asp-route-id="@item.Id" data-target="#modal-action-user"  
                                   class="btn btn-info">  
                                    <i class="glyphicon glyphicon-pencil"></i>  Edit  
                                </a>                           
                                <a id="deleteUserModal" data-toggle="modal" asp-action="DeleteUser" asp-route-id="@item.Id" data-target="#modal-action-user" class="btn btn-danger">  
                                    <i class="glyphicon glyphicon-trash"></i>  Delete  
                                </a>  
                            </td>  
                        </tr>  
                    }  
                </tbody>  
            </table>  
        </div>  
    </div>  
      
    @Html.Partial("_Modal", new BootstrapModel { ID = "modal-action-user", AreaLabeledId = "modal-action-user-label", Size = ModalSize.Large })  
      
    @section scripts  
    {  
        <script src="~/js/user-index.js" asp-append-version="true"></script>  
    }  

It shows all forms in the Bootstrap model popup so create the user - index.js file as per the following code snippet.

    (function ($) {  
    function User() {  
    var $this = this;  
      
    function initilizeModel() {  
    $("#modal-action-user").on('loaded.bs.modal', function (e) {  
      
    }).on('hidden.bs.modal', function (e) {  
    $(this).removeData('bs.modal');  
    });  
    }  
    $this.init = function () {  
    initilizeModel();  
    }  
    }  
    $(function () {  
    var self = new User();  
    self.init();  
    })  
    }(jQuery))  

When the application runs and calls the index() action method from UserController with a HttpGet request, it gets all the users listed in the UI, as shown in Figure 4. 

Add User 
To pass the data from UI to the controller to add a user, use the same view model named UserViewModel. The AuthorController has an action method named AddUser which returns the view to add a user. The code snippet mentioned below is for the same action method for both GET and Post requests.
    [HttpGet]  
            public ActionResult AddUser()  
            {  
                UserViewModel model = new UserViewModel();  
      
                return PartialView("_AddUser", model);  
            }  
      
            [HttpPost]  
            public ActionResult AddUser(UserViewModel model)  
            {  
                User userEntity = new User  
                {  
                    UserName = model.UserName,  
                    Email = model.Email,  
                    Password = model.Password,  
                    AddedDate = DateTime.UtcNow,  
                    ModifiedDate = DateTime.UtcNow,  
                    IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString(),  
                    UserProfile = new UserProfile  
                    {  
                        FirstName = model.FirstName,  
                        LastName = model.LastName,  
                        Address = model.Address,  
                        AddedDate = DateTime.UtcNow,  
                        ModifiedDate = DateTime.UtcNow,  
                        IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString()  
                    }  
                };  
                userService.InsertUser(userEntity);  
                if (userEntity.Id > 0)  
                {  
                    return RedirectToAction("index");  
                }  
                return View(model);  
            }  


The GET request for the AddUser action method returns _AddUser partial view; the code snippet follows under the User folder of views.
    @model UserViewModel  
    @using OA.Web.Models  
      
    <form asp-action="AddUser" role="form">  
        @await Html.PartialAsync("_ModalHeader", new ModalHeader { Heading = "Add User" })  
        <div class="modal-body form-horizontal">  
            <div class="row">  
                <div class="col-lg-6">  
                    <div class="form-group">  
                        <label asp-for="FirstName" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="FirstName" class="form-control" />  
                        </div>  
                    </div>  
                    <div class="form-group">  
                        <label asp-for="LastName" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="LastName" class="form-control" />  
                        </div>  
                    </div>  
                    <div class="form-group">  
                        <label asp-for="Email" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="Email" class="form-control" />  
                        </div>  
                    </div>  
                </div>  
                <div class="col-lg-6">  
                    <div class="form-group">  
                        <label asp-for="UserName" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="UserName" class="form-control" />  
                        </div>  
                    </div>  
                    <div class="form-group">  
                        <label asp-for="Password" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input type="password" asp-for="Password" class="form-control" />  
                        </div>  
                    </div>  
                    <div class="form-group">  
                        <label asp-for="Address" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="Address" class="form-control" />  
                        </div>  
                    </div>  
                </div>  
            </div>  
        </div>  
        @await Html.PartialAsync("_ModalFooter", new ModalFooter { })  
    </form>  


When the application runs and you click on the Add User button, it makes a GET request for the AddUser() action; add a user screen, as shown in Figure 5. 

Edit User
To pass the data from UI to a controller to edit a user, use same view model named UserViewModel. The UserController has an action method named EditUser, which returns the view to edit a user. The code snippet mentioned below is  for the same action method for both GET and Post requests.
    public ActionResult EditUser(int? id)  
          {  
              UserViewModel model = new UserViewModel();  
              if (id.HasValue && id != 0)  
              {  
                  User userEntity = userService.GetUser(id.Value);  
                  UserProfile userProfileEntity = userProfileService.GetUserProfile(id.Value);  
                  model.FirstName = userProfileEntity.FirstName;  
                  model.LastName = userProfileEntity.LastName;  
                  model.Address = userProfileEntity.Address;  
                  model.Email = userEntity.Email;  
              }  
              return PartialView("_EditUser", model);  
          }  
      
          [HttpPost]  
          public ActionResult EditUser(UserViewModel model)  
          {  
              User userEntity = userService.GetUser(model.Id);  
              userEntity.Email = model.Email;  
              userEntity.ModifiedDate = DateTime.UtcNow;  
              userEntity.IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString();  
              UserProfile userProfileEntity = userProfileService.GetUserProfile(model.Id);  
              userProfileEntity.FirstName = model.FirstName;  
              userProfileEntity.LastName = model.LastName;  
              userProfileEntity.Address = model.Address;  
              userProfileEntity.ModifiedDate = DateTime.UtcNow;  
              userProfileEntity.IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString();  
              userEntity.UserProfile = userProfileEntity;  
              userService.UpdateUser(userEntity);  
              if (userEntity.Id > 0)  
              {  
                  return RedirectToAction("index");  
              }  
              return View(model);  
          }  


The GET request for the EditUser action method returns _EditUser partial view, where code snippet follows under the User folder of views.
    @model UserViewModel  
    @using OA.Web.Models  
      
    <form asp-action="EditUser" role="form">  
        @await Html.PartialAsync("_ModalHeader", new ModalHeader { Heading = "Edit User" })  
        <div class="modal-body form-horizontal">  
            <div class="row">              
                <input asp-for="Id" />  
                    <div class="form-group">  
                        <label asp-for="FirstName" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="FirstName" class="form-control" />  
                        </div>  
                    </div>  
                    <div class="form-group">  
                        <label asp-for="LastName" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="LastName" class="form-control" />  
                        </div>  
                    </div>  
                    <div class="form-group">  
                        <label asp-for="Email" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="Email" class="form-control" />  
                        </div>  
                    </div>           
                
                    <div class="form-group">  
                        <label asp-for="Address" class="col-lg-3 col-sm-3 control-label"></label>  
                        <div class="col-lg-6">  
                            <input asp-for="Address" class="form-control" />  
                        </div>  
                    </div>  
                  
            </div>  
        </div>  
        @await Html.PartialAsync("_ModalFooter", new ModalFooter { })  
    </form>  


When the application runs and you click on the Edit button in the User listing, it makes a GET request for the EditUser() action, then the edit user screen is shown in Figure 6. 

 

Delete User
The UserController has an action method named DeleteUser, which returns view to delete a user. The code snippet mentioned below is for the same action method for both GET and Post requests.
    [HttpGet]  
            public PartialViewResult DeleteUser(int id)  
            {  
                UserProfile userProfile = userProfileService.GetUserProfile(id);  
                string name = $"{userProfile.FirstName} {userProfile.LastName}";  
                return PartialView("_DeleteUser", name);  
            }  
      
            [HttpPost]  
            public ActionResult DeleteUser(long id, FormCollection form)  
            {  
                userService.DeleteUser(id);            
                return RedirectToAction("Index");  
            }  

The GET request for the DeleteUser action method returns _DeleteUser partial View. The code snippet mentioned below is under the User folder of Views.
    @using OA.Web.Models  
      
    <form asp-action="DeleteUser" role="form">  
        @Html.Partial("_ModalHeader", new ModalHeader { Heading = "Delete User" })  
      
        <div class="modal-body form-horizontal">  
            Are you want to delete @Model?  
        </div>  
        @Html.Partial("_ModalFooter", new ModalFooter { SubmitButtonText = "Delete" })  
    </form>  


When the application runs and the user clicks on the "Delete" button in the user listing, it makes a GET request for the
 
DeleteUser() action, then the delete user screen is shown, as below.



Conclusion
This article introduced Onion Architecture in ASP.NET Core, using Entity Framework Core with the "code first" development approach. It’s widely accepted architecture these days. We used Bootstrap, CSS, and JavaScript for the user interface design in this application. 



ASP.NET MVC Hosting - HostForLIFE.eu :: MVC and Entity Framework-Based Server-Side Processing with Custom Range Filtering

clock July 22, 2026 11:47 by author Peter

This lesson will teach us how to use jQuery DataTables to accomplish server-side processing with custom range filtering. I will demonstrate the server-side paging, sorting, and filtering of a DataTable in an ASP.NET MVC application. Server-side refers to the use of C# code in the Controller section behind the file. To create custom multicolumn server-side filtering in jQuery DataTables, we may remove the global search box and use our own filter area with input fields like textbox and dropdown. This allows us to deal with jQuery DataTables by implementing our own filter sections wherever on our site.

With capabilities like pagination, searching, state saving, multi-column sorting with data type recognition, and much more, DataTable is the most potent and user-friendly jQuery plugin for presenting tabular data with ZERO or minimum configuration.

The following technologies must be understood in order to read this article.

The prerequisites of this article include knowledge of the following technologies.

  • ASP.NET MVC
  • HTML
  • JavaScript
  • AJAX
  • CSS
  • Bootstrap
  • C# Programming
  • C# LINQ
  • jQuery

Note. Before going through the session, I suggest you first visit my previous articles with a back-end section.

    Retrieve Records In jQuery Datatable Using Entity Framework And Bootstrap
    Performance Issue In jQuery DataTable About Fetching Records And Steps To Fix It

Steps to be followed
Step 1. Add a new action into the Controller to get the View where we will implement the jQuery DataTable with server-side paging and sorting.
Code
public ActionResult Filter()
{
    return View();
}

Step 2. Add a View for the action (here "filter") and design.

Code
@{
    ViewBag.Title = "HFL - Filter Records";
}
<h2 style="color: blue
">HFL-Server Side Processing With Custom Range Filtering</h2>
<style>
    table {
        font-family: arial, sans-serif;
        border-collapse: collapse;
        width: 100%;
    }
    td, th {
        border: 1px solid #dddddd
;
        text-align: left;
        padding: 8px;
    }
    tr:nth-child(even) {
        background-color: #dddddd
;
    }
    .custom-loader-color {
        color: #fff 
!important;
        font-size: 40px !important;
    }
    .custom-loader-background {
        background-color: #f60 
!important;
    }
    .custom-middle-align {
        vertical-align: middle !important;
    }
</style>
<div style="width:90%; margin:0 auto">
    <div style="background-color:#f5f5f5
; padding:20px">
        <h2 style="color: blue
">Filter Records</h2>
        <table>
            <tbody>
                <tr>
                    <td style="color: blue
">City</td>
                    <td><input type="text" class="form-control" id="txtCity" /></td>
                    <td style="color: blue
">State</td>
                    <td>
                        <select id="ddState" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
                            <option value="">All States</option>
                            <option value="Karnataka">Karnataka</option>
                            <option value="Andhra Pradesh">Andhra Pradesh</option>
                            <option value="Georgia">Georgia</option>
                            <option value="Uttar Pradesh">Uttar Pradesh</option>
                            <option value="Odisha">Odisha</option>
                        </select>
                    </td>
                    <td>
                        <input type="button" class="btn btn-success btn-md" value="Filter" id="btnFilter" />
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
    @* jQuery DataTables *@
    <div style="width:90%; margin:0 auto;">
        <table id="myTable" class="table table-responsive table-striped">
            <thead>
                <tr>
                    <th style="background-color: Yellow
;color: blue
">First Name</th>
                    <th style="background-color: Yellow
;color: blue
">Last Name</th>
                    <th style="background-color: Yellow
;color: blue
">Age</th>
                    <th style="background-color: Yellow
;color: blue
">Address</th>
                    <th style="background-color: Yellow
;color: blue
">City</th>
                    <th style="background-color: Yellow
;color: blue
">State</th>
                </tr>
            </thead>
        </table>
    </div>
</div>
@* Load bootstrap datatable css *@
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/css/bootstrap.css" rel="stylesheet" />
<link href="//cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css" rel="stylesheet" />
@* Load bootstrap datatable js and initialize DataTable *@
@section Scripts {
    <script src="//code.jquery.com/jquery-3.3.1.js"></script>
    <script src="//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
    <script src="//cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js"></script>
    <script>
        $(document).ready(function () {
            // jQuery DataTables initialization
            $('#myTable').DataTable({
                "language": {
                    "processing": "<div class='overlay custom-loader-background'><i class='fa fa-cog fa-spin custom-loader-color'></i></div>"
                },
                "processing": true,
                "serverSide": true,
                "orderMulti": false,
                "dom": '<"top"i>rt<"bottom"lp><"clear">',
                "ajax": {
                    "url": "/home/FilterData",
                    "type": "POST",
                    "datatype": "json"
                },
                "columns": [
                    { "data": "FirstName", "name": "FirstName", "autoWidth": true },
                    { "data": "LastName", "name": "LastName", "autoWidth": true },
                    { "data": "Age", "name": "Age", "autoWidth": true },
                    { "data": "Address", "name": "Address", "autoWidth": true },
                    { "data": "City", "name": "City", "autoWidth": true },
                    { "data": "State", "name": "State", "autoWidth": true }
                ]
            });

            // DataTables filtering on button click
            var oTable = $('#myTable').DataTable();
            $('#btnFilter').click(function () {
                oTable.columns(4).search($('#txtCity').val().trim());
                oTable.columns(5).search($('#ddState').val().trim());
                oTable.draw();
            });
        });
    </script>
}


Markup
Code description

Here, I have added a textbox for City and a dropdown for State to filter the records. I used some static records in the dropdown for basic understanding and in my next session, I will fill the dropdown from the database using Entity Framework.

<div style="background-color:#f5f5f5
; padding:20px;">
    <h2 style="color: blue
;">Filter Records</h2>
    <table>
        <tbody>
            <tr>
                <td style="color: blue
;">City</td>
                <td><input type="text" class="form-control" id="txtCity" /></td>
                <td style="color: blue
;">State</td>
                <td>
                    <select id="ddState" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
                        <option value="">All States</option>
                        <option value="
London">London</option>
                        <option value="
Manchester">Manchester</option>
                        <option value="
Liverpool">Liverpool</option>
                        <option value="
Birmingham">Birmingham</option>
                        <option value="York">York</option>
                    </select>
                </td>
                <td>
                    <input type="button" class="btn btn-success btn-md" value="Filter" id="btnFilter" />
                </td>
            </tr>
        </tbody>
    </table>
</div>


I have updated the code to implement custom multicolumn server-side filtering in jQuery DataTables by removing the default global search box. This initialization variable allows you to specify where in the DOM you want DataTables to introduce the various controls it composes to the page.
    <"top"i> means it is showing the info of entries.
    rt means it is showing the progress bar with loading records in DataTable.
    <"bottom"lp> means it is showing the length of records and also, the paging in the page.
    <"clear"> means it clears the controls or any data inside div element.

    "dom": '<"top"i>rt<"bottom"lp><"clear">'

The following piece of code will enable the data loading from server-side. The path "/home/FilterData" is the function that will be returning data from server side. The columns here are the exact names of the properties that we have created in the table and uploaded using the Entity Data Model file. Here, we can get the index number of the table's columns.
$('#myTable').DataTable({
    "language": {
        "processing": "<div class='overlay custom-loader-background'><i class='fa fa-cog fa-spin custom-loader-color'></i></div>"
    },
    "processing": true,
    "serverSide": true,
    "orderMulti": false,
    "dom": '<"top"i>rt<"bottom"lp><"clear">',
    "ajax": {
        "url": "/home/FilterData",
        "type": "POST",
        "datatype": "json"
    },
    "columns": [
        { "data": "FirstName", "name": "FirstName", "autoWidth": true }, //index 0
        { "data": "LastName", "name": "LastName", "autoWidth": true }, //index 1
        { "data": "Age", "name": "Age", "autoWidth": true }, //index 2
        { "data": "Address", "name": "Address", "autoWidth": true }, //index 3
        { "data": "City", "name": "City", "autoWidth": true }, //index 4
        { "data": "State", "name": "State", "autoWidth": true } //index 5
    ]
});


The following piece of code is used to apply custom search on jQuery DataTables. I have applied search for the city name using DataTable column index 4 and search for state name using DataTable column index 5.
oTable = $('#myTable').DataTable();
$('#btnFilter').click(function () {
    oTable.columns(4).search($('#txtCity').val().trim());
    oTable.columns(5).search($('#ddState').val().trim());
    oTable.draw();
});
});

Step 3. Add another action (here "FilterData") for fetching the data from the database and implementing the logic for server-side paging and sorting.

Code
[HttpPost]
public ActionResult FilterData()
{
    // Initialization.
    JsonResult result = new JsonResult();
    try
    {
        var draw = Request.Form.GetValues("draw").FirstOrDefault();
        var start = Request.Form.GetValues("start").FirstOrDefault();
        var length = Request.Form.GetValues("length").FirstOrDefault();
        var sortColumn = Request.Form.GetValues("columns[" + Request.Form.GetValues("order[0][column]").FirstOrDefault()
                        + "][name]").FirstOrDefault();
        var sortColumnDir = Request.Form.GetValues("order[0][dir]").FirstOrDefault();
        var city = Request.Form.GetValues("columns[4][search][value]").FirstOrDefault();
        var state = Request.Form.GetValues("columns[5][search][value]").FirstOrDefault();
        int pageSize = length != null ? Convert.ToInt32(length) : 0;
        int skip = start != null ? Convert.ToInt16(start) : 0;
        int recordsTotal = 0;
        using (HFLDBEntities dc = new HFLDBEntities())
        {
            var v = (from a in dc.employees select a);

            if (!string.IsNullOrEmpty(city))
            {
                v = v.Where(a => a.City.Contains(city));
            }
            if (!string.IsNullOrEmpty(state))
            {
                v = v.Where(a => a.State == state);
            }
            if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDir)))
            {
                v = v.OrderBy(sortColumn + " " + sortColumnDir);
            }
            recordsTotal = v.Count();
            var data = v.Skip(skip).Take(pageSize).ToList();

            return Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data },
                        JsonRequestBehavior.AllowGet);
        }
    }
    catch (Exception ex)
    {
        // Handle exception (log or display error)
        Console.WriteLine(ex); // Log exception details to console
    }
    // Return empty or default result if exception occurs
    return result;
}


Code description

I have described the code using the comment line in every line of code. It will be easy for a quick understanding of the code flow. In this piece of code, which is based on searching, sorting, and pagination information sent from the DataTable plugin, the following has been done: The data is being loaded first. It is being churned out based on the search criteria. Data is then sorted by a provided column in a provided order. Lastly, it is paginated and returned.

I have declared two variables which contain the informaion of two columns for filtering records with their index values as I have described in the View section.
var city = Request.Form.GetValues("columns[4][search][value]").FirstOrDefault();
var state = Request.Form.GetValues("columns[5][search][value]").FirstOrDefault();


The following is the piece of code for filtering records using city and state columns.
if (!string.IsNullOrEmpty(city))
{
    v = v.Where(a => a.City.Contains(city));
}
if (!string.IsNullOrEmpty(state))
{
    v = v.Where(a => a.State == state);
}


For sorting, we need to add a reference of System.Linq.Dynamic.
if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDir)))
{
    v = v.OrderBy(sortColumn + " " + sortColumnDir);
}


Output
During the initial load, the processing loader will look like below.

All states
Filter records using state dropdown, as shown below.



Filter records using city textbox.

Filter records using both, City and State.

Summary
In this write-up, we have learned how to

  • Filter records using custom multicolumn server-side features.
  • Remove default global search box of jQuery DataTable by using initialisation variable in DOM.
  • Get record's length, sorting and pagination information with the DataTable plugin.
  • Get Server-side integration of DataTable plugin with ASP.NET MVC 5.


ASP.NET MVC Hosting - HostForLIFE.eu :: Stripe Payment Gateway Integration with ASP.NET Core MVC

clock February 10, 2025 07:09 by author Peter

We'll go over every step of integrating the Stripe Payment Gateway into an ASP.NET Core MVC application in this post. After completing this tutorial, you will have a complete payment system that enables customers to use Stripe's safe checkout to make purchases.

Stripe is a popular payment gateway that allows businesses to accept payments online. It supports credit cards, debit cards, and other payment methods. Stripe provides a secure and easy-to-integrate API for developers. In this article, we’ll use Stripe Checkout, which is a pre-built payment page hosted by Stripe. This approach is secure and requires minimal setup.

Introduction
Before starting, ensure you have the following.

  • Stripe Account: Sign up at Stripe.
  • .NET SDK: Install the latest .NET SDK from here.
  • IDE: Use Visual Studio, Visual Studio Code, or any preferred IDE.
  • Stripe API Keys: Retrieve your Publishable Key and Secret Key from the Stripe Dashboard.

Step 1. Create a Stripe Account

  1. Go to Stripe and sign up for an account.
  2. Once logged in, navigate to Developers > API Keys.
  3. Copy your publishable key and secret key. These will be used in your ASP.NET Core application.

Step 2. Set Up an ASP.NET Core MVC Project

  • Open Visual Studio or your preferred IDE.
  • Create a new ASP.NET Core Web App (Model-View-Controller) project.
    • Name the project (e.g., StripePaymentDemo).
    • Select .NET 6.0 or later as the framework.
  • Build and run the project to ensure it’s set up correctly.

Step 3. Install Stripe.NET NuGet Package
Stripe provides an official .NET library to interact with its API. Install it via the Package Manager Console.
Install-Package Stripe.net

Step 4. Configure Stripe in appsettings.json
Add your Stripe API keys to the appsettings.json file.
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Stripe": {
    "PublishableKey": "YOUR_STRIPE_PUBLISHED_KEY",
    "SecretKey": "YOUR_SECRET_KEY"
  },
  "AllowedHosts": "*"
}

Step 5. Configure Stripe in the Program.cs
Configure Stripe in the Program.cs file.
using Stripe;

namespace StripePaymentDemoApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            // Add services to the container
            builder.Services.AddControllersWithViews();
            StripeConfiguration.ApiKey = builder.Configuration["Stripe:SecretKey"];
            var app = builder.Build();
            // Configure the HTTP request pipeline
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios,
                // see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();
            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            app.Run();
        }
    }
}

Step 6. Create a Payment Controller
Create a new controller named: PaymentController.cs.using Microsoft.AspNetCore.Mvc;
using Stripe.Checkout;

namespace StripePaymentDemoApp.Controllers
{
    public class PaymentController : Controller
    {
        private readonly IConfiguration _configuration;
        public PaymentController(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        public IActionResult Checkout()
        {
            // Pass the Stripe Publishable Key to the view
            ViewBag.StripePublishableKey = _configuration["Stripe:PublishableKey"];
            return View();
        }
        [HttpPost]
        public async Task<IActionResult> CreateCheckoutSession()
        {
            // Create a Stripe Checkout Session
            var options = new SessionCreateOptions
            {
                PaymentMethodTypes = new List<string> { "card" },
                LineItems = new List<SessionLineItemOptions>
                {
                    new SessionLineItemOptions
                    {
                        PriceData = new SessionLineItemPriceDataOptions
                        {
                            Currency = "usd",
                            ProductData = new SessionLineItemPriceDataProductDataOptions
                            {
                                Name = "Test Product",
                            },
                            UnitAmount = 2000, // $20.00 (in cents)
                        },
                        Quantity = 1,
                    },
                },
                Mode = "payment",
                SuccessUrl = Url.Action("Success", "Payment", null, Request.Scheme),
                CancelUrl = Url.Action("Cancel", "Payment", null, Request.Scheme),
            };
            var service = new SessionService();
            var session = await service.CreateAsync(options);
            // Redirect to Stripe Checkout
            return Redirect(session.Url);
        }
        public IActionResult Success()
        {
            return View();
        }
        public IActionResult Cancel()
        {
            return View();
        }
    }
}
Step 7. Create Views
Checkout View (Views/Payment/Checkout.cshtml).
@{
ViewData["Title"] = "Checkout";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Checkout</h1>
<form asp-action="CreateCheckoutSession" method="post">
<button type="submit" class="btn btn-primary">Pay with Stripe</button>
</form>


Success View (Views/Payment/Success.cshtml).
@{
ViewData["Title"] = "Payment Successful";
Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Payment Successful</h1>
<p>Thank you for your payment!</p>

Cancel View (Views/Payment/Cancel.cshtml).
@{
ViewData["Title"] = "Payment Canceled";
Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Payment Canceled</h1>
<p>Your payment was canceled.</p>

Step 8. Run and Test the Application

  • Run the application using dotnet run or your IDE’s run command.
  • Navigate to /Payment/Checkout in your browser.
  • Click the "Pay with Stripe" button to be redirected to the Stripe Checkout page.
  • Use the following test card details.
    • Card Number: 4242 4242 4242 4242.
    • Expiration Date: Any future date.
    • CVC: Any 3 digits.
    • ZIP Code: Any value.

Let's run the application and start the payments with Stripe.

Click the Pay with Stripe Button.


Fill in the payment details with test credentials and click the pay button.

Let's look at our most recent transactions on the Stripe dashboard.


Step 9. Handle Webhooks (Optional)
To handle payment confirmation and other events, set up a webhook endpoint.

Create a Webhook Endpoint in the Stripe Dashboard.

  • Go to Developers > Webhooks in the Stripe Dashboard.
    • Add a new endpoint with your server's URL (e.g., https://yourdomain.com/Payment/Webhook).
    • Add Webhook Secret to:appsettings.json.

{
  "Stripe": {
    "WebhookSecret": "your_webhook_secret_here"
  }
}


Add Webhook Handler in:PaymentController.cs.
[HttpPost]
public async Task<IActionResult> Webhook()
{
    var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();

    try
    {
        var stripeEvent = EventUtility.ConstructEvent(
            json,
            Request.Headers["Stripe-Signature"],
            _configuration["Stripe:WebhookSecret"]
        );
        // Handle events
        if (stripeEvent.Type == Events.CheckoutSessionCompleted)
        {
            var session = stripeEvent.Data.Object as Session;
            // Handle successful payment
        }
        return Ok();
    }
    catch (StripeException e)
    {
        return BadRequest();
    }
}



ASP.NET MVC Hosting - HostForLIFE.eu :: Scalable ASP.NET MVC Application Design Patterns

clock February 3, 2025 06:14 by author Peter

Design patterns are tried-and-true fixes for typical program design issues. Implementing these principles can enhance the scalability, testability, and maintainability of code in ASP.NET MVC projects. This article examines important design patterns seen in ASP.NET MVC projects and offers real-world examples of how to use them.

1. Repository Pattern
The repository pattern abstracts data access logic, providing a clean separation between the business logic and the data layer.

Benefits

  • Promotes loose coupling between the application and data storage.
  • Simplifies unit testing by allowing mocking of the data layer.

Implementation
// IRepository Interface
public interface IRepository<T> where T : class
{
    IEnumerable<T> GetAll();
    T GetById(int id);
    void Insert(T entity);
    void Update(T entity);
    void Delete(int id);
}

// Repository Implementation
public class Repository<T> : IRepository<T> where T : class
{
    private readonly ApplicationDbContext _context;
    private DbSet<T> entities;

    public Repository(ApplicationDbContext context)
    {
        _context = context;
        entities = context.Set<T>();
    }

    public IEnumerable<T> GetAll() => entities.ToList();
    public T GetById(int id) => entities.Find(id);
    public void Insert(T entity) => entities.Add(entity);
    public void Update(T entity) => _context.Entry(entity).State = EntityState.Modified;
    public void Delete(int id) => entities.Remove(GetById(id));
}


2. Unit of Work Pattern
The unit of work pattern helps manage transactions by coordinating changes across multiple repositories in a single transaction.

Benefits

  • Ensures consistency across repositories.
  • Reduces redundant calls to the database.

Implementation
public class UnitOfWork : IDisposable
{
    private readonly ApplicationDbContext _context;
    private IRepository<Product> _productRepository;

    public UnitOfWork(ApplicationDbContext context)
    {
        _context = context;
    }

    public IRepository<Product> ProductRepository
    {
        get
        {
            return _productRepository ??= new Repository<Product>(_context);
        }
    }

    public void Save()
    {
        _context.SaveChanges();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}


3. Dependency Injection (DI)
Dependency injection (DI) injects dependencies into controllers or classes instead of creating them directly.

Benefits

  • Reduces tight coupling.
  • Simplifies testing by allowing dependency substitution.

Implementation
Configure DI in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IRepository<Product>, Repository<Product>>();
    services.AddScoped<UnitOfWork>();
    services.AddControllersWithViews();
}


Inject Dependencies in Controller
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int StockQuantity { get; set; }
}

Products Controller
using System.Linq;
using System.Web.Mvc;
using MVCDesignPatternsApp.Models;
using MVCDesignPatternsApp.Repositories;

public class ProductsController : Controller
{
    private readonly UnitOfWork _unitOfWork;

    public ProductsController(UnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    // GET: Products
    public ActionResult Index()
    {
        var products = _unitOfWork.ProductRepository.GetAll().ToList();
        return View(products);
    }

    // GET: Products/Details/5
    public ActionResult Details(int id)
    {
        var product = _unitOfWork.ProductRepository.GetById(id);
        if (product == null)
        {
            return HttpNotFound();
        }
        return View(product);
    }

    // GET: Products/Create
    public ActionResult Create()
    {
        return View();
    }

    // POST: Products/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Product product)
    {
        if (ModelState.IsValid)
        {
            _unitOfWork.ProductRepository.Insert(product);
            _unitOfWork.Save();
            return RedirectToAction("Index");
        }
        return View(product);
    }

    // GET: Products/Edit/5
    public ActionResult Edit(int id)
    {
        var product = _unitOfWork.ProductRepository.GetById(id);
        if (product == null)
        {
            return HttpNotFound();
        }
        return View(product);
    }

    // POST: Products/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(Product product)
    {
        if (ModelState.IsValid)
        {
            _unitOfWork.ProductRepository.Update(product);
            _unitOfWork.Save();
            return RedirectToAction("Index");
        }
        return View(product);
    }

    // GET: Products/Delete/5
    public ActionResult Delete(int id)
    {
        var product = _unitOfWork.ProductRepository.GetById(id);
        if (product == null)
        {
            return HttpNotFound();
        }
        return View(product);
    }

    // POST: Products/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public ActionResult DeleteConfirmed(int id)
    {
        _unitOfWork.ProductRepository.Delete(id);
        _unitOfWork.Save();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _unitOfWork.Dispose();
        }
        base.Dispose(disposing);
    }
}

Views
Ensure you have corresponding views in the Views/Products/ folder:

  • Index.cshtml: Display the product list.
  • Details.cshtml: Show product details.
  • Create.cshtml: Form to add a new product.
  • Edit.cshtml: Form to update product information.
  • Delete.cshtml: Confirm product deletion.

View Example for Index.cshtml
@model IEnumerable<YourNamespace.Models.Product>

<h2>Product List</h2>

<p>
    @Html.ActionLink("Create New Product", "Create")
</p>

<table class="table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Price</th>
            <th>Stock Quantity</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
    @foreach (var item in Model) {
        <tr>
            <td>@item.Name</td>
            <td>@item.Price</td>
            <td>@item.StockQuantity</td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.Id })
            </td>
        </tr>
    }
    </tbody>
</table>

4. Factory Pattern
The factory pattern centralizes object creation logic.

Benefits

  • Decouples object creation from usage.
  • Promotes flexibility for varying object requirements.

Implementation
Factory Implementation

public interface IProductService
{
    void ProcessOrder();
}

public class PhysicalProductService : IProductService
{
    public void ProcessOrder() => Console.WriteLine("Processing physical product order.");
}

public class DigitalProductService : IProductService
{
    public void ProcessOrder() => Console.WriteLine("Processing digital product order.");
}

public class ProductServiceFactory
{
    public IProductService GetProductService(string productType)
    {
        return productType switch
        {
            "Physical" => new PhysicalProductService(),
            "Digital" => new DigitalProductService(),
            _ => throw new ArgumentException("Invalid product type")
        };
    }
}

Usage in Controller
public class OrdersController : Controller
{
    private readonly ProductServiceFactory _factory;

    public OrdersController(ProductServiceFactory factory)
    {
        _factory = factory;
    }

    public void CreateOrder(string productType)
    {
        var service = _factory.GetProductService(productType);
        service.ProcessOrder();
    }
}

5. Singleton Pattern
The singleton pattern ensures only one instance of a class is created and shared.

Benefits

  • Ideal for shared resources like logging or caching.
  • Ensures a single point of control.

Implementation
Singleton Class
public sealed class LogManager
{
    private static readonly Lazy<LogManager> instance = new(() => new LogManager());

    private LogManager() { }

    public static LogManager Instance => instance.Value;

    public void Log(string message) => Console.WriteLine($"Log: {message}");
}


6. Command Pattern
The command pattern encapsulates a request as an object, allowing for more complex request handling.

Benefits

  • Supports undoable operations.
  • Decouples request handling from request execution.

Implementation
Command Interface and Implementation
public interface ICommand
{
    void Execute();
}

public class SaveOrderCommand : ICommand
{
    public void Execute() => Console.WriteLine("Order saved.");
}

public class CancelOrderCommand : ICommand
{
    public void Execute() => Console.WriteLine("Order canceled.");
}

Invoker Class
public class CommandInvoker
{
    private readonly List<ICommand> _commands = new();

    public void AddCommand(ICommand command) => _commands.Add(command);

    public void ExecuteCommands()
    {
        foreach (var command in _commands)
        {
            command.Execute();
        }
        _commands.Clear();
    }
}

Output

 



About HostForLIFE.eu

HostForLIFE.eu 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 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Month List

Tag cloud

Sign in