Monday, March 27, 2017

EF Database Mapper

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Dummy.Model
{
    [Table("Items")]
    public class Item
    {
        [Key]
        public int Id { get; set; }
        [Required]
        [StringLength(50)]
        public string Name { get; set; }
        [Required]
        public decimal Price { get; set; }
        [StringLength(500)]
        public string Description { get; set; }
        [Required]
        [StringLength(500)]
        public string Address { get; set; }

        public int CategoryId { get; set; }

        [ForeignKey("CategoryId")]
        public virtual Category Categories { get; set; }

        public virtual ICollection<OrderItem> OrderItems { get; set; }

        public Item()
        {
            OrderItems = new HashSet<OrderItem>();
        }
    }

    [Table("Categories")]
    public class Category
    {
        [Key]
        public int CategoryId { get; set; }
        [StringLength(50)]
        public string Name { get; set; }
        [StringLength(500)]
        public string Description { get; set; }
        public virtual ICollection<Item> Items { get; set; }

        public Category()
        {
            Items = new HashSet<Item>();
        }
    }
    [Table("OrderItems")]
    public class OrderItem
    {

        [Key]
        public int OrderItemId { get; set; }
        public int OrdersId { get; set; }
        public int ItemsId { get; set; }

        public int Quantity { get; set; }
        public decimal Price { get; set; }
        [ForeignKey("OrdersId")]
        public virtual Order Orders { get; set; }
        [ForeignKey("ItemsId")]
        public virtual Item Items { get; set; }

        public OrderItem()
        {
            Orders = new Order();
            Items = new Item();
        }
    }

    [Table("Orders")]
    public class Order
    {
        [Key]
        public int OrderId { get; set; }
        public DateTime Time { get; set; }

        public int CustomerId { get; set; }

        public virtual ICollection<OrderItem> OrderItems { get; set; }
        [ForeignKey("CustomerId")]
        public virtual Customer Customer { get; set; }

        public Order()
        {
            OrderItems = new HashSet<OrderItem>();
            Customer = new Customer();
        }
    }
    [Table("Customers")]
    public class Customer
    {
        [Key]
        public int CustomerId { get; set; }
        [Required]
        [StringLength(50)]
        public string Name { get; set; }

        public DateTime DOB { get; set; }
        public virtual ICollection<Order> Orders { get; set; }

        public virtual CustomerContacts CustomerContacts { get; set; }
        public Customer()
        {
            Orders = new HashSet<Order>();
        }
    }

    [Table("CustomerContacts")]
    public class CustomerContacts
    {

        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CustomerId { get; set; }
        [Required]
        [StringLength(50)]
        public string Phone { get; set; }
        [Required]
        [EmailAddress]
        [StringLength(50)]
        public string Email { get; set; }

        [Required]
        [StringLength(500)]
        public string Address { get; set; }

        [ForeignKey("CustomerId")]
        public virtual Customer Customers { get; set; }

        public CustomerContacts()
        {
        }
    }
}


///////////////
using Dummy.Model;
using System.Data.Entity;
namespace Dummy
{
    public class PlutoContext : DbContext
    {
        public PlutoContext() : base(@"Data Source=DELL\SQLEXPRESS;Initial Catalog=Dummey;Integrated Security=True")
        { }
        public DbSet<Item> Items { get; set; }
        public DbSet<Category> Categories { get; set; }
        public DbSet<OrderItem> OrderItems { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<CustomerContacts> CustomerContacts { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Customer>().
            HasOptional(e => e.CustomerContacts)
                    .WithRequired(e => e.Customers);
        }
    }
}

Thursday, March 16, 2017

Javascript designing patterns


module Test.Caller {
 
    var app = (() => {
        var apiCalles = {
            getItems: () => {
                return $.ajax({
                    url: 'http://localhost:58261/api/some/getValues',
                    contentType: 'application/json',
                });
            }
        }
        function listItems(e) {
            alert($(e.target).attr('id'));
            apiCalles.getItems().done((e) => {
                console.log();
            }).fail((e) => {
                console.error(e);
            });
        }
        function initControles() {
            $('#btn').off('click').on('click', listItems.bind(this));
        }
        var validation = {
            form1: () => { },
            form2: () => { }
        };
        return {
            init: () => { initControles(); }
        }
    })();
 
