0% found this document useful (0 votes)
37 views43 pages

MVC 19nh12

Uploaded by

Đức Minh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
37 views43 pages

MVC 19nh12

Uploaded by

Đức Minh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 43

shorturl.

at/eORSX
10/10/2022
https://angular.io/guide/setup-local
ng --version
ng new dating-app > Yes > CSS
ng serve
ng add @ng-bootstrap/ng-bootstrap
ng generate component navbar
Program.cs
using System.Text;
using DatingApp.API.Data;
using DatingApp.API.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;

var builder = WebApplication.CreateBuilder(args);


var services = builder.Services;
var connectionString = builder.Configuration
.GetConnectionString("Default");
// Add services to the container.

services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddCors(o =>
o.AddPolicy("CorsPolicy", builder =>
builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()));

services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(connectionString));

services.AddScoped<ITokenService, TokenService>();

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["TokenKey"]))
};
});

var app = builder.Build();

// Configure the HTTP request pipeline.


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

app.UseCors("CorsPolicy");

app.UseHttpsRedirection();

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();
app.component.ts
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { AppUser } from './_models/app-user';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
name = 'An Trinh';
users: AppUser[] = [];

constructor(private httpClient: HttpClient) {}

ngOnInit(): void {
this.httpClient.get<AppUser[]>("https://localhost:7219/api/Auth")
.subscribe(
response => this.users = response,
error => console.log(error)
);
}
}

app.component.html
<app-navbar></app-navbar>
<h3 class="text-center">Hello, {{ name }}</h3>
<table class="container table table-striped table-bordered table-hover">
<thead>
<th>Id</th>
<th>Name</th>
<th>Email</th>
</thead>
<tbody>
<tr *ngFor="let user of users">
<td>{{ user.id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
</tr>
</tbody>
</table>

app-user.ts
export class AppUser {
id: number = 0;
username: string = "";
email: string = "";
}

navbar.component.html
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">DATING APP</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
</ul>
<form class="d-flex">
<input
class="form-control me-2"
type="text"
placeholder="Username"
aria-label="Username"
/>
<input
class="form-control me-2"
type="password"
placeholder="Password"
aria-label="Password"
/>
<button class="btn btn-outline-success" type="submit">Login</button>
</form>
</div>
</div>
</nav>
03/10/2022
https://jwt.io
- dotnet add package
Microsoft.AspNetCore.Authentication.JwtBearer
- dotnet add package System.IdentityModel.Tokens.Jwt
Program.cs
using DatingApp.API.Data;
using DatingApp.API.Services;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);


var services = builder.Services;
var connectionString = builder.Configuration
.GetConnectionString("Default");
// Add services to the container.

services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(connectionString));

services.AddScoped<ITokenService, TokenService>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["TokenKey"]))
};
});

var app = builder.Build();

// Configure the HTTP request pipeline.


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

app.UseHttpsRedirection();

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();
app.Run();

TokenService.cs
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

namespace DatingApp.API.Services
{
public class TokenService : ITokenService
{
private readonly IConfiguration _configuration;
public TokenService(IConfiguration configuration)
{
_configuration = configuration;
}

public string CreateToken(string username)


{
var claims = new List<Claim>()
{
new Claim(JwtRegisteredClaimNames.NameId, username),
new Claim(JwtRegisteredClaimNames.Email, $"{username}@dating.app"),
};
var symmetricKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["TokenKey"])
);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = new SigningCredentials(
symmetricKey, SecurityAlgorithms.HmacSha512Signature)
};

var tokenHandler = new JwtSecurityTokenHandler();

var token = tokenHandler.CreateToken(tokenDescriptor);

return tokenHandler.WriteToken(token);
}
}
}

ITokenService.cs
using DatingApp.API.Data.Entities;

namespace DatingApp.API.Services
{
public interface ITokenService
{
string CreateToken(string username);
}
}

appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"TokenKey": "super secret key!",
"ConnectionStrings": {
"Default": "Server=localhost,1433;Database=DatingApp12;User Id=DbEditor;Password=Covid19@@2022;"
}
}

AuthController.cs
using System.Security.Cryptography;
using System.Text;
using DatingApp.API.Data;
using DatingApp.API.Data.Entities;
using DatingApp.API.DTOs;
using DatingApp.API.Services;
using Microsoft.AspNetCore.Mvc;

