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 :: Using Gemini AI to Automate Image Captions and Alt Text in ASP.NET Core MVC

clock November 27, 2025 07:25 by author Peter

Images play a major role in modern web applications, including dynamic content portals, product pages, and blogs. However, creating quality alt text and captions for each uploaded image is frequently a laborious, tedious process. An uploaded image can be automatically analyzed by the AI to produce:

  • A meaningful, context-aware caption
  • SEO-friendly alt text
  • Multiple variations for each
  • Output in any language

This article shows you how to integrate Gemini AI into ASP.NET Core MVC (.NET 10) to process images and generate high-quality descriptive text.

Why Use Gemini AI for Image Captioning?
Gemini AI is trained on a massive multimodal dataset, which means:

  • It understands visual context (objects, scenes, emotions, actions)
  • It can generate human-like captions
  • It supports multiple languages
  • It can return multiple options so users can choose the best one

Features We Will Implement

  • Upload an image in ASP.NET Core MVC
  • Send the image bytes to Gemini AI
  • Ask Gemini to generate:
    • Multiple caption options
    • Multiple alt text variations
    • Output in multiple languages
  • Render results on the page
  • SEO-friendly and accessible output

Before diving into the code, first you have to create a project in Visual Studio (2026 prefer) and have a Gemini API key that you can get it from Google AI Studio .

Project Structure
Below image shows the project structure that I am following to demonstrate the implementation.

Add Gemini API Key to appsettings.json
{
  "Gemini": {
    "ApiKey": "your-api-key-here"
  }
}

You can store the API key in User Secrets for security.
Create the Image Upload View
<div class="container mt-5">
    <div class="card shadow p-4">
        <h2 class="mb-4 text-center">AI Image Caption Generator</h2>
        <form asp-action="Analyze" enctype="multipart/form-data" method="post">
            <div class="mb-3">
                <label class="form-label">Select Image</label>
                <input type="file" name="file" class="form-control" required />
            </div>
            <div class="mb-3">
                <label class="form-label">Select Language</label>
                <select name="language" class="form-select">
                    <option value="en">English</option>
                    <option value="ne">Nepali</option>
                    <option value="hi">Hindi</option>
                    <option value="es">Spanish</option>
                    <option value="fr">French</option>
                    <option value="ja">Japanese</option>
                </select>
            </div>
            <button class="btn btn-primary w-100">Analyze Image</button>
        </form>
    </div>
</div>


Create the Service to Handle Gemini Connection
This GeminiService is responsible to handle connection with the Gemini AI API with the prompt. Uploaded image converts into the base64Image as Geimin AI requires base64Image.
public class GeminiService
{
    private readonly IConfiguration _config;
    private readonly IHttpClientFactory _httpClientFactory;

    public GeminiService(IConfiguration config, IHttpClientFactory httpClientFactory)
    {
        _config = config;
        _httpClientFactory = httpClientFactory;
    }

    public async Task<(List<string> captions, List<string> alts)>
        AnalyzeImageAsync(byte[] imageBytes, string mimeType, string language = "English")
    {
        string apiKey = _config["Gemini:ApiKey"];
        if (string.IsNullOrEmpty(apiKey))
            throw new Exception("Gemini API Key missing");
        var http = _httpClientFactory.CreateClient();
        string base64Image = Convert.ToBase64String(imageBytes);
        var requestBody = new
        {
            contents = new[]
            {
            new {
                parts = new object[]
                {
                    new { text =
                        $"Analyze this image and return:" +
                        $"\n - 5 caption options" +
                        $"\n - 5 alt text options" +
                        $"\n - Language: {language}" +
                        $"\nRespond in JSON only: {{ \"captions\": [...], \"alts\": [...] }}"
                    },
                    new {
                        inline_data = new {
                            mime_type = mimeType,
                            data = base64Image
                        }
                    }
                }
            }
        }
        };
        string url =
            $"https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent?key={apiKey}";
        var response = await http.PostAsync(
            url,
            new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json")
        );

        if (!response.IsSuccessStatusCode)
        {
            string error = await response.Content.ReadAsStringAsync();
            throw new Exception($"Gemini API Error: {error}");
        }

        var json = await response.Content.ReadFromJsonAsync<JsonElement>();
        var textResponse = json
            .GetProperty("candidates")[0]
            .GetProperty("content")
            .GetProperty("parts")[0]
            .GetProperty("text")
            .GetString();

        textResponse = textResponse.Replace("```json", "").Replace("```", "");
        var resultJson = JsonDocument.Parse(textResponse).RootElement;
        var captions = resultJson.GetProperty("captions")
            .EnumerateArray().Select(x => x.GetString()).ToList();

        var alts = resultJson.GetProperty("alts")
            .EnumerateArray().Select(x => x.GetString()).ToList();

        return (captions, alts);
    }
}


Register GeminiService

In the program.cs file, add below lines of code to register HttpClient and GeminiService.
// Register HttpClient and GeminiService
builder.Services.AddHttpClient();
builder.Services.AddSingleton<GeminiService>();


Create a Controller

When the user uploads an image, the ImageController processes the form submission, converts the file into bytes, detects its MIME type, and sends the prepared image data to the GeminiService for further processing by Gemini AI.
public class ImageController: Controller
{
    private readonly GeminiService _gemini;

