Contact Form

Name

Email *

Message *

How Insert Update Delete curd step by Step in Angular 9 with api Asp.net Core EF DB First approach


Step .1
app.module.ts


 import { BrowserModule } from "@angular/platform-browser";  
 import { NgModule } from "@angular/core";  
 import { HttpClientModule } from "@angular/common/http";  
 import { ReactiveFormsModule } from "@angular/forms";  
 import { AppRoutingModule } from "./app-routing.module";  
 import { AppComponent } from "./app.component";  
 import { BlogPostsComponent } from "./Components/blog-posts/blog-posts.component";  
 import { BlogPostComponent } from "./Components/blog-post/blog-post.component";  
 import { BlogPostAddEditComponent } from "./Components/blog-post-add-edit/blog-post-add-edit.component";  
 import { BlogPostService } from "./services/blog-post.service";  
 @NgModule({  
  declarations: [  
   AppComponent,  
   BlogPostsComponent,  
   BlogPostComponent,  
   BlogPostAddEditComponent,  
  ],  
  imports: [  
   BrowserModule,  
   HttpClientModule,  
   AppRoutingModule,  
   ReactiveFormsModule,  
  ],  
  providers: [BlogPostService],  
  bootstrap: [AppComponent],  
 })  
 export class AppModule {}  


app.component.html

 <div class="container">  
  <a [routerLink]="['/']" class="btn btn-danger">Home</a>  
  <router-outlet></router-outlet>  
 </div>  

blog-posts.component.html

 <h1>Blog posts</h1>  
 <p *ngIf="!(blogPosts$ | async)"><em>Loading...</em></p>  
 <p>  
  <a [routerLink]="['/add']" class="btn btn-primary float-right mb-3">New post</a>  
 </p>  
 <table class="table table-sm table-hover" *ngIf="(blogPosts$ | async)?.length>0">  
  <thead>  
   <tr>  
    <th>#</th>  
    <th>Title</th>  
    <th>Creator</th>  
    <th>Date</th>  
    <th></th>  
    <th></th>  
   </tr>  
  </thead>  
  <tbody>  
   <tr *ngFor="let blogPost of (blogPosts$ | async)">  
    <td>{{ blogPost.employeeId }}</td>  
    <td><a [routerLink]="['/blogpost/', blogPost.employeeId]">{{ blogPost.employeeName }}</a></td>  
    <td>{{ blogPost.phoneNumber }}</td>  
    <td>{{ blogPost.skillId }}</td>  
    <td><a [routerLink]="['/blogpost/edit/', blogPost.employeeId]" class="btn btn-primary btn-sm float-right">Edit</a></td>  
    <td><a [routerLink]="" (click)="delete(blogPost.employeeId)" class="btn btn-danger btn-sm float-right">Delete</a></td>  
   </tr>  
  </tbody>  
 </table>  
blog-posts.component.ts
 import { Component, OnInit } from '@angular/core';  
 import { BlogPost } from 'src/app/services/models/BlogPos';  
 import { Observable } from 'rxjs';  
 import { BlogPostService } from 'src/app/services/blog-post.service';  
 @Component({  
  selector: 'app-blog-posts',  
  templateUrl: './blog-posts.component.html',  
  styleUrls: ['./blog-posts.component.css']  
 })  
 export class BlogPostsComponent implements OnInit {  
  blogPosts$: Observable<BlogPost[]>;  
  constructor(private blogPostService: BlogPostService) {  
  }  
  ngOnInit() {  
   this.loadBlogPosts();  
  }  
  loadBlogPosts() {  
   this.blogPosts$ = this.blogPostService.getBlogPosts();  
  }  
  delete(postId) {  
   const ans = confirm('Do you want to delete blog post with id: ' + postId);  
   if (ans) {  
    this.blogPostService.deleteBlogPost(postId).subscribe((data) => {  
     this.loadBlogPosts();  
    });  
   }  
  }  
 }  
