1654244880
MongoDB es una base de datos de documentos con la escalabilidad y flexibilidad que desea con las consultas e indexación que necesita. MongoDB almacena datos en documentos versátiles similares a JSON. Esto significa que los campos variarán de un documento a otro y la estructura de datos se puede cambiar con el tiempo.
MongoDB tiene una documentación excepcionalmente buena. Abra este enlace para explorar más características de MongoDB.
C# Corner también tiene un conjunto de buenos artículos sobre MongoDB. Consulte estos artículos para comenzar con MongoDB.
MongoDB Atlas es una base de datos en la nube totalmente administrada. Atlas maneja toda la complejidad de implementar, administrar y reparar sus implementaciones en el proveedor de servicios en la nube de su elección (Azure, AWS y GCP).
Actualmente, MongoDB Atlas proporciona 512 MB de espacio libre. Ya escribí un artículo para crear un clúster MongoDB gratuito y conectarme con la aplicación MVC. Consulte este artículo .
En esta publicación, veremos todos los pasos para conectar la base de datos MongoDB con la aplicación web .NET 6 y consumir esta API web en una aplicación Angular 13. Usaremos un clúster MongoDB Atlas ya aprovisionado para crear nuestra base de datos.
Podemos abrir Visual Studio 2022 y elegir la plantilla ASP.NET Core Web API. Después de elegir un nombre y un directorio válidos, podemos elegir .NET 6.0 framework.
La nueva aplicación estará lista en unos momentos.
Podemos instalar la biblioteca MongoDB.Driver usando NuGet Package Manager.
Arriba está el controlador oficial MongoDB .NET creado por MongoDB Inc.
Podemos crear una carpeta de "Modelos" y crear una clase de Empleado dentro de esta carpeta.
Empleado.cs
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace MongoDBDotNET6.Models
{
public class Employee
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }
public string Name { get; set; } = null!;
public string Designation { get; set; } = null!;
public string Company { get; set; } = null!;
public string Cityname { get; set; } = null!;
public string Address { get; set; } = null!;
}
}
En la clase anterior, la propiedad Id es:
Podemos crear una clase DatabaseSettings dentro de la carpeta Modelos.
DatabaseSettings.cs
namespace MongoDBDotNET6.Models
{
public class DatabaseSettings
{
public string ConnectionString { get; set; } = null!;
public string DatabaseName { get; set; } = null!;
}
}
La clase anterior se usa para almacenar la conexión de la base de datos y el nombre dentro del archivo appsettings.json. Estas propiedades de conexión se utilizarán para configurar la conexión entre la base de datos MongoDB y la aplicación .NET.
También podemos agregar propiedades de conexión dentro del archivo appsettings.json.
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"DatabaseSettings": {
"ConnectionString": "mongodb+srv://<username>:<password>@sarathlal.8vuub.mongodb.net/?retryWrites=true&w=majority",
"DatabaseName": "EmployeeDB"
}
}
Podemos crear un servicio de empleado dentro de una nueva carpeta "Servicios"
EmployeeService.cs
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using MongoDBDotNET6.Models;
namespace MongoDBDotNET6.Services
{
public class EmployeeService
{
private readonly IMongoCollection<Employee> _employeeCollection;
public EmployeeService(
IOptions<DatabaseSettings> dabaseSettings)
{
var mongoClient = new MongoClient(dabaseSettings.Value.ConnectionString);
var mongoDatabase = mongoClient.GetDatabase(dabaseSettings.Value.DatabaseName);
_employeeCollection = mongoDatabase.GetCollection<Employee>("Employee");
}
public async Task<List<Employee>> GetAsync() =>
await _employeeCollection.Find(_ => true).ToListAsync();
public async Task<Employee?> GetAsync(string id) =>
await _employeeCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
public async Task CreateAsync(Employee newEmployee) =>
await _employeeCollection.InsertOneAsync(newEmployee);
public async Task UpdateAsync(string id, Employee updatedEmployee) =>
await _employeeCollection.ReplaceOneAsync(x => x.Id == id, updatedEmployee);
public async Task RemoveAsync(string id) => await _employeeCollection.DeleteOneAsync(x => x.Id == id);
}
}
En el servicio anterior, hemos implementado todos los métodos para operaciones CRUD con la base de datos MongoDB. Usaremos este servicio dentro de nuestro controlador API pronto.
Podemos cambiar el archivo Program.cs con los cambios de código a continuación.
Programa.cs
using MongoDBDotNET6.Models;
using MongoDBDotNET6.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.Configure<DatabaseSettings>(builder.Configuration.GetSection("DatabaseSettings"));
builder.Services.AddSingleton<EmployeeService>();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var MyAllowedOrigins = "_myAllowedOrigins";
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowedOrigins,
builder =>
{
builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.UseCors(MyAllowedOrigins);
app.Run();
El código anterior se usa para registrar la inyección de dependencia con las propiedades de configuración de la base de datos del archivo appsettings.json. Además, la clase EmployeeService está registrada con DI para admitir la inyección de constructores en las clases de consumo. La vida útil del servicio singleton es más adecuada porque EmployeeService depende directamente de MongoClient.
También hemos agregado el código para habilitar CORS (Cross Origin Resource Sharing).
Podemos crear un controlador API EmployeeController dentro de la carpeta Controladores y agregar el código a continuación.
EmployeeController.cs
using Microsoft.AspNetCore.Mvc;
using MongoDBDotNET6.Models;
using MongoDBDotNET6.Services;
namespace MongoDBDotNET6.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
private readonly EmployeeService _employeeService;
public EmployeeController(EmployeeService employeeService) => _employeeService = employeeService;
[HttpGet]
public async Task<List<Employee>> Get() => await _employeeService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Employee>> Get(string id)
{
var employee = await _employeeService.GetAsync(id);
if (employee is null)
{
return NotFound();
}
return employee;
}
[HttpPost]
public async Task<IActionResult> Post(Employee newEmployee)
{
await _employeeService.CreateAsync(newEmployee);
return NoContent();
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Employee updatedEmployee)
{
var employee = await _employeeService.GetAsync(id);
if (employee is null)
{
return NotFound();
}
updatedEmployee.Id = employee.Id;
await _employeeService.UpdateAsync(id, updatedEmployee);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var employee = await _employeeService.GetAsync(id);
if (employee is null)
{
return NotFound();
}
await _employeeService.RemoveAsync(id);
return NoContent();
}
}
}
Hemos utilizado la clase EmployeeService para implementar operaciones CRUD dentro del controlador API.
El controlador tiene métodos de acción para admitir solicitudes HTTP GET, POST, PUT y DELETE.
Hemos completado la aplicación Web API. Puede usar swagger para probar las operaciones CRUD si es necesario.
Podemos usar los comandos Angular CLI para crear aplicaciones Angular y otros componentes.
ng nuevo MongoDBAngular13
Podemos elegir la opción de enrutamiento como Sí.
Podemos agregar bibliotecas bootstrap y font-awesome al proyecto.
npm install bootstrap font-awesome
Debemos cambiar el archivo "styles.css" en la carpeta raíz con los cambios a continuación para acceder a estos paquetes globalmente en la aplicación sin más referencias.
estilos.css
@import "~bootstrap/dist/css/bootstrap.css";
@import "~font-awesome/css/font-awesome.css";
Cree una variable de entorno dentro de la clase de entorno para baseUrl. Esto se utilizará en toda la aplicación.
medio ambiente.ts
export const environment = {
production: false,
baseUrl: 'http://localhost:5000/'
};
Podemos crear una interfaz de empleado ahora.
ng g clase empleado\empleado
Utilice el siguiente código.
empleado.ts
export interface Employee {
id: string,
name: string,
address: string,
company: string,
designation: string,
cityname: string
}
Ahora podemos crear un servicio para empleados.
ng g servicio empleado\empleado
Utilice el siguiente código.
empleado.servicio.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, throwError, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Employee } from './employee';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class EmployeeService {
private employeesUrl = environment.baseUrl + 'api/employee';
constructor(private http: HttpClient) { }
getEmployees(): Observable<Employee[]> {
return this.http.get<Employee[]>(this.employeesUrl)
.pipe(
catchError(this.handleError)
);
}
getEmployee(id: string | null): Observable<Employee> {
if (id === '') {
return of(this.initializeEmployee());
}
const url = `${this.employeesUrl}/${id}`;
return this.http.get<Employee>(url)
.pipe(
catchError(this.handleError)
);
}
createEmployee(employee: Employee): Observable<Employee> {
employee.id = '';
return this.http.post<Employee>(this.employeesUrl, employee)
.pipe(
catchError(this.handleError)
);
}
deleteEmployee(id: string): Observable<{}> {
const url = `${this.employeesUrl}/${id}`;
return this.http.delete<Employee>(url)
.pipe(
catchError(this.handleError)
);
}
updateEmployee(employee: Employee): Observable<Employee> {
const url = `${this.employeesUrl}/${employee.id}`;
return this.http.put<Employee>(url, employee)
.pipe(
map(() => employee),
catchError(this.handleError)
);
}
private handleError(err: any) {
let errorMessage: string;
if (err.error instanceof ErrorEvent) {
errorMessage = `An error occurred: ${err.error.message}`;
} else {
errorMessage = `Backend returned code ${err.status}: ${err.body.error}`;
}
console.error(err);
return throwError(() => errorMessage);
}
private initializeEmployee(): Employee {
return {
id: "",
name: "",
address: "",
company: "",
designation: "",
cityname: ""
};
}
}
Podemos crear un componente de lista de empleados. Este componente se utilizará para mostrar toda la información de los empleados. Este componente también se utiliza para editar y eliminar datos de empleados.
ng g componente empleado\EmployeeList
Podemos cambiar el archivo de clase con el siguiente código.
lista-de-empleados.component.ts
import { Component, OnInit } from '@angular/core';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
@Component({
selector: 'app-employee-list',
templateUrl: './employee-list.component.html',
styleUrls: ['./employee-list.component.css']
})
export class EmployeeListComponent implements OnInit {
pageTitle = 'Employee List';
filteredEmployees: Employee[] = [];
employees: Employee[] = [];
errorMessage = '';
_listFilter = '';
get listFilter(): string {
return this._listFilter;
}
set listFilter(value: string) {
this._listFilter = value;
this.filteredEmployees = this.listFilter ? this.performFilter(this.listFilter) : this.employees;
}
constructor(private employeeService: EmployeeService) { }
performFilter(filterBy: string): Employee[] {
filterBy = filterBy.toLocaleLowerCase();
return this.employees.filter((employee: Employee) =>
employee.name.toLocaleLowerCase().indexOf(filterBy) !== -1);
}
ngOnInit(): void {
this.getEmployeeData();
}
getEmployeeData() {
this.employeeService.getEmployees()
.subscribe({
next: (employees) => {
this.employees = employees;
this.filteredEmployees = employees;
},
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employees in employee list')
});
}
deleteEmployee(id: string, name: string): void {
if (id === '') {
this.onSaveComplete();
} else {
if (confirm(`Are you sure want to delete this Employee: ${name}?`)) {
this.employeeService.deleteEmployee(id)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Delete employee in employee list')
});
}
}
}
onSaveComplete(): void {
this.employeeService.getEmployees()
.subscribe({
next: (employees) => {
this.employees = employees;
this.filteredEmployees = employees;
},
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employees in employee list')
});
}
}
También podemos cambiar la plantilla y los archivos de estilo.
lista-de-empleados.component.html
<div class="card">
<div class="card-header">
{{pageTitle}}
</div>
<div class="card-body">
<div class="row" style="margin-bottom:15px;">
<div class="col-md-2">Filter by:</div>
<div class="col-md-4">
<input type="text" [(ngModel)]="listFilter" />
</div>
<div class="col-md-2"></div>
<div class="col-md-4">
<button class="btn btn-primary mr-3" [routerLink]="['/employees/0/edit']">
New Employee
</button>
</div>
</div>
<div class="row" *ngIf="listFilter">
<div class="col-md-6">
<h4>Filtered by: {{listFilter}}</h4>
</div>
</div>
<div class="table-responsive">
<table class="table mb-0" *ngIf="employees && employees.length">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Company</th>
<th>Designation</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let employee of filteredEmployees">
<td>
<a [routerLink]="['/employees', employee.id]">
{{ employee.name }}
</a>
</td>
<td>{{ employee.address }}</td>
<td>{{ employee.company }}</td>
<td>{{ employee.designation}} </td>
<td>
<button class="btn btn-outline-primary btn-sm"
[routerLink]="['/employees', employee.id, 'edit']">
Edit
</button>
</td>
<td>
<button class="btn btn-outline-warning btn-sm"
(click)="deleteEmployee(employee.id,employee.name);">
Delete
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div *ngIf="errorMessage" class="alert alert-danger">
Error: {{ errorMessage }}
</div>
lista-de-empleados.componente.css
thead {
color: #337AB7;
}
Podemos crear un componente de edición de empleados con el siguiente comando
ng g componente empleado\EmpleadoEditar
Modifique el archivo de clase con el siguiente código.
empleado-editar.component.ts
import { Component, OnInit, OnDestroy, ElementRef, ViewChildren } from '@angular/core';
import { FormControlName, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
@Component({
selector: 'app-employee-edit',
templateUrl: './employee-edit.component.html',
styleUrls: ['./employee-edit.component.css']
})
export class EmployeeEditComponent implements OnInit, OnDestroy {
@ViewChildren(FormControlName, { read: ElementRef }) formInputElements!: ElementRef[];
pageTitle = 'Employee Edit';
errorMessage!: string;
employeeForm!: FormGroup;
tranMode!: string;
employee!: Employee;
private sub!: Subscription;
displayMessage: { [key: string]: string } = {};
private validationMessages: { [key: string]: { [key: string]: string } };
constructor(private fb: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private employeeService: EmployeeService) {
this.validationMessages = {
name: {
required: 'Employee name is required.',
minlength: 'Employee name must be at least three characters.',
maxlength: 'Employee name cannot exceed 50 characters.'
},
cityname: {
required: 'Employee city name is required.',
}
};
}
ngOnInit() {
this.tranMode = "new";
this.employeeForm = this.fb.group({
name: ['', [Validators.required,
Validators.minLength(3),
Validators.maxLength(50)
]],
address: '',
cityname: ['', [Validators.required]],
company: '',
designation: '',
});
this.sub = this.route.paramMap.subscribe(
params => {
const id = params.get('id');
const cityname = params.get('cityname');
if (id == '0') {
const employee: Employee = { id: "0", name: "", address: "", company: "", designation: "", cityname: "" };
this.displayEmployee(employee);
}
else {
this.getEmployee(id);
}
}
);
}
ngOnDestroy(): void {
this.sub.unsubscribe();
}
getEmployee(id: string | null): void {
this.employeeService.getEmployee(id)
.subscribe({
next: (employee: Employee) => this.displayEmployee(employee),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employee in employee edit')
});
}
displayEmployee(employee: Employee): void {
if (this.employeeForm) {
this.employeeForm.reset();
}
this.employee = employee;
if (this.employee.id == '0') {
this.pageTitle = 'Add Employee';
} else {
this.pageTitle = `Edit Employee: ${this.employee.name}`;
}
this.employeeForm.patchValue({
name: this.employee.name,
address: this.employee.address,
company: this.employee.company,
designation: this.employee.designation,
cityname: this.employee.cityname
});
}
deleteEmployee(): void {
if (this.employee.id == '0') {
this.onSaveComplete();
} else {
if (confirm(`Are you sure want to delete this Employee: ${this.employee.name}?`)) {
this.employeeService.deleteEmployee(this.employee.id)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Delete employee in employee edit')
});
}
}
}
saveEmployee(): void {
if (this.employeeForm.valid) {
if (this.employeeForm.dirty) {
const e = { ...this.employee, ...this.employeeForm.value };
if (e.id === '0') {
this.employeeService.createEmployee(e)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Create employee in employee edit')
});
} else {
this.employeeService.updateEmployee(e)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Update employee in employee edit')
});
}
} else {
this.onSaveComplete();
}
} else {
this.errorMessage = 'Please correct the validation errors.';
}
}
onSaveComplete(): void {
this.employeeForm.reset();
this.router.navigate(['/employees']);
}
}
JavaScript
Copiar
También podemos cambiar el archivo de plantilla.
empleado-editar.component.html
<div class="card">
<div class="card-header">
{{pageTitle}}
</div>
<div class="card-body">
<form novalidate (ngSubmit)="saveEmployee()" [formGroup]="employeeForm">
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="employeeNameId">Employee Name</label>
<div class="col-md-7">
<input class="form-control" id="employeeNameId" type="text" placeholder="Name (required)"
formControlName="name" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="citynameId">City</label>
<div class="col-md-7">
<input class="form-control" id="citynameid" type="text" placeholder="Cityname (required)"
formControlName="cityname" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="addressId">Address</label>
<div class="col-md-7">
<input class="form-control" id="addressId" type="text" placeholder="Address" formControlName="address" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="companyId">Company</label>
<div class="col-md-7">
<input class="form-control" id="companyId" type="text" placeholder="Company" formControlName="company" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="designationId">Designation</label>
<div class="col-md-7">
<input class="form-control" id="designationId" type="text" placeholder="Designation"
formControlName="designation" />
</div>
</div>
<div class="form-group row mb-2">
<div class="offset-md-2 col-md-6">
<button class="btn btn-primary" style="width:80px;margin-right:10px;" type="submit"
[title]="employeeForm.valid ? 'Save your entered data' : 'Disabled until the form data is valid'"
[disabled]="!employeeForm.valid">
Save
</button>
<button class="btn btn-outline-secondary" style="width:80px;margin-right:10px;" type="button"
title="Cancel your edits" [routerLink]="['/employees']">
Cancel
</button>
<button class="btn btn-outline-warning" *ngIf="pageTitle != 'Add Employee'"
style="width:80px;margin-right:10px" type="button" title="Delete this product" (click)="deleteEmployee()">
Delete
</button>
</div>
</div>
</form>
</div>
<div class="alert alert-danger" *ngIf="errorMessage">{{errorMessage}}
</div>
</div>
Necesitamos un componente más para mostrar los detalles del empleado en una ventana separada. Podemos crear ahora.
ng g componente empleado\EmployeeDetail
Podemos cambiar el archivo de clase con el siguiente código.
empleado-detalle.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
@Component({
selector: 'app-employee-detail',
templateUrl: './employee-detail.component.html',
styleUrls: ['./employee-detail.component.css']
})
export class EmployeeDetailComponent implements OnInit {
pageTitle = 'Employee Detail';
errorMessage = '';
employee: Employee | undefined;
constructor(private route: ActivatedRoute,
private router: Router,
private employeeService: EmployeeService) { }
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
if (id) {
this.getEmployee(id);
}
}
getEmployee(id: string) {
this.employeeService.getEmployee(id)
.subscribe({
next: (employee) => this.employee = employee,
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employee in employee details')
});
}
onBack(): void {
this.router.navigate(['/employees']);
}
}
Modifique el archivo de plantilla con el siguiente código.
empleado-detalle.component.html
<div class="card">
<div class="card-header"
*ngIf="employee">
{{pageTitle + ": " + employee.name}}
</div>
<div class="card-body"
*ngIf="employee">
<div class="row">
<div class="col-md-8">
<div class="row">
<div class="col-md-3">Name:</div>
<div class="col-md-6">{{employee.name}}</div>
</div>
<div class="row">
<div class="col-md-3">City:</div>
<div class="col-md-6">{{employee.cityname}}</div>
</div>
<div class="row">
<div class="col-md-3">Address:</div>
<div class="col-md-6">{{employee.address}}</div>
</div>
<div class="row">
<div class="col-md-3">Company:</div>
<div class="col-md-6">{{employee.company}}</div>
</div>
<div class="row">
<div class="col-md-3">Designation:</div>
<div class="col-md-6">{{employee.designation}}</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-4">
<button class="btn btn-outline-secondary mr-3"
style="width:80px;margin-right:10px;"
(click)="onBack()">
<i class="fa fa-chevron-left"></i> Back
</button>
<button class="btn btn-outline-primary"
style="width:80px;margin-right:10px;"
[routerLink]="['/employees', employee.id,'edit']">
Edit
</button>
</div>
</div>
</div>
<div class="alert alert-danger"
*ngIf="errorMessage">
{{errorMessage}}
</div>
</div>
Cree el componente del menú de navegación ahora.
ng g componente NavMenu
Modifique el archivo de clase con el siguiente código.
menú de navegación.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-nav-menu',
templateUrl: './nav-menu.component.html',
styleUrls: ['./nav-menu.component.css']
})
export class NavMenuComponent implements OnInit {
isExpanded = false;
ngOnInit() {
}
collapse() {
this.isExpanded = false;
}
toggle() {
this.isExpanded = !this.isExpanded;
}
}
Podemos cambiar el archivo de plantilla con el siguiente código.
menú-nav.component.html
<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" [routerLink]='["/"]'>Employee App</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse"
aria-label="Toggle navigation" [attr.aria-expanded]="isExpanded" (click)="toggle()">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse" [ngClass]='{"show": isExpanded}'>
<ul class="navbar-nav flex-grow">
<li class="nav-item" [routerLinkActive]='["link-active"]' [routerLinkActiveOptions]='{ exact: true }'>
<a class="nav-link text-dark" [routerLink]='["/"]'>Home</a>
</li>
<li class="nav-item" [routerLinkActive]='["link-active"]'>
<a class="nav-link text-dark" [routerLink]='["/employees"]'>Employees</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<footer>
<nav class="navbar navbar-light bg-white mt-5 fixed-bottom">
<div class="navbar-expand m-auto navbar-text">
Developed with <i class="fa fa-heart"></i> by <b>Sarathlal
Saseendran</b>
</div>
</nav>
</footer>
También podemos cambiar el archivo de hoja de estilo con el siguiente código.
menú-nav.component.css
html {
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
.fa-heart {
color: hotpink;
}
Cree el componente final Inicio ahora.
ng g componente casa
No hay cambio de código para el archivo de clase. Podemos cambiar el archivo de plantilla html con el siguiente código.
inicio.componente.html
<div style="text-align:center;">
<h3>Web Application with MongoDB, .NET 6, and Angular 13</h3>
<p>Welcome to our new single-page Employee application, built with below technologies:</p>
<img src="../../assets/MongoDB DotnetCore Angular1.png" width="700px">
</div>
Debemos agregar una referencia para los siguientes módulos en la clase app.module.
aplicación.módulo.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { EmployeeListComponent } from './employee/employee-list/employee-list.component';
import { EmployeeEditComponent } from './employee/employee-edit/employee-edit.component';
import { EmployeeDetailComponent } from './employee/employee-detail/employee-detail.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component';
@NgModule({
declarations: [
AppComponent,
EmployeeListComponent,
EmployeeEditComponent,
EmployeeDetailComponent,
NavMenuComponent,
HomeComponent
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
También debemos agregar los valores de ruta a continuación en la clase app-routing.module.
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { EmployeeDetailComponent } from './employee/employee-detail/employee-detail.component';
import { EmployeeEditComponent } from './employee/employee-edit/employee-edit.component';
import { EmployeeListComponent } from './employee/employee-list/employee-list.component';
import { HomeComponent } from './home/home.component';
const routes: Routes = [
{ path: '', component: HomeComponent, pathMatch: 'full' },
{
path: 'employees',
component: EmployeeListComponent
},
{
path: 'employees/:id',
component: EmployeeDetailComponent
},
{
path: 'employees/:id/edit',
component: EmployeeEditComponent
},
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Podemos cambiar app.component.html con el siguiente código.
aplicación.componente.html
<body>
<app-nav-menu></app-nav-menu>
<div class="container">
<router-outlet></router-outlet>
</div>
</body>
Hemos completado el código Angular. Podemos ejecutar Web API y Angular ahora.
Haga clic en el menú Empleados y agregue un nuevo registro de empleado.
Los empleados agregados aparecerán en formato de cuadrícula en la pantalla.
Puede hacer clic en el nombre del empleado y mostrar los detalles en una pantalla separada.
Tenemos funciones de edición y eliminación de datos de empleados disponibles en la aplicación.
También tenemos disponible el filtro de nombre del empleado en la cuadrícula.
En esta publicación, hemos visto cómo conectar la base de datos MongoDB en ASP.NET 6 Web API y consumir los puntos finales de API en una aplicación Angular 13. Hemos creado todas las operaciones CRUD y vemos cómo funciona. Hemos aprovisionado un clúster MongoDB Atlas gratuito y hemos creado una base de datos en él. Por favor, siéntase libre de dar sus valiosos comentarios sobre esta publicación.
Esta historia se publicó originalmente en https://www.c-sharpcorner.com/article/easily-create-web-app-with-mongodb-net-6-and-angular-13/
1654244880
MongoDB es una base de datos de documentos con la escalabilidad y flexibilidad que desea con las consultas e indexación que necesita. MongoDB almacena datos en documentos versátiles similares a JSON. Esto significa que los campos variarán de un documento a otro y la estructura de datos se puede cambiar con el tiempo.
MongoDB tiene una documentación excepcionalmente buena. Abra este enlace para explorar más características de MongoDB.
C# Corner también tiene un conjunto de buenos artículos sobre MongoDB. Consulte estos artículos para comenzar con MongoDB.
MongoDB Atlas es una base de datos en la nube totalmente administrada. Atlas maneja toda la complejidad de implementar, administrar y reparar sus implementaciones en el proveedor de servicios en la nube de su elección (Azure, AWS y GCP).
Actualmente, MongoDB Atlas proporciona 512 MB de espacio libre. Ya escribí un artículo para crear un clúster MongoDB gratuito y conectarme con la aplicación MVC. Consulte este artículo .
En esta publicación, veremos todos los pasos para conectar la base de datos MongoDB con la aplicación web .NET 6 y consumir esta API web en una aplicación Angular 13. Usaremos un clúster MongoDB Atlas ya aprovisionado para crear nuestra base de datos.
Podemos abrir Visual Studio 2022 y elegir la plantilla ASP.NET Core Web API. Después de elegir un nombre y un directorio válidos, podemos elegir .NET 6.0 framework.
La nueva aplicación estará lista en unos momentos.
Podemos instalar la biblioteca MongoDB.Driver usando NuGet Package Manager.
Arriba está el controlador oficial MongoDB .NET creado por MongoDB Inc.
Podemos crear una carpeta de "Modelos" y crear una clase de Empleado dentro de esta carpeta.
Empleado.cs
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace MongoDBDotNET6.Models
{
public class Employee
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }
public string Name { get; set; } = null!;
public string Designation { get; set; } = null!;
public string Company { get; set; } = null!;
public string Cityname { get; set; } = null!;
public string Address { get; set; } = null!;
}
}
En la clase anterior, la propiedad Id es:
Podemos crear una clase DatabaseSettings dentro de la carpeta Modelos.
DatabaseSettings.cs
namespace MongoDBDotNET6.Models
{
public class DatabaseSettings
{
public string ConnectionString { get; set; } = null!;
public string DatabaseName { get; set; } = null!;
}
}
La clase anterior se usa para almacenar la conexión de la base de datos y el nombre dentro del archivo appsettings.json. Estas propiedades de conexión se utilizarán para configurar la conexión entre la base de datos MongoDB y la aplicación .NET.
También podemos agregar propiedades de conexión dentro del archivo appsettings.json.
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"DatabaseSettings": {
"ConnectionString": "mongodb+srv://<username>:<password>@sarathlal.8vuub.mongodb.net/?retryWrites=true&w=majority",
"DatabaseName": "EmployeeDB"
}
}
Podemos crear un servicio de empleado dentro de una nueva carpeta "Servicios"
EmployeeService.cs
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using MongoDBDotNET6.Models;
namespace MongoDBDotNET6.Services
{
public class EmployeeService
{
private readonly IMongoCollection<Employee> _employeeCollection;
public EmployeeService(
IOptions<DatabaseSettings> dabaseSettings)
{
var mongoClient = new MongoClient(dabaseSettings.Value.ConnectionString);
var mongoDatabase = mongoClient.GetDatabase(dabaseSettings.Value.DatabaseName);
_employeeCollection = mongoDatabase.GetCollection<Employee>("Employee");
}
public async Task<List<Employee>> GetAsync() =>
await _employeeCollection.Find(_ => true).ToListAsync();
public async Task<Employee?> GetAsync(string id) =>
await _employeeCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
public async Task CreateAsync(Employee newEmployee) =>
await _employeeCollection.InsertOneAsync(newEmployee);
public async Task UpdateAsync(string id, Employee updatedEmployee) =>
await _employeeCollection.ReplaceOneAsync(x => x.Id == id, updatedEmployee);
public async Task RemoveAsync(string id) => await _employeeCollection.DeleteOneAsync(x => x.Id == id);
}
}
En el servicio anterior, hemos implementado todos los métodos para operaciones CRUD con la base de datos MongoDB. Usaremos este servicio dentro de nuestro controlador API pronto.
Podemos cambiar el archivo Program.cs con los cambios de código a continuación.
Programa.cs
using MongoDBDotNET6.Models;
using MongoDBDotNET6.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.Configure<DatabaseSettings>(builder.Configuration.GetSection("DatabaseSettings"));
builder.Services.AddSingleton<EmployeeService>();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var MyAllowedOrigins = "_myAllowedOrigins";
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowedOrigins,
builder =>
{
builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.UseCors(MyAllowedOrigins);
app.Run();
El código anterior se usa para registrar la inyección de dependencia con las propiedades de configuración de la base de datos del archivo appsettings.json. Además, la clase EmployeeService está registrada con DI para admitir la inyección de constructores en las clases de consumo. La vida útil del servicio singleton es más adecuada porque EmployeeService depende directamente de MongoClient.
También hemos agregado el código para habilitar CORS (Cross Origin Resource Sharing).
Podemos crear un controlador API EmployeeController dentro de la carpeta Controladores y agregar el código a continuación.
EmployeeController.cs
using Microsoft.AspNetCore.Mvc;
using MongoDBDotNET6.Models;
using MongoDBDotNET6.Services;
namespace MongoDBDotNET6.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
private readonly EmployeeService _employeeService;
public EmployeeController(EmployeeService employeeService) => _employeeService = employeeService;
[HttpGet]
public async Task<List<Employee>> Get() => await _employeeService.GetAsync();
[HttpGet("{id:length(24)}")]
public async Task<ActionResult<Employee>> Get(string id)
{
var employee = await _employeeService.GetAsync(id);
if (employee is null)
{
return NotFound();
}
return employee;
}
[HttpPost]
public async Task<IActionResult> Post(Employee newEmployee)
{
await _employeeService.CreateAsync(newEmployee);
return NoContent();
}
[HttpPut("{id:length(24)}")]
public async Task<IActionResult> Update(string id, Employee updatedEmployee)
{
var employee = await _employeeService.GetAsync(id);
if (employee is null)
{
return NotFound();
}
updatedEmployee.Id = employee.Id;
await _employeeService.UpdateAsync(id, updatedEmployee);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> Delete(string id)
{
var employee = await _employeeService.GetAsync(id);
if (employee is null)
{
return NotFound();
}
await _employeeService.RemoveAsync(id);
return NoContent();
}
}
}
Hemos utilizado la clase EmployeeService para implementar operaciones CRUD dentro del controlador API.
El controlador tiene métodos de acción para admitir solicitudes HTTP GET, POST, PUT y DELETE.
Hemos completado la aplicación Web API. Puede usar swagger para probar las operaciones CRUD si es necesario.
Podemos usar los comandos Angular CLI para crear aplicaciones Angular y otros componentes.
ng nuevo MongoDBAngular13
Podemos elegir la opción de enrutamiento como Sí.
Podemos agregar bibliotecas bootstrap y font-awesome al proyecto.
npm install bootstrap font-awesome
Debemos cambiar el archivo "styles.css" en la carpeta raíz con los cambios a continuación para acceder a estos paquetes globalmente en la aplicación sin más referencias.
estilos.css
@import "~bootstrap/dist/css/bootstrap.css";
@import "~font-awesome/css/font-awesome.css";
Cree una variable de entorno dentro de la clase de entorno para baseUrl. Esto se utilizará en toda la aplicación.
medio ambiente.ts
export const environment = {
production: false,
baseUrl: 'http://localhost:5000/'
};
Podemos crear una interfaz de empleado ahora.
ng g clase empleado\empleado
Utilice el siguiente código.
empleado.ts
export interface Employee {
id: string,
name: string,
address: string,
company: string,
designation: string,
cityname: string
}
Ahora podemos crear un servicio para empleados.
ng g servicio empleado\empleado
Utilice el siguiente código.
empleado.servicio.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, throwError, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Employee } from './employee';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class EmployeeService {
private employeesUrl = environment.baseUrl + 'api/employee';
constructor(private http: HttpClient) { }
getEmployees(): Observable<Employee[]> {
return this.http.get<Employee[]>(this.employeesUrl)
.pipe(
catchError(this.handleError)
);
}
getEmployee(id: string | null): Observable<Employee> {
if (id === '') {
return of(this.initializeEmployee());
}
const url = `${this.employeesUrl}/${id}`;
return this.http.get<Employee>(url)
.pipe(
catchError(this.handleError)
);
}
createEmployee(employee: Employee): Observable<Employee> {
employee.id = '';
return this.http.post<Employee>(this.employeesUrl, employee)
.pipe(
catchError(this.handleError)
);
}
deleteEmployee(id: string): Observable<{}> {
const url = `${this.employeesUrl}/${id}`;
return this.http.delete<Employee>(url)
.pipe(
catchError(this.handleError)
);
}
updateEmployee(employee: Employee): Observable<Employee> {
const url = `${this.employeesUrl}/${employee.id}`;
return this.http.put<Employee>(url, employee)
.pipe(
map(() => employee),
catchError(this.handleError)
);
}
private handleError(err: any) {
let errorMessage: string;
if (err.error instanceof ErrorEvent) {
errorMessage = `An error occurred: ${err.error.message}`;
} else {
errorMessage = `Backend returned code ${err.status}: ${err.body.error}`;
}
console.error(err);
return throwError(() => errorMessage);
}
private initializeEmployee(): Employee {
return {
id: "",
name: "",
address: "",
company: "",
designation: "",
cityname: ""
};
}
}
Podemos crear un componente de lista de empleados. Este componente se utilizará para mostrar toda la información de los empleados. Este componente también se utiliza para editar y eliminar datos de empleados.
ng g componente empleado\EmployeeList
Podemos cambiar el archivo de clase con el siguiente código.
lista-de-empleados.component.ts
import { Component, OnInit } from '@angular/core';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
@Component({
selector: 'app-employee-list',
templateUrl: './employee-list.component.html',
styleUrls: ['./employee-list.component.css']
})
export class EmployeeListComponent implements OnInit {
pageTitle = 'Employee List';
filteredEmployees: Employee[] = [];
employees: Employee[] = [];
errorMessage = '';
_listFilter = '';
get listFilter(): string {
return this._listFilter;
}
set listFilter(value: string) {
this._listFilter = value;
this.filteredEmployees = this.listFilter ? this.performFilter(this.listFilter) : this.employees;
}
constructor(private employeeService: EmployeeService) { }
performFilter(filterBy: string): Employee[] {
filterBy = filterBy.toLocaleLowerCase();
return this.employees.filter((employee: Employee) =>
employee.name.toLocaleLowerCase().indexOf(filterBy) !== -1);
}
ngOnInit(): void {
this.getEmployeeData();
}
getEmployeeData() {
this.employeeService.getEmployees()
.subscribe({
next: (employees) => {
this.employees = employees;
this.filteredEmployees = employees;
},
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employees in employee list')
});
}
deleteEmployee(id: string, name: string): void {
if (id === '') {
this.onSaveComplete();
} else {
if (confirm(`Are you sure want to delete this Employee: ${name}?`)) {
this.employeeService.deleteEmployee(id)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Delete employee in employee list')
});
}
}
}
onSaveComplete(): void {
this.employeeService.getEmployees()
.subscribe({
next: (employees) => {
this.employees = employees;
this.filteredEmployees = employees;
},
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employees in employee list')
});
}
}
También podemos cambiar la plantilla y los archivos de estilo.
lista-de-empleados.component.html
<div class="card">
<div class="card-header">
{{pageTitle}}
</div>
<div class="card-body">
<div class="row" style="margin-bottom:15px;">
<div class="col-md-2">Filter by:</div>
<div class="col-md-4">
<input type="text" [(ngModel)]="listFilter" />
</div>
<div class="col-md-2"></div>
<div class="col-md-4">
<button class="btn btn-primary mr-3" [routerLink]="['/employees/0/edit']">
New Employee
</button>
</div>
</div>
<div class="row" *ngIf="listFilter">
<div class="col-md-6">
<h4>Filtered by: {{listFilter}}</h4>
</div>
</div>
<div class="table-responsive">
<table class="table mb-0" *ngIf="employees && employees.length">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Company</th>
<th>Designation</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let employee of filteredEmployees">
<td>
<a [routerLink]="['/employees', employee.id]">
{{ employee.name }}
</a>
</td>
<td>{{ employee.address }}</td>
<td>{{ employee.company }}</td>
<td>{{ employee.designation}} </td>
<td>
<button class="btn btn-outline-primary btn-sm"
[routerLink]="['/employees', employee.id, 'edit']">
Edit
</button>
</td>
<td>
<button class="btn btn-outline-warning btn-sm"
(click)="deleteEmployee(employee.id,employee.name);">
Delete
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div *ngIf="errorMessage" class="alert alert-danger">
Error: {{ errorMessage }}
</div>
lista-de-empleados.componente.css
thead {
color: #337AB7;
}
Podemos crear un componente de edición de empleados con el siguiente comando
ng g componente empleado\EmpleadoEditar
Modifique el archivo de clase con el siguiente código.
empleado-editar.component.ts
import { Component, OnInit, OnDestroy, ElementRef, ViewChildren } from '@angular/core';
import { FormControlName, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
@Component({
selector: 'app-employee-edit',
templateUrl: './employee-edit.component.html',
styleUrls: ['./employee-edit.component.css']
})
export class EmployeeEditComponent implements OnInit, OnDestroy {
@ViewChildren(FormControlName, { read: ElementRef }) formInputElements!: ElementRef[];
pageTitle = 'Employee Edit';
errorMessage!: string;
employeeForm!: FormGroup;
tranMode!: string;
employee!: Employee;
private sub!: Subscription;
displayMessage: { [key: string]: string } = {};
private validationMessages: { [key: string]: { [key: string]: string } };
constructor(private fb: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private employeeService: EmployeeService) {
this.validationMessages = {
name: {
required: 'Employee name is required.',
minlength: 'Employee name must be at least three characters.',
maxlength: 'Employee name cannot exceed 50 characters.'
},
cityname: {
required: 'Employee city name is required.',
}
};
}
ngOnInit() {
this.tranMode = "new";
this.employeeForm = this.fb.group({
name: ['', [Validators.required,
Validators.minLength(3),
Validators.maxLength(50)
]],
address: '',
cityname: ['', [Validators.required]],
company: '',
designation: '',
});
this.sub = this.route.paramMap.subscribe(
params => {
const id = params.get('id');
const cityname = params.get('cityname');
if (id == '0') {
const employee: Employee = { id: "0", name: "", address: "", company: "", designation: "", cityname: "" };
this.displayEmployee(employee);
}
else {
this.getEmployee(id);
}
}
);
}
ngOnDestroy(): void {
this.sub.unsubscribe();
}
getEmployee(id: string | null): void {
this.employeeService.getEmployee(id)
.subscribe({
next: (employee: Employee) => this.displayEmployee(employee),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employee in employee edit')
});
}
displayEmployee(employee: Employee): void {
if (this.employeeForm) {
this.employeeForm.reset();
}
this.employee = employee;
if (this.employee.id == '0') {
this.pageTitle = 'Add Employee';
} else {
this.pageTitle = `Edit Employee: ${this.employee.name}`;
}
this.employeeForm.patchValue({
name: this.employee.name,
address: this.employee.address,
company: this.employee.company,
designation: this.employee.designation,
cityname: this.employee.cityname
});
}
deleteEmployee(): void {
if (this.employee.id == '0') {
this.onSaveComplete();
} else {
if (confirm(`Are you sure want to delete this Employee: ${this.employee.name}?`)) {
this.employeeService.deleteEmployee(this.employee.id)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Delete employee in employee edit')
});
}
}
}
saveEmployee(): void {
if (this.employeeForm.valid) {
if (this.employeeForm.dirty) {
const e = { ...this.employee, ...this.employeeForm.value };
if (e.id === '0') {
this.employeeService.createEmployee(e)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Create employee in employee edit')
});
} else {
this.employeeService.updateEmployee(e)
.subscribe({
next: () => this.onSaveComplete(),
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Update employee in employee edit')
});
}
} else {
this.onSaveComplete();
}
} else {
this.errorMessage = 'Please correct the validation errors.';
}
}
onSaveComplete(): void {
this.employeeForm.reset();
this.router.navigate(['/employees']);
}
}
JavaScript
Copiar
También podemos cambiar el archivo de plantilla.
empleado-editar.component.html
<div class="card">
<div class="card-header">
{{pageTitle}}
</div>
<div class="card-body">
<form novalidate (ngSubmit)="saveEmployee()" [formGroup]="employeeForm">
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="employeeNameId">Employee Name</label>
<div class="col-md-7">
<input class="form-control" id="employeeNameId" type="text" placeholder="Name (required)"
formControlName="name" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="citynameId">City</label>
<div class="col-md-7">
<input class="form-control" id="citynameid" type="text" placeholder="Cityname (required)"
formControlName="cityname" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="addressId">Address</label>
<div class="col-md-7">
<input class="form-control" id="addressId" type="text" placeholder="Address" formControlName="address" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="companyId">Company</label>
<div class="col-md-7">
<input class="form-control" id="companyId" type="text" placeholder="Company" formControlName="company" />
</div>
</div>
<div class="form-group row mb-2">
<label class="col-md-3 col-form-label" for="designationId">Designation</label>
<div class="col-md-7">
<input class="form-control" id="designationId" type="text" placeholder="Designation"
formControlName="designation" />
</div>
</div>
<div class="form-group row mb-2">
<div class="offset-md-2 col-md-6">
<button class="btn btn-primary" style="width:80px;margin-right:10px;" type="submit"
[title]="employeeForm.valid ? 'Save your entered data' : 'Disabled until the form data is valid'"
[disabled]="!employeeForm.valid">
Save
</button>
<button class="btn btn-outline-secondary" style="width:80px;margin-right:10px;" type="button"
title="Cancel your edits" [routerLink]="['/employees']">
Cancel
</button>
<button class="btn btn-outline-warning" *ngIf="pageTitle != 'Add Employee'"
style="width:80px;margin-right:10px" type="button" title="Delete this product" (click)="deleteEmployee()">
Delete
</button>
</div>
</div>
</form>
</div>
<div class="alert alert-danger" *ngIf="errorMessage">{{errorMessage}}
</div>
</div>
Necesitamos un componente más para mostrar los detalles del empleado en una ventana separada. Podemos crear ahora.
ng g componente empleado\EmployeeDetail
Podemos cambiar el archivo de clase con el siguiente código.
empleado-detalle.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Employee } from '../employee';
import { EmployeeService } from '../employee.service';
@Component({
selector: 'app-employee-detail',
templateUrl: './employee-detail.component.html',
styleUrls: ['./employee-detail.component.css']
})
export class EmployeeDetailComponent implements OnInit {
pageTitle = 'Employee Detail';
errorMessage = '';
employee: Employee | undefined;
constructor(private route: ActivatedRoute,
private router: Router,
private employeeService: EmployeeService) { }
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
if (id) {
this.getEmployee(id);
}
}
getEmployee(id: string) {
this.employeeService.getEmployee(id)
.subscribe({
next: (employee) => this.employee = employee,
error: (err) => this.errorMessage = <any>err,
complete: () => console.info('Get employee in employee details')
});
}
onBack(): void {
this.router.navigate(['/employees']);
}
}
Modifique el archivo de plantilla con el siguiente código.
empleado-detalle.component.html
<div class="card">
<div class="card-header"
*ngIf="employee">
{{pageTitle + ": " + employee.name}}
</div>
<div class="card-body"
*ngIf="employee">
<div class="row">
<div class="col-md-8">
<div class="row">
<div class="col-md-3">Name:</div>
<div class="col-md-6">{{employee.name}}</div>
</div>
<div class="row">
<div class="col-md-3">City:</div>
<div class="col-md-6">{{employee.cityname}}</div>
</div>
<div class="row">
<div class="col-md-3">Address:</div>
<div class="col-md-6">{{employee.address}}</div>
</div>
<div class="row">
<div class="col-md-3">Company:</div>
<div class="col-md-6">{{employee.company}}</div>
</div>
<div class="row">
<div class="col-md-3">Designation:</div>
<div class="col-md-6">{{employee.designation}}</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-4">
<button class="btn btn-outline-secondary mr-3"
style="width:80px;margin-right:10px;"
(click)="onBack()">
<i class="fa fa-chevron-left"></i> Back
</button>
<button class="btn btn-outline-primary"
style="width:80px;margin-right:10px;"
[routerLink]="['/employees', employee.id,'edit']">
Edit
</button>
</div>
</div>
</div>
<div class="alert alert-danger"
*ngIf="errorMessage">
{{errorMessage}}
</div>
</div>
Cree el componente del menú de navegación ahora.
ng g componente NavMenu
Modifique el archivo de clase con el siguiente código.
menú de navegación.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-nav-menu',
templateUrl: './nav-menu.component.html',
styleUrls: ['./nav-menu.component.css']
})
export class NavMenuComponent implements OnInit {
isExpanded = false;
ngOnInit() {
}
collapse() {
this.isExpanded = false;
}
toggle() {
this.isExpanded = !this.isExpanded;
}
}
Podemos cambiar el archivo de plantilla con el siguiente código.
menú-nav.component.html
<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" [routerLink]='["/"]'>Employee App</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse"
aria-label="Toggle navigation" [attr.aria-expanded]="isExpanded" (click)="toggle()">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse" [ngClass]='{"show": isExpanded}'>
<ul class="navbar-nav flex-grow">
<li class="nav-item" [routerLinkActive]='["link-active"]' [routerLinkActiveOptions]='{ exact: true }'>
<a class="nav-link text-dark" [routerLink]='["/"]'>Home</a>
</li>
<li class="nav-item" [routerLinkActive]='["link-active"]'>
<a class="nav-link text-dark" [routerLink]='["/employees"]'>Employees</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<footer>
<nav class="navbar navbar-light bg-white mt-5 fixed-bottom">
<div class="navbar-expand m-auto navbar-text">
Developed with <i class="fa fa-heart"></i> by <b>Sarathlal
Saseendran</b>
</div>
</nav>
</footer>
También podemos cambiar el archivo de hoja de estilo con el siguiente código.
menú-nav.component.css
html {
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
.fa-heart {
color: hotpink;
}
Cree el componente final Inicio ahora.
ng g componente casa
No hay cambio de código para el archivo de clase. Podemos cambiar el archivo de plantilla html con el siguiente código.
inicio.componente.html
<div style="text-align:center;">
<h3>Web Application with MongoDB, .NET 6, and Angular 13</h3>
<p>Welcome to our new single-page Employee application, built with below technologies:</p>
<img src="../../assets/MongoDB DotnetCore Angular1.png" width="700px">
</div>
Debemos agregar una referencia para los siguientes módulos en la clase app.module.
aplicación.módulo.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { EmployeeListComponent } from './employee/employee-list/employee-list.component';
import { EmployeeEditComponent } from './employee/employee-edit/employee-edit.component';
import { EmployeeDetailComponent } from './employee/employee-detail/employee-detail.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component';
@NgModule({
declarations: [
AppComponent,
EmployeeListComponent,
EmployeeEditComponent,
EmployeeDetailComponent,
NavMenuComponent,
HomeComponent
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
También debemos agregar los valores de ruta a continuación en la clase app-routing.module.
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { EmployeeDetailComponent } from './employee/employee-detail/employee-detail.component';
import { EmployeeEditComponent } from './employee/employee-edit/employee-edit.component';
import { EmployeeListComponent } from './employee/employee-list/employee-list.component';
import { HomeComponent } from './home/home.component';
const routes: Routes = [
{ path: '', component: HomeComponent, pathMatch: 'full' },
{
path: 'employees',
component: EmployeeListComponent
},
{
path: 'employees/:id',
component: EmployeeDetailComponent
},
{
path: 'employees/:id/edit',
component: EmployeeEditComponent
},
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Podemos cambiar app.component.html con el siguiente código.
aplicación.componente.html
<body>
<app-nav-menu></app-nav-menu>
<div class="container">
<router-outlet></router-outlet>
</div>
</body>
Hemos completado el código Angular. Podemos ejecutar Web API y Angular ahora.
Haga clic en el menú Empleados y agregue un nuevo registro de empleado.
Los empleados agregados aparecerán en formato de cuadrícula en la pantalla.
Puede hacer clic en el nombre del empleado y mostrar los detalles en una pantalla separada.
Tenemos funciones de edición y eliminación de datos de empleados disponibles en la aplicación.
También tenemos disponible el filtro de nombre del empleado en la cuadrícula.
En esta publicación, hemos visto cómo conectar la base de datos MongoDB en ASP.NET 6 Web API y consumir los puntos finales de API en una aplicación Angular 13. Hemos creado todas las operaciones CRUD y vemos cómo funciona. Hemos aprovisionado un clúster MongoDB Atlas gratuito y hemos creado una base de datos en él. Por favor, siéntase libre de dar sus valiosos comentarios sobre esta publicación.
Esta historia se publicó originalmente en https://www.c-sharpcorner.com/article/easily-create-web-app-with-mongodb-net-6-and-angular-13/
1621426329
AppClues Infotech is one of the leading Enterprise Angular Web Apps Development Company in USA. Our dedicated & highly experienced Angular app developers build top-grade Angular apps for your business with immersive technology & superior functionalities.
For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910
#top enterprise angular web apps development company in usa #enterprise angular web apps development #hire enterprise angular web apps developers #best enterprise angular web app services #custom enterprise angular web apps solution #professional enterprise angular web apps developers
1602560783
In this article, we’ll discuss how to use jQuery Ajax for ASP.NET Core MVC CRUD Operations using Bootstrap Modal. With jQuery Ajax, we can make HTTP request to controller action methods without reloading the entire page, like a single page application.
To demonstrate CRUD operations – insert, update, delete and retrieve, the project will be dealing with details of a normal bank transaction. GitHub repository for this demo project : https://bit.ly/33KTJAu.
Sub-topics discussed :
In Visual Studio 2019, Go to File > New > Project (Ctrl + Shift + N).
From new project window, Select Asp.Net Core Web Application_._
Once you provide the project name and location. Select Web Application(Model-View-Controller) and uncheck HTTPS Configuration. Above steps will create a brand new ASP.NET Core MVC project.
Let’s create a database for this application using Entity Framework Core. For that we’ve to install corresponding NuGet Packages. Right click on project from solution explorer, select Manage NuGet Packages_,_ From browse tab, install following 3 packages.
Now let’s define DB model class file – /Models/TransactionModel.cs.
public class TransactionModel
{
[Key]
public int TransactionId { get; set; }
[Column(TypeName ="nvarchar(12)")]
[DisplayName("Account Number")]
[Required(ErrorMessage ="This Field is required.")]
[MaxLength(12,ErrorMessage ="Maximum 12 characters only")]
public string AccountNumber { get; set; }
[Column(TypeName ="nvarchar(100)")]
[DisplayName("Beneficiary Name")]
[Required(ErrorMessage = "This Field is required.")]
public string BeneficiaryName { get; set; }
[Column(TypeName ="nvarchar(100)")]
[DisplayName("Bank Name")]
[Required(ErrorMessage = "This Field is required.")]
public string BankName { get; set; }
[Column(TypeName ="nvarchar(11)")]
[DisplayName("SWIFT Code")]
[Required(ErrorMessage = "This Field is required.")]
[MaxLength(11)]
public string SWIFTCode { get; set; }
[DisplayName("Amount")]
[Required(ErrorMessage = "This Field is required.")]
public int Amount { get; set; }
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime Date { get; set; }
}
C#Copy
Here we’ve defined model properties for the transaction with proper validation. Now let’s define DbContextclass for EF Core.
#asp.net core article #asp.net core #add loading spinner in asp.net core #asp.net core crud without reloading #asp.net core jquery ajax form #asp.net core modal dialog #asp.net core mvc crud using jquery ajax #asp.net core mvc with jquery and ajax #asp.net core popup window #bootstrap modal popup in asp.net core mvc. bootstrap modal popup in asp.net core #delete and viewall in asp.net core #jquery ajax - insert #jquery ajax form post #modal popup dialog in asp.net core #no direct access action method #update #validation in modal popup
1595344320
Corona Virus Pandemic has brought the world to a standstill.
Countries are on a major lockdown. Schools, colleges, theatres, gym, clubs, and all other public places are shut down, the country’s economy is suffering, human health is on stake, people are losing their jobs and nobody knows how worse it can get.
Since most of the places are on lockdown, and you are working from home or have enough time to nourish your skills, then you should use this time wisely! We always complain that we want some ‘time’ to learn and upgrade our knowledge but don’t get it due to our ‘busy schedules’. So, now is the time to make a ‘list of skills’ and learn and upgrade your skills at home!
And for the technology-loving people like us, Knoldus Techhub has already helped us a lot in doing it in a short span of time!
If you are still not aware of it, don’t worry as Georgia Byng has well said,
“No time is better than the present”
– Georgia Byng, a British children’s writer, illustrator, actress and film producer.
No matter if you are a developer (be it front-end or back-end) or a data scientist, tester, or a DevOps person, or, a learner who has a keen interest in technology, Knoldus Techhub has brought it all for you under one common roof.
From technologies like Scala, spark, elastic-search to angular, go, machine learning, it has a total of 20 technologies with some recently added ones i.e. DAML, test automation, snowflake, and ionic.
Every technology in Tech-hub has n number of templates. Once you click on any specific technology you’ll be able to see all the templates of that technology. Since these templates are downloadable, you need to provide your email to get the template downloadable link in your mail.
These templates helps you learn the practical implementation of a topic with so much of ease. Using these templates you can learn and kick-start your development in no time.
Apart from your learning, there are some out of the box templates, that can help provide the solution to your business problem that has all the basic dependencies/ implementations already plugged in. Tech hub names these templates as xlr8rs (pronounced as accelerators).
xlr8rs make your development real fast by just adding your core business logic to the template.
If you are looking for a template that’s not available, you can also request a template may be for learning or requesting for a solution to your business problem and tech-hub will connect with you to provide you the solution. Isn’t this helpful 🙂
To keep you updated, the Knoldus tech hub provides you with the information on the most trending technology and the most downloaded templates at present. This you’ll be informed and learn the one that’s most trending.
Since we believe:
“There’s always a scope of improvement“
If you still feel like it isn’t helping you in learning and development, you can provide your feedback in the feedback section in the bottom right corner of the website.
#ai #akka #akka-http #akka-streams #amazon ec2 #angular 6 #angular 9 #angular material #apache flink #apache kafka #apache spark #api testing #artificial intelligence #aws #aws services #big data and fast data #blockchain #css #daml #devops #elasticsearch #flink #functional programming #future #grpc #html #hybrid application development #ionic framework #java #java11 #kubernetes #lagom #microservices #ml # ai and data engineering #mlflow #mlops #mobile development #mongodb #non-blocking #nosql #play #play 2.4.x #play framework #python #react #reactive application #reactive architecture #reactive programming #rust #scala #scalatest #slick #software #spark #spring boot #sql #streaming #tech blogs #testing #user interface (ui) #web #web application #web designing #angular #coronavirus #daml #development #devops #elasticsearch #golang #ionic #java #kafka #knoldus #lagom #learn #machine learning #ml #pandemic #play framework #scala #skills #snowflake #spark streaming #techhub #technology #test automation #time management #upgrade
1608388622
#mongodb tutorial #mongodb tutorial for beginners #mongodb database #mongodb with c# #mongodb with asp.net core #mongodb