    public ImageController(GeminiService gemini)
    {
        _gemini = gemini;
    }

    public IActionResult Index() => View();

    [HttpPost]
    [RequestSizeLimit(10 * 1024 * 1024)] // 10 MB
    public async Task<IActionResult> Analyze(IFormFile file, string language = null)
    {
        if (file == null || file.Length == 0)
        {
            ModelState.AddModelError("file", "Please select an image file.");
            return View("Upload");
        }

        using var ms = new MemoryStream();
        await file.CopyToAsync(ms);
        var bytes = ms.ToArray();

        var result = new ResponseModel();
        try
        {
            var mimeType = MimeTypeHelper.GetMimeType(file.FileName);
            var content = await _gemini.AnalyzeImageAsync(bytes, mimeType, language);
            result.Alts = content.alts;
            result.Captions = content.captions;
        }
        catch (Exception ex)
        {
            //error handling
            TempData["Error"] = "Failed to analyze the uploaded image. Error: " + ex.Message;
            return RedirectToAction("Upload");
        }

        // Pass model to view
        return View("Result", result);
    }
}


Create the Result View

@using ImageAnalyzer.Models
@model ResponseModel
@{
    ViewData["Title"] = "AI Result";
}
<div class="container mt-5">
    <div class="card shadow p-4">
        <h2 class="mb-4 text-center">AI Generated Caption & Alt Text</h2>
        @if(Model.Alts.Any())
        {
            <h3>Suggested Alt text</h3>
            <ul>
                @foreach(var alt in Model.Alts)
                {
                    <li>@alt</li>
                }
            </ul>
        }

        @if(Model.Captions.Any())
        {
            <h3>Suggested Captions</h3>
            <ul>
                @foreach(var caption in Model.Captions)
                {
                    <li>@caption</li>
                }
            </ul>
        }

        <a href="/image" class="btn btn-secondary mt-3">Analyze Another Image</a>
    </div>
</div>


SEO Benefits

Using AI-generated caption & alt text improves:

  • Google Image Search ranking
  • Accessibility score
  • User engagement
  • Localized content reach
  • Content creation time

Your editors no longer need to write text manually—AI does it instantly.

Conclusion
Using Gemini AI to automate alt text and image captions in ASP.NET Core MVC is:

  • Easy to execute
  • Excellent for SEO
  • Beneficial to accessibility
  • Very efficient in terms of time
  • Supports all required languages.

Your program may automatically describe every uploaded image with a few lines of code, adding richness, intelligence, and user-friendliness to the material.



ASP.NET MVC Hosting - HostForLIFE.eu :: Knowing How to View.cshtml Locate the Appropriate Controller in ASP.NET Core MVC

clock November 25, 2025 06:15 by author Peter

Model-View-Controller is a potent design used by ASP.NET Core MVC, where each component has a distinct role:

  • Controller → Handles requests
  • View (.cshtml) → Displays UI
  • Model → Carries data

One common question for beginners is:
How does a .cshtml View know which controller it belongs to?

The simple answer is:

  • Views never call controllers.
  • Controllers call the views.

Let's break this down step-by-step.

1. MVC Routing: The Real Connection Between Controller and View

ASP.NET Core uses a default routing pattern:
/{controller}/{action}/{id?}
This means:

  • The first part of the URL selects the controller
  • The second part selects the action method inside that controller
  • The view is determined by the action method

Example URL
/Account/Login

Meaning:

URL PartMapped To
Account AccountController
Login Login() action method
id? Optional

So when you open that URL, the framework:

  • Finds AccountController
  • Executes Login()
  • Returns Login.cshtml

2. How Controllers Return Views
Inside a controller, you normally write:
public IActionResult Login()
{
return View();
}

When ASP.NET Core sees return View();, it looks for a .cshtml file that matches the action method name.

In this case:
Controller name → AccountController
Action method → Login()

So MVC loads the file here:

  • Views/Account/Login.cshtml
  • This is how the connection is made.

3. The View Folder Naming Convention
The MVC folder structure is very important:

Views
└── Account
    └── Login.cshtml


Rule 1 — Folder name = Controller name (without "Controller")
Controller: HomeController → Folder: Views/Home/
Controller: ProductController → Folder: Views/Product/

Rule 2 — View file name = Action method name
Action: Index() → View: Index.cshtml
Action: Details() → View: Details.cshtml

4. What If You Want to Load a Different View?

You can specify a different file name:
return View("CustomPage");

This loads:
Views/Account/CustomPage.cshtml

5. Shared Views
Sometimes you want a view that multiple controllers can use.

ASP.NET Core will look second in:
Views/Shared/

For example:
Views/Shared/Error.cshtml

6. Summary Diagram
User enters URL → MVC Routing → Finds Controller → Runs Action → Returns View (.cshtml)

Or visually:
/Account/Login
  ↓
AccountController
  ↓
Login() action
  ↓
Views/Account/Login.cshtml


Final Thoughts
The connection between .cshtml and controller is not magic —
it is handled through:

  • Routing
  • Folder naming conventions
  • Action method names
  • Return View() method

Once you understand this, the entire MVC workflow becomes easy.



ASP.NET MVC Hosting - HostForLIFE.eu :: How to Fix Issues with an ASP.NET MVC Website?

clock October 28, 2025 08:20 by author Peter