blog-post-add-edit.component.html
 <h1>{{actionType}} blog post</h1>  
 <form [formGroup]="form" (ngSubmit)="save()" #formDir="ngForm" novalidate>  
  <div class="form-group row">  
   <label class=" control-label col-md-12">employee Name</label>  
   <div class="col-md-12">  
    <input class="form-control" type="text" formControlName="employeeName">  
   </div>  
   <span class="text-danger ml-3" *ngIf="employeeName.invalid && formDir.submitted">  
    employee Name is required.  
   </span>  
  </div>  
  <div class="form-group row">  
   <label class="control-label col-md-12" for="phoneNumber">phone Number</label>  
   <div class="col-md-12">  
    <textarea class="form-control" rows="15" formControlName="phoneNumber"></textarea>  
   </div>  
   <span class="text-danger ml-3" *ngIf="phoneNumber.invalid && formDir.submitted">  
    phone Number is required.  
   </span>  
  </div>  
  <div class="form-group row">  
   <label class=" control-label col-md-12">skillId</label>  
   <div class="col-md-12">  
    <input class="form-control" type="text" formControlName="skillId">  
   </div>  
   <span class="text-danger ml-3" *ngIf="skillId.invalid && formDir.submitted">  
    skillId is required.  
   </span>  
  </div>  
  <div class="form-group row">  
   <label class=" control-label col-md-12">yearsExperience</label>  
   <div class="col-md-12">  
    <input class="form-control" type="text" formControlName="yearsExperience">  
   </div>  
   <span class="text-danger ml-3" *ngIf="yearsExperience.invalid && formDir.submitted">  
    yearsExperience is required.  
   </span>  
  </div>  
  <div class="form-group">  
   <button type="submit" class="btn btn-success float-right">Save</button>  
   <button class="btn btn-secondary float-left" (click)="cancel()">Cancel</button>  
  </div>  
 </form>  
blog-post-add-edit.component.ts
 import { Component, OnInit } from '@angular/core';  
 import { BlogPost } from 'src/app/services/models/BlogPos';  
 import { FormBuilder, FormGroup, Validators } from '@angular/forms';  
 import { Router, ActivatedRoute } from '@angular/router';  
 import { BlogPostService } from 'src/app/services/blog-post.service';  
 @Component({  
  selector: 'app-blog-post-add-edit',  
  templateUrl: './blog-post-add-edit.component.html',  
  styleUrls: ['./blog-post-add-edit.component.css']  
 })  
 export class BlogPostAddEditComponent implements OnInit {  
   form: FormGroup;  
   actionType: string;  
   formemployeeName: string;  
   formphoneNumber: string;  
   formskillId: string;  
   formyearsExperience: string;  
   employeeId: number;  
   errorMessage: any;  
   existingBlogPost: BlogPost;  
   // tslint:disable-next-line: max-line-length  
   constructor(private blogPostService: BlogPostService, private formBuilder: FormBuilder, private avRoute: ActivatedRoute, private router: Router) {  
    const idParam = 'id';  
    this.actionType = 'Add';  
    this.formemployeeName = 'employeeName';  
    this.formphoneNumber = 'phoneNumber';  
    this.formskillId = 'skillId';  
    this.formyearsExperience = 'yearsExperience';  
    if (this.avRoute.snapshot.params[idParam]) {  
     this.employeeId = this.avRoute.snapshot.params[idParam];  
    }  
    this.form = this.formBuilder.group(  
     {  
      employeeIdemployeeId: 0,  
      employeeName: ['', [Validators.required]],  
      phoneNumber: ['', [Validators.required]],  
      skillId: ['', [Validators.required]],  
      yearsExperience: ['', [Validators.required]]  
     }  
    );  
   }  
   ngOnInit() {  
    if (this.employeeId > 0) {  
     this.actionType = 'Edit';  
     this.blogPostService.getBlogPost(this.employeeId)  
      .subscribe(data => (  
       this.existingBlogPost = data,  
       this.form.controls[this.formemployeeName].setValue(data.employeeName),  
       this.form.controls[this.formphoneNumber].setValue(data.phoneNumber),  
       this.form.controls[this.formskillId].setValue(data.skillId),  
       this.form.controls[this.formyearsExperience].setValue(data.yearsExperience)  
      ));  
    }  
   }  
   save() {  
    if (!this.form.valid) {  
     return;  
    }  
    if (this.actionType === 'Add') {  
     const blogPost: BlogPost = {  
      employeeName: this.form.get(this.formemployeeName).value,  
      phoneNumber: this.form.get(this.formphoneNumber).value,  
      skillId: this.form.get(this.formskillId).value,  
      yearsExperience: this.form.get(this.formyearsExperience).value  
     };  
     this.blogPostService.saveBlogPost(blogPost)  
      .subscribe((data) => {  
       this.router.navigate(['/blogpost', data.employeeId]);  
      });  
    }  
    if (this.actionType === 'Edit') {  
     const blogPost: BlogPost = {  
      employeeId: this.existingBlogPost.employeeId,  
      employeeName: this.form.get(this.formemployeeName).value,  
      phoneNumber: this.form.get(this.formphoneNumber).value,  
      skillId: this.form.get(this.formskillId).value,  
      yearsExperience: this.form.get(this.formyearsExperience).value  
     };  
     this.blogPostService.updateBlogPost(blogPost.employeeId, blogPost)  
      .subscribe((data) => {  
       this.router.navigate([this.router.url]);  
      });  
    }  
   }  
   cancel() {  
    this.router.navigate(['/']);  
   }  
   get employeeName() { return this.form.get(this.formemployeeName); }  
   get phoneNumber() { return this.form.get(this.formphoneNumber); }  
   get skillId() { return this.form.get(this.formskillId); }  
   get yearsExperience() { return this.form.get(this.formyearsExperience); }  
  }  