    $(document).ready(app.init);
}

//////////////////////////////////////////////////////////////////

var app2 = {
 
    bindEvents() {
        $('#btn').off('click').on('click', this.toggleTime.bind(this));
    },
    toggleTime(e) {
        alert($(e.target).attr('id'));
    }, init() {
        var $self = app2;
        $self.bindEvents();
    },
}
$(document).ready(app2.init);

Wednesday, February 22, 2017

Best Practices


01) use jquary class for module wise

example :-
                             
                      module Ecart.User.ViewInfo{
                             var m =  (()=>{
                                 var apiCalls ={
                                        get(e):{
                                             return $.ajax({});
                                        },
                                       insert(e):{
                                         return $.ajax({});
                                      }
                                },
                                function get(e?){
                                    if(!validateForm()){return;}
                                    apiCalls.get(e).done((r)=>{console.log(r);}).fail((r)=>{alert('failed');});
                                }
                               function insert(e?){
                                   if(!validateForm()){return;}
                                   apiCalls.insert(e).done((r)=>{console.log(r);}).fail((r)=>{alert('fail');});
                               }

                             function validateForm(){
                                    return true;
                             }
                                  return{
                                        int:()=>{
                                             // int controlls for this module.
                                            // call crud functions.
                                             $('#btnClick').on('click',this,insert);
                                        },
                                       
                                 }
                            });

                       $(document).ready(m.init);
                 }

02) Think Web api method as Noun. not as the verb.

      public class StudentController:ApiController{
           
          [HttpGet]
          [Route("Students")]
          public IHttpResponse Get(){}

          [HttpGet]
          [Route("Students/{id}")]
          public IHttpResponse Get(int id){}

          [HttpPost]
          [Route("Student}s")]
          public IHttpResponse Post(Student obj){}

          [HttpDelete]
          [Route("Students/{id}")]
          public IHttpResponse Post(int id){}

          [HttpPut]
          [Route("Students")]
          public IHttpResponse Put(Student object){}
  
     }
        
in that case use plural except singular for identity routing 

03) User Automapper to Domain transfer to Different Domain.


using X.App_Start
public class AutomapperConfig(){
     public void Register(){
       // register mapping
    }
}

// call to mapping from Globle.ascx
public class Globle{
  
     public void Application_Start(){
       // call to registration
       new AutomapperConfig().Register();
    }
}


04) Always return IHttpResponse type from Api method

          public IHttpResult Get(){
              try{
                   if(!Validate()){
                       return BadRequest('error list converted to json');
                    }
                    else{ 
                       return Ok<T>(result); 
                     }
                    }catch(Exception e){
                return Content<Exception>(HttpStatusCode.InternalServerError,e);
              }
         }

05) Be Always Asyncronas 

          public async Task <IHttpResult> Insert(T object){
                 await c.Insert(T); 
                 return Ok();
         }


06) Always do Server side validation.


     public static bool IsModelValied(object x, out List<string> e)
        {
            ValidationContext context = new ValidationContext(x, null, null);
            IList<ValidationResult> errors = new List<ValidationResult>();
            var ex = new List<string>();
            bool isValied = true;
            if (!Validator.TryValidateObject(x, context, errors, true))
            {
                isValied = false;
                foreach (ValidationResult result in errors)
                {
                    ex.Add(result.ErrorMessage);
                }
            }
            e = ex;
            return isValied;
        }
              

   public Task<IHttpResponse> Insert(T obj){

         var err = new List<string>();
          if(!IsModelValied(T,out err)){
             return BadRequest(JSON.Stringify(err));
           }
         return Ok();
    }

07) Use Dependency injection 

Controller 

public class StudentService:ApiController{

      StudentDbService service;
      public A(UnitOfWork _uow){
          serice = new StudentDbServive(_uow);
      }

}

08) Use Lamda Expression what you need

public void Insert(){

     var lst = new List<T>();
     Action<string> come = (e)=>{ lst.Add(e); };

     Predicate<string> =passwordLength= (e)=>{ return e.length > 10; }
    
     Func<string,string>  some2 = (e) =>{ return e.string();}
}


09) use Unit of work.


