Thursday, May 14, 2020

How to ignore property conditionally during JSON serialization

Consider i have class Employer, i want serialize this class to json string and need ignore some properties conditionally. For ex: in my example, i want to include address1 and address2 only if it has valid values


  public class Employer
    {
 public int id { get; set; }

        public string name { get; set; }
       
 public string ssn { get; set; }

        public string address1 { get; set; }

        public string address2 { getset; }
   }



Declare some values


Employer employer = new Employer(){ … address1 = "some value", address2 = null };


Now serialize it for json string


var jsonstring = JsonConvert.SerializeObject(employer,
                       Newtonsoft.Json.Formatting.None,
                       new JsonSerializerSettings
                       {
                           
                       });

Here you will get all the properties.

Now lets see how to ignore the properties conditionally, you can choose either one of these options.

Option 1: Use ShouldSerialize property inside class itself like below. But you need add individual shouldSerialize property for each class property.

  public class Employer
    {
 public int id { get; set; }

        public string name { get; set; }
       
 public string ssn { get; set; }

        public string address1 { get; set; }

        public string address2 { get; set; }

        public bool ShouldSerializeaddress1()
        {
            // don't serialize if it is null or empty or add any your custom conditions
            return !string.IsNullOrEmpty(address1);
        }
        public bool ShouldSerializeaddress2()
        {
            // don't serialize if it is null or empty or add any your custom conditions
            return !string.IsNullOrEmpty(address2);
        }

   }


Option 2: Instead creating multiple ShouldSerialize property inside class, we can create ContractResolver and add it in Json serialization as below,

Create Resolver Class,

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Linq;
using System.Reflection;
...

  public class EmployerShouldSerializeContractResolver : DefaultContractResolver
    {
        public new static readonly EmployerShouldSerializeContractResolver Instance = new EmployerShouldSerializeContractResolver();

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);

            if (property.DeclaringType == typeof(Employer))
            {
                property.ShouldSerialize =
                    instance =>
                    {
                        //ignore default values
                        return instance.GetType().GetProperty(member.Name).GetValue(instance, null) != property.DefaultValue;
                    };
            }

            return property;
        }

    }


Include it in JSON serialization,

var jsonstring = JsonConvert.SerializeObject(employer,
                       Newtonsoft.Json.Formatting.None,
                       new JsonSerializerSettings
                       {
                           ContractResolver = new EmployerShouldSerializeContractResolver()
                       });


Friday, April 24, 2020

Angular CLI - Custom Date validator

Angular supports of custom validators. Here i have created custom validator to validate date for template drive forms.

Directive: date-validator.directive.ts


import { AbstractControl, ValidatorFn, FormControl } from '@angular/forms';
import * as moment from 'moment';
import { NG_VALIDATORS, Validator } from '@angular/forms';
import { Directive } from '@angular/core';

// validation function
function validateDateFactory(): ValidatorFn {
  return (c: AbstractControl) => {

    let isValid = moment(c.value, 'M/D/YYYY', true).isValid();

    if (isValid) {
      return null;
    } else {
      return {
        validDate: {
          valid: false
        }
      };
    }
  }
}

@Directive({
  selector: '[validDate][ngModel]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: ValidDateValidator, multi: true }
  ]
})
export class ValidDateValidator implements Validator {
  validator: ValidatorFn;

  constructor() {
    this.validator = validateDateFactory();
  }

  validate(c: FormControl) {
    return this.validator(c);
  }

}


Html:
<input type="text" [(ngModel)]="someDateModal" validDate />

Monday, August 19, 2019

Angular CLI - How to cache Http Service calls simply using rxjs

To cache simply in Angular 7 CLI, here used rxjs on HttpClient.

To cache entire country list, we can use as follows,


import { map, catchError, shareReplay } from 'rxjs/operators';
import { throwError, Observable } from 'rxjs';

private countryCache$ = Observable<any>;
  getCountryList() {
    if (!this.countryCache$) {
      this.countryCache$ =
        this.http.get('/api/country/getCountryList')
          .pipe(
            map(response => {
              return response;
            }),
            catchError((error, caught) => {
              return throwError(error);
            }),
            shareReplay(1)
          );

    }
    return this.countryCache$;
  }