BlogPos.ts
 export class BlogPost {  
  employeeId?: number;  
  employeeName: string;  
  phoneNumber: string;  
  skillId: number;  
  yearsExperience: number;  
 }  
blog-post.service.ts
 import { Injectable } from '@angular/core';  
 import { HttpClient, HttpHeaders } from '@angular/common/http';  
 import { Observable, throwError } from 'rxjs';  
 import { retry, catchError } from 'rxjs/operators';  
 import { environment } from 'src/environments/environment';  
 import { BlogPost } from './models/BlogPos';  
 @Injectable({  
  providedIn: 'root'  
 })  
 export class BlogPostService {  
  myAppUrl: string;  
  myApiUrl: string;  
  httpOptions = {  
   headers: new HttpHeaders({  
    'Content-Type': 'application/json; charset=utf-8'  
   })  
  };  
  constructor(private http: HttpClient) {  
    this.myAppUrl = environment.appUrl;  
    this.myApiUrl = 'api/TblEmployees/';  
  }  
  getBlogPosts(): Observable<BlogPost[]> {  
   return this.http.get<BlogPost[]>(this.myAppUrl + this.myApiUrl)  
   .pipe(  
    retry(1),  
    catchError(this.errorHandler)  
   );  
  }  
  getBlogPost(postId: number): Observable<BlogPost> {  
    return this.http.get<BlogPost>(this.myAppUrl + this.myApiUrl + postId)  
    .pipe(  
     retry(1),  
     catchError(this.errorHandler)  
    );  
  }  
  saveBlogPost(blogPost): Observable<BlogPost> {  
    return this.http.post<BlogPost>(this.myAppUrl + this.myApiUrl, JSON.stringify(blogPost), this.httpOptions)  
    .pipe(  
     retry(1),  
     catchError(this.errorHandler)  
    );  
  }  
  updateBlogPost(postId: number, blogPost): Observable<BlogPost> {  
    return this.http.put<BlogPost>(this.myAppUrl + this.myApiUrl + postId, JSON.stringify(blogPost), this.httpOptions)  
    .pipe(  
     retry(1),  
     catchError(this.errorHandler)  
    );  
  }  
  deleteBlogPost(postId: number): Observable<BlogPost> {  
    return this.http.delete<BlogPost>(this.myAppUrl + this.myApiUrl + postId)  
    .pipe(  
     retry(1),  
     catchError(this.errorHandler)  
    );  
  }  
  errorHandler(error) {  
   let errorMessage = '';  
   if (error.error instanceof ErrorEvent) {  
    // Get client-side error  
    errorMessage = error.error.message;  
   } else {  
    // Get server-side error  
    errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;  
   }  
   console.log(errorMessage);  
   return throwError(errorMessage);  
  }  
 }  