public interface IUnitOfWork
   {
       GenericRepository<Student> StudentRepository { get; }
       GenericRepository<Subject> SubjectRepository { get; }
       GenericRepository<StudentSubject> StudentSubjectRepository { get; }
       GenericRepository<UserAuthontication> UserAuthonticationRepository { get; }
       void Save();
       Task SaveAsync();
       DbContext Context { get; }
 
   }
   public class UnitOfWork : IUnitOfWorkIDisposable
   {
       public UnitOfWork(IContext cnt, Enums.ERunType type)
       {
           if (type == Enums.ERunType.Debug)
           {
               context = (SchoolContext)cnt;
               context.Configuration.AutoDetectChangesEnabled=false;
           }
           else
           {
               context = (MockDbContext)cnt;
           }
       }
       private DbContext context;
       private GenericRepository<Student> studentRepository;
       public DbContext Context
       {
           get
           {
               return context;
           }
       }
       public GenericRepository<Student> StudentRepository
       {
           get
           {
 
               if (this.studentRepository == null)
               {
                   this.studentRepository = new GenericRepository<Student>(context);
               }
               return studentRepository;
           }
       }
public void Save()
        {
            context.SaveChanges();
        }
        public async Task SaveAsync()
        {
            await context.SaveChangesAsync();
        }
        private bool disposed = false;
 
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }
 
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }


10) Use Genaric repository


public class GenericRepository<TEntitywhere TEntity : class
  {
      internal DbContext context;
      internal DbSet<TEntity> dbSet;
 
      public GenericRepository(DbContext context)
      {
          this.context = context;
          this.dbSet = context.Set<TEntity>();
      }
 
      public virtual IEnumerable<TEntity> Get(
          Expression<Func<TEntitybool>> filter = null,
          Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
          string includeProperties = "")
      {
          IQueryable<TEntity> query = dbSet;
 
          if (filter != null)
          {
              query = query.Where(filter);
          }
 
          foreach (var includeProperty in includeProperties.Split
              (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
          {
              query = query.Include(includeProperty);
          }
 
          if (orderBy != null)
          {
              return orderBy(query).ToList();
          }
          else
          {
              return query.ToList();
          }
      }
 
      public virtual TEntity GetByID(object id)
      {
          return dbSet.Find(id);
      }
 
      public virtual void Insert(TEntity entity)
      {
          dbSet.Add(entity);
      }
 
      public virtual void Delete(object id)
      {
          TEntity entityToDelete = dbSet.Find(id);
          if (entityToDelete!= null)
          {
              Delete(entityToDelete);
          }
      }
 
      public virtual void Delete(TEntity entityToDelete)
      {
          if (context.Entry(entityToDelete).State == EntityState.Detached)
          {
              dbSet.Attach(entityToDelete);
          }
          dbSet.Remove(entityToDelete);
      }
 
      public virtual void Update(TEntity entityToUpdate)
      {
          dbSet.AddOrUpdate(entityToUpdate);
      }
  }


11. Be Interface Every ware

Api base interface

public interface IService<T>  
   {
       Task<IHttpActionResult> Insert(T item);
       Task<IHttpActionResult> Delete(int Id);
       Task<IHttpActionResult> Update(T item);
       Task<IHttpActionResult> Get();
       Task<IHttpActionResult> GetSingle(int studentId);
   }
public class StudentServiceController : BaseServiceControllerIService<StudentViewModel>
  {

PlutoContext

   public interface IContext
    {
        DbSet<Student> Students { get; set; }
        DbSet<Subject> Subjects { get; set; }
        DbSet<StudentSubject> StudentSubjects { get; set; }
        DbSet<UserAuthontication> UserAuthontications { get; set; }
    }
 
   public class SchoolContext : DbContext,IContext 
   {


Genatic repository

public interface IRepositoryRead<Twhere T : class
   {
       IEnumerable<T> Get(Expression<Func<Tbool>> filter = null,
           Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
           string includeProperties = "");
       T GetByID(object id);
   }
 
   public interface IRepositoryUpdate<Twhere T : class {
       void Insert(T entity);
       void Delete(object id);
       void Delete(T entityToDelete);
       void Update(T entityToUpdate);
   }
 
   public interface IRepositoryUpdateAsync<Twhere T : class {
 
       Task<int> InsertAsync(T entity);
       Task DeleteAsync(object id);
       Task UpdateAsync(T entityToUpdate);
   }

public interface IStudentDbService : IRepositoryRead<StudentBo>, IRepositoryUpdateAsync<StudentBo>
    {
        IEnumerable<StudentBo> Get(Expression<Func<Studentbool>> filter = nullFunc<IQueryable<Student>, IOrderedQueryable<Student>> orderBy = nullstring includeProperties = "");
    }

public class StudentDbService : IStudentDbService
   {
.............................


12) Use cache everywhere


using System.Runtime.Caching;
public class MemoryCacher
    {
        public static bool Add(string key, object value, DateTimeOffset absExpiration)
        {
            MemoryCache memoryCache = MemoryCache.Default;
            return memoryCache.Add(key, value, absExpiration);
        }
 
        public static object GetValue(string key)
        {
            MemoryCache memoryCache = MemoryCache.Default;
            return memoryCache.Get(key);
        }
         
        public static void Delete(string key)
        {
            MemoryCache memoryCache = MemoryCache.Default;
            if (memoryCache.Contains(key))
            {
                memoryCache.Remove(key);
            }
        }
    }

in this case put all cache keys in one place like CacheKeysConfig.cs as const string.

13). Use Json Format


config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html"));

14) Use Following Folder structure



     X (Api,Utility/)
     Lib /
          X.Domain
          X.Bo -->Utility(Enums)
          X.DbAccess --> Context / Migration
          X.DbService --> Service / Interface / Infastucture
     Test / X.UnitTest,X.AutomationTest,X.MockData


15) use attribute base routing for.

01) api versioning.
02) web api method as noun

[RouterPrefix('v1')]
public class StudentController:ApiController{

[Route("student")]
       public async Task<IHttpActionResult> Get()
       {}
[Route("student/{Id:int}")]
       public async Task<IHttpActionResult> GetSingle(int Id)
       {}
[Route("student")]
        public async Task<IHttpActionResult> Insert(StudentViewModel item)
        {}

[Route("student")]
        public async Task<IHttpActionResult>  Update(StudentViewModel item)
        {}

[Route("student/{Id:int}")]
       public async Task<IHttpActionResult> Delete(int Id)
       {}
}

     

16) use observer to bind values to html.


17) use template for itoration date


18) Use GZip To compress result

https://damienbod.com/2014/07/16/web-api-using-gzip-compression/
https://github.com/azzlack/Microsoft.AspNet.WebApi.MessageHandlers.Compression
   


19) KISS (Keep It Simple and Stupid)


  1. do not expose more than expert.
  2. return thing in similar way.
    public async Task<IHttpResponse> Response(){
         return Ok<T>(value);
         return BadRequest(string content);
         return Component(ResponseCode.InternalServerError,Ex);
    }
  3. use only common Response Code. not all. 404/200/401/500/403

20) Documentation 


21) Consider about Versioning

       [RouterPrefix('api/v2')]
       public class StudentController : ApiController{}



22) Result Filtering / Sorting / Searching / Pagination



    quay string  GET /tickets?fields=id,subject,customer_name,updated_at&state=open&sort=-updated_at&skip=10&take=100




23) Errors and Exception Handling


return json message format 
{ "code" : 1024, "message" : "Validation Failed", "errors" : [ { "code" : 5432, "field" : "first_name", "message" : "First name cannot have fancy characters" }, { "code" : 5622, "field" : "password", "message" : "Password cannot be blank" } ] }





24) use Customer action filter always

public XController:ApiController{ [Validation] public async Task<IHttpResponse> Insert(Student s){ return null; } } public ValidationActionFilter:ActionFilter{ public override void OnActionExecuting(HttpContext x){ //check context model state is valied if(!x.ModelState.IsValied()){ //set context as bad request x.Response = new HttpResponseMessage<Json>("some validation failded",badRequest); } } } // finally this action filter must register on Globle.asax public static void Configure(config){ config.Filter.Add(new ValidationActionFilter()); }

25) User Following exception type for following reasons.

406 - notAcceptable (not trigger on database (primary key violation))
404 - not found
200 - OK
201 - created
403 - Forbidden
400 - bad request

26 Handle sql exception (Primary key | forign key) by following way

custom exception for db
public class DbPKViolationException:Exception
    {
        public DbPKViolationException() : base() { }
        public DbPKViolationException(string message) : base(message) { }
    }
    public class DbFKViolationException : Exception
    {
        public DbFKViolationException() : base() { }
        public DbFKViolationException(string message) : base(message) { }
    }
    public class DbUniqKeyViolationException : Exception
    {
        public DbUniqKeyViolationException() : base() { }
        public DbUniqKeyViolationException(string message) : base(message) { }
    }

genetic exception handler

protected Exception HandleException(Exception exception)
       {
           var x = exception;
           while (x.InnerException != null)
           {
               x = exception.InnerException;
           }
           var sqlException = x as SqlException;
           if (sqlException==null)
           {
               throw x;
           }
           if (sqlException.Number == 2627 || sqlException.Number == 2601)
           {
               throw new DbPKViolationException();
           } 
           throw exception;
       }
   }


Service class : base service


public UserBo GetByID(object id)
       {
           try
           {
               return Mapper.Map<UserBo>(this.uow.UserRepository.GetByID(Convert.ToUInt32(id)));
           }
           catch (Exception ex)
           {
               throw HandleException(ex);
           }
       }


Controller class

[HttpPost]
[Route("user/login")]
public async Task<IHttpActionResult> Login(UserViewModel entity)
{
    try
    {
        var o = this.service.Login(Mapper.Map<UserBo>(entity));

        return Ok();
    }
    catch (ArgumentException)
    {
        return Content<string>(HttpStatusCode.NotAcceptable, "invalied user name or password");
    }
    catch (Exception ex)
    {
        return await LogErrors(ex);
    }
}




Wednesday, February 15, 2017

Lambda expression


Delegate



 delegate string AppendName (string firstName, string lastName);
public static void main(){

       AppendName nc = delegate (string firstName, string lastName)
            {
                var s = sequenceId.ToString();
                var zero = string.Empty;
                for (var i = 0; i < (5 - s.Length); i++)
                {
                    zero += "0";
                }
                var serialNumber = $"{eventId.Substring(10, 5)}-{zero}{sequenceId}";
                return serialNumber;
            };

     nc("chamith","saranga");
     nc("sajeeka","nanayakkara");
   nc("nalaka","gamage");
}


Func (return function)


public static void main(){


       Func<string,string> append = (e)=>{
   
          return e.toLower();

     };

   append("chamith");
}

 BookingItems = ((Func<List<BookingItemBo>>) (() =>
                    {
                        return result.BookingItem.Select(p => new BookingItemBo(p.ScheduleId, p.SeatNo,
                            p.BookingItemJourneyInfo.FromCityId, p.BookingItemJourneyInfo.ToCityId,
                            p.BookingItemJourneyInfo.FromStopId, p.BookingItemJourneyInfo.ToStopId,
                            p.BookingItemJourneyInfo.JourneyStartDateTime.SpecifiedAsUtc(),
                            p.BookingItemJourneyInfo.JourneyEndDateTime.SpecifiedAsUtc(),
                            p.Customer)).ToList();
                    }))()

Action (void function)


public static void main(){

      Action<string> print = (e) =>{

         console.WriteLine(e);
      };
}


Multiple parameter with Func


Func<intintint> getRate = (e,d) =>
                   {
 
                       return 1;
                   };

Pass function as a parameter using lamda expression

   static void Main(string[] args)
        {
            int result = 0;
            LamdaExpression(10,15,(e) => { result = e; });
            System.Console.WriteLine($"this is lamda expression {result}");
            System.Console.Read();
        }

        static void LamdaExpression(int first,int second,Action<int>  abc)
        {
            abc(first+second);
        }

-----------------------------------------------
public class Program
{
    static void Main(string[] args)
    {
        var x = new Process();
        x.LongRuniningProcess((int x2)=> {
            Console.WriteLine(x2);
        });
    }
}
public class Process
{
    public void LongRuniningProcess(Action<int> callBack)
    {
        for (int i = 0; i < 10000; i++)
        {
            Thread.Sleep(100);
            //copy file
            callBack(i);
        }
    }   

}

=======================================================
Enumerable (create list with some defaults)


  1. create List<int> from 0 to 100
    IEnumerable<int> arr = Enumerable.Range(0, 100);
  2. create List<T> with some default object.
    IEnumerable<Student> str = new Enumerable.Repeate(new Student("CHAMITH"),10);






CS Events