Repository and Unit of Work Pattern .Net Core

The Repository and Unit of Work pattern creates an abstraction layer between Data Access Layer (DAL) and the business logic. This isolates concerns making it easier to test or implement TDD.

The Repository Pattern

What do we need

  1. A repository interface for the entity
  2. The implementation of such interface
  3. Registration of the repository service in the application
  4. Inject and use it in the controllers

Example

1. Create an interface for the entity.
using System.Collections.Generic;

namespace MyApi.Models
{
    public interface IBlogPostRepository
    {
        void Add(BlogPost post);
        IEnumerable GetAll();
        BlogPost Find(int key);
        void Remove(int key);
        void Update(BlogPost item);
    }
}
2. Implement the interface
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyApi.Models
{
    public class BlogPostRepository : IBlogPostRepository
    {
        private readonly BlogPostContext _context;

        public BlogPostRepository(BlogPostContext context)
        {
            _context = context;
            Add(new BlogPost { Title = "Hello World!" });
        }

        public IEnumerable GetAll()
        {
            return _context.BlogPosts.ToList();
        }

        public void Add(BlogPost post)
        {
            _context.BlogPosts.Add(post);
            _context.SaveChanges();
        }

        public BlogPost Find(int key)
        {
            return _context.BlogPosts.FirstOrDefault(p => p.Key == key);
        }

        public void Remove(int key)
        {
            var entity = _context.BlogPosts.First(p => p.Key == key);
            _context.BlogPosts.Remove(entity);
            _context.SaveChanges();
        }

        public void Update(BlogPost post)
        {
            _context.BlogPosts.Update(post);
            _context.SaveChanges();
        }
    }
}
3. Register the service

This is usually done in Startup.cs.
Read about Dependency Injection and how to register services in the docs.

services.AddScoped<IBlogPostRepository, BlogPostRepository>();
4. Inject it to the controller via the constructor.
namespace MyApi.Controllers
{
    [Route("api/[controller]")]
    public class BlogPostController : Controller
    {
        public IBlogPostRepository BlogPosts { get; set; }
        public BlogPostController(IBlogPostRepository blogPostItems)
        {
            BlogPosts = blogPostItems;
        }
    }
}

Unit Of work

The docs explain it clearly:

The unit of work class serves one purpose: to make sure that when you use multiple repositories, they share a single database context. That way, when a unit of work is complete you can call the SaveChanges method on that instance of the context and be assured that all related changes will be coordinated. All that the class needs is a Save method and a property for each repository. Each repository property returns a repository instance that has been instantiated using the same database context instance as the other repository instances.

What do we need

  1. Unit of Work Interface
  2. Unit of Work Implementation Class
  3. Register as a service
  4. Inject it and use it in the Controllers

Example