To cache object by it's parameter we can use as follows,in this example cached country information by it's name.

private countryInfoCache$ = new Map<string, Observable<any>>();
getCountryInfo(countryName: string) {

    if (!this.countryInfoCache$.get(countryName)) {

      let countryInfoCacheResult =
        this.http.get('/api/country/getCountryInfoByName',
          { 'countryName': countryName })
          .pipe(
            map(response => {
              return response;
            }),
            catchError((error, caught) => {
              return throwError(error);
            }),
            shareReplay(1)
          );

      this.countryInfoCache$.set(countryName, countryInfoCacheResult);
    }
    return this.countryInfoCache$.get(countryName);

  }

Wednesday, August 7, 2019

Angular CLI - How to use async and await

In Angular Cli, we can use async and await to perform service calls to wait for the promise. Usually we do call first service and then in subscribe method we do perform other logics. But now we can use toPromise method with asyn/await to perform the same as below,

Existing approach:


saveMethod(){
this.someService.getFirstResult().subscribe((data) ={
//second service depend on first service data
this.someService.getSecondResult(data.id).subscribe((data2) => {
        //Do perform your business logics here..
});
});
}


Aysnc/Await approach:

async saveMethod(){
let data = await this.someService.getFirstResult().toPromise();
//second service depend on first service data
let data2 = await this.someService.getSecondResult(data.id).toPromise();
//Do perform your business logics here..
}


Monday, July 29, 2019

Angular CLI - Handle Error Globally

To handle error globally in Angular 7 Cli, follow below steps

Ref: https://angular.io/api/core/ErrorHandler

Steps:

- Create ErrorHanlder file as below


import { Injectable, ErrorHandler } from '@angular/core';

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
  constructor(private ngZone: NgZone) {
  }

  handleError(error) {
    this.ngZone.run(() => {
//use ngZone to attach context to Angular's zone
//custom logic to do anything, for ex: toastService can be injected and shown here
    });

    //log as error to console
    console.error(error);
  }
}



-  Inject GlobalErrorHandler into app.module.ts providers as below


import { NgModule, ErrorHandler } from '@angular/core';
import { GlobalErrorHandler } from './core/config/error.handler';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
  ],
  providers: [
    …,
    { provide: ErrorHandler, useClass: GlobalErrorHandler },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }


-  Now throw error from anywhere, it will be catched in GlobalErrorHanlder

import { catchError, map } from 'rxjs/operators';

import { Observable, of, throwError } from 'rxjs';
….

getUser(): Observable<User> {
      return this.http.get(this.getUserUrl      )
        .pipe(
        map(response => { return <User>response; }),
        catchError((error, caught) => {
          //handled error globally
          return throwError(error);
        }));

    }

Monday, April 22, 2019

C# - Pdf rotate using iTextSharp

In C#, with opensource iTextSharp can be find in nuget package, we can easily rotate each pdf pages and save as new file, use below code

using iTextSharp.text;
using iTextSharp.text.pdf;

using System.IO;


namespace PdfRotate
{
    class Program
    {
        static void Main(string[] args)
        {
            //INFO: Change input and ouput path here
            string pdfFilePath = @"C:\Files\sample.pdf";
            string outputPath = @" C:\Files\sampleoutput.pdf ";

            //INFO: Change rotate degree here to 90, 180 etc
            RotatePages(pdfFilePath, outputPath, 180);           
        }

        private static void RotatePages(string pdfFilePath, string outputPath, int rotateDegree)
        {
            PdfReader reader = new PdfReader(pdfFilePath);
            int pagesCount = reader.NumberOfPages;

            for (int n = 1; n <= pagesCount; n++)
            {
                PdfDictionary page = reader.GetPageN(n);
                PdfNumber rotate = page.GetAsNumber(PdfName.ROTATE);
                int rotation =
                        rotate == null ? rotateDegree : (rotate.IntValue + rotateDegree) % 360;

                page.Put(PdfName.ROTATE, new PdfNumber(rotation));
            }

            PdfStamper stamper = new PdfStamper(reader, new FileStream(outputPath, FileMode.Create));
            stamper.Close();
            reader.Close();
        }
    }
}