Unexpected issues that impact functionality, performance, or user experience might occasionally arise when a ASP.NET MVC website is run in production. Any ASP.NET MVC developer must be able to diagnose and fix mistakes efficiently, regardless of whether they are runtime exceptions, deployment failures, or configuration issues. This article covers the most typical causes, tools, and recommended practices for troubleshooting issues in ASP.NET MVC applications.

<system.web>
  <customErrors mode="Off"/>
  <compilation debug="true"/>
</system.web>

  • customErrors = Off shows full error details.
  • debug = true provides a stack trace.
  • Do NOT enable these in production.

Step 2: Check the Event Viewer Logs
If your MVC site is hosted on IIS, Windows Event Viewer is a great place to find exception logs.

Open Event Viewer

  • Navigate to Windows Logs > Application
  • Look for .NET Runtime or Application Error
  • This helps identify runtime crashes and application pool failures.

Step 3: Use Try-Catch and Global Error Handling
Catch unhandled errors globally using Application_Error in Global.asax or a custom filter.

Global.asax
protected void Application_Error()
{
    var exception = Server.GetLastError();
    // Log the exception
    System.Diagnostics.Trace.TraceError(exception.ToString());
}


Custom HandleErrorAttribute
public class CustomErrorHandler : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        // Log exception here
        base.OnException(filterContext);
    }
}


Register in FilterConfig.cs:
filters.Add(new CustomErrorHandler());

Step 4: Check IIS Configuration and Permissions
Common IIS issues:

IssueSolution
HTTP 500 Internal Server Error Check .NET version and pipeline mode
HTTP 404 Not Found Enable MVC routing & extensionless URLs
Access Denied Errors Grant folder permissions to IIS_IUSRS
Application Pool Stopped Automatically Enable "Always Running" and check logs

Step 5: Debug Route Errors

Wrong URL routing can lead to 404 errors.

Use this debugging helper:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);


Also check:

  • Missing controllers/actions
  • Incorrect parameter names
  • Route conflicts

Step 6: Troubleshoot Dependency and DLL Issues
Example runtime error:
Could not load file or assembly 'Newtonsoft.Json'

Solutions:

  • Check bin folder for missing DLLs
  • Install via NuGet:
  • Install-Package Newtonsoft.Json
  • Ensure Copy Local = true for references

Step 7: Log Exceptions Using Logging Tools
Instead of relying on console logs, use structured logging:

  • NLog
  • Serilog
  • Elmah (popular for MVC)

Example with NLog:
private static readonly Logger logger = LogManager.GetCurrentClassLogger();

try
{
    // some logic
}
catch(Exception ex)
{
    logger.Error(ex);
}


Step 8: Debug Using Browser Developer Tools
Use F12 Developer Tools for:

  • Network call failures (500/404 status)
  • JavaScript runtime errors
  • Invalid AJAX responses
  • Missing CSS/JS files

Step 9: Use Remote Debugging (Advanced)
Attach Visual Studio debugger to the live IIS process:

  • Install Remote Debugging Tools on the server
  • From Visual Studio → Debug → Attach to Process

Select w3wp.exe
Great for live issue reproduction.

Step 10: Enable Friendly Error Pages in Production
Use custom error pages to show user-friendly messages.
<customErrors mode="On" defaultRedirect="~/Error">
  <error statusCode="404" redirect="~/Error/NotFound"/>
  <error statusCode="500" redirect="~/Error/ServerError"/>
</customErrors>

Common MVC Error Checklist

 

 

Error TypeQuick Fix

Configuration Error

Check web.config

Dependency DLL Missing

Reinstall NuGet package

Database Connection Failed

Test connection string

Unauthorized Error (401/403)

Check IIS authentication

NullReferenceException

Validate objects

View Not Found

Verify view name/path

Route Not Matching

Fix RouteConfig

Conclusion

Troubleshooting a .NET MVC application becomes much easier when you follow a systematic approach. Always:
✔ Enable logging
✔ Capture error details
✔ Check IIS & permissions
✔ Validate configuration
✔ Test routing and dependencies

With the right techniques, you’ll diagnose and resolve most issues quickly and professionally.



ASP.NET MVC Hosting - HostForLIFE.eu :: Hello World Program In ASP.NET MVC

clock October 14, 2025 08:13 by author Peter

Step 1
Create project


Open Visual Studio -> click File -> New-> Project. 

Visual C#-> Web -> ASP.NET Web Application-> write Project Name-> OK.

Select MVC template. Empty-> Click MVC Folder-> OK.

MVC Folders are created.

Let's understand MVC architecture in ASP.NET
MVC stands for Model, View and Controller. MVC separates an application into three components - Model, View and Controller.

Model
Model represents the shape of the data and business logic. It maintains the data of the Application. Model objects retrieve and store model state in a database.

View
View is a user interface. View displays the data, using model, to the user and also enables them to modify the data.

Controller
Controller handles the user request.

The flow of the user's request in ASP.NET MVC is given below.

First user enters a URL in the Browser (www.google.com)
It goes to the Server and calls an appropriate controller.
The Controller uses the appropriate View and Model, creates the response and sends it back to the user.
Controller handles the user's requests, so first we have to create a Controller

Step 2
Add Controller
Go to the controllers folder-> Add-> Controller-> Select MVC 5 Controller Empty->Add.

