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 :: Controllers in MVC: An Introduction

clock June 12, 2025 09:06 by author Peter

This article provides an overview of the Controller in MVC. As you know, MVC stands for Model , View and Controller; so, Controller plays a very important role in MVC. We'll learn the controller actions and action results in here and how the controllers are used to interact with the MVC applications.

Overview
The controller in MVC is responsible for responding the request made against the ASP.NET MVC Web Application. Each browser request is mapped to a specific controller that is defined in the MVC application.

Suppose you are entering the following URL in the browser:
http://localhost:1234/Sample

It means that the Controller is called SampleController. The browser is making a request to the controller so now the SampleController is responsible for providing the response to the browser. It might be possible that the controller returns a specific view back to the browser or the controller might redirect the user to another controller.

Getting Started
Let us create a Controller in a MVC application. To create a controller you must have the MVC application so at first we'll create the MVC application and then controller. Just follow the procedure below.

Step 1: Create an ASP.NET Web Application and enter the name as in the following:

Step 2: Select MVC Project Template in the One ASP.NET Wizard.

Step 3: In the Solution Explorer, right-click on the Controllers folder then click on "Add" -> "Controller...".

Step 4: Now select the MVC Empty Controller.

And enter the name as Sample as in the following:


After entering the controller name, using scaffolding there is a folder named Sample (the same name as the newly added controller) will be added automatically in the Views folder. Have a look:


Step 5: You can see the newly added controller has code as in the following:
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
    namespace DemoMvc.Controllers  
    {  
        public class SampleController : Controller  
        {  
            // GET: Sample  
            public ActionResult Index()  
            {  
                return View();  
            }  
        }  
    } 

In the code above, you can see that the controller is created in the form of a class so you can say that it is just a class that is derived from the Controller class. This class inherits the Controller class (base class). In the next section, we'll understand the actions.

Overview of Actions in Controller

The actions are disclosed by the controller. An action is a method on a controller that is called when you enter a specific URL in the browser. Suppose you enter the following URL in the browser:
http://localhost:1234/Sample/Index

The Index() method is called through the preceding URL. This Index() method is stored in the SampleController. It is necessary that the access modifier of the action method must be public. This action method of any controller cannot be overloaded further and also cannot be a static method.

Overview of Action Results
As you can see in the preceding action method that the return type of that Index() action method is ActionResult, so an action method returns an action result. An action result is what a controller action returns in response to a browser request.

There are various types of action results supported in the MVC, as given below:

  • ViewResult: Represents HTML and markup.
  • EmptyResult: No Result
  • RedirectResult: a redirection to a new URL
  • JsonResult: a JSON result that is used in ajax app
  • JavaScriptResult: a JavaScript result
  • ContentResult: a text result

In most cases the controller action returns a ViewResult as in the following:
    public class SampleController : Controller  
    {  
        // GET: Sample  
        public ActionResult Index()  
        {  
            return View();  
        }  
    } 


You can see in the code above that the View is used to return a ViewResult. When this is returned, HTML is returned to the browser. You can see the methods of the controller base class:

  • View: Returns a ViewResult action result.
  • Redirect: Returns a RedirectResult
  • JSON: Returns a JsonResult
  • JavaScript: Returns a JavaScriptResult
  • RedirectToAction: Returns a RedirectToActionResult

So, suppose you want to redirect from one controller to another controller, you need to use the RedirectToAction() method. Have a look:
    using System.Web.Mvc;  
    namespace DemoMvc.Controllers  
    {  
        public class SampleController : Controller  
        {  
            // GET: Sample  
            public ActionResult Index()  
            {  
                return View();  
            }  
            public ActionResult SampleWorld()  
            {  
                return RedirectToAction("Welcome");  
            }  
            public ActionResult Welcome()  
            {  
                return View();  
            }  
        }  
    } 

Suppose we want to use the ContentResult action result because it is special. It returns an action result as simple plain text. Have a look:

    using System.Web.Mvc;  
    namespace DemoMvc.Controllers  
    {  
        public class SampleController : Controller  
        {  
            // GET: Sample  
            public ActionResult Index()  
            {  
                return View();  
            }  
            public ActionResult Welcome()  
            {  
                return Content("Hello and Welcome to MVC");  
            }  
        }  
    } 


Adding View
You can add a view for every controller in a very easy way. Have a look at the following procedure.

Step 1: Just right-click on the controller and select Add View

Step 2: Just click on Add in the next wizard

 

Step 3: When you run the Welcome View, you can see the following screenshot

You can check out in the browser URL that the Welcome controller action method is called of the SampleController. That's it.

Summary
This article provided an overview of the controller, controller actions and action results of ASP.NET MVC. In here you learned the overview of controllers, next we'll learn the custom routes in controllers. Thanks for reading



ASP.NET MVC Hosting - HostForLIFE.eu :: Use the Dapper and Repository Patterns to Create a CRUD Application in.NET 8 MVC

clock May 7, 2025 09:33 by author Peter

Creating a CRUD (Create, Read, Update, Delete) application is a core skill for any .NET developer. In this guide, we'll show you how to build a CRUD app using ASP.NET Core MVC (.NET 8), Dapper ORM, and the Repository Pattern. This approach is fast, easy to maintain, and great for building real-world applications.


Building an ASP.NET MVC project using Dapper Micro ORM and .NET 8.0 involves 10 key steps. Here's a simple breakdown to help you set up the project effectively.

  • Create a New ASP.NET Core MVC Project
  • Install Dapper and Microsoft.Data.SqlClient Packages
  • Set Up SQL Server Database and Table
  • Configure Database Connection
  • Create the model
  • Create a DBContext Folder inside the folder create the DapperContext.cs file
  • Create a Repository Folder inside the folder create IStudentRepo.cs and StudentRepo.cs file
  • Configure Dependency Injection
  • Create Controller
  • Create Views

