How to Create Crud App using asp.net core Web API thru Db First Approach
Step 1: Create a New .NET Core Web API Project
Step 2: Install Required NuGet Packages
Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Tools (use for migration)
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Design (db 1st approach, already exist db then)
Step 3: Scaffold the Database
Scaffold-DbContext "Server=DESKTOP-9M9EDAA\SQLEXPRESS;Database=DbDot;Trusted_Connection=True; TrustServerCertificate = True; MultipleActiveResultSets = true" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
or
scaffold "Your_Connection_String" Microsoft.EntityFrameworkCore.SqlServer -o Models (o denotes Output Directory)
Your_Connection_String = "Server=.;Database=YourDatabase;Trusted_Connection=True; Trusted_Connection=True; MultipleActiveResultSet=True; TrustServerCertificate=True;"
Step 4: Modify DbContext file
DbContext file ko modify karne ka main reason ye h ki OnConfiguring me connection string aa jata h jo ki security base pe sahi nhi h es liye OnConfiguring method ko replace kar de niche diye gaye sare code se.
private readonly IConfiguration _configuration;
public EcommDbContext(IConfiguration configuration , DbContextOptions<DbDotContext> options)
: base(options)
{
_configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var connectionString = _configuration.GetConnectionString("DbDot");
optionsBuilder.UseSqlServer(connectionString);
}
}
Step 5: Configure the Database in appsettings.json
"ConnectionStrings": {
"DefaultConnection": "Server=DESKTOP-9M9EDAA\SQLEXPRESS;Database=DbDot;Trusted_Connection=True; TrustServerCertificate = True; MultipleActiveResultSets = true" },
Step 6: Update Program.cs
Program.cs
builder.Services.AddDbContext<DbDotContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
Step 7
. Repo(folder->IRepository, Repository)
IRepository.cs
namespace DotApi.Repo{ public interface IRepository<T> where T : class { Task<IEnumerable<T>> GetAllAsync(); Task<T> GetByIdAsync(int id); Task<T> AddAsync(T entity); Task<T> UpdateAsync(T entity); Task<bool> DeleteAsync(int id); }}Repository.cs
using DotApi.Data;using Microsoft.EntityFrameworkCore;
namespace DotApi.Repo{ public class Repository<T> : IRepository<T> where T : class { private readonly AppDbContext _db; private readonly DbSet<T> _dbSet; public Repository(AppDbContext db) { _db = db; _dbSet = _db.Set<T>(); } // Get All Records public async Task<IEnumerable<T>> GetAllAsync() { return await _dbSet.ToListAsync(); }
// Get a Single Record by ID public async Task<T> GetByIdAsync(int id) { return await _dbSet.FindAsync(id); }
// Add a New Record public async Task<T> AddAsync(T item) { await _dbSet.AddAsync(item); await _db.SaveChangesAsync(); return item; }
// Update an Existing Record public async Task<T> UpdateAsync(T item) { _dbSet.Update(item); await _db.SaveChangesAsync(); return item; }
// Delete a Record by ID public async Task<bool> DeleteAsync(int id) { // Fetch the entity to delete var item = await _dbSet.FindAsync(id); if (item == null) { return false; // Entity not found }
_dbSet.Remove(item); await _db.SaveChangesAsync(); return true; // Successfully deleted } }}Step 8
. Service (folder)
UserService.csusing DotApi.Models;using DotApi.Repo;using Microsoft.Extensions.Logging;
namespace DotApi.Service{ public class UserService { private readonly IRepository<User> _repository; private readonly ILogger<UserService> _logger;
public UserService(IRepository<User> repository, ILogger<UserService> logger) { _repository = repository; _logger = logger; }
public async Task<IEnumerable<User>> GetAllUsersAsync() { try { return await _repository.GetAllAsync(); } catch (Exception ex) { _logger.LogError(ex, "Error fetching all Users."); throw; } }
public async Task<User> GetUserAsync(int id) { try { var User = await _repository.GetByIdAsync(id); if (User == null) { _logger.LogWarning($"User with ID {id} not found."); throw new KeyNotFoundException($"User with ID {id} not found."); } return User; } catch (Exception ex) { _logger.LogError(ex, $"Error fetching User with ID {id}."); throw; } }
public async Task<User> AddUserAsync(User User) { try { if (User == null || string.IsNullOrEmpty(User.Name)) { throw new ArgumentException("Invalid User data."); } return await _repository.AddAsync(User); } catch (Exception ex) { _logger.LogError(ex, "Error adding User."); throw; } }
public async Task<User> UpdateUserAsync(User User) { try { if (User == null || string.IsNullOrEmpty(User.Name)) { throw new ArgumentException("Invalid User data."); } return await _repository.UpdateAsync(User); } catch (Exception ex) { _logger.LogError(ex, "Error updating User."); throw; } }
public async Task<bool> DeleteUserAsync(int id) { try { var result = await _repository.DeleteAsync(id); if (!result) { _logger.LogWarning($"User with ID {id} not found for deletion."); } return result; } catch (Exception ex) { _logger.LogError(ex, $"Error deleting User with ID {id}."); throw; } } }}
Steps 8.Controllers(folder)
using DotApi.Models;using DotApi.Service;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.Extensions.Logging;
namespace DotApi.Controllers{ [Route("api/[controller]")] [ApiController] public class UserController : ControllerBase { private readonly UserService _UserService; private readonly ILogger<UserController> _logger;
public UserController(UserService UserService, ILogger<UserController> logger) { _UserService = UserService; _logger = logger; }
[HttpGet] public async Task<IActionResult> GetAllUsers() { try { var Users = await _UserService.GetAllUsersAsync(); return Ok(Users); } catch (Exception ex) { _logger.LogError(ex, "Error retrieving all Users."); return StatusCode(StatusCodes.Status500InternalServerError, "Internal Server Error"); } }
[HttpGet("{id}")] public async Task<IActionResult> GetUser(int id) { try { var User = await _UserService.GetUserAsync(id); if (User == null) { _logger.LogWarning($"User with ID {id} not found."); return NotFound($"User with ID {id} not found."); } return Ok(User); } catch (Exception ex) { _logger.LogError(ex, $"Error retrieving User with ID {id}."); return StatusCode(StatusCodes.Status500InternalServerError, "Internal Server Error"); } }
[HttpPost] public async Task<IActionResult> PostUser(User User) { try { if (User == null || string.IsNullOrEmpty(User.Name)) { return BadRequest("Invalid User data."); }
var newUser = await _UserService.AddUserAsync(User); return CreatedAtAction(nameof(GetUser), new { id = newUser.UserId }, newUser); } catch (Exception ex) { _logger.LogError(ex, "Error adding User."); return StatusCode(StatusCodes.Status500InternalServerError, "Internal Server Error"); } }
[HttpPut] public async Task<IActionResult> PutUser(User User) { try { if (User == null || User.UserId <= 0) { return BadRequest("Invalid User data."); }
var updatedUser = await _UserService.UpdateUserAsync(User); return Ok(updatedUser); } catch (Exception ex) { _logger.LogError(ex, "Error updating User."); return StatusCode(StatusCodes.Status500InternalServerError, "Internal Server Error"); } }
[HttpDelete("{id}")] public async Task<IActionResult> DeleteUser(int id) { try { var result = await _UserService.DeleteUserAsync(id); if (!result) { return NotFound($"User with ID {id} not found for deletion."); } return NoContent(); } catch (Exception ex) { _logger.LogError(ex, $"Error deleting User with ID {id}."); return StatusCode(StatusCodes.Status500InternalServerError, "Internal Server Error"); } } }}===========================================================================================For .NET 8, you don't need to install any of these packages manually for HttpClient or JSON handling. The functionality is built into the framework.
1.appsettings.json
"ApiSettings": { "BaseUrl" : "https://localhost:7140/"}
2. Models (folder dragndrop from api)3.Services (IUserApiService, UserApiService)
4.IUserApiService.csusing DotWeb.Models;
namespace DotWeb.Service.UserService{ public interface IUserApiService { Task<IEnumerable<User>> GetAllUsersAsync(); Task<User> GetUserByIdAsync(int id); Task<User> AddUserAsync(User User); Task<User> UpdateUserAsync(User User); Task<bool> DeleteUserAsync(int id);
}}5.UserService.csusing System.Net.Http;using Newtonsoft.Json;using DotWeb.Models;using System.Text.Json;
namespace DotWeb.Service.UserService{ public class UserApiService { private readonly HttpClient _httpClient; public UserApiService(HttpClient httpClient) { _httpClient = httpClient; }
public async Task<IEnumerable<User>> GetAllUsersAsync() { var response = await _httpClient.GetAsync("api/User"); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
return System.Text.Json.JsonSerializer.Deserialize<IEnumerable<User>>(content, options);
}
public async Task<User> GetUserByIdAsync(int id) { var response = await _httpClient.GetAsync($"api/User/{id}"); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; return System.Text.Json.JsonSerializer.Deserialize<User>(content, options); }
public async Task<User> AddUserAsync(User User) { var response = await _httpClient.PostAsJsonAsync("api/User", User); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; return System.Text.Json.JsonSerializer.Deserialize<User>(content, options); }
public async Task<User> UpdateUserAsync(User User) { var response = await _httpClient.PutAsJsonAsync($"api/User/{User.UserId}", User); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; return System.Text.Json.JsonSerializer.Deserialize<User>(content, options); }
public async Task<bool> DeleteUserAsync(int id) { var response = await _httpClient.DeleteAsync($"api/User/{id}"); return response.IsSuccessStatusCode; }
}}
6.program.csvar apiBaseUrl = builder.Configuration["ApiSettings:BaseUrl"];builder.Services.AddHttpClient<UserApiService>(client =>{ client.BaseAddress = new Uri(apiBaseUrl);});7.Controllers(folder)using System.Linq;using System.Reflection;using DotWeb.Models;using DotWeb.Service.UserService;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Mvc;
namespace DotWeb.Controllers{ public class UserController : Controller { private readonly UserApiService _userService; private readonly IWebHostEnvironment _webHostEnvironment;
public UserController(UserApiService userService, IWebHostEnvironment webHostEnvironment) { _userService = userService; _webHostEnvironment = webHostEnvironment; }
public async Task<IActionResult> Index() { var users = await _userService.GetAllUsersAsync(); return View(users); }
public async Task<IActionResult> Details(int id) { var user = await _userService.GetUserByIdAsync(id); if (user == null) { return NotFound(); } return View(user); }
public IActionResult Create() { var model = new UserViewModel { CountryList = GetCountries(), // Populate countries from your database or an API StateList = new List<string>(), // Empty initially, will be populated based on selected country CityList = new List<string>() // Empty initially, will be populated based on selected state }; return View(model); } [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(UserViewModel user) { try { if (ModelState.IsValid) { // Allowed file extensions var allowedExtensions = new[] { ".jpg", ".jpeg", ".png" };
// Validate file if (user.Photo != null && user.Photo.Length > 0) { var fileExtension = Path.GetExtension(user.Photo.FileName).ToLower();
// Check file extension if (!allowedExtensions.Contains(fileExtension)) { ModelState.AddModelError("", "Only JPG, JPEG, and PNG files are allowed."); return View(user); }
// Check file size (1 KB to 1 MB) if (user.Photo.Length < 1024 || user.Photo.Length > 1048576) { ModelState.AddModelError("", "File size must be between 1 KB and 1 MB."); return View(user); }
// Save the file string fileName = Guid.NewGuid().ToString() + Path.GetExtension(user.Photo.FileName); string folder = Path.Combine(_webHostEnvironment.WebRootPath, "images"); string filePath = Path.Combine(folder, fileName);
// Ensure the directory exists if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); }
using (var stream = new FileStream(filePath, FileMode.Create)) { await user.Photo.CopyToAsync(stream); }
// Create User entity var data = new User() { Name = user.Name, Age = user.Age, Sex = user.Sex, DateOfBirth = user.DateOfBirth, SelfPic = fileName, PasswordHash = user.PasswordHash, Email = user.Email, Mobile = user.Mobile, AadharNumber = user.AadharNumber, PANNumber = user.PANNumber, CurrentAddress = user.CurrentAddress, CorrespondenceAddress = user.CorrespondenceAddress, Country = user.Country, State = user.State, City = user.City, Pincode = user.Pincode }; // Add user to the database await _userService.AddUserAsync(data); TempData["Success"] = "User Added Successfully!"; // Redirect to the index page return RedirectToAction(nameof(Index)); } else { ModelState.AddModelError("", "Profile picture is required."); return View(user); } } user.CountryList = GetCountries(); // Re-populate the countries user.StateList = (List<string>)GetStates(user.Country); // Re-populate the states based on selected country user.CityList = (List<string>)GetCities(user.State); // Re-populate the cities based on selected state
return View(user); } catch (Exception ex) { // Log the exception (if needed) and rethrow or handle appropriately ModelState.AddModelError("", "An error occurred while creating the user. Please try again."); return View(user); } } [HttpGet] public IActionResult GetStates(string countryId) { if (string.IsNullOrEmpty(countryId)) { return Json(new List<string>()); }
var states = GetStatesForCountry(countryId); // Get states based on country return Json(states); // Return as JSON to be processed by the client }
[HttpGet] public IActionResult GetCities(string stateId) { if (string.IsNullOrEmpty(stateId)) { return Json(new List<string>()); }
var cities = GetCitiesForState(stateId); // Get cities based on state return Json(cities); // Return as JSON to be processed by the client }
private List<string> GetCountries() { // Example: Fetch list of countries from database or an API return new List<string> { "India", "USA", "Canada" }; }
private List<string> GetStatesForCountry(string countryId) { // Fetch states based on selected country (from database or API) if (countryId == "India") { return new List<string> { "Delhi", "Maharashtra", "Karnataka" }; } else if (countryId == "USA") { return new List<string> { "California", "Texas", "Florida" }; } else if (countryId == "Canada") { return new List<string> { "Ontario", "Quebec", "British Columbia" }; } return new List<string>(); }
private List<string> GetCitiesForState(string stateId) { // Fetch cities based on selected state (from database or API) if (stateId == "Delhi") { return new List<string> { "New Delhi", "Old Delhi" }; } else if (stateId == "California") { return new List<string> { "Los Angeles", "San Francisco" }; } else if (stateId == "Ontario") { return new List<string> { "Toronto", "Ottawa" }; } return new List<string>(); }
public async Task<IActionResult> Edit(int id) { var user = await _userService.GetUserByIdAsync(id); if (user == null) { return NotFound(); } return View(user); }
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(User user, IFormFile profilePicture) { if (ModelState.IsValid) { // Check if a new profile picture is uploaded if (profilePicture != null && profilePicture.Length > 0) { // Validate file extension var allowedExtensions = new[] { ".jpg", ".jpeg", ".png" }; var fileExtension = Path.GetExtension(profilePicture.FileName).ToLower();
if (!allowedExtensions.Contains(fileExtension)) { ModelState.AddModelError("", "Only JPG, JPEG, and PNG files are allowed."); return View(user); // Return the view with error }
// Validate file size (1 KB to 1 MB) if (profilePicture.Length < 1024 || profilePicture.Length > 1048576) { ModelState.AddModelError("", "File size must be between 1 KB and 1 MB."); return View(user); // Return the view with error }
// Ensure the uploads directory exists var uploadDirectory = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads"); if (!Directory.Exists(uploadDirectory)) { Directory.CreateDirectory(uploadDirectory); }
// Delete the old file if (!string.IsNullOrEmpty(user.SelfPic)) { var oldFilePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", user.SelfPic); if (System.IO.File.Exists(oldFilePath)) { System.IO.File.Delete(oldFilePath); } }
// Save the new profile picture var fileName = Guid.NewGuid().ToString() + fileExtension; var filePath = Path.Combine(uploadDirectory, fileName);
using (var stream = new FileStream(filePath, FileMode.Create)) { await profilePicture.CopyToAsync(stream); }
// Update the user with the new file path user.SelfPic = Path.Combine("uploads", fileName); // Save relative path }
// Update the user details (including the profile picture path if updated) await _userService.UpdateUserAsync(user);
return RedirectToAction(nameof(Index)); // Redirect after successful update }
return View(user); // Return the view with validation errors if ModelState is invalid }
public async Task<IActionResult> Delete(int id) { var user = await _userService.GetUserByIdAsync(id); if (user == null) { return NotFound(); } return View(user); }
[HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(int id) { await _userService.DeleteUserAsync(id); return RedirectToAction(nameof(Index)); } }}
How to Create Crud app using asp.net core Web Api thru Db First approach or reverse engineering
Reviewed by Rikesh
on
December 02, 2024
Rating:
No comments: