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 6 Hosting - HostForLIFE.eu :: Using Detailed Views for Global Search in ASP.NET Core MVC

clock July 11, 2024 08:06 by author Peter

We'll go over how to add a global search function to an ASP.NET Core MVC application in this article. This feature will provide search results with photographs and have a drop-down filter to search through all categories, products, and particular categories or goods. To ensure full end-to-end operation, we'll also develop detailed views for the search results.

Step 1: Configure Models and Database
We will first establish our models and database context. We'll use two models in this example: Product and Category.

Models

In the Models folder, create the Product and Category models.
namespace GlobalSearchInAspNetCoreMVC.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string? Description { get; set; }
        public string ImageUrl { get; set; }
        public int CategoryId { get; set; }
        public Category Category { get; set; }
    }
}


namespace GlobalSearchInAspNetCoreMVC.Models
{
    public class Category
    {
        public int Id { get; set; }
        public string? Name { get; set; }
    }
}

namespace GlobalSearchInAspNetCoreMVC.Models
{
    public class SearchResultItem
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public string? Description { get; set; }
        public string? ImageUrl { get; set; }
    }
}

Database Context
Create the ApplicationDbContext in the Data folder.
using GlobalSearchInAspNetCoreMVC.Models;
using Microsoft.EntityFrameworkCore;
namespace GlobalSearchInAspNetCoreMVC.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
        public DbSet<Product> Products { get; set; }
        public DbSet<Category> Categories { get; set; }
    }

}


Step 2. Create and Seed the Database
Configure the database connection string in appsettings.json.
{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=SQLLiteDatabase.db"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}


Update the Startup. cs or Program. cs to use the ApplicationDbContext.
using GlobalSearchInAspNetCoreMVC.AppService;
using GlobalSearchInAspNetCoreMVC.Data;
using GlobalSearchInAspNetCoreMVC.IAppServices;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddScoped<ISearchService, SearchService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();
});
app.Run();

Create a migration and update the database.
add-migration GlobalSearch
update-database


Seed the Database
Create a DataSeeder class to seed the database with initial data.
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
namespace GlobalSearchInAspNetCoreMVC.Data
{
    public static class DataSeeder
    {
        public static void Seed(IServiceProvider serviceProvider)
        {
            using (var context = new ApplicationDbContext(
                serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>()))
            {
                if (!context.Products.Any())
                {
                    context.Products.AddRange(
                        new Product { Name = "Product 1", Description = "Description 1", ImageUrl = "/images/product1.jpg" },
                        new Product { Name = "Product 2", Description = "Description 2", ImageUrl = "/images/product2.jpg" }
                    );
                    context.SaveChanges();
                }
                if (!context.Categories.Any())
                {
                    context.Categories.AddRange(
                        new Category { Name = "Category 1" },
                        new Category { Name = "Category 2" }
                    );
                    context.SaveChanges();
                }
            }
        }
    }
}


Or save the data using a database query.
-- Insert dummy data into Categories table
INSERT INTO Categories (Name)
VALUES
    ('Electronics'),
    ('Books'),
    ('Clothing'),
    ('Home & Kitchen'),
    ('Sports & Outdoors');
-- Insert dummy data into Products table
INSERT INTO Products (Name, Description, ImageUrl, CategoryId)
VALUES
    ('Smartphone', 'Latest model smartphone with advanced features', 'https://via.placeholder.com/150/0000FF/808080?text=Smartphone', 1),
    ('Laptop', 'High performance laptop suitable for gaming and work', 'https://via.placeholder.com/150/FF0000/FFFFFF?text=Laptop', 1),
    ('Headphones', 'Noise-cancelling over-ear headphones', 'https://via.placeholder.com/150/FFFF00/000000?text=Headphones', 1),
    ('Science Fiction Book', 'A gripping science fiction novel', 'https://via.placeholder.com/150/00FF00/000000?text=Science+Fiction+Book', 2),
    ('Cookbook', 'Delicious recipes for home cooks', 'https://via.placeholder.com/150/FF69B4/000000?text=Cookbook', 2),
    ('T-shirt', 'Comfortable cotton T-shirt', 'https://via.placeholder.com/150/800080/FFFFFF?text=T-shirt', 3),
    ('Jeans', 'Stylish denim jeans', 'https://via.placeholder.com/150/FFA500/FFFFFF?text=Jeans', 3),
    ('Blender', 'High-speed blender for smoothies and soups', 'https://via.placeholder.com/150/000080/FFFFFF?text=Blender', 4),
    ('Coffee Maker', 'Programmable coffee maker with timer', 'https://via.placeholder.com/150/FFC0CB/000000?text=Coffee+Maker', 4),
    ('Yoga Mat', 'Non-slip yoga mat for all types of exercise', 'https://via.placeholder.com/150/008080/FFFFFF?text=Yoga+Mat', 5),
    ('Dumbbells', 'Set of adjustable dumbbells', 'https://via.placeholder.com/150/000000/FFFFFF?text=Dumbbells', 5);


Call the seeder in the Program. cs.
public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();
    using (var scope = host.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        var context = services.GetRequiredService<ApplicationDbContext>();
        context.Database.Migrate();
        DataSeeder.Seed(services);
    }
    host.Run();
}

Step 3. Implement the Search Service
Create a search service to handle the search logic.

ISearchService.cs

using GlobalSearchInAspNetCoreMVC.Models;
namespace GlobalSearchInAspNetCoreMVC.IAppServices
{
    public interface ISearchService
    {
        Task<IEnumerable<object>> SearchAsync(string searchTerm,string filter);
        Task<SearchResultItem> GetItemByIdAsync(int id);
    }
}

SearchService.cs
using GlobalSearchInAspNetCoreMVC.Data;
using GlobalSearchInAspNetCoreMVC.IAppServices;
using GlobalSearchInAspNetCoreMVC.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace GlobalSearchInAspNetCoreMVC.AppService
{
    public class SearchService : ISearchService
    {
        private readonly ApplicationDbContext _context;
        public SearchService(ApplicationDbContext context)
        {
            _context = context;
        }
        public async Task<IEnumerable<object>> SearchAsync(string searchTerm, string filter)
        {
            List<object> results = new List<object>();

            if (filter == "all" || filter == "products")
            {
                var products = await _context.Products
                    .Where(p => p.Name.Contains(searchTerm) || p.Description.Contains(searchTerm))
                    .Select(p => new { p.Id, p.Name, p.Description, p.ImageUrl })
                    .ToListAsync();

                results.AddRange(products);
            }
            if (filter == "all" || filter == "categories")
            {
                var categories = await _context.Categories
                    .Where(c => c.Name.Contains(searchTerm))
                    .Select(c => new { c.Id, c.Name })
                    .ToListAsync();

                results.AddRange(categories);
            }
            return results;
        }
        public async Task<SearchResultItem> GetItemByIdAsync(int id)
        {
            var product = await _context.Products.FindAsync(id);
            if (product != null)
            {
                return new SearchResultItem
                {
                    Id = product.Id,
                    Name = product.Name,
                    Description = product.Description,
                    ImageUrl = product.ImageUrl
                };
            }
            var category = await _context.Categories.FindAsync(id);
            if (category != null)
            {
                return new SearchResultItem
                {
                    Id = category.Id,
                    Name = category.Name,
                    Description = "Category"
                };
            }
            return null;
        }
    }
}

Step 4. Create the HomeController
Create the HomeController to handle the search and detail views.

HomeController.cs

using GlobalSearchInAspNetCoreMVC.IAppServices;
using Microsoft.AspNetCore.Mvc;
namespace GlobalSearchInAspNetCoreMVC.Controllers
{
    public class HomeController : Controller
    {
        private readonly ISearchService _searchService;

        public HomeController(ISearchService searchService)
        {
            _searchService = searchService;
        }
        public IActionResult Index()
        {
            return View();
        }
        public async Task<IActionResult> Details(int id)
        {
            var item = await _searchService.GetItemByIdAsync(id);
            if (item == null)
            {
                return NotFound();
            }
            return View(item);
        }
    }
}


Step 5. Create the Views
Views/Home/Index.cshtml
<div class="text-center">
    <h1 class="display-4">Search</h1>
    <div class="form-group">
        <select id="search-filter" class="form-control">
            <option value="all">All</option>
            <option value="products">Products</option>
            <option value="categories">Categories</option>
        </select>
    </div>
    <input type="text" id="search-input" placeholder="Search..." class="form-control" />
    <div id="search-results" class="dropdown-menu" style="display: block; position: absolute; width: 100%;"></div>
</div>
@section Scripts {
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        $(document).ready(function () {
            function performSearch() {
                let query = $('#search-input').val();
                let filter = $('#search-filter').val();
                if (query.length >= 3) {
                    $.ajax({
                        url: '/api/search',
                        type: 'GET',
                        data: { query: query, filter: filter },
                        success: function (data) {
                            let results = $('#search-results');
                            results.empty();
                            if (data.length > 0) {
                                data.forEach(item => {
                                    if (item.imageUrl) { // Check if item has an image
                                        results.append(`
                                                        <a class="dropdown-item" href="/Home/Details/${item.id}">
                                                    <img src="${item.imageUrl}" alt="${item.name}" style="width:50px; height:50px;"/>
                                                    ${item.name || item.description}
                                                </a>
                                               `);
                                    } else {
                                        results.append(`<a class="dropdown-item" href="/Home/Details/${item.id}">${item.name || item.description}</a>`);
                                    }
                                });
                            } else {
                                results.append('<a class="dropdown-item">No results found</a>');
                            }
                        }
                    });
                } else {
                    $('#search-results').empty();
                }
            }
            $('#search-input').on('input', performSearch);
            $('#search-filter').on('change', performSearch);
        });
    </script>
}