It will open Add Controller dialog, as shown below.

Write Controller Name. Do not delete the word Controller. Remember, controller name must end with Controller.

This will create HomeController class with Index method in HomeController.cs file under Controllers folder, as shown below.

Step 3
Add View

Open a HomeController class -> right click inside Index method -> click Add View.

In Add View dialogue box, keep the view name as Index.

This will create View.

Step 4

    Write code in controller class as shown below  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
    namespace HelloWorldExample.Controllers {  
        public class HomeController: Controller {  
            public ActionResult Index() {  
                ViewBag.message = "Hello World";  
                return View();  
            }  
        }  
    }  

Step 5
    Write code in View as shown below  
    @ {  
        Layout = null;  
    } < !DOCTYPE html > < html > < head > < meta name = "viewport"  
    content = "width=device-width" / > < title > Index < /title> < /head> < body > < div > @ViewBag.message < /div> < /body> < /html>  


Note
Here, I am using ViewBag. It is used to transfer the data from the controller to the view.

Output



ASP.NET MVC Hosting - HostForLIFE.eu :: Creating Layout (Master) Pages In MVC

clock September 26, 2025 09:42 by author Peter

This article explains how we can create the Layout (Master) page in MVC 5. Also, it explains the components of Master Page.

Creating Layout Pages


Create a new MVC Project.

Add MVC Layout page in Share folder.
Note: Share folder pages can be used across the project.

Add the below content to the Layout page.

Nav- Nav tags are generally used for navigation bar. We can add links to navigate between the pages.

@RenderSection- Render section is just like a place holder where we can place our code that we can inject from the content page. If we make render section property true, we must need to add this section in all the pages which are used in this layout page, otherwise it will go through as a not implemented error. If we want to make this an option, we need to set it to false.

@RenderBody- RenderBody is a place holder to display the content of the View.

Header & Footer- These are useful to display the header and footer information.

Add Controller and its View to create your page.

Select a new layout page while creating the View.

The below Index View is created by using _RKMaster.cshtml page. In general, if you use _Layout.cshtml, it doesn't display here because it is set in the global default Master page. If we want to set our Layout page as default layout page, we need to set it in _ViewStart.html page, as shown below.

Add the Render section and page content in the View.

Configure your Controller in Route Config to take it as default, and execute the project.

Final View- The header, nav, and footer are coming from the Master Layout page, while the section and page body are rendering from the View page.

Hope this article helps you in understanding the Layout pages and its content.



ASP.NET MVC Hosting - HostForLIFE.eu :: How To Use Cookie In ASP.NET Core Application?

clock September 12, 2025 08:02 by author Peter

Anyone interested in learning how to use the Asp.net core MVC application to save data in browser cookies should read this post. You can use the ASP.NET Core MVC web application to develop a sample web application if you wish to put it into practice.

Let's begin.

In essence, a cookie is a tiny bit of information sent to the user's web browser by the server. It might be saved by the browser and sent back to the same server with a subsequent request. Usually, the browser uses it to determine whether two requests originated from the same browser.

Types of cookie 
Persistent cookie

A cookie that has not to have expired time which is called a persistent cookie 

Non-Persistent cookie

Cookie which has expired time is called a Non-persistent cookie 

Adding cookie to the browser
First, add methods inside the Home controller. I have created an action method as CreateCookie and I have added key as DemoCookie. After that I have stored string value as Yogesh so we can store this value in the client browser 
public IActionResult CreateCookie() {
    string key = "DemoCookie:;
    string value = Yogesh;
    cookieOptions obj = new CookieOptions();
    obj.Expires = DateTime.Now.AddDays(7);
    Response.Cookie.Append(key, value, options);
    return view();
}


To see the cookie which is added in the browser I am using Google Chrome.

Now we will see how to retrieve data from cookies, here I have created Action Method ReadData that is used to retrieve data from cookies.
public IActionResult Read Data() {
    string key = "DemoCookie";
    var CookieValue = Request.Cookies[key];
    return View();
}

Now we will see how to delete data that is stored in cookies, here I have created the Action method Delete to perform the Delete operation on the cookie.

public IActionResult Delete() {
    string key = "DemoCookie";
    string value = DateTime.Now.ToString();
    CookieOptions options = new CookieOptions();
    options.Expires = DateTime.Now.AddDays(-1);
    Response.Cookies.Append(key, value, options);
    return View();
}

Summary 
In this article, we have seen how to store data into cookies and retrieve and delete data from cookies. Hope you guys like it. Happy Coding!



ASP.NET MVC Hosting - HostForLIFE.eu :: A Comprehensive Guide on Partial View vs. ViewComponent in ASP.NET MVC/Core

clock September 3, 2025 07:12 by author Peter

Both appear to be comparable at first glance. They enable us to reuse user interface elements on other sites. However, they differ greatly under the hood. The distinctions, applications, performance factors, and when to pick one over the other will all be covered in this article.

What is a Partial View?

  • A Partial View is a Razor view (.cshtml) file that can be reused inside other views.
  • It is essentially a fragment of HTML + Razor that does not have its own controller logic.

Think of it like a shared template. If you’ve worked with ASP.NET WebForms before, you can compare it to a UserControl (.ascx).
Example