Continue following the steps mentioned above.

Step 1. Create a New ASP.NET Core MVC Project.

Choose the MVC project template.

Configure your new project by giving it a meaningful name and selecting the folder where it should be created.

No changes are needed in the Additional Information section.

The project window appears as shown in the image below.

Step 2. Install Dapper and Microsoft.Data.SqlClient Packages. Navigate to Tools > NuGet Package Manager > Manage NuGet Packages for Solution.

Go to the Browse tab, search for Dapper, and select the first package that appears. Check the box next to your project name, ensure the latest version is selected (update it if not), and then click Install.

Go to the Browse tab, and search for Microsoft.Data.SqlClient, and select the first package that appears. Tick the checkbox next to your project name, make sure the latest version is selected (update if necessary), and then click Install.

Click Accept to agree to the license terms and proceed with the installation.


Open Solution Explorer, navigate to Dependencies > Packages and verify that both installed packages are listed. This confirms they were successfully added to your project.


Step 3. Set Up SQL Server Database and Table
Open SQL Server Management Studio (SSMS), then launch a New Query window. Use the following query to create a new database and table.
--Create a database StudentDB.
CREATE DATABASE StudentDB;
Use StudentDB;

--Create a table Students with fields: ID, Name, Age, Email.
CREATE TABLE Student(
               ID int primary key identity(1,1),
               Name varchar(50),
               Age int,
               Email varchar(50)
);

Step 4. Configure Database Connection
Add the connection string to the appsettings.json file, ensuring that the entries are separated by commas (,).


"ConnectionStrings": {
    "DefaultConnection": "Server=LAPTOP-TD1MGGBL;Database=StudentDB;Trusted_Connection=True;TrustServerCertificate=True;"
}


Step 5. Create the model
Right-click on the Models folder, select Add > Class and name it Student.cs. After creating the class, add the following code.


File: Student.cs
namespace CURD_Demo.Models
{
    public class Student
    {
        public int Id { get; set; }
        public required string Name { get; set; }
        public int Age { get; set; }
        public required string Email { get; set; }
    }
}


Step 6. Create a DBContext Folder inside the folder ADD DapperContext.cs file.
Right-click on the project name in Solution Explorer, then go to Add > New Folder and name it DBContext. Inside the DBContext folder, add a class named DapperContext.cs and include the following code inside the file.

 

File: DappContext.cs
using Microsoft.Data.SqlClient;
using System.Data;

namespace CURD_Demo.DBContext
{
    public class DapperContext
    {
        private readonly IConfiguration _configuration;
        private readonly string? _connectionString;
        public DapperContext(IConfiguration configuration)
        {
            _configuration = configuration;
            _connectionString = _configuration.GetConnectionString("DefaultConnection");
        }
        public IDbConnection CreateConnection() => new SqlConnection(_connectionString);
    }
}


Step 7. Create a Repository Folder inside the folder then create IStudentRepo.cs and StudentRepo.cs files.
Right-click on the project name in Solution Explorer, then go to Add > New Folder and name it Repository. Inside the Repository folder, add an interface named IStudentRepo.cs and a class named StudentRepo.cs. After creating these files, add the following code inside each file.


File: IStudentRepo.cs
using CURD_Demo.Models;

namespace CURD_Demo.Repository
{
    public interface IStudentRepo
    {
        IEnumerable<Student> GetAll();
        Student? GetById(int id);
        void Add(Student student);
        void Update(Student student);
        void Delete(int id);
    }
}


File: StudentRepo.cs
using CURD_Demo.Models;
using CURD_Demo.DBContext;
using Dapper;
namespace CURD_Demo.Repository
{
    public class StudentRepo : IStudentRepo
    {
        private readonly DapperContext _context;
        public StudentRepo(DapperContext context)
        {
            _context = context;
        }
        public IEnumerable<Student> GetAll()
        {
            using (var connection = _context.CreateConnection())
            {
                var sql = "SELECT * FROM Student";
                return connection.Query<Student>(sql);
            }
        }
        public Student? GetById(int id)
        {
            using (var connection = _context.CreateConnection())
            {
                var sql = "SELECT * FROM Student WHERE Id = @Id";
                return connection.QuerySingleOrDefault<Student>(sql, new { Id = id });
            }
        }
        public void Add(Student student)
        {
            using (var connection = _context.CreateConnection())
            {
                var sql = "INSERT INTO Student (Name, Age, Email) VALUES (@Name, @Age, @Email)";
                connection.Execute(sql, student);
            }
        }
        public void Update(Student student)
        {
            using (var connection = _context.CreateConnection())
            {
                var sql = "UPDATE Student SET Name = @Name, Age = @Age, Email = @Email WHERE Id = @Id";
                connection.Execute(sql, student);
            }
        }
        public void Delete(int id)
        {
            using (var connection = _context.CreateConnection())
            {
                var sql = "DELETE FROM Student WHERE Id = @Id";
                connection.Execute(sql, new { Id = id });
            }
        }
    }
}


Step 8. Configure Dependency Injection
Open the Program.cs file and add the necessary dependencies for Dapper and the repositories using the following code.


File: Program.cs
//Configure Dependency Injection

builder.Services.AddSingleton<CURD_Demo.DBContext.DapperContext>();
builder.Services.AddScoped<CURD_Demo.Repository.IStudentRepo, CURD_Demo.Repository.StudentRepo>();


Step 9. Create Controller
Right-click on the Controllers folder, select Add > Controller, then choose MVC Controller - Empty and click Add. In the pop-up window, enter StudentController as the controller name and click Add. This will create StudentController inside the Controllers folder. Then, add the following code to the StudentController.cs file.

 

File: StudentController.cs
using CURD_Demo.Models;
using Microsoft.AspNetCore.Mvc;
using CURD_Demo.Repository;