Views/Home/Details.cshtml
@model SearchResultItem
@{
    ViewData["Title"] = "Details";
}
<div class="text-center">
    <h1 class="display-4">Details</h1>
    @if (Model != null)
    {
        <div class="card" style="width: 18rem;">
            @if (!string.IsNullOrEmpty(Model.ImageUrl))
            {
                <img class="card-img-top" src="@Model.ImageUrl" alt="Card image cap">
            }
            <div class="card-body">
                <h5 class="card-title">@Model.Name</h5>
                <p class="card-text">@Model.Description</p>
            </div>
        </div>
    }
    else
    {
        <p>Item not found.</p>
    }
</div>


Step 6. Create the Search Controller
using GlobalSearchInAspNetCoreMVC.IAppServices;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace GlobalSearchInAspNetCoreMVC.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class SearchController : ControllerBase
    {
        private readonly ISearchService _searchService;

        public SearchController(ISearchService searchService)
        {
            _searchService = searchService;
        }
        [HttpGet]
        public async Task<IActionResult> Get(string query, string filter)
        {
            if (string.IsNullOrEmpty(query))
            {
                return BadRequest("Query cannot be empty");
            }
            var results = await _searchService.SearchAsync(query, filter);
            return Ok(results);
        }
    }
}

Step 7. Run and Test
Now that everything is set up, run your application. You should be able to search for products and categories using the dropdown filter, view the search results with images, and click on each result to see detailed information.

Step 8. Output

Conclusion
We've added a global search function to an ASP.NET Core MVC application in this article. Creating models, establishing the database context, populating the database with initial information, putting the search service into operation, and generating the required views and controllers were all addressed. This complete implementation ought to offer a thorough grasp of how to create a search feature in ASP.NET Core MVC applications.

 



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Using Gmail Server to Send Email in ASP.NET Core MVC

clock July 2, 2024 07:11 by author Peter

This tutorial will show you how to use the Gmail server in an ASP.NET Core MVC application to send emails. For handling the email functionality, we will make use of the MailKit and MimeKit libraries.

Step 1: Establish an MVC ASP.NET Core project

  • Make a new project in Visual Studio by opening it.
  • Click "Next" after selecting "ASP.NET Core Web Application".
  • Click "Create" after giving your project a name.
  • Make sure ".NET Core" and "ASP.NET Core 3.1 or later" are selected when you choose "Web Application (Model-View-Controller)". Press "Create."

Step 2 Install the necessary NuGet packages
To facilitate emailing, install the MailKit and MimeKit packages.

  • Navigating to Tools > NuGet Package Manager > Package Manager Console will launch the NuGet Package Manager Console.
  • Execute the subsequent commands.
Install-Package MailKit
Install-Package MimeKit


Step 3. Configure SMTP Settings
Add your Gmail SMTP settings in the appsettings.json file.
{
  "SmtpSettings": {
    "Server": "smtp.gmail.com",
    "Port": 587,
    "SenderName": "Your Name",
    "SenderEmail": "[email protected]",
    "Username": "[email protected]",
    "Password": "your-app-specific-password"
  }
}


To generate an app-specific password, follow these steps.
Go to your Google Account
  • Visit myaccount.google.com.
Security Settings
  • Navigate to the "Security" section.
App Passwords
  • Under "Signing in to Google," find "App passwords."
  • You might need to sign in again.
  • Select "App passwords."
Generate an app password
  • Select the app (e.g., Mail) and the device (e.g., Windows Computer) from the dropdown.
  • Click "Generate."
  • Google will provide a 16-character password.
Update Your Configuration
  • Use this 16-character password in your appsettings.json instead of your normal Google account password.
Step 4. Create the Email Service
Create a service to handle the email-sending logic. Add a new class EmailService.cs to your project.
using MimeKit;
using MailKit.Net.Smtp;
using Microsoft.Extensions.Configuration;
using System.Threading.Tasks;
namespace EmailSendingInAspNetCoreMVC.Services
{
    public class EmailService
    {
        private readonly IConfiguration _configuration;
        public EmailService(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        public async Task SendEmailAsync(string toEmail, string subject, string message)
        {
            var emailMessage = new MimeMessage();
            emailMessage.From.Add(new MailboxAddress(_configuration["SmtpSettings:SenderName"], _configuration["SmtpSettings:SenderEmail"]));
            emailMessage.To.Add(new MailboxAddress("", toEmail));
            emailMessage.Subject = subject;
            emailMessage.Body = new TextPart("plain") { Text = message };
            using (var client = new SmtpClient())
            {
                await client.ConnectAsync(_configuration["SmtpSettings:Server"], int.Parse(_configuration["SmtpSettings:Port"]), MailKit.Security.SecureSocketOptions.StartTls);
                await client.AuthenticateAsync(_configuration["SmtpSettings:Username"], _configuration["SmtpSettings:Password"]);
                await client.SendAsync(emailMessage);
                await client.DisconnectAsync(true);
            }
        }
    }
}


Step 5. Register for the Email Service

Register the EmailService in the Startup.cs file.
using EmailSendingInAspNetCoreMVC.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddSingleton<EmailService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();


Step 6. Create the EmailViewModel
Add a new class EmailViewModel.cs to your Models folder.
namespace EmailSendingInAspNetCoreMVC.ViewModels
{
    public class EmailViewModel
    {
        public string? ToEmail { get; set; }
        public string? Subject { get; set; }
        public string? Message { get; set; }
    }
}


Step 7. Create the Email Controller
Add a new controller EmailController.cs to handle the email sending requests.
using EmailSendingInAspNetCoreMVC.Sevices;
using EmailSendingInAspNetCoreMVC.ViewModels;
using Microsoft.AspNetCore.Mvc;
namespace EmailSendingInAspNetCoreMVC.Controllers
{
    public class EmailController : Controller
    {
        private readonly EmailService _emailService;

        public EmailController(EmailService emailService)
        {
            _emailService = emailService;
        }
        [HttpGet]
        public IActionResult SendEmail()
        {
            return View();
        }
        [HttpPost]
        public async Task<IActionResult> SendEmail(EmailViewModel model)
        {
            if (ModelState.IsValid)
            {
                await _emailService.SendEmailAsync(model.ToEmail, model.Subject, model.Message);
                ViewBag.Message = "Email sent successfully!";
            }
            return View(model);
        }
    }
}


Step 8. Create the Email View

Create a new view SendEmail.cshtml in the Views/Email folder.
@model EmailViewModel
@{
    ViewData["Title"] = "Send Email";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<form asp-action="SendEmail" method="post">
    <div>
        <label asp-for="ToEmail"></label>
        <input asp-for="ToEmail" type="email" required />
        <span asp-validation-for="ToEmail"></span>
    </div>
    <div>
        <label asp-for="Subject"></label>
        <input asp-for="Subject" type="text" required />
        <span asp-validation-for="Subject"></span>
    </div>
    <div>
        <label asp-for="Message"></label>
        <textarea asp-for="Message" required></textarea>
        <span asp-validation-for="Message"></span>
    </div>
    <div>
        <input type="submit" value="Send Email" />
    </div>
</form>
@if (ViewBag.Message != null)
{
    <p>@ViewBag.Message</p>
}

Step 9. Add Validation Scripts
Ensure that validation scripts are included in your _Layout.cshtml.
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js"></script>


Step 10. Run the Application
Build and run your application.
Navigate to /Email/SendEmail.
Fill out the form and send an email.

Conclusion
By following this guide, you will successfully integrate email-sending functionality into your ASP.NET Core MVC application using the Gmail SMTP server. Utilizing `MailKit` and `MimeKit` libraries ensures secure and efficient handling of emails. Setting up an `EmailService`, creating an `EmailViewModel`, and configuring an `EmailController` with a corresponding view will provide a complete solution for sending emails. Generating an application-specific password for Gmail ensures compatibility with accounts that have two-factor authentication enabled. This setup enhances your application's functionality and enables effective communication with users.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Using AJAX to Integrate Third-Party API in ASP.NET Core MVC

clock June 24, 2024 07:09 by author Peter

Your web application's functionality can be substantially increased by integrating third-party APIs, which give it access to and usage of outside resources. We will look at how to use AJAX to incorporate a third-party API into an ASP.NET Core Razor Pages application in this article. Using a sample in which we retrieve public holidays from an API and present them in a Bootstrap table, we will illustrate this procedure.

Step 1. Setting up the ASP.NET Core Razor Pages project
First, create a new ASP.NET Core Razor Pages project in Visual Studio:

  • Open Visual Studio and create a new project.
  • Select ASP.NET Core Web Application and click Next.
  • Name your project and click Create.
  • Choose NET Core" and ASP.NET Core 5.0 or later.
  • Select Web Application (Model-View-Controller) and click Create.

Step 2. Creating the Razor Page
Next, add a new Razor Page to your project:

  • Right-click on the Pages folder and select Add > New Item
  • Choose Razor Page and name it Index.

Step 3. Designing the Razor Page
Edit the Index.cshtml file to include a form for user input and a Bootstrap table to display the fetched data.
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}
<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <form id="inputForm">
        <input type="text" id="yearValue" name="yearValue" placeholder="Enter Year value">
        <input type="text" id="countryCode" name="countryCode" placeholder="Enter countryCode value">
        <button type="submit">Submit</button>
    </form>
</div>
<div class="container mt-4">
    <div class="row">
        <div class="col-md-12">
            <table id="holidayTable" class="table table-striped">
                <thead>
                    <tr>
                        <th>Date</th>
                        <th>Local Name</th>
                        <th>Name</th>
                        <th>Country Code</th>
                        <th>Fixed</th>
                        <th>Global</th>
                        <th>Types</th>
                    </tr>
                </thead>
                <tbody id="tableBody"></tbody>
            </table>
        </div>
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $("#inputForm").submit(function (e) {
            debugger;
            e.preventDefault();
            var yearValue = $("#yearValue").val();
            var countryCode = $("#countryCode").val();

            $.ajax({
                type: "GET",
                url: "https://date.nager.at/api/v3/publicholidays/" + yearValue + "/" + countryCode,
                success: function (data) {
                    console.log(data);
                    populateTable(data);
                },
                error: function (error) {
                    console.log(error);
                }
            });
        });
    });
    function populateTable(data) {
        debugger;
        var tableBody = $("#tableBody");
        tableBody.empty();

        data.forEach(function (holiday) {
            var row = $("<tr>");
            row.append($("<td>").text(holiday.date));
            row.append($("<td>").text(holiday.localName));
            row.append($("<td>").text(holiday.name));
            row.append($("<td>").text(holiday.countryCode));
            row.append($("<td>").text(holiday.fixed));
            row.append($("<td>").text(holiday.global));
            row.append($("<td>").text(holiday.types.join(', ')));
            tableBody.append(row);
        });
    }