namespace DatingApp.API.Controllers
{
public class AuthController : BaseController
{
private readonly DataContext _context;
private readonly ITokenService _tokenService;
public AuthController(
DataContext context,
ITokenService tokenService)
{
_context = context;
_tokenService = tokenService;
}

[HttpPost("register")]
public IActionResult Register([FromBody] AuthUserDto authUserDto)
{
authUserDto.Username = authUserDto.Username.ToLower();
if (_context.AppUsers.Any(u => u.Username == authUserDto.Username))
{
return BadRequest("Username is already registered!");
}

using var hmac = new HMACSHA512();


var passwordBytes = Encoding.UTF8.GetBytes(authUserDto.Password);
var newUser = new User
{
Username = authUserDto.Username,
PasswordSalt = hmac.Key,
PasswordHash = hmac.ComputeHash(passwordBytes)
};
_context.AppUsers.Add(newUser);
_context.SaveChanges();
var token = _tokenService.CreateToken(newUser.Username);
return Ok(token);
}

[HttpPost("login")]
public IActionResult Login([FromBody] AuthUserDto authUserDto)
{
authUserDto.Username = authUserDto.Username.ToLower();
var currentUser = _context.AppUsers
.FirstOrDefault(u => u.Username == authUserDto.Username);

if (currentUser == null)
{
return Unauthorized("Username is invalid.");
}
using var hmac = new HMACSHA512(currentUser.PasswordSalt);
var passwordBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(authUserDto.Password));
for (int i = 0; i < currentUser.PasswordHash.Length; i++)
{
if (currentUser.PasswordHash[i] != passwordBytes[i])
{
return Unauthorized("Password is invalid.");
}
}

var token = _tokenService.CreateToken(currentUser.Username);


return Ok(token);
}

[Authorize]
[HttpGet]
public IActionResult Get()
{
return Ok(_context.AppUsers.ToList());
}
}
}
19/09/2022
- dotnet add package Microsoft.EntityFrameworkCore
- dotnet add package
Microsoft.EntityFrameworkCore.Design
- dotnet add package
Microsoft.EntityFrameworkCore.SqlServer
- dotnet add package Pomelo.EntityFrameworkCore.MySql
- dotnet-ef migrations add InitialDb -o Data/Migrations
- dotnet-ef database update
- dotnet-ef migrations add AddPasswordToUser
- dotnet-ef database update
AuthUserDto.cs
using System.ComponentModel.DataAnnotations;

namespace DatingApp.API.DTOs
{
public class AuthUserDto
{
[Required]
[MaxLength(256)]
public string Username { get; set; }

[Required]
[MaxLength(256)]
public string Password { get; set; }
}
}
BaseController.cs
using Microsoft.AspNetCore.Mvc;

namespace DatingApp.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BaseController : ControllerBase
{
}
}

AuthController.cs
using Microsoft.AspNetCore.Mvc;

namespace DatingApp.API.Controllers
{
public class AuthController : BaseController
{
private readonly DataContext _context;
public AuthController(DataContext context)
{
_context = context;
}

public IActionResult Register([FromBody] AuthUserDto authUserDto)


{
authUserDto.Username = authUserDto.Username.ToLower();
if (_context.AppUsers.Any(u => u.Username == authUserDto.Username))
{
return BadRequest("Username is already registered!");
}

using var hmac = new HMACSHA512();


var passwordBytes = Encoding.UTF8.GetBytes(authUserDto.Password);
var newUser = new User
{
Username = authUserDto.Username,
PasswordSalt = hmac.Key,
PasswordHash = hmac.ComputeHash(passwordBytes)
};
_context.AppUsers.Add(newUser);
_context.SaveChanges();
return Ok(newUser.Username);
}

}
}
Program.cs
using DatingApp.API.Data;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);


var services = builder.Services;
var connectionString = builder.Configuration
.GetConnectionString("Default");
// Add services to the container.

services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(connectionString));

var app = builder.Build();

// Configure the HTTP request pipeline.


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

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();
app.Run();

MySQL
// https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql
var serverVersion = new MySqlServerVersion(new Version(8, 0, 29));
// Replace 'YourDbContext' with the name of your own DbContext derived class.
services.AddDbContext<DataContext>(
dbContextOptions => dbContextOptions
.UseMySql(connectionString, serverVersion)
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
);

AppSettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Default": "Server=localhost;Database=DatingApp12;Trusted_Connection=True;"
"Default": "server=localhost;database=DatingApp12;user=user;password=password
}
}
User.cs
using System.ComponentModel.DataAnnotations;

namespace DatingApp.API.Data.Entities
{
public class User
{
[Key]
public int Id { get; set; }

[Required]
[MaxLength(256)]
public string Username { get; set; }

[MaxLength(256)]
public string Email { get; set; }

public byte[] PasswordHash { get; set; }

public byte[] PasswordSalt { get; set; }


}
}
12/09/2022
https://github.com/minhanbkdn/DatingApp/
dotnet new sln -n DatingApp
dotnet new webapi -n DatingApp.API -o
DatingApp.API
dotnet sln add DatingApp.API
code DatingApp.API
29/08/2022
ProductController.cs
using Microsoft.AspNetCore.Mvc;
using ProductManager.Models;
using ProductManager.Services;