namespace CURD_Demo.Controllers
{
    public class StudentController : Controller
    {
        private readonly IStudentRepo _studentRepo;
        public StudentController(IStudentRepo studentRepo)
        {
            _studentRepo = studentRepo;
        }
        public IActionResult Student()
        {
            var students = _studentRepo.GetAll();
            return View(students);
        }
        public IActionResult Details(int id)
        {
            var student = _studentRepo.GetById(id);
            if (student == null)
            {
                return NotFound();
            }
            return View(student);
        }
        public IActionResult Create()
        {
            return View();
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(Student student)
        {
            if (ModelState.IsValid)
            {
                _studentRepo.Add(student);
                return RedirectToAction(nameof(Student));
            }
            return View(student);
        }
        public IActionResult Edit(int id)
        {
            var student = _studentRepo.GetById(id);
            if (student == null)
            {
                return NotFound();
            }
            return View(student);
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Edit(Student student)
        {
            if (ModelState.IsValid)
            {
                _studentRepo.Update(student);
                return RedirectToAction(nameof(Student));
            }
            return View(student);
        }
        public IActionResult Delete(int id)
        {
            var student = _studentRepo.GetById(id);
            if (student == null)
            {
                return NotFound();
            }
            return View(student);
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult DeleteConfirmed(int id)
        {
            _studentRepo.Delete(id);
            return RedirectToAction(nameof(Student));
        }
    }
}


Step 10. Create Views
Right-click on the Views folder, navigate to Add > New Item, select Razor View - Empty, and click Add. In the pop-up window, enter Student.cshtml as the name and click Add. This will create a Student.cshtml file inside the View/Student folder. Then, add the following code inside the Student.cshtml file.

 

File: Student.cshtml
@model IEnumerable<CURD_Demo.Models.Student>
@{
    ViewData["Title"] = "Students";
}

<h2>Student List</h2>

<div>
    <a asp-action="Create" class="btn btn-primary">Add New Student</a>
</div>
<table class="table table-bordered">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Email)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Age)
            </th>
            <th>
                Actions
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach (var student in Model)
        {
            <tr>
                <td>
                    @{
                        @student.Name
                    }
                </td>
                <td>
                    @{
                        @student.Email
                    }
                </td>
                <td>
                    @{
                        @student.Age
                    }
                </td>
                <td>
                    <a asp-action="Edit" asp-route-id="@student.Id">Edit</a> |
                    <a asp-action="Delete" asp-route-id="@student.Id">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>

Right-click on the Student folder, navigate to Add > New Item, select Razor View - Empty, and click Add. In the pop-up window, enter Create.cshtml as the name and click Add. This will create a Create.cshtml file inside the Student folder. Then, add the following code inside the Create.cshtml file.

File: Create.cshtml

@model CURD_Demo.Models.Student
@{
    ViewData["Title"] = "Create Student";
}

<h2>Add Student</h2>
<form asp-action="Create" method="post">
    <div class="form-group">
        <label for="Name" class="form-label"></label>
        <input name="Name" placeholder="Enter Your Name" class="form-control" />
        <span class="text-danger"></span>
    </div>
    <div class="form-group">
        <label for="Email" class="control-label"></label>
        <input name="Email" placeholder="Enter Your Email" class="form-control" />
        <span class="text-danger"></span>
    </div>
    <div class="form-group">
        <label for="Age" class="control-label"></label>
        <input name="Age" placeholder="Enter Your Age" class="form-control" />
        <span class="text-danger"></span>
    </div>
    <button type="submit" class="btn btn-primary">Create</button>
    <a asp-action="Student">Back</a>
</form>


Right-click on the Student folder, navigate to Add > New Item, select Razor View - Empty, and click Add. In the pop-up window, enter Edit.cshtml as the name and click Add. This will create a Edit.cshtml file inside the Student folder. Then, add the following code inside the Edit.cshtml file.

File: Edit.cshtml
@model CURD_Demo.Models.Student
@{
    ViewData["Title"] = "Edit";
}

<h2>EditStudent</h2>
<form asp-action="Edit" metod="post">
    <input type="hidden" asp-for="Id" />
    <div class="form-group">
        <label asp-for="Name" class="form-label"></label>
        <input asp-for="Name" placeholder="Enter Your Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Email" class="form-label"></label>
        <input asp-for="Email" placeholder="Enter Your Email" class="form-control" />
        <span asp-validation-for="Email" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Age" class="form-label"></label>
        <input asp-for="Age" placeholder="Enter Your Age" class="form-control" />
        <span asp-validation-for="Age" class="text-danger"></span>
    </div>
    <button type="submit" class="btn btn-primary">Update</button>
</form>

Right-click on the Student folder, navigate to Add > New Item, select Razor View - Empty, and click Add. In the pop-up window, enter Delete.cshtml as the name and click Add. This will create a Delete.cshtml file inside the Student folder. Then, add the following code inside the Delete.cshtml file.

File: Delete.cshtml
@model CURD_Demo.Models.Student
@{
    ViewData["Title"] = "Delete";
}

<h2>Delete Student</h2>
<div>
    <h4>Are you sure you want to delete this Student?</h4>
    <div>
        <p>Name: @Model.Name</p>
        <p>Email: @Model.Email</p>
        <p>Age: @Model.Age</p>
    </div>
</div>

<form method="post" asp-action="DeleteConfirmed">
    <input type="hidden" asp-for="Id" />
    <div class="form-group">
        <button type="submit" class="btn btn-danger">Delete</button>
        <a asp-action="Index" class="btn btn-secondary">Cancel</a>
    </div>
</form>

Conclusion

In this article, we walked through the process of building a complete CRUD application using ASP.NET Core MVC (.NET 8), Dapper ORM, and the Repository Pattern. By combining the simplicity and performance of Dapper with a clean architecture approach, you’ve created a project that is both efficient and easy to maintain. This setup is ideal for small to medium-sized applications where performance matters and development speed is important. Whether you're a beginner exploring .NET or a developer looking to use lightweight tools over heavy ORMs, this project serves as a solid foundation for real-world applications.

Thank you for taking the time to read this article! I hope it helped you understand how to build a CRUD application using ASP.NET Core MVC, Dapper ORM, and the Repository Pattern. If you found this guide helpful, feel free to share it with others or leave your feedback.

Happy coding!



ASP.NET MVC Hosting - HostForLIFE.eu :: Building a User Subscription Module in ASP.NET MVC with C# 14

clock April 29, 2025 10:00 by author Peter

In modern web applications, subscription-based features are essential for managing user access, monetizing content, or offering tiered services. In this guide, we will build a comprehensive User Subscription Module using ASP.NET MVC (Model-View-Controller) and C# 14. The module will support:

  • User registration and login
  • Subscription plan selection
  • Payment integration (mocked)
  • Role-based access based on subscription level
  • Subscription management (upgrade/downgrade/cancel)

We’ll also take advantage of new C# 14 features such as primary constructors, collection expressions, field-backed properties, and extension members to make our code more concise and modern. These features help streamline the codebase and make it easier to read and maintain, especially in large applications with many interrelated components.

By the end of this tutorial, you'll have a functioning module that you can integrate into an existing ASP.NET MVC project. Whether you're building a SaaS platform or a content subscription service, the patterns and practices here will provide a strong foundation for building reliable, scalable subscription systems.

1. Project Setup
The first step in developing our subscription module is to use Visual Studio to create a new ASP.NET MVC application. Our data models, business logic, and user interface elements will be constructed upon this basis. Select the MVC template and set up your authentication preferences according to your user base's requirements when prompted during project creation. In order to enable Entity Framework and ASP.NET Identity, which are essential to our user and subscription management features, we must install a few NuGet packages after building the project. Microsoft, for instance. We may construct our database access layer and Microsoft.AspNet.Identity using EntityFramework. EntityFramework offers the ability to authenticate users.

Install-Package Microsoft.EntityFramework -Version 6.4.4
Install-Package Microsoft.AspNet.Identity.EntityFramework
Install-Package Stripe.net // Optional for real payment integration

These packages lay the groundwork for our entire system. With Entity Framework, we can interact with the database using strongly typed models, and Identity gives us a comprehensive system for managing users and roles. The Stripe package is optional but included for future scalability and integration.

Using NuGet simplifies the setup process and ensures that you get the latest, most secure versions of each dependency. This modular approach also makes the project easier to maintain, since each package can be updated independently of the others.

2. Define Models

To store and manage subscription data, we need to define our data models. These include SubscriptionPlan for defining available plans, UserSubscription to represent a user’s active or past subscriptions, and ApplicationUser which extends ASP.NET Identity’s user model. Each of these models plays a key role in organizing how data is stored and retrieved.

public class SubscriptionPlan
{
    public int Id { get; set; }

    public string Name
    {
        get => field;
        set => field = value ?? throw new ArgumentNullException(nameof(value));
    }

    public decimal Price { get; set; }
    public string Description { get; set; }
    public int DurationInDays { get; set; }
}

public class UserSubscription
{
    public int Id { get; set; }
    public string UserId { get; set; }
    public int PlanId { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public bool IsActive => DateTime.UtcNow <= EndDate;

    public virtual ApplicationUser User { get; set; }
    public virtual SubscriptionPlan Plan { get; set; }
}

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<UserSubscription> Subscriptions { get; set; }
}

These classes map to tables in our SQL database and help organize our business logic. The use of navigation properties (virtual) allows us to navigate related entities easily when using Entity Framework. The UserSubscription model is especially critical for tracking start and end dates, which will be used to determine access.

In C# 14, field-backed properties like Name in SubscriptionPlan help ensure data integrity with built-in validation. This allows us to enforce rules such as requiring names to be non-null directly in the model, rather than repeating this logic throughout the codebase.

3. Add Subscription Logic to DbContext

Next, we extend our DbContext to include our new models. This allows us to use EF to manage our tables and data.

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public DbSet<SubscriptionPlan> SubscriptionPlans { get; set; }
    public DbSet<UserSubscription> UserSubscriptions { get; set; }

    public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { }

    public static ApplicationDbContext Create() => new();
}

This DbContext class bridges your application to the database. Entity Framework uses it to perform CRUD operations and generate SQL queries under the hood. The DbSet<T> properties tell EF which entities should be tracked and mapped to database tables.

The constructor and factory method (Create) show how to simplify context initialization, and using the latest syntax from C# 14 makes it even more concise. Keeping the context clean and modular helps when unit testing or transitioning to more advanced patterns like repository or unit-of-work.

4. Seed Subscription Plans
Add seed data to initialize plans in development or production environments.

context.SubscriptionPlans.AddOrUpdate(p => p.Name,
    new SubscriptionPlan { Name = "Free", Price = 0, Description = "Basic access", DurationInDays = 30 },
    new SubscriptionPlan { Name = "Pro", Price = 9.99M, Description = "Pro features", DurationInDays = 30 },
    new SubscriptionPlan { Name = "Enterprise", Price = 29.99M, Description = "All features", DurationInDays = 90 }
);

Seeding is essential to provide default options without requiring manual input every time the database is recreated. This is useful not only in development but also in CI/CD pipelines for automated deployments. These plans can be adjusted or extended later to suit business needs.

This code ensures that users always have valid plans to choose from. It's especially useful when the app is first launched, ensuring a smooth experience from the very first interaction.
5. Controllers and Views
Here’s a controller that uses a primary constructor:
[Authorize]
public class SubscriptionController(ApplicationDbContext db) : Controller
{
    public ActionResult Index() => View(db.SubscriptionPlans.ToList());