</script>


Step 4. Adding jQuery and AJAX Script
In the Index.cshtml file, include jQuery, and write the AJAX call to fetch data from the third-party API. Make sure to include the security token if required.
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $("#inputForm").submit(function (e) {
            debugger;
            e.preventDefault();
            var yearValue = $("#yearValue").val();
            var countryCode = $("#countryCode").val();
            $.ajax({
                type: "GET",
                url: "https://date.nager.at/api/v3/publicholidays/" + yearValue + "/" + countryCode,
                success: function (data) {
                    console.log(data);
                    populateTable(data);
                },
                error: function (error) {
                    console.log(error);
                }
            });
        });
    });
    function populateTable(data) {
        debugger;
        var tableBody = $("#tableBody");
        tableBody.empty();

        data.forEach(function (holiday) {
            var row = $("<tr>");
            row.append($("<td>").text(holiday.date));
            row.append($("<td>").text(holiday.localName));
            row.append($("<td>").text(holiday.name));
            row.append($("<td>").text(holiday.countryCode));
            row.append($("<td>").text(holiday.fixed));
            row.append($("<td>").text(holiday.global));
            row.append($("<td>").text(holiday.types.join(', ')));
            tableBody.append(row);
        });
    }
</script>


In this script

  • The form submission is handled by preventing the default action and getting the input values.
  • An AJAX GET request is made to the third-party API with the year and country code values.
  • The security token is included in the request headers.
  • On a successful response, the populateTable function dynamically creates rows and cells in the table to display the fetched data.

Step 5. Running the Application

  • Build and run the application.
  • Navigate to the /Index page.
  • Enter the year and country code values and submit the form.
  • The public holidays data will be fetched from the API and displayed in the Bootstrap table.

Output

\

Conclusion

Setting up the form and table on the Razor page, performing the AJAX request with the required arguments and headers, and dynamically updating the table with the retrieved data are all part of integrating a third-party API using AJAX in an ASP.NET Core Razor Pages application. Without refreshing the website, this method enables a smooth and interactive user experience.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Connect a Database with C#, ADO.NET, and ASP.NET MVC?

clock June 19, 2024 09:14 by author Peter

The seamless integration of databases is essential for current web development's data management and retrieval processes. This article explains how to create a robust C# Data Access Layer (DAL) that can interface with a MySQL database. This code provides an example of how to implement such a DAL. Using a MySQL database is the responsibility of the ClsDal class. It has functions to manage connection strings and get data out of the database.

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using MySql.Data.MySqlClient;

namespace DemoAPI.DB_Logic
{
    public class ClsDal
    {
        private static string mstrPath = null;
        static ClsCommonCryptography mobjCryptography = new ClsCommonCryptography();

        public static DataSet Qry_WithDataSet(string ProcWithParameter)
        {
            IErrorRepository error = new ErrorRepository();
            DataSet ds = new DataSet();
            try
            {
                if (GetConnStr() != null)
                {
                    MySqlConnection sqlCon = new MySqlConnection(mstrPath);

                    sqlCon.Open();

                    MySqlCommand sqlCmd = new MySqlCommand(ProcWithParameter, sqlCon);

                    sqlCmd.CommandTimeout = 0;

                    MySqlDataAdapter sqlDataAdapter = new MySqlDataAdapter
                    {
                        SelectCommand = sqlCmd
                    };

                    DataSet dtReturn = new DataSet();

                    sqlDataAdapter.Fill(dtReturn);

                    sqlCmd.Dispose();
                    sqlDataAdapter.Dispose();
                    sqlCon.Dispose();

                    return dtReturn;
                }
                else
                {
                    return null;
                }
            }
            catch (MySqlException sqlEx)
            {
                error.DBlogError("Qry_WithDataSet", ProcWithParameter, "Output" + "\n" + sqlEx.ToString());
                return null;
            }
            catch (Exception ex)
            {
                error.DBlogError("DBError Method : Qry_WithDataSet", ProcWithParameter, "Output" + "\n" + ex.ToString());
                return null;
            }
        }

        private static string GetConnStr()
        {
            IErrorRepository error = new ErrorRepository();
            try
            {
                mstrPath = System.Configuration.ConfigurationManager.ConnectionStrings["DbConn"].ConnectionString.ToString();
                mstrPath = mobjCryptography.StringDecrypt(mstrPath);
                return mstrPath;
            }
            catch (Exception ex)
            {
                error.DBlogError("DBError Method : GetConnStr", mstrPath, "Output" + "\n" + ex.ToString());
                return null;
            }
        }
    }
}


Data Access Layer (DAL) for MySQL database operations is defined by the supplied C# code as the ClsDal class in the DemoAPI.DB_Logic namespace. It offers techniques to safely manage connections and query the database. A decrypted connection string that is obtained from the configuration file is used by the Qry_WithDataSet method to run SQL queries or stored procedures against the database. Ensuring strong error management, it manages exceptions through organized error logging. While both methods use an `IErrorRepository` interface to log database-related issues, the GetConnStr method decrypts and obtains the database connection string. Generally speaking, this code promotes security and dependability by encapsulating best practices for database interaction in the context of web applications.

Conclusion  

For MySQL databases, implementing a Data Access Layer in C# requires connection management, query execution, and error handling done right. These best practices are demonstrated by the given code, which shows how to safely connect to a MySQL database, run queries, and log problems for maintenance and troubleshooting.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Stopping XSS Attacks in MVC ASP.NET

clock June 13, 2024 07:45 by author Peter

When malicious scripts are inserted into web sites that other users are seeing, it can lead to cross-site scripting (XSS) attacks, which pose a serious security risk. This article shows how to use best practices and built-in security capabilities in ASP.NET Core MVC to develop a basic blog application while guarding against XSS attacks.

Step 1. Create the ASP.NET Core MVC Project
Create a new ASP.NET Core MVC project
dotnet new mvc -n BlogApp
cd BlogApp


Add Entity Framework Core Packages
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.Security.Application

Step 2. Set Up Entity Framework Core
Create the database context and models
Create a Data folder and add ApplicationDbContext.cs
using Microsoft.EntityFrameworkCore;
using XSSAttackInAspNetCoreMVC.Model;
namespace XSSAttackInAspNetCoreMVC.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
        public DbSet<BlogPost> BlogPosts { get; set; }
    }
}

Configure the Database Context in Startup.cs
using Microsoft.EntityFrameworkCore;
using XSSAttackInAspNetCoreMVC.Data;
namespace XSSAttackInAspNetCoreMVC
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            // Add services to the container.
            builder.Services.AddRazorPages();
            builder.Services.AddControllersWithViews();
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
            var app = builder.Build();
            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();
            app.MapRazorPages();
            app.UseEndpoints(routes =>
            {
                routes.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
            app.Run();
        }
    }
}


Add Connection String in appsettings.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=BlogAppDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Create the Initial Migration and Update the Database
dotnet ef migrations add InitialCreate
dotnet ef database update