app-routing.module.ts
 import { NgModule } from '@angular/core';  
 import { Routes, RouterModule } from '@angular/router';  
 import { BlogPostsComponent } from './Components/blog-posts/blog-posts.component';  
 import { BlogPostComponent } from './Components/blog-post/blog-post.component';  
 import { BlogPostAddEditComponent } from './Components/blog-post-add-edit/blog-post-add-edit.component';  
 const routes: Routes = [  
  { path: '', component: BlogPostsComponent, pathMatch: 'full' },  
  { path: 'blogpost/:id', component: BlogPostComponent },  
  { path: 'add', component: BlogPostAddEditComponent },  
  { path: 'blogpost/edit/:id', component: BlogPostAddEditComponent },  
  { path: '**', redirectTo: '/' }  
 ];  
 @NgModule({  
  imports: [RouterModule.forRoot(routes)],  
  exports: [RouterModule]  
 })  
 export class AppRoutingModule { }  


API

Install-Package Microsoft.EntityFrameworkCore.SqlServer

1. Scaffold-DbContext "Server=.;Database=MbkTest;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models


2.  Scaffold-DbContext "Server=.;Database=MbkTest;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables tblSkills -Force

Scaffold-DbContext [-Connection] [-Provider] [-OutputDir] [-Context] [-Schemas>] [-Tables>] 
                    [-DataAnnotations] [-Force] [-Project] [-StartupProject] [<CommonParameters>]

Startup.cs
 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Threading.Tasks;  
 using CurdAPP2.Models;  
 using Microsoft.AspNetCore.Builder;  
 using Microsoft.AspNetCore.Hosting;  
 using Microsoft.AspNetCore.HttpsPolicy;  
 using Microsoft.AspNetCore.Mvc;  
 using Microsoft.EntityFrameworkCore;  
 using Microsoft.Extensions.Configuration;  
 using Microsoft.Extensions.DependencyInjection;  
 using Microsoft.Extensions.Logging;  
 using Microsoft.Extensions.Options;  
 namespace CurdAPP2  
 {  
   public class Startup  
   {  
     public Startup(IConfiguration configuration)  
     {  
       Configuration = configuration;  
     }  
     public IConfiguration Configuration { get; }  
     // This method gets called by the runtime. Use this method to add services to the container.  
     public void ConfigureServices(IServiceCollection services)  
     {  
       services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);  
       services.AddDbContext<MbkTestContext>(options =>  
           options.UseSqlServer(Configuration.GetConnectionString("MbkTestCon")));  
       services.AddCors(options =>  
       {  
         options.AddPolicy("CorsPolicy",  
           builder => builder.AllowAnyOrigin()  
             .AllowAnyMethod()  
             .AllowAnyHeader()  
             .AllowCredentials());  
       });  
     }  
     // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
     public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
     {  
       if (env.IsDevelopment())  
       {  
         app.UseDeveloperExceptionPage();  
       }  
       else  
       {  
         // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.  
         app.UseHsts();  
       }  
        //app.UseMvc();  
       app.UseCors("CorsPolicy");  
       app.UseHttpsRedirection();  
       app.UseStaticFiles();  
       //app.UseSpaStaticFiles();  
       app.UseMvc(routes =>  
       {  
         routes.MapRoute(  
           name: "default",  
           template: "{controller}/{action=Index}/{id?}");  
       });  
     }  
   }  
 }  
appsettings.json
 {  
  "Logging": {  
   "LogLevel": {  
    "Default": "Warning"  
   }  
  },  
  "AllowedHosts": "*",  
  "ConnectionStrings": {  
   "MbkTestCon": "Server=.;Database=MbkTest;Trusted_Connection=True;MultipleActiveResultSets=true"  
  }  
 }  