_LoginPartial.cshtml
@if (User.Identity.IsAuthenticated)
{
    <p>Welcome, @User.Identity.Name</p>
    <a href="/Account/Logout">Logout</a>
}
else
{
    <a href="/Account/Login">Login</a>
}

You can include it in your main view as:
@Html.Partial("_LoginPartial")

or asynchronously:

@await Html.PartialAsync("_LoginPartial")
Key Point: A Partial View does not have its own logic. It depends on the data passed from the parent view’s controller.

What is a ViewComponent?
A ViewComponent is like a mini-controller.
It combines C# logic + a Razor view into a self-contained unit.

It allows you to encapsulate business logic and rendering in one place, making it perfect for widgets that require their own data fetching.

Example
ViewComponents/CartSummaryViewComponent.cs
public class CartSummaryViewComponent : ViewComponent
{
    private readonly ICartService _cartService;

    public CartSummaryViewComponent(ICartService cartService)
    {
        _cartService = cartService;
    }

    public IViewComponentResult Invoke()
    {
        var cart = _cartService.GetCart(User.Identity.Name);
        return View(cart);
    }
}


The Razor view (Views/Shared/Components/CartSummary/Default.cshtml):
<div class="cart-summary">
    <p>Items in cart: @Model.Items.Count</p>
    <p>Total: @Model.TotalPrice.ToString("C")</p>
</div>

Usage in your main view:
@await Component.InvokeAsync("CartSummary")

Key Point: A ViewComponent has its own logic and data source. It does not rely on the parent controller’s model.

Key Differences Between Partial View and ViewComponent

FeaturePartial ViewViewComponent
Definition Reusable HTML + Razor fragment Mini controller + view
Logic Handling No (uses parent’s controller/model) Yes (has its own C# logic class)
Data Binding Uses parent ViewData, ViewBag, Model Accepts parameters, independent model
Execution Rendered inside parent’s lifecycle Executes independently like a child action
Reusability Best for static/common layouts Best for dynamic, data-driven widgets
Performance Lightweight Slightly heavier but cleaner separation
Examples Header, Footer, Menu, Static widgets Notifications, Cart summary, Latest posts

When to Use Partial View?

Use a Partial View when:

  • You only need reusable HTML markup.
  • Data comes from the parent controller.
  • Example scenarios:
  • Website header and footer
  • Navigation menus
  • Shared static templates like the Terms & Conditions section

Code Example

@Html.Partial("_Header")
@Html.Partial("_Footer")


When to Use ViewComponent?

Use a ViewComponent when:

  • You need business logic + view rendering together.
  • Data comes from a different source than the parent view.
  • You want testability (since ViewComponents can be unit tested).
  • Example scenarios:
    • Shopping cart summary
    • Latest blog posts widget
    • Notification panel
    • User profile box

Code Example
@await Component.InvokeAsync("LatestPosts", new { count = 5 })

Performance Considerations

  • Partial View is faster for simple static rendering because it does not invoke additional logic.
  • ViewComponent is slightly heavier, but it provides better separation of concerns and testability.
  • In real-world projects, mixing both approaches works best.

Conclusion
ASP.NET MVC/Core offers two strong tools for creating modular, maintainable applications: Partial Views and ViewComponents.

  • For basic, static UI fragments, use partial views.
  • For reusable, logic-driven user interface elements, use ViewComponents.

You may improve the scalability, maintainability, and cleanliness of your application by selecting the appropriate strategy for each situation.



ASP.NET MVC Hosting - HostForLIFE.eu :: ASP.NET Core MVC Applications' Data Security

clock August 29, 2025 08:00 by author Peter

Data security is one of the most critical concerns when building ASP.NET Core MVC applications. From user credentials to financial transactions, sensitive data must be protected against threats such as SQL Injection, Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), and unauthorized access. In this article, we’ll explore end-to-end data security practices in ASP.NET Core MVC applications with real-world code examples and best practices that you can apply directly in your projects.

1. Enforce HTTPS Everywhere
Always use TLS/SSL to ensure secure communication between the client and server.

Program.cs
builder.Services.AddHttpsRedirection(options =>
{
    options.HttpsPort = 443;
});

var app = builder.Build();
app.UseHttpsRedirection();

Never transmit sensitive data over plain HTTP.

2. Secure Authentication and Authorization

ASP.NET Core provides Identity for authentication, or you can use external providers like Google, Azure AD, or JWT tokens.

Authorization Policy Example
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
});


Controller Usage
[Authorize(Policy = "AdminOnly")]
public IActionResult AdminDashboard()
{
    return View();
}


Always store passwords using hashing algorithms. ASP.NET Core Identity uses PBKDF2 by default.

3. Protect Sensitive Configuration Data

Never hardcode credentials or API keys in your appsettings.json .
Development → Use User Secrets
dotnet user-secrets set "DbPassword" "SuperSecurePassword123!"

Production → Use Azure Key Vault

builder.Configuration.AddAzureKeyVault(
new Uri("https://myvault.vault.azure.net/"),
new DefaultAzureCredential());


This keeps sensitive data out of source control.

4. Encrypt Sensitive Data at Rest

If your app handles PII (Personally Identifiable Information) such as SSN, credit card numbers, or health records, use encryption.

AES Encryption Helper
public static class EncryptionHelper
{
    private static readonly string Key = "YourEncryptionKey1234"; // Store securely