Step 3. Create Controllers and Views
Create the BlogPost Model
Create a Models folder and add BlogPost.cs
using System.ComponentModel.DataAnnotations;
namespace XSSAttackInAspNetCoreMVC.Model
{
    public class BlogPost
    {
        public int Id { get; set; }
        [Required]
        [StringLength(100)]
        public string? Title { get; set; }
        [Required]
        public string? Content { get; set; }
        public DateTime Created { get; set; }
    }
}


Create the BlogController
Create a Controllers folder and add BlogController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.Security.Application;
using XSSAttackInAspNetCoreMVC.Data;
using XSSAttackInAspNetCoreMVC.Model;
namespace XSSAttackInAspNetCoreMVC.Controllers
{
    public class BlogController : Controller
    {
        private readonly ApplicationDbContext _context;
        public BlogController(ApplicationDbContext context)
        {
            _context = context;
        }
        [HttpGet]
        public IActionResult Index()
        {
            var posts = _context.BlogPosts.ToList();
            return View(posts);
        }
        [HttpGet]
        public IActionResult Create()
        {
            return View();
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(BlogPost model)
        {
            if (ModelState.IsValid)
            {
                // Sanitize inputs before saving to the database
                model.Title = Sanitizer.GetSafeHtmlFragment(model.Title);
                model.Content = Sanitizer.GetSafeHtmlFragment(model.Content);
                _context.BlogPosts.Add(model);
                _context.SaveChanges();
                return RedirectToAction(nameof(Index));
            }
            return View(model);
        }
    }
}

Create the Views
Create a Views/Blog folder and add the following views
Index.cshtml
@model IEnumerable<XSSAttackInAspNetCoreMVC.Model.BlogPost>
<!DOCTYPE html>
<html>
<head>
    <title>Blog Posts</title>
</head>
<body>
    <h1>Blog Posts</h1>
    <a asp-controller="Blog" asp-action="Create">Create New Post</a>
    <ul>
        @foreach (var post in Model)
        {
            <li>
                <h2>@post.Title</h2>
                <p>@Html.Raw(@post.Content)</p>
                <p><small>@post.Created</small></p>
            </li>
        }
    </ul>
</body>
</html>


Create.cshtml
@model XSSAttackInAspNetCoreMVC.Model.BlogPost
<!DOCTYPE html>
<html>
<head>
    <title>Create Blog Post</title>
</head>
<body>
    <h1>Create Blog Post</h1>
    <form asp-action="Create" method="post" asp-antiforgery="true">
        <div class="form-group">
            <label asp-for="Title"></label>
            <input asp-for="Title" class="form-control" />
            <span asp-validation-for="Title" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Content"></label>
            <textarea asp-for="Content" class="form-control"></textarea>
            <span asp-validation-for="Content" class="text-danger"></span>
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
    <a asp-controller="Blog" asp-action="Index">Back to List</a>
</body>
</html>


Step 4. Add Client-Side Validation

Enable Client-Side Validation
Add the necessary scripts to _Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - XSSAttackInAspNetCoreMVC</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/XSSAttackInAspNetCoreMVC.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">XSSAttackInAspNetCoreMVC</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-action="Index" asp-controller="Blog">Blog</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - XSSAttackInAspNetCoreMVC - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>


Step 5. Run the Application
dotnet run

Output
If we want to submit the script in the form after doing the above steps the site will sanatize the input if the script is found the site will not accept the data.

After submitting this data, we will debug the inputs in the code, and we will not receive the script attack on my website.


You can see from the result that we don't receive any output pertaining to the scripts in the view after sanitization.

Conclusion

By following these instructions, you have developed a basic ASP.NET Core MVC application that shields users against XSS threats while enabling them to make and read blog posts. In order to display content properly, the application employs built-in encoding features and sanitizes user inputs before saving them to the database. By using this method, you may be sure that your application is safe against frequent XSS attacks.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Mastering ASP.NET Core Identity in ASP.NET Core MVC?

clock June 7, 2024 10:30 by author Peter

Any web application that needs user authorization and authentication must include ASP.NET Core Identity. It provides a smooth method for controlling roles, tokens, claims, passwords, and users. You may use this guide to set up and use ASP.NET Core Identity in your application in an efficient manner.


ASP.NET Core Identity Installation
Install the ASP.NET Core Identity required NuGet package.
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore

Configuring Identity Services
builder.Services.AddIdentity<AppUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequiredLength = 7;
    options.Password.RequireUppercase = true;

    options.User.RequireUniqueEmail = true;
})
             .AddEntityFrameworkStores<AppDbContext>()
             .AddTokenProvider<DataProtectorTokenProvider<AppUser>>(TokenOptions.DefaultProvider);


Configure Middleware
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});


Models for the Application
AppUser

using Microsoft.AspNetCore.Identity;

namespace A_MicrosoftAspNetCoreIdentityManagement.Models
{
    public class AppUser : IdentityUser
    {
        [PersonalData]
        public string FirstName { get; set; }

        [PersonalData]
        public string LastName { get; set; }
    }
}


Profile
namespace A_MicrosoftAspNetCoreIdentityManagement.Models
{
        public class Profile
        {
            public int ProfileId { get; set; }
            public string? FirstName { get; set; }
            public string? LastName { get; set; }
            public string? FullName { get; set; }

            public string? TagLine { get; set; }
            public string? About { get; set; }
            public string? Country { get; set; }
            public string? City { get; set; }

            public string? UserName { get; set; }
            public string? PhoneNumber { get; set; }

            public string? FacebookLink { get; set; }
            public string? TwitterLink { get; set; }
            public DateTime MemberSince { get; set; }
            public string? Website { get; set; }
            public string? ContactVerified { get; set; }

            public string? HeaderImageUrl { get; set; }
            public string? DisplayImageUrl { get; set; }
            public string? ProfileUrl { get; set; }

            public int ProfileBadgeId { get; set; }
            //Navigational Properties
            public virtual ICollection<ProfileBadge>? ProfileBadges { get; set; }
    }
}


Creating the Application Database Context
using A_MicrosoftAspNetCoreIdentityManagement.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace A_MicrosoftAspNetCoreIdentityManagement.Data
{
    public class AppDbContext : IdentityDbContext<AppUser>
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {

        }

        public DbSet<Profile> Profiles { get; set; }
        public DbSet<ProfileBadge> ProfileBadges { get; set; }
        public DbSet<Badge> badges { get; set; }
        public DbSet<DeactivatedProfile> DeactivatedProfiles { get; set; }
    }
}

C#
Setting Up Middleware

app.UseAuthentication();
app.UseAuthorization();


Configuring Identity Options
services.Configure<IdentityOptions>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequiredLength = 8;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireUppercase = true;
    options.Password.RequireLowercase = false;
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.User.RequireUniqueEmail = true;
});