namespace ProductManager.Controllers
{
public class ProductController : Controller
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}

public IActionResult Index()


{
var products = _productService.GetProducts();
return View(products);
}

public IActionResult Create()


{
var categories = _productService.GetCategories();
return View(categories);
}

public IActionResult Update(int id)


{
var product = _productService.GetProductById(id);
if (product == null) return RedirectToAction("Create");
ViewBag.Product = product;
var categories = _productService.GetCategories();
return View(categories);
}

public IActionResult Save(Product product)


{
_productService.CreateProduct(product);
return RedirectToAction("Index");
}
}
}
IProductService.cs
using ProductManager.Models;

namespace ProductManager.Services
{
public interface IProductService
{
List<Product> GetProducts();
Product? GetProductById(int id);
void CreateProduct(Product product);
void UpdateProduct(Product product);
void DeleteProduct(int id);
List<Category> GetCategories();
}
}

ProductService.cs
using ProductManager.Models;

namespace ProductManager.Services
{
public class ProductService : IProductService
{
private readonly DataContext _context;
public ProductService(DataContext context)
{
_context = context;
}

public void CreateProduct(Product product)


{
_context.Products.Add(product);
_context.SaveChanges();
}

public void DeleteProduct(int id)


{
var existedProduct = GetProductById(id);
if (existedProduct == null) return;
_context.Products.Remove(existedProduct);
_context.SaveChanges();
}

public Product? GetProductById(int id)


{
return _context.Products.FirstOrDefault(p => p.Id == id);
}

public List<Product> GetProducts()


{
return _context.Products
.Include(x => x.Category)
.ToList();
}

public void UpdateProduct(Product product)


{
var existedProduct = GetProductById(product.Id);
if (existedProduct == null) return;
existedProduct.Name = product.Name;
existedProduct.Slug = product.Slug;
existedProduct.Price = product.Price;
existedProduct.Quantity = product.Quantity;
existedProduct.CategoryId = product.CategoryId;
_context.Update(existedProduct);
_context.SaveChanges();
}

public IActionResult Delete(int id)


{
_productService.DeleteProduct(id);
return RedirectToAction("Index");
}

public List<Category> GetCategories()


{
return _context.Category.ToList();
}
}
}
Create.cshtml
@model List<Category>;
@{
ViewData["Title"] = "Product Create Page";
var categories = Model;
}

<form action="/Product/Save" method="post">


<div class="form-group">
<label for="Name">Name</label>
<input type="text" class="form-control" id="Name" name="Name">
</div>
<div class="form-group">
<label for="Slug">Slug</label>
<input type="text" class="form-control" id="Slug" name="Slug">
</div>
<div class="form-group">
<label for="Price">Price</label>
<input type="number" class="form-control" id="Price" name="Price">
</div>
<div class="form-group">
<label for="Quantity">Quantity</label>
<input type="number" class="form-control" id="Quantity" name="Quantity">
</div>
<div class="form-group">
<label for="CategoryId">Category</label>
<select class="form-control" id="CategoryId" name="CategoryId">
@foreach (var category in categories)
{
<option value="@category.Id">
@category.Name
</option>
}
</select>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>

Update.cshtml
@model List<Category>;
@{
ViewData["Title"] = "Product Create Page";
var categories = Model;
var product = ViewBag.Product;
}

<form action="/Product/Save" method="post">


<div class="form-group">
<label for="Id">Id</label>
<input type="text" class="form-control" id="Id" name="Id" value="@product.Id" readonly>
</div>
<div class="form-group">
<label for="Name">Name</label>
<input type="text" class="form-control" id="Name" name="Name" value="@product.Name">
</div>
<div class="form-group">
<label for="Slug">Slug</label>
<input type="text" class="form-control" id="Slug" name="Slug" value="@product.Slug">
</div>
<div class="form-group">
<label for="Price">Price</label>
<input type="number" class="form-control" id="Price" name="Price" value="@product.Price">
</div>
<div class="form-group">
<label for="Quantity">Quantity</label>
<input type="number" class="form-control" id="Quantity" name="Quantity" value="@product.Quantity">
</div>
<div class="form-group">
<label for="CategoryId">Category</label>
<select class="form-control" id="CategoryId" name="CategoryId">
@foreach (var category in categories)
{
@if (category.Id == product.CategoryId)
{
<option value="@category.Id" selected>
@category.Name
</option>
}
else {
<option value="@category.Id">
@category.Name
</option>
}
}
</select>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>