    public static string Encrypt(string plainText)
    {
        using var aes = Aes.Create();
        var encryptor = aes.CreateEncryptor(Encoding.UTF8.GetBytes(Key), aes.IV);
        using var ms = new MemoryStream();
        ms.Write(aes.IV, 0, aes.IV.Length);
        using var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
        using (var sw = new StreamWriter(cs)) sw.Write(plainText);
        return Convert.ToBase64String(ms.ToArray());
    }
}

Store only encrypted values in your database.

5. Validate Input & Prevent SQL Injection

ASP.NET Core Entity Framework Core automatically parameterizes queries, protecting against SQL injection.

Wrong (Vulnerable)
var user = _context.Users.FromSqlRaw(
$"SELECT * FROM Users WHERE Username = '{username}'").FirstOrDefault();

Correct (Safe)
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Username == username);

Always use LINQ queries or parameterized SQL.

6. Prevent Cross-Site Scripting (XSS)

ASP.NET Core Razor automatically encodes output.

<p>@Model.Name</p> <!-- Safe -->

If you must allow HTML.
@Html.Raw(Model.Description) // Use carefully

Use libraries like Ganss.XSS to sanitize user-generated content.

7. Enable CSRF Protection

ASP.NET Core MVC provides built-in CSRF protection with anti-forgery tokens.

Controller
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult SaveData(MyModel model)
{
    // Save logic
    return RedirectToAction("Index");
}


View
<form asp-action="SaveData" method="post">
    @Html.AntiForgeryToken()
    <button type="submit">Submit</button>
</form>


This prevents malicious sites from posting forms on behalf of logged-in users.

8. Secure Cookies & Sessions

Always configure cookies with HttpOnly and Secure flags.

builder.Services.ConfigureApplicationCookie(options =>
{
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.SlidingExpiration = true;
});

This prevents cookie theft via JavaScript.

9. Secure File Uploads

If your app allows file uploads.

  • Validate file types & sizes.
  • Store files outside. wwwroot
  • Rename files to avoid execution.

Example validation
if (!file.ContentType.StartsWith("image/"))
throw new Exception("Invalid file type!");


10. Enable Security Headers
Add middleware to strengthen browser protections.
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    context.Response.Headers.Add("X-Frame-Options", "DENY");
    context.Response.Headers.Add("X-XSS-Protection", "1; mode=block");
    await next();
});


Use NWebSec for advanced headers.

11. Logging & Monitoring

  • Use Serilog/NLog for structured logging.
  • Monitor failed login attempts.
  • Never log sensitive data (passwords, tokens, credit cards).

12. Prevent Denial of Service (DoS) Attacks
ASP.NET Core 7 and later support built-in rate limiting.
builder.Services.AddRateLimiter(_ => _
.AddFixedWindowLimiter("fixed", options =>
{
    options.Window = TimeSpan.FromSeconds(10);
    options.PermitLimit = 5;
}));


Deploy a WAF (Web Application Firewall) in production.

Conclusion

Securing data in ASP.NET Core MVC applications requires a multi-layered approach.

Enforce HTTPS

  • Secure authentication & authorization
  • Protect configuration & secrets
  • Encrypt sensitive data
  • Prevent SQL Injection, XSS, and CSRF.
  • Harden cookies, sessions, file uploads, and headers
  • Enable logging, monitoring, and rate limiting

By following these practices, you’ll ensure your application complies with modern security standards and is resilient against common web vulnerabilities.



ASP.NET MVC Hosting - HostForLIFE.eu :: PDF Generation in ASP.NET Core MVC using Puppeteer Sharp

clock August 22, 2025 09:06 by author Peter

In today’s digital world, internet activities are a vital part of our everyday life. Web-based applications are becoming more and more necessary as a result of this. The capacity to create PDFs from HTML is a common need of many web-based programs. Online ticketing, certifications, online purchase invoices, and many more are examples of everyday use cases.


Although utilities like DinkToPdf and iTextSharp can convert HTML to PDF, they frequently have trouble rendering in current CSS and JavaScript. This is Puppeteer Sharp's strong suit.

Puppeteer Sharp provides browser-quality PDFs, supports dynamic content, and integrates seamlessly into .NET apps, making it a significant improvement over traditional PDF generation libraries for web content.

Puppeteer Sharp is a .NET port of Google’s Puppeteer, a Node.js library for controlling Chrome or Chromium. It allows developers to.

  • Render HTML just like a browser would.
  • Apply advanced CSS styling.
  • Run JavaScript before capturing.
  • Export the rendered page to a PDF.

Benefits of using Puppeteer Sharp

  • Accurate Rendering: It uses the Chromium browser engine to maintain the accuracy of rendering.
  • Modern CSS and JavaScript Support: It can handle dynamic pages and animations.
  • Custom Layouts: Paper sizes, margins, headers and footers can be customized.
  • Automation Ready: It can be used in background tasks.


Installing Puppeteer Sharp

  • Using Visual Studio (NuGet Package Manager UI)
    • Right-click on your project in Solution Explorer.
    • Select Manage NuGet Packages for Solution.
    • Go to the Browse tab.
    • Search for PuppeteerSharp.
    • Select the latest stable version.
    • Click Install.

Using Package Manager Console: Open Tools > NuGet Package Manager > Package Manager Console, then run.