Creating Controllers and Views for Authentication
Account Controller
Create an AccountController to handle registration, login, and logout.
using A_MicrosoftAspNetCoreIdentityManagement.Data;
using A_MicrosoftAspNetCoreIdentityManagement.Models;
using A_MicrosoftAspNetCoreIdentityManagement.Services;
using A_MicrosoftAspNetCoreIdentityManagement.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace A_MicrosoftAspNetCoreIdentityManagement.Controllers
{
    public class AccountController : Controller
    {
        private SignInManager<AppUser> _signInManager;
        private UserManager<AppUser> _userManager;
        private RoleManager<IdentityRole> _roleManager;
        private readonly AppDbContext _context;

        public AccountController(AppDbContext context, SignInManager<AppUser> signInManager, UserManager<AppUser> userManager, RoleManager<IdentityRole> roleManager)
        {
            _context = context;
            _signInManager = signInManager;
            _userManager = userManager;
            _roleManager = roleManager;
        }

        public IActionResult Login()
        {
            if (this.User.Identity.IsAuthenticated)
            {
                return RedirectToAction("Index", "Roles");
            }
            return View();
        }

        [HttpPost, ActionName("Login")]
        public async Task<IActionResult> LoginPost(LoginViewModel loginModel)
        {

            if (ModelState.IsValid)
            {
                var profile = _context.Profiles.Where(p => p.UserName == loginModel.Email).SingleOrDefault();
                var deactivated = _context.DeactivatedProfiles.Where(e => e.ProfileId == profile.ProfileId).FirstOrDefault();
                if (deactivated != null)
                {
                    ModelState.AddModelError("", $"Your profile has been blocked:{deactivated.Reason}. Please contact administrator [email protected]");
                    return View();
                }
                var result = await _signInManager.PasswordSignInAsync(loginModel.Email, loginModel.Password, loginModel.RememberMe, false);

                if (result.Succeeded)
                {
                    var user = await _userManager.FindByEmailAsync(loginModel.Email);
                    var roles = await _userManager.GetRolesAsync(user);
                    var primaryRole = roles.FirstOrDefault();

                    HttpContext.Session.SetString("ProfileId", profile.ProfileId.ToString());
                    HttpContext.Session.SetString("ProfileRole", primaryRole ?? "Member");
                    if (!string.IsNullOrWhiteSpace(profile.DisplayImageUrl))
                    {
                        HttpContext.Session.SetString("ProfileImage", profile.DisplayImageUrl);

                    }
                    else
                    {
                        HttpContext.Session.SetString("ProfileImage", "favicon.ico");
                    }

                    if(primaryRole == "Vendor")
                    {
                        return RedirectToAction("Index", "Roles");
                    }
                    else if (primaryRole == "Artist")
                    {
                        return RedirectToAction("BuyerDashBoard", "Roles");
                    }
                    else if (primaryRole == "Buyer")
                    {
                        return RedirectToAction("BuyerDashBoard", "Roles");
                    }
                    else if (primaryRole == "Admin")
                    {
                        return RedirectToAction("Index", "Roles");
                    }
                    else if (primaryRole == "Member")
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
            }
            ModelState.AddModelError("", "Faild to Login");
            return View();
        }

        public async Task<IActionResult> Logout()
        {
            await _signInManager.SignOutAsync();
            return RedirectToAction("Index", "Home");
        }

        public IActionResult Register()
        {
            return View();
        }

        [HttpPost, ActionName("Register")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> RegisterPost(RegisterViewModel registerModel)
        {
            if (ModelState.IsValid)
            {
                AppUser user = new AppUser
                {
                    FirstName = registerModel.FirstName,
                    LastName = registerModel.LastName,
                    UserName = registerModel.Email,
                    PhoneNumber = registerModel.PhoneNumber,
                    Email = registerModel.Email
                };

                Profile profile = new Profile
                {
                    UserName = registerModel.Email,
                    FirstName = registerModel.FirstName,
                    LastName = registerModel.LastName,
                    FullName = registerModel.FirstName + " " + registerModel.LastName,
                    PhoneNumber = registerModel.PhoneNumber
                };

                var result = await _userManager.CreateAsync(user, registerModel.Password);
                if (result.Succeeded)
                {
                    bool roleExists = await _roleManager.RoleExistsAsync(registerModel.RoleName);
                    if (!roleExists)
                    {
                        await _roleManager.CreateAsync(new IdentityRole(registerModel.RoleName));
                    }

                    if (!await _userManager.IsInRoleAsync(user, registerModel.RoleName))
                    {
                        await _userManager.AddToRoleAsync(user, registerModel.RoleName);
                    }

                    if (!string.IsNullOrWhiteSpace(user.Email))
                    {
                        // Claim[] claim = new Claim(ClaimTypes.GivenName, user.FirstName);
                        Claim[] claims = new Claim[]
                        {
                          new Claim(ClaimTypes.Email, user.Email),
                          new Claim(ClaimTypes.GivenName, user.FirstName),
                          new Claim(ClaimTypes.Surname, user.LastName)
                        };
                        await _userManager.AddClaimsAsync(user, claims);
                    }

                    //Add profile data
                    _context.Profiles.Add(profile);
                    await _context.SaveChangesAsync();

                    var resultSignIn = await _signInManager.PasswordSignInAsync(registerModel.Email, registerModel.Password, registerModel.RememberMe, false);
                    if (resultSignIn.Succeeded)
                    {
                        HttpContext.Session.SetString("ProfileId", profile.ProfileId.ToString());
                        HttpContext.Session.SetString("ProfileImage", "favicon.ico");
                        return RedirectToAction("Index", "Roles");
                    }
                }
                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError("", error.Description);
                }
            }
            return View();
        }

        public IActionResult ChangePassword()
        {
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> ChangePassword(ChangePassworViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);

            }
            AppUser user = await _userManager.FindByNameAsync(User.Identity.Name);

            var result = await _userManager.ChangePasswordAsync(user, model.CurrentPassword, model.NewPassword);

            if (result.Succeeded)
            {
                ViewBag.Message = "Your password has been updated";
                return View();
            }
            return View();

        }

        public DeactivatedProfile DeactivatedCheck(int id)
        {
            return _context.DeactivatedProfiles.Where(e => e.ProfileId == id).FirstOrDefault();
        }

        public IActionResult VerifyContact()
        {
            var profile = _context.Profiles.Where(u => u.UserName == User.Identity.Name).FirstOrDefault();

            VerifyContactViewModel model = new VerifyContactViewModel
            {
                Email = profile.UserName,
                PhoneNumber = profile.PhoneNumber,
                Status = profile.ContactVerified
            };

            return View(model);
        }

        [HttpPost]
        public IActionResult VerifyContact(VerifyContactViewModel model)
        {
            if (ModelState.IsValid)
            {
                if (model.VerificationCode == "5186")
                {
                    var profile = _context.Profiles.Where(u => u.UserName == User.Identity.Name).FirstOrDefault();

                    profile.ContactVerified = "Verified";
                    _context.Profiles.Update(profile);
                    _context.SaveChanges();
                    ViewBag.Message = "Contact Verified";
                    return View(model);
                }
                else
                {
                    ModelState.AddModelError("", $"You entered wrong code.Please enter code sent on your email");
                    return View(model);
                }

            }

            return View(model);
        }

        public async Task<string> ConfirmContact()
        {
            var email = User.Identity.Name;
            await EmailService.SendEmailAsync(new MailRequest() { ToEmail = email, Subject = "Verification Code", Body = "Your Verification Code is:5186" });
            //Send verification code
            return "Verification Code Sent to your email";
        }

        public IActionResult ForgotPassword()
        {
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByNameAsync(model.Email);
                if (user == null)
                {
                    // Don't reveal that the user does not exist or is not confirmed
                    return View("ForgotPasswordConfirmation");
                }

                // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
                // Send an email with this link
                string code = await _userManager.GeneratePasswordResetTokenAsync(user);
                var callbackUrl = Url.Action("ResetPassword", "Account", new { Email = user.Email, Code = code }, protocol: Request.Scheme);
                // await _userManager.SendEmailAsync(user.Id, "Reset Password", "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>");
                await EmailService.SendEmailAsync(new MailRequest() { ToEmail = user.Email, Subject = "Reset Password", Body = "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>" });
                return RedirectToAction("ForgotPasswordConfirmation", "Account");
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        // GET: /Account/ForgotPasswordConfirmation
        [AllowAnonymous]
        public IActionResult ForgotPasswordConfirmation()
        {
            return View();
        }

        //
        // GET: /Account/ResetPassword
        [AllowAnonymous]
        public IActionResult ResetPassword(string email, string code)
        {
            return code == null ? View("Error") : View();
        }

        // POST: /Account/ResetPassword
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            var user = await _userManager.FindByNameAsync(model.Email);
            if (user == null)
            {
                // Don't reveal that the user does not exist
                return RedirectToAction("ResetPasswordConfirmation", "Account");
            }
            var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
            if (result.Succeeded)
            {
                return RedirectToAction("ResetPasswordConfirmation", "Account");
            }

            AddErrors(result);
            return View();
        }

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError("", error.ToString());
            }
        }

        [AllowAnonymous]
        public IActionResult ResetPasswordConfirmation()
        {
            return View();
        }
    }
}


ViewModel Classes
LoginViewModel
using System.ComponentModel.DataAnnotations;

namespace A_MicrosoftAspNetCoreIdentityManagement.ViewModels
{
    public class LoginViewModel
    {
        [Required(ErrorMessage = "Please enter your email")]
        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }

        [Display(Name = "Password")]
        [Required(ErrorMessage = "Please enter your password.")]
        public string Password { get; set; }

        [Display(Name = "Remember Me")]
        public bool RememberMe { get; set; }
    }
}

RegisterViewModel
using System.ComponentModel.DataAnnotations;

namespace A_MicrosoftAspNetCoreIdentityManagement.ViewModels
{
    public class RegisterViewModel: LoginViewModel
    {
        [Display(Name = "First Name")]
        [Required(ErrorMessage = "Please enter your first name")]
        public string FirstName { get; set; }

        [Display(Name = "Last Name")]
        [Required(ErrorMessage = "Please enter your last name")]
        public string LastName { get; set; }

        [Display(Name = "Role Name")]
        [Required(ErrorMessage = "Please select a role")]
        public string RoleName { get; set; }

        [Display(Name = "Phone Number")]
        [Required(ErrorMessage = "Please enter your phone number")]
        [DataType(DataType.PhoneNumber)]
        public string PhoneNumber { get; set; }
    }
}

Register and Login Views
Create views for registration and login.

Register.cshtml
@model RegisterViewModel

@{
    ViewData["Title"] = "Register";
    Layout = "/Pages/Shared/_Layout.cshtml";
}

<!-- FORM POPUP -->
<div class="form-popup">

    <!-- /CLOSE BTN -->
    <!-- FORM POPUP HEADLINE -->
    <div class="form-popup-headline primary">
        <h2>Register Account</h2>
        <p>Register now and start making money from home!</p>
    </div>
    <!-- /FORM POPUP HEADLINE -->
    <!-- FORM POPUP CONTENT -->
    <div class="form-popup-content">
        <form id="register-form4" method="post" enctype="multipart/form-data" asp-action="Register">
            <div asp-validation-summary="ModelOnly" class="Error-Message"></div>
            <label asp-for="FirstName" class="rl-label"></label>
            <input asp-for="FirstName" type="text" placeholder="First Name">
            <span asp-validation-for="FirstName" class="Error-Message"></span>

            <label asp-for="LastName" class="rl-label"></label>
            <input asp-for="LastName" type="text" placeholder="Last Name">
            <span asp-validation-for="LastName" class="Error-Message"></span>

            <label asp-for="PhoneNumber" class="rl-label"></label>
            <input asp-for="PhoneNumber" type="text" placeholder="Phone Number">
            <span asp-validation-for="PhoneNumber" class="Error-Message"></span>

            <label asp-for="Email" class="rl-label"></label>
            <input asp-for="Email" type="email" placeholder="[email protected]">
            <span asp-validation-for="Email" class="Error-Message"></span>

            <label asp-for="Password" class="rl-label"></label>
            <input asp-for="Password" type="password" placeholder="Enter your password here...">
            <span asp-validation-for="Password" class="Error-Message"></span>

            <label asp-for="RoleName" class="rl-label"></label>
            <select asp-for="RoleName" class="form-control">
                <option value="">Select Role</option>
                <option value="Member">Member</option>
                <option value="Vendor">Vendor</option>
                <option value="Artist">Artist</option>
            </select>
            <span asp-validation-for="RoleName" class="Error-Message"></span>

            <button class="button mid dark">Register <span class="primary">Now!</span></button>
        </form>
    </div>
    <!-- /FORM POPUP CONTENT -->