TblEmployeesController.cs
 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Threading.Tasks;  
 using Microsoft.AspNetCore.Http;  
 using Microsoft.AspNetCore.Mvc;  
 using Microsoft.EntityFrameworkCore;  
 using CurdAPP2.Models;  
 namespace CurdAPP2.Controllers  
 {  
   [Route("api/[controller]")]  
   [ApiController]  
   public class TblEmployeesController : ControllerBase  
   {  
     private readonly MbkTestContext _context;  
     public TblEmployeesController(MbkTestContext context)  
     {  
       _context = context;  
     }  
     // GET: api/TblEmployees  
     [HttpGet]  
     public async Task<ActionResult<IEnumerable<TblEmployees>>> GetTblEmployees()  
     {  
       return await _context.TblEmployees.ToListAsync();  
     }  
     // GET: api/TblEmployees/5  
     [HttpGet("{id}")]  
     public async Task<ActionResult<TblEmployees>> GetTblEmployees(int id)  
     {  
       var tblEmployees = await _context.TblEmployees.FindAsync(id);  
       if (tblEmployees == null)  
       {  
         return NotFound();  
       }  
       return tblEmployees;  
     }  
     // PUT: api/TblEmployees/5  
     [HttpPut("{id}")]  
     public async Task<IActionResult> PutTblEmployees(int id, TblEmployees tblEmployees)  
     {  
       if (id != tblEmployees.EmployeeId)  
       {  
         return BadRequest();  
       }  
       _context.Entry(tblEmployees).State = EntityState.Modified;  
       try  
       {  
         await _context.SaveChangesAsync();  
       }  
       catch (DbUpdateConcurrencyException)  
       {  
         if (!TblEmployeesExists(id))  
         {  
           return NotFound();  
         }  
         else  
         {  
           throw;  
         }  
       }  
       return NoContent();  
     }  
     // POST: api/TblEmployees  
     [HttpPost]  
     public async Task<ActionResult<TblEmployees>> PostTblEmployees(TblEmployees tblEmployees)  
     {  
       _context.TblEmployees.Add(tblEmployees);  
       await _context.SaveChangesAsync();  
       return CreatedAtAction("GetTblEmployees", new { id = tblEmployees.EmployeeId }, tblEmployees);  
     }  
     // DELETE: api/TblEmployees/5  
     [HttpDelete("{id}")]  
     public async Task<ActionResult<TblEmployees>> DeleteTblEmployees(int id)  
     {  
       var tblEmployees = await _context.TblEmployees.FindAsync(id);  
       if (tblEmployees == null)  
       {  
         return NotFound();  
       }  
       _context.TblEmployees.Remove(tblEmployees);  
       await _context.SaveChangesAsync();  
       return tblEmployees;  
     }  
     private bool TblEmployeesExists(int id)  
     {  
       return _context.TblEmployees.Any(e => e.EmployeeId == id);  
     }  
   }  
 }  

 CREATE TABLE [dbo].[tblEmployees](  
      [EmployeeID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,  
      [EmployeeName] [varchar](50) NULL,  
      [PhoneNumber] [varchar](50) NULL,  
      [SkillID] [int] NULL,  
      [YearsExperience] [int] NULL,  
 PRIMARY KEY CLUSTERED   
 (  
      [EmployeeID] ASC  
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
 ) ON [PRIMARY]  
 GO  
 SET ANSI_PADDING OFF  
 GO  
 SET IDENTITY_INSERT [dbo].[tblEmployees] ON   
 INSERT [dbo].[tblEmployees] ([EmployeeID], [EmployeeName], [PhoneNumber], [SkillID], [YearsExperience]) VALUES (1, N'Suhana Kalla', N'9869569634', 2, 11111)  
 INSERT [dbo].[tblEmployees] ([EmployeeID], [EmployeeName], [PhoneNumber], [SkillID], [YearsExperience]) VALUES (2, N'Ashish Kalla', N'9869166077', 8, 14)  
 INSERT [dbo].[tblEmployees] ([EmployeeID], [EmployeeName], [PhoneNumber], [SkillID], [YearsExperience]) VALUES (3, N'Manoj Kalla', N'9869569634', 1, 24)  
 INSERT [dbo].[tblEmployees] ([EmployeeID], [EmployeeName], [PhoneNumber], [SkillID], [YearsExperience]) VALUES (6, N'Murli Vyas', N'9261166012', 5, 18)  
 INSERT [dbo].[tblEmployees] ([EmployeeID], [EmployeeName], [PhoneNumber], [SkillID], [YearsExperience]) VALUES (8, N'wer', N'1', 1, 1)  
 SET IDENTITY_INSERT [dbo].[tblEmployees] OFF  

Configuration React JS ( Installation ) in Windows


Install NodeJS and NPM:
Go to https://nodejs.org/en/
Download latest version of NodeJS LTS with Administrator privileges.
Install Visual Studio Code:
Go to https://code.visualstudio.com/
Downloaded latest version.
Run VS Code.
It should recommend to install Git. Follow instructions to install Git for Windows.
After installation, should be able to get version of git.
Open terminal and type:
COPY
git --version
Followed by:
COPY
node --version
Followed by:
COPY
npm --version
Each should give versions installed on Windows.
Install React from terminal:
COPY
npm install -g create-react-app
If successful, you should be able to get version:
COPY
create-react-app --version
Create react project:
COPY
create-react-app <projectname>
Run project:
COPY
cd <projectname>
npm start
Expected output in terminal (and should auto open browser to port 3000):
COPY
Compiled successfully!

You can now view <project_name> in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://<your_ip_address>:3000/

Note that the development build is not optimized.
To create a production build, use yarn build.


how To block Facebook and youtube on Mikrotik on layer 7

Regular expression  rule at Layer7 Protocols Press + Sign  to add 

^.+(facebook.com|youtube).*$
Create Filter Rule as below steps
1. choose Foward at General tab
2. add Regular expression layer 7 
3. Action Tab  action Drop 
It's working 100% 



How to Create Script port forwarding from local using mikrotik


Just run this Script, to change your IP Scheme  and   interface and Port


/ip firewall nat
add action=dst-nat chain=dstnat disabled=no dst-port=80 in-interface=ether1
 protocol=tcp to-addresses=192.168.1.20 to-ports=80

How to Create Mikrotik Queue Script of all IP

To run this Script ,Just open Mikrotik Router terminal and run

:for x from 1 to 254 do={/queue simple add name="queue-$x" max-limit=1M/1M target="192.168.10.$x"}


 Your can Change download and upload limit and add your ip Scheme

how to WAN combine in Mikrotik

/ip address
add address=192.168.0.1/24 network=192.168.0.0 broadcast=192.168.0.255 interface=Local
add address=192.168.1.2/24 network=192.168.1.0 broadcast=192.168.1.255 interface=WAN1
add address=192.168.2.2/24 network=192.168.2.0 broadcast=192.168.2.255 interface=WAN2

/ip dns set allow-remote-requests=yes cache-max-ttl=1w cache-size=5000KiB max-udp-packet-size=512 servers=8.8.8.8

/ip firewall mangle
add chain=input in-interface=WAN1 action=mark-connection new-connection-mark=WAN1_conn
add chain=input in-interface=WAN2 action=mark-connection new-connection-mark=WAN2_conn

add chain=output connection-mark=WAN1_conn action=mark-routing new-routing-mark=to_WAN1
add chain=output connection-mark=WAN2_conn action=mark-routing new-routing-mark=to_WAN2

add chain=prerouting dst-address=192.168.1.0/24 action=accept in-interface=Local
add chain=prerouting dst-address=192.168.2.0/24 action=accept in-interface=Local

add chain=prerouting dst-address-type=!local in-interface=Local per-connection-classifier=both-addresses-and-ports:2/0 action=mark-connection new-connection-mark=WAN1_conn passthrough=yes
add chain=prerouting dst-address-type=!local in-interface=Local per-connection-classifier=both-addresses-and-ports:2/1 action=mark-connection new-connection-mark=WAN2_conn passthrough=yes

add chain=prerouting connection-mark=WAN1_conn in-interface=Local action=mark-routing new-routing-mark=to_WAN1
add chain=prerouting connection-mark=WAN2_conn in-interface=Local action=mark-routing new-routing-mark=to_WAN2

/ip route
add dst-address=0.0.0.0/0 gateway=192.168.1.1 routing-mark=to_WAN1 check-gateway=ping
add dst-address=0.0.0.0/0 gateway=192.168.2.1 routing-mark=to_WAN2 check-gateway=ping

add dst-address=0.0.0.0/0 gateway=192.168.1.1 distance=1 check-gateway=ping
add dst-address=0.0.0.0/0 gateway=192.168.2.1 distance=2 check-gateway=ping

/ip firewall nat
add chain=srcnat out-interface=WAN1 action=masquerade
add chain=srcnat out-interface=WAN2 action=masquerade

Top Most using tips in daily life Excel and Word tips