    public ActionResult Subscribe(int id) => View(db.SubscriptionPlans.Find(id));

    [HttpPost]
    public ActionResult SubscribeConfirmed(int id)
    {
        var userId = User.Identity.GetUserId();
        var plan = db.SubscriptionPlans.Find(id);

        var subscription = new UserSubscription
        {
            UserId = userId,
            PlanId = plan.Id,
            StartDate = DateTime.UtcNow,
            EndDate = DateTime.UtcNow.AddDays(plan.DurationInDays)
        };

        db.UserSubscriptions.Add(subscription);
        db.SaveChanges();

        return RedirectToAction("MySubscription");
    }

    public ActionResult MySubscription()
    {
        var userId = User.Identity.GetUserId();
        var activeSub = db.UserSubscriptions
            .Include("Plan")
            .Where(s => s.UserId == userId && s.IsActive)
            .OrderByDescending(s => s.EndDate)
            .FirstOrDefault();

        return View(activeSub);
    }
}


This controller manages the user's interaction with subscription plans. It retrieves available plans, handles subscription actions, and displays the user's current subscription. Using C# 14 primary constructors simplifies dependency injection, especially when there are few dependencies.

The controller is tied to Identity for user management, ensuring that actions like subscribing are tied to the correct user context. This integration of business logic and authentication is central to secure and personalized application flows.

6. Access Control Based on Subscription

Create a custom authorization attribute:
public class SubscriptionAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var userId = httpContext.User.Identity.GetUserId();
        var db = new ApplicationDbContext();
        var sub = db.UserSubscriptions.FirstOrDefault(x => x.UserId == userId && x.EndDate >= DateTime.UtcNow);
        return sub != null;
    }
}