</div>
<!-- /FORM POPUP -->
@section Scripts {
    <!-- jQuery -->
    <script src="~/js/vendor/jquery-3.1.0.min.js"></script>
    <script src="~/js/vendor/twitter/jquery.tweet.min.js"></script>
    <!-- Side Menu -->
    <script src="~/js/side-menu.js"></script>
    <!-- User Quickview Dropdown -->
    <script src="~/js/user-board.js"></script>
    <!-- Footer -->
    <script src="~/js/footer.js"></script>
    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
}


Login.cshtml
@model LoginViewModel

@{
    ViewData["Title"] = "Login";
    Layout = "/Pages/Shared/_Layout.cshtml";
}

<!-- FORM POPUP -->
<div class="form-popup">

    <!-- FORM POPUP HEADLINE -->
    <div class="form-popup-headline secondary">
        <h2>Login to your Account</h2>
        <p>Enter now to your account and start buying and selling!</p>
    </div>
    <!-- /FORM POPUP HEADLINE -->
    <!-- FORM POPUP CONTENT -->
    <div class="form-popup-content">
        <form id="login-form2" method="post" enctype="multipart/form-data" asp-action="Login">
            <div asp-validation-summary="ModelOnly" class="Error-Message"></div>
            <label asp-for="Email" class="rl-label"></label>
            <input asp-for="Email" type="text" placeholder="[email protected]" required>
            <span asp-validation-for="Email" class="Error-Message"></span>
            <label asp-for="Password" class="rl-label"></label>
            <input asp-for="Password" type="password" placeholder="Enter your password here..." required>
            <span asp-validation-for="Password" class="Error-Message"></span>
            <!-- CHECKBOX -->
            <input asp-for="RememberMe" type="checkbox" checked>
            <label asp-for="RememberMe" class="label-check">
                <span class="checkbox primary primary"><span></span></span>
                Remember username and password
            </label>
            <span asp-validation-for="RememberMe" class="Error-Message"></span>
            <!-- /CHECKBOX -->
            <p>Forgot your password? <a asp-action="ForgotPassword" asp-controller="Account" class="primary">Click here!</a></p>
            <button class="button mid dark">Login <span class="primary">Now!</span></button>
        </form>
        <!-- LINE SEPARATOR -->
        <hr class="line-separator double">

    </div>
    <!-- /FORM POPUP CONTENT -->
</div>
<!-- /FORM POPUP -->
@section Scripts {
    <!-- jQuery -->
    <script src="~/js/vendor/jquery-3.1.0.min.js"></script>
    <script src="~/js/vendor/twitter/jquery.tweet.min.js"></script>
    <!-- Side Menu -->
    <script src="~/js/side-menu.js"></script>
    <!-- User Quickview Dropdown -->
    <script src="~/js/user-board.js"></script>
    <!-- Footer -->
    <script src="~/js/footer.js"></script>
    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
}


Adding Email Confirmation and Password Recovery
Enable email confirmation and password recovery to enhance security.

Email Configuration

namespace A_MicrosoftAspNetCoreIdentityManagement.Configurations
{
    public class EmailConfiguration
    {
        public static string SenderEmail = "[email protected]";
        public static string Password = "test123/";
        public static string Host = "smtp.gmail.com";
        public static int Port = 465;
        public static bool UseSsl = true;
        public static string DisplayName = "MVC Support";
    }
}

Email Service

using A_MicrosoftAspNetCoreIdentityManagement.Configurations;
using MailKit.Net.Smtp;
using MimeKit;

namespace A_MicrosoftAspNetCoreIdentityManagement.Services
{
    public static class EmailService
    {
        public async static Task SendEmailAsync(MailRequest mailRequest)
        {
            var email = new MimeMessage();
            email.Sender = MailboxAddress.Parse(EmailConfiguration.SenderEmail);
            email.To.Add(MailboxAddress.Parse(mailRequest.ToEmail));
            email.Subject = mailRequest.Subject;
            var builder = new BodyBuilder();
            if (mailRequest.Attachments != null)
            {
                byte[] fileBytes;
                foreach (var file in mailRequest.Attachments)
                {
                    if (file.Length > 0)
                    {
                        using (var ms = new MemoryStream())
                        {
                            file.CopyTo(ms);
                            fileBytes = ms.ToArray();
                        }
                        builder.Attachments.Add(file.FileName, fileBytes, ContentType.Parse(file.ContentType));
                    }
                }
            }
            builder.HtmlBody = mailRequest.Body;
            email.Body = builder.ToMessageBody();
            using var smtp = new SmtpClient();
            smtp.Connect(EmailConfiguration.Host, EmailConfiguration.Port, EmailConfiguration.UseSsl);
            smtp.Authenticate(EmailConfiguration.SenderEmail, EmailConfiguration.Password);
            await smtp.SendAsync(email);
            smtp.Disconnect(true);
        }
    }
    public class MailRequest
    {
        public string ToEmail { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public List<IFormFile> Attachments { get; set; }
    }
}

Enable Password Recovery
Add actions for password recovery.

[HttpPost]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await _userManager.FindByNameAsync(model.Email);
        if (user == null)
        {
            // Don't reveal that the user does not exist or is not confirmed
            return View("ForgotPasswordConfirmation");
        }

        // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
        // Send an email with this link
        string code = await _userManager.GeneratePasswordResetTokenAsync(user);
        var callbackUrl = Url.Action("ResetPassword", "Account", new { Email = user.Email, Code = code }, protocol: Request.Scheme);
        // await _userManager.SendEmailAsync(user.Id, "Reset Password", "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>");
        await EmailService.SendEmailAsync(new MailRequest() { ToEmail = user.Email, Subject = "Reset Password", Body = "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>" });
        return RedirectToAction("ForgotPasswordConfirmation", "Account");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}


Output

If our role is vendor, then the vendor dashboard will be shown on the screen.

If our role is buyer, then the buyer dashboard will be shown on the screen.

 



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: ASP.NET MVC: Transferring Values from Partial Views to Parent Views

clock May 31, 2024 09:09 by author Peter

In ASP.NET MVC applications, partial views are often used to simplify and modularize the user experience. On the other hand, there are times when communication between partial views and their parent views might be challenging, particularly when transmitting values or data. This article explores effective ways to transfer values from partial views to their parent views in ASP.NET MVC, hence enhancing interactivity and user experience.

What is partial views?
Partial views, denoted by the _ prefix convention in ASP.NET MVC, are reusable components that allow developers to encapsulate specific pieces of HTML and Razor code. These partial views can be shown inside of parent views through modularization and code reuse, which promotes a more structured and manageable codebase.

Challenges in passing values
Passing values or data from a partial view back to its parent view is a typical requirement in web development. This can be challenging since partial views are divided and do not offer direct access to the components or features of the parent view. However, there are several approaches that can break through this barrier and allow parent views and partial views to communicate with each other without difficulty.

Example
Let's look at an example where there is a form input field in a partial view, and the value entered has to be sent back to the parent view for processing.
Partial view (_MyPartialView.cshtml)

<div>
    <input type="text" id="inputValue" />
</div>
<script>
    var value = document.getElementById('inputValue').value;
    window.parent.updateMainView(value);
</script>


Parent view (Index.cshtml)

<h2>Main View</h2>
<div id="displayValue"></div>
<script>
    function updateMainView(value) {
        document.getElementById('displayValue').innerText = "Value from Partial View: " + value;
    }
</script>


Conclusion
In ASP.NET MVC development, variables from partial views must be passed to parent views in order to improve user experience and interactivity. Using JavaScript messaging or direct function invocation, developers can establish seamless communication channels across views, enabling dynamic data interchange and interactive user interfaces. By learning these techniques, developers may produce more dependable and engaging ASP.NET MVC web applications.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Building an Interactive Location Selector with Google Maps in ASP.NET MVC?

clock May 16, 2024 10:05 by author Peter

Discover how to build a fully functional location selector feature for your ASP.NET MVC application using Google Maps API.

Introduction
This article provides a comprehensive, step-by-step guide to integrating Google Maps, allowing users to click on a map, select a location, and store it for future reference. From setting up Google Maps API to implementing JavaScript for map integration and handling user interactions, you'll find detailed instructions to create an interactive mapping feature. Additionally, learn how to seamlessly integrate database operations to store selected locations and retrieve them for display.