1. Interface
public interface IUnitOfWork
{
    IBlogPostRepository BlogPostRepository { get; }
    IPageRepository PageRepository { get; }
    void Save();
}
2. Interface
public class UnitOfWork : IUnitOfWork
{
    private readonly BlogPostContext _context;
    {
    IBlogPostRepository _blogPostRepository { get; }
    IPageRepository _pageRepository { get; }
    public UnitOfWork(BlogPostContext context)
    {
        _context = context;
    }

    public IBlogPostRepository BlogRepository
    {
        get
        {
            return _blogPostRepository = _blogPostRepository ?? new IBlogPostRepository(_context);
        }
    }

    public IPageRepository IPageRepository
    {
        get
        {
            return _pageRepository = _pageRepository ?? new IPageRepository(_context);
        }
    }

    public void Save()
    {
        _context.SaveChanges();
    }
}
3. Register as a service for DI
services.AddScoped<IUnitOfWork, UnitOfWork>();
4.Use in the controllers
_unitOfWork.BlogPostRepository.Create(new BlogPost()
{
    Title = "My new title"
});

_unitOfWork.PageRepository.Create(new Page()
{
    Title = "Sample Title",
    Content = "Sample content"
});

_unitOfWork.Save();

WordPress Rest API v2 Order by Random

order-by-random

To order the results coming back from wp api we can use the filter:
rest_{#post_type}_collection_params.

For example, if your post type is review:


add_filter( 'rest_review_collection_params', 'prefix_rest_orderby_rand', 10, 1 );
function prefix_rest_orderby_rand( $params ) {
    $params['orderby']['enum'][] = 'rand';
    return $params;
}

Ordering by random may impact performance.

Decrease the size of an EBS Volume in AWS

decrease-ebs

At this point you there is no way to decrease the size of an EBS volume from the AWS panel and you will have to do it manually.

To get started create a new volume in the AWS panel and attach it to your instance

Format the disk

[ubuntu ~]$ sudo mkfs -t ext4 /dev/smalldrive

Create a temporary folder and mount the new disk

[ubuntu ~]$ sudo mkdir /path/to/temp/folder
[ubuntu ~]$ sudo mount /dev/smalldrive /path/to/temp/folder

Copy the files from the old disk into the new one

[ubuntu ~]$ sudo rsync -aHAXxSP /path/to/folder/ /path/to/temp/folder

Unmount both drives

[ubuntu ~]$ sudo umount /dev/largedrive
[ubuntu ~]$ sudo umount /dev/smalldrive

Mount the new (small) drive on the old folder

[ubuntu ~]$ sudo mount /dev/smalldrive /path/to/folder

Update fstab so the new disk gets mounted after restarting the instance

[ubuntu ~]$ sudo vim /etc/fstab
/dev/xvdg /path/to/folder ext4 defaults 0 1

**Don’t forget to remove the entry for the old (large) drive**

Finally, remove the old disk from the AWS panel

How to install Fail2Ban Ubuntu to block attacks to wordpress xmlrpc

fail2ban-xmlrpc

This is a very rough guide to be used only as guidance when setting up fail2ban. This simple setup should work on a low traffic server.

1. Install fail2ban

sudo apt-get update
sudo apt-get install fail2ban

2. Add a filter

Go to /etc/fail2ban/filter.d
Create a file called apache-xmlrpc.conf

On this file add:

[Definition]
failregex = ^<HOST> .*POST .*xmlrpc\.php.*
ignoreregex =

3. Enable the filter

Go to /etc/fail2ban/jail.conf

On this file add the following:

[apache-xmlrpc-access]

enabled  = true
port     = http,https
filter   = apache-xmlrpc
logpath  = /var/log/apache*/*access.log
maxretry = 6

You can change the maxretry set your log path.

4. Finish up by restarting fail2ban

sudo service fail2ban restart

5. Start fail2ban after reboot

Bonus: Set fail2ban to start after a reboot

Configure a service to run at startup in Ubuntu

start-service-after-reboot-ubuntu
To automatically start a service like apache, nginx, fail2ban or others after a reboot you can do the following:

sudo update-rc.d fail2ban defaults

If the service is already set to be automatically restarted you will see the following:

System start/stop links for /etc/init.d/fail2ban already exist.

Allow SVG uploads to WordPress Media Library

upload-svg-wordpress-media-library
This function allows you to upload svg files to your wordpress media library.
You can this function to your theme’s functions file (functions.php)

function my_custom_mime_types($mimes) {
	$mimes['svg'] = 'image/svg+xml';
	return $mimes;
}
add_filter('upload_mimes', __NAMESPACE__ . '\\my_custom_mime_types');

Responsive Bootstrap hover dropdowns

Bootstrap 3 Responsive Hover Dropdowns
This adds hover behaviour to bootstrap’s dropdown menus using the built in ‘open’ class.
We will do it based on a responsive breakpoint.
In this example the hover behaviour should only happen if the screen is wider than 600px.
At the end we reset to the default behaviour on small screens.


        // Show menus on hover
        function hoverMenu(){
          var breakpoint = 600;
          var dropdown = $('ul.nav li.dropdown');
          if ( $(window).width() > breakpoint ){
            dropdown.hover(function() {
              $(this).addClass('open');
            }, function() {
              $(this).removeClass('open');
            });
          } else {
            // Remove hover behaviour
            dropdown.unbind( "mouseenter mouseleave" );
          }
        }

        //Do it!
        $(document).ready(function(){
          hoverMenu();
        });
        $(window).resize(function(){
          hoverMenu();
        });

If you use a debounce function I recommend you use it as you may not want the screen width to be calculated per pixel when the screen size changes.

...
        //Do it!
        $(document).ready(function(){
          hoverMenu();
        });
        $(window).resize(function(){
          debounce(hoverMenu(), 300);
        });

Add EBS based swap to an EC2 instance

Add EBS Swap To AWS EC2 Instance
1. Create a new EBS volume of around 4-8GB and attach it to your instance.
We will assume the volume is /dev/xvdb
To check wether it is mounted use lsblk

2. If your volume is mounted, unmount it

sudo umount /dev/xvdb

3. Turn this volume into swap

sudo mkswap /dev/xvdb

4. Enable this volume as swap

sudo swapon /dev/xvdb

5. Make sure it is working as swap

swapon -s

6. Use this disk as swap if instance is restarted

sudo vim /etc/fstab

Add this:

/dev/xvdb       none    swap    sw  0       0

Responsive images: Bootstrap 3 + WordPress Editor

Taken from: https://gist.github.com/mkdizajn/7352469

function bootstrap_responsive_images( $html ){
  $classes = 'img-responsive';
  // check if there are already classes assigned to the anchor
  if ( preg_match('/<img.*? class="/', $html) ) {
    $html = preg_replace('/(<img.*? class=".*?)(".*?\/>)/', '$1 ' . $classes . ' $2', $html);
  } else {
    $html = preg_replace('/(<img.*?)(\/>)/', '$1 class="' . $classes . '" $2', $html);
  }
  // remove dimensions from images,, does not need it!
  $html = preg_replace( '/(width|height)=\"\d*\"\s/', "", $html );
  return $html;
}
add_filter( 'the_content', __NAMESPACE__ . '\\bootstrap_responsive_images',10 );
add_filter( 'post_thumbnail_html', __NAMESPACE__ . '\\bootstrap_responsive_images', 10 );

Convert scss into sass and viceversa

Convert scss into sass and viceversa

To change all .scss files into .sass files inside the current folder use the following code.

sass-convert --recursive --from scss --to sass --indent 't' .

--recursive: All files within the “current folder” and any folders inside the “current folder”

--from: Current file extension (e.g. scss)

--to: Desired file extension (e.g. sass)

--indent: Indentation Style (optional) ‘t’ means tab

The dot at the end means “current folder

See the documentation and installation instructions for sass-convert here: https://www.npmjs.com/package/sass-convert

Basic WordPress .gitignore

Basic Gitignore for WordPress development files

*.log
wp-config.php
wp-content/advanced-cache.php
wp-content/backup-db/
wp-content/backups/
wp-content/blogs.dir/
wp-content/cache/
wp-content/upgrade/
wp-content/uploads/
wp-content/wp-cache-config.php
wp-content/plugins/hello.php

/.htaccess
/license.txt
/readme.html
/sitemap.xml
/sitemap.xml.gz

Add New EBS Volume to EC2 Instance

add-ebs-volume-to-ec2
A short, 3 step guide on how to add a new volume to your EC2 Instance.

Replace #### with your volume and #folder# with your folder path.

1. Format the disk

[ubuntu ~]$ sudo mkfs -t ext4 /dev/####

2. Mount the disk

[ubuntu ~]$ sudo mount /dev/#### #folder#

3. Auto-mount the volume on restart

[ubuntu ~]$ sudo vim /etc/fstab

fstab config

/dev/#### #folder# ext4 defaults 0 1

Update MySQL Database to general utf-8 encoding for backwards compatibility

Fix script for #1273 – Unknown collation: ‘utf8mb4_unicode_ci’

 

$ mysqldump --compatible=mysql4

Or


<!DOCTYPE html>
<html>
<head>
  <title>DB-Convert</title>
  <style>
    body { font-family:"Courier New", Courier, monospace;" }
  </style>
</head>
<body>

<h1>Convert your Database to utf8_general_ci!</h1>

<form action="db-convert.php" method="post">
  dbname: <input type="text" name="dbname"><br>
  dbuser: <input type="text" name="dbuser"><br>
  dbpass: <input type="text" name="dbpassword"><br>
  <input type="submit">
</form>

</body>
</html>
<?php
if ($_POST) {
  $dbname = $_POST['dbname'];
  $dbuser = $_POST['dbuser'];
  $dbpassword = $_POST['dbpassword'];

  $con = mysql_connect('localhost',$dbuser,$dbpassword);
  if(!$con) { echo "Cannot connect to the database ";die();}
  mysql_select_db($dbname);
  $result=mysql_query('show tables');
  while($tables = mysql_fetch_array($result)) {
          foreach ($tables as $key => $value) {
           mysql_query("ALTER TABLE $value CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci");
     }}
  echo "<script>alert('The collation of your database has been successfully changed!');</script>";
}

?>