Use it like this:
[SubscriptionAuthorize]
public ActionResult PremiumContent()
{
    return View();
}


This custom attribute checks if the logged-in user has an active subscription. It’s a lightweight and reusable solution to protect controller actions or entire controllers. It works well for scenarios where only subscribers should access certain parts of the application.

By encapsulating this logic into an attribute, we keep our controller actions clean and focused on what they need to do, rather than how authorization should be enforced. This improves both readability and maintainability.

7. Optional: Mock Payment Service

Handling payments is a critical part of any subscription system, but during development or for MVP testing, it's useful to mock this functionality. A mock payment service allows us to simulate successful transactions without integrating a third-party provider like Stripe or PayPal.

Below is a simple mock PaymentService class. It returns true to simulate a successful payment transaction, regardless of input. This allows you to develop and test your system logic without incurring real charges or managing payment API credentials.
public class PaymentService
{
    public bool ChargeUser(string userId, decimal amount)
    {
        // Simulate a successful payment
        Console.WriteLine($"Charging user {userId} for ${amount}");
        return true;
    }
}


You can integrate this into your subscription flow by calling it before saving the subscription. For example:
var paymentService = new PaymentService();
if (paymentService.ChargeUser(userId, plan.Price))
{
    var subscription = new UserSubscription
    {
        UserId = userId,
        PlanId = plan.Id,
        StartDate = DateTime.UtcNow,
        EndDate = DateTime.UtcNow.AddDays(plan.DurationInDays)
    };

    db.UserSubscriptions.Add(subscription);
    db.SaveChanges();
}

Using a mock now allows you to fully test your end-to-end subscription logic while making it simple to switch to a real provider later. When you're ready for live payments, just replace it PaymentService with a real implementation that connects to your gateway of choice.

8. Extension Members in C# 14

Use extension members to clean check the premium status:
public static class SubscriptionExtensions
{
    extension(UserSubscription subscription)
    {
        public bool IsPremium => ["Pro", "Enterprise"].Contains(subscription.Plan?.Name);
    }
}


Then in your code:

if (userSubscription.IsPremium)
{
    // Show premium features
}

Extension members let you encapsulate logic related to a class without modifying the class itself. This is ideal for computed properties like determining plan tier. It keeps your domain model lean while making your code more expressive. This feature is especially useful in scenarios where your business logic spans multiple types or you need utility-style operations across many parts of the app. You avoid cluttering your core model with too much logic.

9. Views

Here's a simple Index.cshtml:
@model IEnumerable<SubscriptionPlan>
<h2>Choose a Plan</h2>
@foreach (var plan in Model)
{
    <div>
        <h3>@plan.Name</h3>
        <p>@plan.Description</p>
        <p>Price: [email protected]</p>
        @Html.ActionLink("Subscribe", "Subscribe", new { id = plan.Id })
    </div>
}

This view lists all available subscription plans. Each plan includes a button that links to the subscribe confirmation page. The use of Razor syntax makes it easy to iterate through models and generate dynamic HTML. Views like this help users quickly understand the value proposition of each plan. With Bootstrap or Tailwind CSS, you could further enhance the design for a polished, responsive experience.

Conclusion

We built a user subscription module using ASP.NET MVC and C# 14, leveraging modern language features for better performance and readability. We explored models, controllers, access control, extension methods, and mocked payment processing. This provides a solid foundation for a SaaS or subscription-based application. Next steps might include adding webhook support, real payment integration (e.g., Square, Stripe), user dashboards, or analytics.



ASP.NET MVC Hosting - HostForLIFE.eu :: How to Use View Files to Publish ASP.NET Core MVC Project.NET 8?

clock April 15, 2025 07:29 by author Peter

This walkthrough will address the following questions and teach you how to publish CSHTML files along with the project.

  • How to create an Asp.Net Core MVC Project?
  • What are the settings for the Project file to publish the CSHTML file while publishing?
  • What are the settings to be done on the publish screen or wizards before publishing?

We are using Visual Studio 2022 for this walk-through.


How to create an ASP.NET Core MVC Project?