To achieve the functionality in ASP.NET MVC using Google Maps API, you can follow these steps.

1. Set up Google Maps API

Obtain a Google Maps API key from the Google Cloud Console and enable the necessary APIs (Maps JavaScript API, Geocoding API) for your project.

2. Create MVC Controller and Views
Create a controller with actions to handle the requests.
Create views for displaying the map, capturing the location, and displaying stored locations.

3. Implement JavaScript for Maps Integration

  • Use JavaScript to integrate Google Maps into your view.
  • Allow users to click on the map to select a location.
  • Retrieve the latitude and longitude of the selected location.
  • Display the selected location on the map.

4. Store Selected Location

  • When the user submits the selected location, send the latitude and longitude to the server.
  • Store the location in your database along with any additional information you want to associate with it.

5. Retrieve and Display Stored Locations

  • When the user wants to view stored locations, retrieve them from the database.
  • Display the stored locations as clickable links.
  • When a user clicks on a location link, display the location on the map.

Here's a basic example of how you can implement this.

Controller

public class LocationController : Controller
{
    public ActionResult Index()
    {
        // Display map for selecting location
        return View();
    }

    [HttpPost]
    public ActionResult SaveLocation(double latitude, double longitude, string locationName)
    {
        // Save the location in your database
        // Redirect to a success page or back to the map view
        return RedirectToAction("Index"); // Example redirection to Index action
    }

    public ActionResult DisplayLocations()
    {
        // Retrieve stored locations from the database
        // Display a view with clickable links to the stored locations
        return View();
    }
}


View (Index. cshtml)
<!-- Display Google Map -->
<div id="map" style="height: 400px; width: 100%;"></div>

<!-- Button to submit selected location -->
<button id="submitLocation">Submit Location</button>

<script>
    function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
            center: { lat: -34.397, lng: 150.644 },
            zoom: 8
        });

        var marker;

        // Add click event listener to get selected location
        map.addListener('click', function (e) {
            var latitude = e.latLng.lat();
            var longitude = e.latLng.lng();

            // Clear previous marker
            if (marker) {
                marker.setMap(null);
            }

            // Display marker on selected location
            marker = new google.maps.Marker({
                position: { lat: latitude, lng: longitude },
                map: map
            });
        });

        // Event listener for submit button
        document.getElementById('submitLocation').addEventListener('click', function () {
            // Check if marker is defined
            if (marker) {
                // Get selected location data and submit to server
                var latitude = marker.getPosition().lat();
                var longitude = marker.getPosition().lng();
                var locationName = ""; // You may prompt the user for a name
                // Send latitude, longitude, and locationName to the server using AJAX
            } else {
                alert("Please select a location on the map.");
            }
        });
    }
</script>

<!-- Load Google Maps API -->
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Create Dynamic Models with a Database in C#.NET 8 MVC

clock April 17, 2024 07:37 by author Peter

In order to fill database tables with data, models must be created. However, what happens if you have to generate models dynamically rather than building your model with classes and properties? In this scenario, you will have to develop code that uses the table schema to create the models at runtime. In this post, we'll build a dynamic model generator that can produce models from your database table schema automatically using C#.NET 8 MVC.

How does dynamic model generation work?

Developers frequently spend a great deal of effort building models that match the structure of their database tables when using standard C#.NET MVC development. This procedure, which can be laborious, prone to errors, and not very scalable, particularly for applications with big databases, entails defining characteristics for each column in the table. The process of dynamically generating models at runtime based on database table schema is known as dynamic model generation. We can automate this process by querying the database for each table's structure and dynamically creating the associated C# classes, saving us the trouble of constructing model classes by hand for each table.

C#.NET 8 Project for creating dynamic models
You can skip the project creation section if you have previously created the project because I will be going over every step from beginning to end. Let's now create a project to see how this is accomplished.

Step 1: Needs

Since I'll be working with.NET 8, it needs to be installed (if you're using a different version, that depends on your needs).

Step 2. Setting up the Project

  • In the Visual Studio, click 'Create a new project' and click 'Next.'
  • In templates, select 'ASP.NET Core Web App (Model-View-Controller)' and click 'Next'.
  • In the 'Configure your new project' window, name your project, here I have named it 'DynamicModelGenerator' and click 'Next'.
  • In the Additional Information window, in Framework, choose '.NET 8' and click 'Create'.
  • Now, the project is created and the project structure looks like the below image.

Install packages in step three
Let's now install the project-related packages. We will utilize Entity for database operations in our project. Let's install it now.

  • Choose 'Manage NuGet Packages' after clicking 'Project'.
  • Type 'EntityFramework' into the 'Browse' search field.
  • Click 'Install' after selecting it.
  • There will be a pop-up window; click "I accept."
  • Now that Entity Framework is installed, it seems as follows.

Configure the connection string in step four
Let's now update the appsettings.json file with a connection string. In accordance with your database, change the Server, Database, User ID, and Password.

"ConnectionStrings": {
  "DefaultConnection": "Server=******;Database=******;user id=******;Password=******;MultipleActiveResultSets=true;Encrypt=False;"
},

Create Index View

In the HomeController, we have an Index method, by default, it has some boilerplate code written. Let's change it according to our requirements. Here, I am changing some basic code that is needed for our implementation.
In Index.cshtml

@{
    ViewData["Title"] = "Home Page";
}

<div>
    <h2>Dynamic Model Generator</h2>
    <p>Generate dynamic models and use them in your application.</p>
    <p>Click <a href="/get-database-tables">here</a> to get all the tables present in your database.</p>
</div>


In the above, I have added a title to the page, a heading in the home page some info in <p> tag and <a> tag to provide a link on whose click, and a method having route 'get-database-tables' will be called. The view will look like below.

Make a Controller for ModelGenerator
It is best practice to divide your code into distinct controllers based on your needs. So, make a controller and give it a suitable name. 'ModelGeneratorController' is the name I gave it. This is how your controller will appear below.

using Microsoft.AspNetCore.Mvc;
using System.Data.SqlClient;

public class ModelGeneratorController : Controller
{
    //empty controller
}


In this controller, let's add a constructor and a read-only property.
private readonly string _connectionString;

public ModelGeneratorController(IConfiguration configuration)
{
    _connectionString = configuration.GetConnectionString("DefaultConnection");
}


In the above, I added a private read-only string named _connectionString to store the database connection string. Then, I created a constructor and in that, I assigned the connection string stored in our appsettings.json file to the _connectionString property.

Create a method to get all database tables
Now, let's create a method to get all the tables present in our database.

[HttpGet]
[Route("get-database-tables")]
public IActionResult GetDatabaseTables()
{
    var tableNames = new List<string>();

    using (var connection = new SqlConnection(_connectionString))
    {
        connection.Open();
        var command = connection.CreateCommand();
        command.CommandText = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'";
        var reader = command.ExecuteReader();

        while (reader.Read())
        {
            tableNames.Add(reader.GetString(0));
        }

        reader.Close();
    }

    return View(tableNames);
}

In the above code I created a method named GetDatabaseTables(). made it HTTP GET to handle the GET request, method and gave it the route 'get-database-tables', which we used in index.cshtml page.

In this method, I created a variable tableNames, a list of string values, which will be used to store the list of tables present in the database. In the next line, I created a connection with SQL Server and then opened the connection. In the next line, I created a SQL command (SqlCommand) to execute a SQL query against the database. The query selects table names from the INFORMATION_SCHEMA.TABLES view where the TABLE_TYPE is 'BASE TABLE'.

This ensures that only base tables (not views or system tables) are included in the result. In the next line, I executed the command using ExecuteReader() and iterated over the results using a while loop. For each row in the result set, it reads the value of the first column (table name) using the reader.GetString(0) and add it to the tableNames list. After reading all the data, we closed the data reader and the database connection to release resources. At last, I passed the table names to the View().

Create a view to show the tables present in the database

To create a view, right-click on GetDatabaseTables() method, click, 'Add View', and name the view, I named it 'GetDatabaseTables.cshtml'. Your view file is created
In GetDatabaseTables.cshtml
@model List<string>
@{
    ViewData["Title"] = "Database Tables";
}
<!DOCTYPE html>
<html>
<head>
    <title>@ViewData["Title"]</title>
    <style>
        table {
            width: 40%;
            border-collapse: collapse;
        }

        th, td {
            padding: 8px;
            border: 1px solid #ddd;
            text-align: left;
        }

        th {
            background-color: #f2f2f2;
        }

        tr:nth-child(even) {
            background-color: #f2f2f2;
        }

        tr:hover {
            background-color: #ddd;
        }

        a {
            text-decoration: none;
            color: blue;
        }

            a:hover {
                text-decoration: underline;
            }
    </style>