Install-Package PuppeteerSharp

Using .NET CLI: If you prefer the terminal/command line, run.

dotnet add package PuppeteerSharp

Generating a PDF from a Web page
Generate Invoice Example.
    [HttpPost]
    [Route("generate-invoice-pdf")]
    public async Task<IActionResult> GenerateInvoicePdf()
    {
        // Downloads Chromium if it's not already available
        await new BrowserFetcher().DownloadAsync();

        // Launch headless Chromium
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });

        // Open a new page
        await using var page = await browser.NewPageAsync();

        // Navigate to a URL (can also be a local MVC view)
        var url = $"{Request.Scheme}://{Request.Host}/pdf";
        await page.GoToAsync(url, WaitUntilNavigation.Networkidle0);

        // Generate PDF
        var pdfBytes = await page.PdfDataAsync(new PdfOptions
        {
            Format = PaperFormat.A4,
            PrintBackground = true,
            MarginOptions = new MarginOptions
            {
                Top = "20px",
                Bottom = "20px",
                Left = "20px",
                Right = "20px"
            }
        });

        // Close the browser
        await browser.CloseAsync();

        // Returns downloadable file
        var fileName = $"PDF_{DateTime.Now:yyyyMMdd_HHmm}.pdf";
        return File(pdfBytes, "application/pdf", fileName);
    }


Generate an External Web Page as a PDF.
[HttpPost]
[Route("generate-html-pdf")]
public async Task<IActionResult> GenerateHtmlPdf()
{
    // Downloads Chromium if it's not already available
    await new BrowserFetcher().DownloadAsync();

    // Launch headless Chromium
    await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });

    // Open a new page
    await using var page = await browser.NewPageAsync();

    // Navigate to a URL (can also be a local MVC view)
    var url = "https://www.google.com/";
    await page.GoToAsync(url, WaitUntilNavigation.Networkidle0);

    // Generate PDF
    var pdfBytes = await page.PdfDataAsync(new PdfOptions
    {
        Format = PaperFormat.A4,
        PrintBackground = true,
        MarginOptions = new MarginOptions
        {
            Top = "20px",
            Bottom = "20px",
            Left = "20px",
            Right = "20px"
        }
    });

    // Close the browser
    await browser.CloseAsync();

    // Returns downloadable file
    var fileName = $"PDF_{DateTime.Now:yyyyMMdd_HHmm}.pdf";
    return File(pdfBytes, "application/pdf", fileName);
}

Razor View.
<h2>Generate PDF using Puppeteer Sharp</h2>

<div style="display: flex; justify-content: space-between; align-items: center; width: 33%; margin: 50px auto 0 auto;">
    <form asp-controller="Pdf" asp-action="GenerateInvoicePdf" method="post" style="margin: 0;">
        <button type="submit" class="btn btn-primary">Download Invoice PDF</button>
    </form>
    <form asp-controller="Pdf" asp-action="GenerateHtmlPdf" method="post" style="margin: 0;">
        <button type="submit" class="btn btn-primary">Download Web PDF</button>
    </form>
</div>


How does it work?

  • First BrowserFetcher downloads a compatible chromium browser if needed.
  • The LaunchAsync method starts a headless instance of Chromium
  • NewPageAsync opens a new tab in Chromium. If Headless is set to false then you will see the browser's window with tab.
  • GoToAsync navigates to the target URL
  • PDFDataAsync captures the page as a PDF in memory.
  • The PDF is returned as a downloadable file to the client

Additional Tips
For the first time the PDF generation is slow and it’s the common issue with Puppeteer Sharp. To solve this problem, pre-download Chromium. This way, you can avoid first-request delays.

// Pre-download Chromium at startup
var fetcher = new BrowserFetcher();
await fetcher.DownloadAsync();

Suppose you add the above lines of code to your Program.cs, Chromium is downloaded during the application initialization for the first time.

Conclusion

Puppeteer Sharp is one of the powerful tools for PDF generation with modern web compatibility. It brings the flexibility of Chromium automation into the .NET ecosystem. Whether you are adding a PDF export feature or generating screenshots for preview, Puppeteer Sharp is a robust choice in .NET. With just a few lines of code, you can easily automate complex HTML to PDF. Note. Project source code can be downloaded from GitHub



ASP.NET MVC Hosting - HostForLIFE.eu :: Email Notification Using Web API 2 in ASP.NET MVC 5

clock August 7, 2025 08:53 by author Peter

In this post, we'll build the Web API, use MVC 5 to access it, and use Web API 2 to send emails.


Let's begin gradually:

  • Work with a web application by creating an ASP.NET web application.
  • Including a model
  • Including a controller
  • Including a Helper class
  • Using JavaScript and JQuery to Call the Web Api (test web API)
  • To call the API and send an email notification, use the Rest client (Install Fiddler).
Create the project
Start Visual Studio 2013/2015 and from the File menu, select New, then Project.
Select the ASP.NET Web Application project template. Name the project Email Notification and click OK.

Select a template Web API.

Add a model class
A model is an object that represents the data in your application. In this case, the only model is a TeamA item.

Add a class file “TeamA.cs”.