Index.cshtml
@model List<Product>;
@{
ViewData["Title"] = "Product Page";
var products = Model;
}

<div class="text-center">
<h1 class="display-4">Welcome Product Page</h1>
<table class="table table-striped table-hover">
<thead>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
<th>Category</th>
<th>
<a href="/Product/Create" class="btn btn-primary">Create</a>
</th>
</thead>
<tbody>
@foreach (var product in products)
{
<tr>
<td>@product.Id</td>
<td>@product.Name</td>
<td>@product.Price</td>
<td>@product.Quantity</td>
<td>@product.Category.Name</td>
<td>
<a href="/Product/[email protected]" class="btn btn-success">Update</a>
<a href="/Product/[email protected]" class="btn btn-danger">Delete</a>
</td>
</tr>
}
</tbody>
</table>
</div>
27/08/2022
- Extensions: NuGet Gallery

- dotnet add package Microsoft.EntityFrameworkCore


- dotnet add package
Microsoft.EntityFrameworkCore.Design
- dotnet add package
Microsoft.EntityFrameworkCore.SqlServer
- dotnet add package Pomelo.EntityFrameworkCore.MySql
- dotnet tool install --global dotnet-ef
- dotnet tool update --global dotnet-ef
- Ef-db-context
- asp-add-db-context
"ConnectionStrings": {
"Default":
"Server=localhost;Database=ProductDb12;Trusted_Connection=True;"
}

MySQL:
server=localhost;database=ProductDb12;user=user;password=password

using Microsoft.EntityFrameworkCore;
using ProductManager.Models;

var builder = WebApplication.CreateBuilder(args);


var services = builder.Services;
var connectionString = builder.Configuration.GetConnectionString("Default");

// Add services to the container.


services.AddControllersWithViews();
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(connectionString));

var app = builder.Build();


MySQL
https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql
var serverVersion = new MySqlServerVersion(new Version(8, 0, 29));
// Replace 'YourDbContext' with the name of your own DbContext derived class.
services.AddDbContext<DataContext>(
dbContextOptions => dbContextOptions
.UseMySql(connectionString, serverVersion)
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
);
Product.cs
using System.ComponentModel.DataAnnotations;
namespace ProductManager.Models
{
public class Product
{
[Key]
public int Id { get; set; }

[MaxLength(256)]
public string Name { get; set; }

[MaxLength(256)]
public string Slug { get; set; }

public int Price { get; set; }

public int Quantity { get; set; }


}
}
- dotnet-ef migrations add InitialDb
- dotnet-ef database update
- dotnet-ef migrations add
AddSlugIntoProduct
- dotnet-ef database update
- dotnet-ef migrations add
AddTableCategory
- dotnet-ef database update
Category.cs
namespace ProductManager.Models
{
public class Category
{
public Category()
{
Products = new List<Product>();
}
public int Id { get; set; }

public string Name { get; set; }

public List<Product> Products { get; set; }


}
}

Product.cs
using System.ComponentModel.DataAnnotations;

namespace ProductManager.Models
{
public class Product
{
[Key]
public int Id { get; set; }
[MaxLength(256)]
public string Name { get; set; }
[MaxLength(256)]
public string Slug { get; set; }
public int Price { get; set; }
public int Quantity { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
}

DataContext.cs
using Microsoft.EntityFrameworkCore;

namespace ProductManager.Models
{
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options) { }

public DbSet<Product> Products { get; set; }


public DbSet<Category> Category { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
modelBuilder.Entity<Product>()
.HasOne(p => p.Category)
.WithMany(c => c.Products)
.HasForeignKey(p => p.CategoryId);

base.OnModelCreating(modelBuilder);
}
}
}
ProductController.cs
using Microsoft.AspNetCore.Mvc;
using ProductManager.Models;

namespace ProductManager.Controllers
{
public class ProductController : Controller
{
private readonly DataContext _context;
public ProductController(DataContext context)
{
_context = context;
}

public IActionResult Index()


{
var products = _context.Products.ToList();
return View(products);
}
}
}
IProductService.cs
using ProductManager.Models;

namespace ProductManager.Services
{
public interface IProductService
{
List<Product> GetProducts();
}
}

ProductService.cs
using ProductManager.Models;

namespace ProductManager.Services
{
public class ProductService : IProductService
{
private readonly DataContext _context;
public ProductService(DataContext context)
{
_context = context;
}
public List<Product> GetProducts()
{
return _context.Products.ToList();
}
}
}
ProductController.cs
using Microsoft.AspNetCore.Mvc;
using ProductManager.Services;

namespace ProductManager.Controllers
{
public class ProductController : Controller
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}

public IActionResult Index()


{
var products = _productService.GetProducts();
return View(products);
}
}
}
Program.cs

You might also like