Select ASP.NET Core web App (Model-View-Controller as per IMAGE1.

Set the following things in the above image 2:

  • Project name: Set your project name: AspNetMvcNet8Proj.
  • Location: Set your location by clicking… or select previous by clicking on the dropdown list.

  • Framework: Select your .NET version (6.0, 8.0. . .)

We selected .NET 8

  • Authentication Type: None
  • (You can select as per your requirement – None, Individual Accounts, Microsoft Identity Platform, or Windows)
  • Configure for HTTPS: Set Configure for HTTPS for secure request and response.
  • Enable Container Support: Select Docker for Windows or Linux operating system.

After the above selection, choose as per your project requirement. Click on the CREATE button to proceed toward creating a new project.

Press F5 to run the project.


You can see the above project executed successfully.

The next step is to publish the project with a CSHTML file by default while publishing all views files compiled and output into one DLL (assembly). No external CSHTML published.

What are the settings for the Project file to publish the CSHTML file while publishing?

Right-click on the project
Select “Unload Project”

Default Content:
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

</Project>

Change the file to the following settings:
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <PreserveCompilationContext>true</PreserveCompilationContext>
    <MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>

    <!-- To publish views instead of views.dll -->
    <EnableDefaultRazorGenerateItems>false</EnableDefaultRazorGenerateItems>
    <EnableDefaultRazorComponentItems>false</EnableDefaultRazorComponentItems>
    <CopyRazorGenerateFilesToPublishDirectory>true</CopyRazorGenerateFilesToPublishDirectory>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0" />

    <!-- Explicitly include each .cshtml file in the subfolders under Views -->
    <Content Update="Views\**\*.cshtml" CopyToPublishDirectory="PreserveNewest" />
  </ItemGroup>

</Project>

After updating the above settings in the file, close the file again, right-click on the project, and click on “Reload Project”. In the Next step, we set and configure Publish settings.

What are the settings to be done on the publish screen or wizards before publishing?

After Right click on the project, select the “Publish” option.

Select the FOLDER option to publish on the Local Folder and click on the NEXT button.

Select or create a folder where you want to publish the project. Click on the FINISH button after you select the folder location.

Click on Show All settings to set your publish setting more precisely, or directly click on the PUBLISH button. Output of Publish Button:

Error Message: Views\Shared\_Layout.cshtml.css(0,0): Error BLAZOR102: The scoped css file 'Views\Shared\_Layout.cshtml.css' was defined, but no associated razor component or view was found for it.

You can see the error thrown by the publishing process in (Image-10 and Image-11).

Error Solution

Solution 1
You can delete the CSS file “View/Shared/Layout.cshtml” and publish it again.

Solution 2
If you want CSS style or content of the CSS file “View/Shared/Layout.cshtml,” you can create a new CSS file and move this file into the “wwwroot/css” folder and assign the link in the “view/shared/Layout.cshtml” file.


VIEW published successfully

Folder View

You can see in Image-13 and Image-14 Views files were published successfully.



ASP.NET MVC Hosting - HostForLIFE.eu :: Understanding Controller In ASP.NET MVC

clock March 26, 2025 08:41 by author Peter

Here, in this article, we will see more about the controllers and understanding about RouteConfig File. I will be using the same solution which we had used in our previous article. Thus, let's start an introduction.

Open our solution MVCTestApplication, given below:

You can see in our Home Controller class; we have two Action methods; one is Index() and other is HelloAll() . The Index methods are invoked, when you run the Application. Now, just run the Application and you will see:

By default, Hello CsharpCorner has been displayed, because in RouteConfig file, the default action method is Index and we had written “Hello HostForLIFE ” in Index Action Method.

Now, let's type the URL i.e. ControllerName/ActionName and see what we are getting:

As you can see, we had got the same result: “Hello CsharpCorner.” Here, Home is our ControllerName and Index is our Action Method . Similarly, we will see our second Action Method i.e. HelloAll()

As you can see, HelloAll() Action Method has been invoked. Now, let's understand RouteConfig and how these controllers are displayed. Just Open global.asax file in our solution and you will see:

 

Open this file and you will see Application_start () method, in which you will see this line as:

Go to its Definition section, it will redirect to RouteConfig File and you will see:

 

In RouteConfig class, we have default document as:
name:”Default”-Specifies the name

URL: “{Controller}/{action}/{id}” – This line actually says that when you run the solution by default, it will first fire the controllername/index and then Id.

Defaults: As you can see, the default controller' s Home is called and is followed by the action Index and then Id. Note: Here the specified Id is normal and if you want to retrieve the results, you have to pass the Id.

Now, we will see how to pass the Id in our URL and see what output we are getting. Hence, let's start:

In our Homecontroller class, in our Index Action method, just pass a parameter as a string name and return as a name . Now, we will run the Application and see what values we are getting.

When you run the solution, it will ask for the name. Now, let's pass the name in our URL:

As you can see in the output, given above, it had passed Id=1 and got Id=1. Just type Home/index/1 an you will get the output, given above. Now, we will modify the code, write the name and see the output that we will get:

I had passed the name. Now, run the Application. You will see the following output:

Now, just pass the Id and name. We saw the last Id, how to specify the Id or name and how to display it. Now, let's get back to the RouteConfig file and understand the line, given below:

Here, what this line says is: Whatever you are doing in the Controller or in the Index Action method, a trace is getting generated in the form of axd format. We will see how these are generated and how to generate a resource.axd trace. Just open web.config file, shown below:

Just write this line in your web.config file.

Now, run the Application and type trace.axd. You will see the following output:

Click the View details and you will get all the details, shown below:

Scroll down at the bottom of the page and you will see that its path, query string and its respective URLs are:

The trace.axd is useful, when you have built a huge application and you require tracing to find out the details. Conclusion: This was controllers in MVC. I hope you found this article helpful.



ASP.NET MVC Hosting - HostForLIFE.eu :: Using External Projects And Assemblies To Extend MVC Controllers

clock March 18, 2025 07:30 by author Peter

I thought I would take a moment to discuss how one might handle the situation after seeing a recent question on Stack Overflow about how to extend an existing ASP.NET MVC Controller that was present within another assembly or project (i.e., external to the "main" MVC application).

The Fundamental Concept
Assuming you are working on two projects,

  • ProjectA is your primary MVC program.
  • ProjectB is merely a basic class library.

Your goal is to add more controller actions or functionality to an already-existing controller in Project A. These extra steps will originate from a separate project or assembly and won't be included in your primary application. When developing client-specific functionality—that is, when a client requests a certain behavior that might not be pertinent in the main application—this could be helpful.

Thus, for example, your ProjectA controller definition could resemble this:

    namespace ProjectA.Controllers    
    {  
        // This is the primary controller that we want to extend  
        public class FooController : ApplicationController  
        {  
              public ActionResult Index()  
              {  
                  return Content("Foo");  
              }  
        }  
    }   


And you might have a similar class in ProjectB that resembles this,
    namespace ProjectB.Controllers    
    {  
        // You want to essentially add the Bar action to the existing controller  
        public class CustomFooController : FooController  
        {  
            public ActionResult Bar()  
            {  
                return Content("Bar");  
            }  
        }  
    }   


You want to allow all of the different clients to access Foo, but perhaps only a certain client to be exposed to Foo/Bar.

Breaking Down The Steps
This process requires a few different steps that will need to be done to get everything working as expected, which I'll review below,

  • Inheritance
    • The custom controller will inherit from the controller in our main application to streamline extension.
  • Routing
    • Routing can be a tricky business, so using attribute routing might ease some of the burden of fighting with route tables or conflicting controller names.
  • Build Events
    • Build events are just one simple approach to actually getting the necessary .dll files from your custom project into your main application so they can be used.

Taking Advantage of Inheritance
If you actually want to extend the functionality of an existing controller, then inheritance might be the way to go. Inheriting from the controller within your main application will allow you to take advantage of any existing attributes, overridden methods, or underlying base controllers that might already place.

You'll just want to add a reference to your ProjectA project in ProjectB and then target the appropriate controller you wish to inherit from,
    // Other references omitted for brevity  
    using ProjectA.Controllers;  
      
    namespace ProjectB.Controllers    
    {  
        public class CustomFooController : FooController  
        {  
            public ActionResult Bar()  
            {  
                return Content("Bar");  
            }  
        }  
    }   


Leverage Attribute Routing
Doing this kind of thing can get a bit dicey with regards to routing. When you attempt to create this new controller within your current application, it'll attempt to use the existing routes defined in that application, which can lead to naming conflicts and ambiguity if you aren't careful.

Based on the code provided, this means you could easily access /CustomFoo/Bar, but not /Foo/Bar like you might prefer. Thankfully, attribute routing can help with this.

Simply decorate your custom controller action with a [Route] attribute that indicates how you wish to access it,
    [Route("Foo/Bar")]  
    public ActionResult Bar()    
    {  
         return new Content("Bar");  
    }   

This will let MVC know to use map this action to the Foo/Bar URL before taking a look at some of the other routes. In order for attribute routing to work as expected, you'll need to ensure to call the MapMvcAttributeRoutes() method within the RouteConfig.cs file of your main application,
    public static void RegisterRoutes(RouteCollection routes)    
    {  
        // This is important to write up your Route Attributes  
        routes.MapMvcAttributeRoutes();  
      
        // Route declarations omitted for brevity  
    }   


Note
If you were extending a controller that was present within an MVC Area, you would do the same thing within the RegisterArea() method in your AreaRegistration.cs file,
    public override void RegisterArea(AreaRegistrationContext context)    
    {  
        // Wire up any attribute based routing  
        context.Routes.MapMvcAttributeRoutes();  
      
        // Area routing omitted for brevity  
    }   

Properly Scoping Routes
One additional change that will need to be made within your main application will be to prioritize routes within its own namespace. The MapRoute() method supports an overload to handle this via the namespaces parameter.

Set the namespaces parameter to point to the namespaces that you wish to prioritize, namely those in your main application (i.e. "ProjectA.Controllers").
    routes.MapRoute(    
       name: "Default",  
       url: "{controller}/{action}/{id}",  
       defaults: new { controller = "Foo", action = "Index", id = UrlParameter.Optional },  
       // This will prioritize routes within your main application  
       namespaces: new[] { "ProjectA.Controllers"}  
    );   

Putting It All Together
At this point, code-wise, everything should be in place. The only thing left to do is actually get the code from your ProjectB into ProjectA so that you can run it. There are a variety of ways to handle this and configure this entire process, but a very simple one might be through a Build Event. Build Events allow you to execute a bit of code during various stages of the build process.

We are interested in defining a Post-Build event that will move our ProjectB.dll file into the bin directory of ProjectA, which might look like this,
xcopy /E /Y /S "$(ProjectName).dll" "$(SolutionDir)\ProjectA\Bin\"

This would be defined under ProjectB > Properties > Build Events > Post-Build Event Command Line as seen below,

Now if you perform a Rebuild Solution, you should see that all of the proper files have been added to your bin directory as expected,

Now if you were to navigate to /Foo within your application, you would see the content that you might expect,

And likewise, /Foo/Bar should now hit your custom code and do exactly what you'd imagine,




ASP.NET MVC Hosting - HostForLIFE.eu :: ASP.NET MVC Membership Provider

clock March 13, 2025 09:16 by author Peter

Here, we will learn how to use ASP.NET MVC membership provider, create users and their roles using ASP.NET MVC membership, assign roles to users in ASP.NET MVC membership provider, and remove users from roles once we have all user roles from ASP.NET MVC membership. Finally, we will demonstrate how to implement security in ASP.NET MVC applications.

To make security in ASP.NET MVC application use the following method to create the security in ASP.NET MVC application.

Authentication And Authorization in ASP.NET MVC
Authentication: It is the process of checking that the user is valid or not.
Authorization: It is the process of checking that the user is applicable for the process or not.

Membership providers in ASP.NET MVC
Roles based authentication for user in ASP.NET MVC.

We will learn how to create a database for the membership provider in ASP.NET MVC and how to assign role to user, we will create a registration page to understand this.

Let’s create a application for membership provider ASP.NET MVC.
Step 1: Go to visual studio and click on new project -> a window will open from here select a 'ASP.NET MVC4 web application' and give the name for this project in my case I give it as “MVCMembershipProvider "

Now click ok and select a template as Internet Application and engine as Razor engine , after sleeting all these click ok. it will click a solution project this will contain .css file ,script file and MVC application structure.

Step 2: After creation of application let's create a database for this and give the name for this database i gave it as 'MVCApp' and then add a connection string to the database.
    <connectionStrings>  
        <add name="DBConnection" connectionString="Data Source=MUNESH-PC;Database=MVCApp;UID=sa;Password=*****" providerName="System.Data.SqlClient" />  
    </connectionStrings>  


After adding the connection string to the project now we need to create membership tables to the database but before this go to the models folder and have a look on AccountModels.cs class. this class automatically create when we select mvc application as Internet application.

AccountModel.cs class contain following methods.

Now for creating membership tables in database initialize the connection in globel.asax . here we will use code first approach for that we need to add following code in this class.
For adding data table in database membership we need to add a line of code in Global.asax.
WebSecurity.InitializeDatabaseConnection("DBConnection", "UserProfile", "UserId","UserName", autoCreateTables: true);  
Here namespace for WebSecurity is “using WebMatrix.WebData;”

WebSecurity.InitializeDatabaseConnection

Definition for the InitializeDatabaseConnection is:
Public static void InitializeDatabaseConnection (string connectionStringName, stringuserTableName, string userIdColumn, string userNameColumn, bool autoCreateTables);  

connectionStringName: It the name of database table where user information stored.
userTableName: It contain user profile information.
userIdColumn: This column name of table contain user ID this should be integer.
userNameColumn: Column name of table contain user name. This column is basically used to match profile data of user with membership account data.

autoCreateTables: True to indicate that user profile and membership tables should be created if they do not exist; false to indicate that tables should not be created automatically. Although the membership tables can be created automatically, the database itself must already exist.

Now globel.asax page will look like:

Now after all this configuration let's run your application and see the ur hoe page and click on register link which is your page's right side. After running your application you go to the database and see the table, it will generate the following tables for us.

When you will click on registration link the following screen will open with 3 fields.

We can add more fields to this view, for making changes in registration view 1st weneed to add field in database and the  table name is “UserProfile”;


Here we added 3 columns as shown above; now we need to add these column parameters in registration model, it is in Account.cs class which is available in Model.
Code for registration model is:
    public class RegisterModel  
    {  
        [Required]  
        [Display(Name = "User name")]  
        public string UserName  
        {  
            get;  
            set;  
        }  
        [Required]  
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]  
        [DataType(DataType.Password)]  
        [Display(Name = "Password")]  
        public string Password  
        {  
            get;  
            set;  
        }  
        [DataType(DataType.Password)]  
        [Display(Name = "Confirm password")]  
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]  
        public string ConfirmPassword  
        {  
            get;  
            set;  
        }  
        [Required]  
        [Display(Name = "EmailID")]  
        public string EmailId  
        {  
            get;  
            set;  
        }  
        [Required]  
        [Display(Name = "address")]  
        public string Address  
        {  
            get;  
            set;  
        }  
        [Required]  
        [Display(Name = "Mobile No")]  
        public string MobileNo  
        {  
            get;  
            set;  
        }  
    }  


Add these field in registration view:
    <fieldset>  
        <legend>Registration Form</legend>  
        <ol>  
            <li>  
                @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName)  
            </li>  
            <li>  
                @Html.LabelFor(m => m.Password) @Html. PasswordFor (m => m.Password)  
            </li>  
            <li>  
                @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword)  
            </li>  
            <li>  
                @Html.LabelFor(m => m.EmailId) @Html.TextBoxFor(m => m.EmailId)  
            </li>  
            <li>  
                @Html.LabelFor(m => m.Address) @Html.TextBoxFor(m => m.Address)  
            </li>  
            <li>  
                @Html.LabelFor(m => m.MobileNo) @Html.TextBoxFor(m => m.MobileNo)  
            </li>  
        </ol>  
        <input type="submit" value="Register" />  
    </fieldset>  


Now if you will run your application and you will see registration page it will look with new fields.

Now according to this we need to add or handle these field in controller also so for that go to Account Controller and we have to make changes in HTTPPost method of registration Action.

Now the code for this action according to old registration model is:
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);  

Now will make changes in this according to new model:
    WebSecurity.CreateUserAndAccount(model.UserName, model.Password,  
    new  
    {  
       EmailID = model.EmailId,  
       Address = model.Address,  
       MobileNo = model.MobileNo  
    }  
    );  

So the code for the Registration action method is:

    [HttpPost]  
    [AllowAnonymous]  
    [ValidateAntiForgeryToken]  
    public ActionResult Register(RegisterModel model)  
    {  
        if (ModelState.IsValid)  
        {  
            // Attempt to register the user  
            try  
            {  
                WebSecurity.CreateUserAndAccount(model.UserName, model.Password,  
                    new  
                    {  
                        EmailID = model.EmailId,  
                            Address = model.Address,  
                            MobileNo = model.MobileNo  
                    }  
                );  
                WebSecurity.Login(model.UserName, model.Password);  
                return RedirectToAction("Index", "Home");  
            }  
            catch (MembershipCreateUserException e)  
            {  
                ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));  
            }  
        }  
        // If we got this far, something failed, redisplay form  
        return View(model);  
    }  


Now run your application and go to registration page and enter some data to fields then save it ,data will save in database.



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.


Tag cloud

Sign in