Replace the generated code with:
    namespace EmailNotification.Models  
    {  
        public class TeamA  
        {  
            public int Id  
            {  
                get;  
                set;  
            }  
            public string Name  
            {  
                get;  
                set;  
            }  
            public string Type  
            {  
                get;  
                set;  
            }  
            public decimal Price  
            {  
                get;  
                set;  
            }  
        }  
    }  


Add a controller

In the Add Scaffold wizard, select the Web API 2 Empty Controller: Name it EmailNotifier.

In the Add Controller dialog, name the controller "EmailNotifierController " and click Add.

Replace code with the following controller.
    public class EmailNotifierController: ApiController  
    {  
        TeamGroupA[] teamA = new TeamGroupA[]  
        {  
            new TeamGroupA  
            {  
                Id = 1, Name = "zing", Type = "Cricket", Price = 1  
            },  
            new TeamGroupA  
            {  
                Id = 2, Name = "Yo-yo", Type = "Football", Price = 3.75 M  
            },  
            new TeamGroupA  
            {  
                Id = 3, Name = "soft", Type = "Software", Price = 16.99 M  
            }  
        };  
        // Run the application  
        public IEnumerable < TeamGroupA > GetAllTeams()  
        {  
            return teamA;  
        }  
    }  


To keep the example simple, TeamGroupA has stored in a fixed array inside the controller class. But, in a real application, you would get it from the Data access layer or use some other external data source.

The controller defines two methods that return products:
The GetAllTeams method returns the entire list of products as an IEnumerable<TeamGroupA> type.

As we are working with Web API it may contain one or more methods.

Now add new model for AdpaterResponsebase for another API method as SendEmailNotification.cs.

AdapterResponseBase.cs

Replace model code with the following code:
    using System;  
    using System.Collections.Generic;  
    namespace EmailNotification.Models  
    {  
        public class ResponseBase  
        {}  
        public class RequestBase  
        {}  
        public class RequestBase < T > : RequestBase  
        {  
            public RequestBase()  
            {}  
            public RequestBase(T data)  
            {  
                Data = data;  
            }  
            public T Data  
            {  
                get;  
                set;  
            }  
        }  
    }  


Add new Helper class file EMailHelper.cs to folder named Helpers.

    using System;  
    namespace EmailNotofication.Models  
    {  
        public class EmailInput  
        {  
            public string UserName  
            {  
                get;  
                set;  
            }  
            public string EmailId  
            {  
                get;  
                set;  
            }  
        }  
    }  

Now we will start with UI part.

Calling the Web API with Javascript and jQuery

Here we will add an HTML page that uses AJAX to call the web API. We'll use jQuery to make the AJAX calls and also to update the page with the results.
In Solution Explorer, right-click the project and select Add, then select New Item.

In the Add New Item dialog, select the Web node under Visual C#, and then select the HTML Page item. Name the page "index.html".


Replace everything in this file with the following:
    <!DOCTYPE html>  
    <html xmlns="http://www.w3.org/1999/xhtml">  
      
    <head>  
        <title>Notification App</title>  
    </head>  
      
    <body>  
        <div>  
            <h2>All Teams</h2>  
            <ul id="teams" /> </div>  
        <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>  
        <script>  
            var uri = 'api/EmailNotifier/GetAllTeams';  
            $(document).ready(function()  
            {  
                // Send an AJAX request  
                $.getJSON(uri).done(function(data)  
                {  
                    // On success, 'data' contains a list of teams.  
                    $.each(data, function(key, item)  
                    {  
                        // Add a list item for the teams.  
                        $('<li>',  
                        {  
                            text: formatItem(item)  
                        }).appendTo($('#teams'));  
                    });  
                });  
            });  
      
            function formatItem(item)  
            {  
                return item.Name + ': $' + item.Price;  
            }  
        </script>  
    </body>  
      
    </html>  


Getting a List of Teams
To get a list of teams, send an HTTP GET request to "/api/GetAllTeams".

Set index.html as start page:

Run the project,
Yippee! Here we got success for calling Web API using Ajax. Now let’s add method for Email Notification.

We will call SendEmailNotification API using RestClient.

Add the following method to controller:
    [HttpPost]  
    public async Task < IHttpActionResult > SendEmailNotification(EmailInput data)  
    {  
        ResponseBase updateResponse = new ResponseBase();  
        var updateRequest = new RequestBase < EmailInput > (data);  
        try  
        {  
            EMailHelper mailHelper = new EMailHelper(EMailHelper.EMAIL_SENDER, EMailHelper.EMAIL_CREDENTIALS, EMailHelper.SMTP_CLIENT);  
            var emailBody = String.Format(EMailHelper.EMAIL_BODY);  
            if(mailHelper.SendEMail(data.EmailId, EMailHelper.EMAIL_SUBJECT, emailBody))  
            {  
                //   
            }  
        }  
        catch(Exception ex)  
        {}  
        return Ok(updateResponse);  
    }  

You need to add extension for RestClient to your chrome browser to call API. Pass the parameter and do necessary changes to call API from rest client as in the following:

http://localhost:21084/api/EmailNotifier/SendEmailNotification

HTTPPOST
    Content-Type: application/json  
    {  
       "UserName": "xyz",  
       "EmailId" : "[email protected]",  
    }  

Once you click on send button, you can verify input parameter by adding debug point to API in controller

After successful execution we will get response as follows:

Note: To send email you need to add actual email id and credential so that it will work as expected.



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