</head>
<body>
    <div>
        <h1>Database Tables</h1>
        <table>
            <thead>
                <tr>
                    <th>Table Name</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var tableName in Model)
                {
                    <tr>
                        <td>@tableName</td>
                        <td><a href="@Url.Action("CreateDynamicModel", "ModelGenerator", new { tableName = tableName })">Create Dynamic Model</a></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
</body>
</html>


In the above code, I added a directive that specifies the type of model that this view expects. In our case, it expects a List<string>, which means it will receive a list of strings from the controller. Then, added a title to the page. In the body, I created a <div>, and inside that <div>, added a for each loop to iterate over the list of table names and display them in a tabular format with some CSS styling. This will look like below.


Create a method to create a dynamic model
[HttpGet]
[Route("create-dynamic-model")]
public string CreateDynamicModel(string tableName)
{
    StringBuilder classDefinition = new();

    classDefinition.AppendLine($"public class {tableName}Model");
    classDefinition.AppendLine("{");

    List<string> propertyDeclarations = GetPropertyDeclarationsForTable(tableName);

    foreach (var propertyDeclaration in propertyDeclarations)
    {
        classDefinition.AppendLine($"    {propertyDeclaration}");
    }

    classDefinition.AppendLine("}");

    return classDefinition.ToString();
}

In the above method, I created a StringBuilder object and then started constructing a model class by getting property declarations for the table. and inside a for each loop, generated all property declarations. Once the class construction is completed, I returned the constructed class to the view.

Step 10. Create GetPropertyDeclarationsForTable() method

In the above method, we used GetPropertyDeclarationsForTable(), now let's create the method.
private List<string> GetPropertyDeclarationsForTable(string tableName)
{
    List<string> propertyDeclarations = [];

    using (var oldConnection = new SqlConnection(_connectionString))
    {
        oldConnection.Open();

        string sql = $"SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{tableName}'";
        using var cmd = new SqlCommand(sql, oldConnection);
        using SqlDataReader reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            string columnName = reader["COLUMN_NAME"].ToString();
            string dataType = reader["DATA_TYPE"].ToString();
            bool isNullable = reader["IS_NULLABLE"].ToString() == "YES";

            string propertyDeclaration = $"public {GetCSharpType(dataType, isNullable)} {columnName} {{ get; set; }}";
            propertyDeclarations.Add(propertyDeclaration);
        }

        oldConnection.Close();
    }

    return propertyDeclarations;
}


In the above method, I created a list of strings. In the next line, I established the connection and got the data using an SQL connection. In next line, in a while loop, i got the information about the columns and constructed property declaration, using that information. Next, added that declaration to the string list. After closing the connection, I returned the property declarations.

Step 11. Create GetCSharpType() method

In the above method, we used the GetCSharpType() method, so let's create it.
private static string GetCSharpType(string dataType, bool isNullable)
 {
     switch (dataType)
     {
         case "bigint":
             return isNullable ? "long?" : "long";
         case "int":
             return isNullable ? "int?" : "int";
         case "nvarchar":
         case "varchar":
             return "string";
         default:
             return "object";
     }
 }


In this method, I added a switch case in which according to database data type, I returned the appropriate C# data type corresponding to them.

Create a view of the CreateDynamicModel page
To create a view, right-click on CreateDynamicModel () method, click, 'Add View', and name the view, I named it 'CreateDynamicModel .cshtml'. Your view file is created

In CreateDynamicModel.cshtml
@model string

<!DOCTYPE html>
<html>
<head>
    <title>Dynamic Model Class</title>
</head>
<body>
    <h2>Dynamic Model Class</h2>
    <pre>
        @Html.Raw(Model)
    </pre>
</body>
</html>


In the above method, the string coming from the method is shown in the view inside <pre> tag. This will look like below.


Here, we've used C# MVC to successfully develop a dynamic model.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Consuming ASP.NET Web API REST Service In ASP.NET MVC Using HttpClient

clock March 28, 2024 10:10 by author Peter

In numerous forum postings, developers and students have addressed the same question: how to utilize Web API REST Service in an ASP.NET MVC application and how to initiate a call between them to exchange data. So, in response to this need, I decided to write this post to show how to use HttpClient to consume the ASP.NET Web API REST Service in an ASP.NET MVC application.

Prerequisites
If you're not sure what a Web API REST service is or how to construct, publish, and host an ASP.NET Web API REST Service, please watch my video and read the papers linked below. Follow the same steps if you want to learn how to create, host, and consume web API REST services in client applications.

In this article, we will use the same hosted Web API REST service to consume in our created ASP.NET MVC web application. Now, let's start consuming Web API REST service in the ASP.NET MVC application step by step.

Step 1. Create an MVC Application
Start, followed by All Programs, and select Microsoft Visual Studio 2015.
Click File, followed by New, and click Project. Select ASP.NET Web Application Template, provide the Project a name as you wish, and click OK.
After clicking, the following Window will appear. Choose an empty project template and check on the MVC option.

The preceding step creates the simple empty ASP.NET MVC application without a Model, View, and Controller, The Solution Explorer of created web application will look like the following.

Step 2. Install HttpClient library from NuGet
We are going to use HttpClient to consume the Web API REST Service, so we need to install this library from NuGet Package Manager .

What is HttpClient?

HttpClient is base class which is responsible to send HTTP request and receive HTTP response resources i.e from REST services.
To install HttpClient, right click on Solution Explorer of created application and search for HttpClient, as shown in the following image.

Now, click on Install button after choosing the appropriate version. It will get installed after taking few seconds, depending on your internet speed.

Step 3. Install WebAPI.Client library from NuGet
This package is used for formatting and content negotiation which provides support for System.Net.Http. To install, right click on Solution Explorer of created application and search for WebAPI.Client, as shown in following image.


Now, click on Install button after choosing the appropriate version. It will get installed after taking few seconds depending on your internet speed. We have installed necessary NuGet packages to consume Web API REST services in web application. I hope you have followed the same steps.

Step 4. Create Model Class
Now, let us create the Model class named Employee.cs or as you wish, by right clicking on Models folder with same number of entities which are exposing by our hosted Web API REST service to exchange the data. The code snippet of created Employee.cs class will look like this.

Employee.cs
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
}

Step 5. Add Controller Class
Now, let us add ASP.NET MVC controller

After clicking Add button, it will show in the Window. Specify the Controller name as Home with suffix Controller. Now, let's modify the default code of Home controller .

Our hosted Web API REST Service includes these two methods, as given below.

  • GetAllEmployees (GET )
  • GetEmployeeById (POST ) which takes id as input parameter

We are going to call GetAllEmployees method which returns the all employee details ,The hosted web api REST service base URL is http://192.168.95.1:5555/ and to call GetAllEmployees from hosted web API REST service, The URL should be Base url+api+apicontroller name +web api method name as following http://192.168.95.1:5555/api/Employee/GetAllEmployees.

In the preceding url

  • http://localhost:56290 Is the base address of web API service, It can be different as per your server.
  • api It is the used to differentiate between Web API controller and MVC controller request .
  • Employee This is the Web API controller name.
  • GetAllEmployees This is the Web API method which returns the all employee list.

After modifying the code of Homecontroller class, the code will look like the following.

Homecontroller.cs
using ConsumingWebAapiRESTinMVC.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace ConsumingWebAapiRESTinMVC.Controllers
{
    public class HomeController : Controller
    {
        //Hosted web API REST Service base url
        string Baseurl = "http://192.168.95.1:5555/";
        public async Task<ActionResult> Index()
        {
            List<Employee> EmpInfo = new List<Employee>();
            using (var client = new HttpClient())
            {
                //Passing service base url
                client.BaseAddress = new Uri(Baseurl);
                client.DefaultRequestHeaders.Clear();
                //Define request data format
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                //Sending request to find web api REST service resource GetAllEmployees using HttpClient
                HttpResponseMessage Res = await client.GetAsync("api/Employee/GetAllEmployees");
                //Checking the response is successful or not which is sent using HttpClient
                if (Res.IsSuccessStatusCode)
                {
                    //Storing the response details recieved from web api
                    var EmpResponse = Res.Content.ReadAsStringAsync().Result;
                    //Deserializing the response recieved from web api and storing into the Employee list
                    EmpInfo = JsonConvert.DeserializeObject<List<Employee>>(EmpResponse);
                }
                //returning the employee list to view
                return View(EmpInfo);
            }
        }
    }
}


I hope, you have gone through the same steps and understood about the how to use and call Web API REST service resource using HttpClient .

Step 6. Create strongly typed View
Now, right click on Views folder of the created application and create strongly typed View named by Index by choosing Employee class to display the employee list from hosted web API REST Service, as shown in the following image.

Now, click on Add button. It will create View named index after modifying the default code. The code snippet of the Index View looks like the following.

Index.cshtml

@model IEnumerable<ConsumingWebAapiRESTinMVC.Models.Employee>
@{
    ViewBag.Title = "www.compilemode.com";
}
<div class="form-horizontal">
    <hr />
    <div class="form-group">
        <table class="table table-responsive" style="width:400px">
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Name)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.City)
                </th>
            </tr>
            @foreach (var item in Model) {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.Name)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.City)
                    </td>
                </tr>
            }
        </table>
    </div>
</div>


The preceding View will display all employees list . Now, we have done all the coding.

Step 7. Run the Application
After running the Application, the employee list from hosted web API REST service.

I hope, from the above examples, you have learned how to consume Web API REST Service in ASP.NET MVC using HttpClient.

Note

  • Download the Zip file of the Published code to learn and start quickly.
  • This article is just a guideline on how to consume Web API REST Service in ASP.NET MVC application using HttpClient.
  • In this article, the optimization is not covered in depth; do it as per your skills.




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