Javascript Global Error Handler

Today i’have created a simple class to log in the backend the javascript error, so i can have a real time monitoring of how error appear to the users.

We can use a window.onerror and the addEventListener rewrite.

Window.onerror has been available in most browser, but the argument that are passed on each browser are different:

BrowserMessageURLlineNocolNoerrorObj
Firefox
Chrome
Edge
IE 11
IE 10
IE 9, 8
Safari 10 and up
Safari 9
Android Browser 4.4

This is my class with a _wrap function, and a SendError that trasmit the data on the backend

class ErrorHandler {

	constructor() {
		let $this = this;
		$this._prototypeInit();

		window.onerror = function (message, file, line, col, error) {
			let data = message+" from "+error.stack;
			$this.SendError(data);
		};
	}

	_prototypeInit() {
		let $this = this;
		var addEventListener = window.EventTarget.prototype.addEventListener;
		window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
			addEventListener.call(this, event, $this._wrap(callback), bubble);
		}
		var removeEventListener = window.EventTarget.prototype.removeEventListener;
		window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
			removeEventListener.call(this, event, callback._wrapped || callback, bubble);
		}
	}

	_wrap(func) {
		let $this = this;
		if (!func._wrapped) {
			func._wrapped = function () {
				try {
					func.apply(this, arguments);
				} catch (e) {
					let data = e.message+" from "+e.stack;
					$this.SendError(data);
					throw e;
				}
			}
		}
		return func._wrapped;
	}

	SendError(message) {
		let $this = this;
		fetch('/ErrorHandler/WriteLog', {
			method: 'POST',
			body: JSON.stringify({ message: message }),
			headers: {
				'Content-Type': 'application/json'
			}
		}).then(res => res.json()).catch(error => console.error('Error:', error));
	}
}

In the message we put the stacktrace.
To use it at the init of your application:
let handlerError = new HandlerError();

Write to me if you have some suggestion to improve it.

WordPress Plugin Creation Tutorial – Simplest way

Today I asked myself how to explain to a junior, how to create a wordpress plugin, the simplest way. Without the inclusion of complex structures with public folder, includes, ….., but something very very simple.

Below I will explain how to create a plugin to manage some date, in this example is a Sport Race:
– Create Sport Race
– Insert members of a Sport Race
– Show table with Sport Race, and manage data (bulk delete)
– Show table with Sport Race, and manage data (bulk delete)
– Upload media using WordPress System (media manager of wordpress)

You can download it on: GITHUB

The structure of the project in the Plugin name directory is:

As you can see, a simple list of file with no directory

My project as two section: Sport Race and Members
Each section is composed by two file: _page.php and _table.php
And a file of system: plugin_activation.php

For example now analyze two file: sportrace_page.php and sportrace_table.php

For the sportrace_table.php will explain in the next article how to create a table, now take a look at file, is very simple.
For now i will explain how to use it in the sportrace_page.php

At top of page we put

<?php 
global $wpdb;

// jQuery
wp_enqueue_script('jquery');
// This will enqueue the Media Uploader script
wp_enqueue_media();
?>

For the inclusion of table put:

<?php 
echo '<form method="post">';
require_once 'sportrace_table.php';
$class = new Sportrace_Table();
$class->prepare_items();
$class->display();
echo '</form>';
?>

In the plugin_activation.php you can find the mysql create query and the menu inclusion!

Let’s start to create your wordpress plugin! Simple and Fast!

Ebay OAuth 2 Generate Token and Refresh – PHP

Today i will show to you how to use a OAuth 2 on Ebay, so how you can take your token, and then use it.

At first you must to register on https://developer.ebay.com

Then you must to set your Application on (Sandbox/Test or Production, in this guide i show to you Production procedure) https://developer.ebay.com/my/keys

After you must to have a situation like this:

Now we have:
– Client ID
– Dev ID
– Client Secret

We need:
– Authorization Code
– Access Token
– Refresh Token

Authorization Code

At first we must to generate the Authorization Code, and for this procedure we must to paste an url on the browser and copy the query string “code”.
So click on the “User token link”

Click on “Get a Token from eBay via Your Application”

Then you must to “Add eBay Redirect URL”
So you generate your app details, you can see the
“Your branded eBay Production Sign In (OAuth)” or if sandbox (test)
“Your branded eBay SandboxSign In (OAuth)”

Copy the link, that is like:

https://auth.ebay.com/oauth2/authorize?client_id=App-PRD-hhhhhf72-3hhb&response_type=code&redirect_uri=YourName-App–okllp&scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly

Put this link on your browser, and login with your ebay account, so then you must to redirect on another page that sayd to you that the application has grant, and in the url bar you find your authorization code.

https://signin.ebay.com/ws/eBayISAPI.dll?ThirdPartyAuthSucessFailure&isAuthSuccessful=true&code=v%5K1.1HH%…..w&expires_in=299

Access Token and Refresh Token

Now with our authorization code, we call this url to take our access and refresh token.
For this call we need the authorization header, and create a base64 encode with clientID and certID.
And then in the parameter set Authorization code and RuName

$link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode('<clientid>:<certid>');
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=authorization_code&code==<authorization-code-value>&redirect_uri=<RuName-value>");
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
            $this->refreshToken = $json["refresh_token"];
        }

Why we have access token and refresh token?

We use Access Token for all the api request on eBay service.
We use Refresh Token to regenerate a Access Token.

Access token is valid 2 hour, but Refresh Token is valid 18 months.

How can i refresh my access token?

You must to take a call to this service, passing your refresh code, and the service return to you your new access token

$link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode('<clientid>:<certid>');
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=refresh_token&refresh_token<your-refresh-token>&scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.analytics.readonly");
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
        }

I suggest to save your Access Token and Refresh Token on Database.

At the end my eBay API Simple Class

<?php

class EbayAPI
{
    protected $devID;
    protected $appID;
    protected $certID;
    protected $clientID;
    protected $serverUrl;
    public $userToken;
    protected $paypalEmailAddress;
    protected $ruName;


    public function __construct()
    {
        $this->devID = '<your-dev-id>'; // these prod keys are different from sandbox keys
        $this->appID = '<your-app-id>';
        $this->certID = '<your-cert-id>';
        $this->clientID = '<your-client-id>';
        //set the Server to use (Sandbox or Production)
        $this->serverUrl = 'https://api.ebay.com/ws/api.dll';      // server URL different for prod and sandbox
        //the token representing the eBay user to assign the call with

        $this->authCode = '<paste here your authorization code>'; 
        $this->authToken ="";
        $this->refreshToken ="";
        $this->ruName= "";

        $this->paypalEmailAddress= 'PAYPAL_EMAIL_ADDRESS';
        
    }

    public function firstAuthAppToken() {
        $url = "https://auth.ebay.com/oauth2/authorize?client_id=".$this->clientID."&response_type=code&redirect_uri=".$this->ruName."&scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.analytics.readonly";       
    }

    public function authorizationToken()
    {
        $link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode($this->clientID.':'.$this->certID);
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=authorization_code&code=".$this->authCode."&redirect_uri=".$this->ruName);
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
            $this->refreshToken = $json["refresh_token"]; 
        } 
    }

    public function refreshToken()
    {
        $link = "https://api.ebay.com/identity/v1/oauth2/token";
        $codeAuth = base64_encode($this->clientID.':'.$this->certID);
        $ch = curl_init($link);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Authorization: Basic '.$codeAuth
        ));
        echo $this->refreshToken;
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=refresh_token&refresh_token=".$this->refreshToken."&scope=https://api.ebay.com/oauth/api_scope https://api.ebay.com/oauth/api_scope/sell.marketing.readonly https://api.ebay.com/oauth/api_scope/sell.marketing https://api.ebay.com/oauth/api_scope/sell.inventory.readonly https://api.ebay.com/oauth/api_scope/sell.inventory https://api.ebay.com/oauth/api_scope/sell.account.readonly https://api.ebay.com/oauth/api_scope/sell.account https://api.ebay.com/oauth/api_scope/sell.fulfillment.readonly https://api.ebay.com/oauth/api_scope/sell.fulfillment https://api.ebay.com/oauth/api_scope/sell.analytics.readonly");
        $response = curl_exec($ch);
        $json = json_decode($response, true);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if($json != null)
        {
            $this->authToken = $json["access_token"];
        } 
    }
}

Yii 2 Framework Configure on Plesk 17 – Nginx

Hi,
today i want to explain how to configure a app with framework Yii 2 on your hosting Plesk.
In my case i have Plesk 17.8, the problem is how to configure the subdirectory and so how to convert the htaccess of Yii 2 app.

On Plesk 17 you must to configure the site, on run PHP-FPM un on nginx.
So go in the Hosting Setting of the domain:

Hosting Setting

So go in the Hosting Setting of the domain:

Apache & nginx Settings

You must to disable Proxy mode

Than we must to configure the Additional nginx directives
So go in the Apache & nginx Settings of the domain
Than into Additional nginx directives copy this code (change YOURDOMAIN with the domain that you want to configure):

set $base_root /var/www/vhosts/YOURDOMAIN/httpdocs;

charset UTF-8;
index index.php index.html;

location / {
	root $base_root/frontend/web;
	try_files $uri $uri/ /frontend/web/index.php$is_args$args;

	location ~ ^/assets/.+\.php(/|$) {
		deny all;
	}
}

location /admin {
	alias $base_root/backend/web/;

	# prevent the directory redirect to the URL with a trailing slash
	location = /admin {
		# if your location is "/backend", try use "/backend/backend/web/index.php$is_args$args"
		# bug ticket: https://trac.nginx.org/nginx/ticket/97
		try_files $uri /backend/web/index.php$is_args$args;
	}

	try_files $uri $uri/ /backend/web/index.php$is_args$args;

	location ~ ^/admin/assets/.+\.php(/|$) {
		deny all;
	}
}

location ~ ^/.+\.php(/|$) {
	rewrite (?!^/((frontend|backend)/web|admin))^ /frontend/web$uri break;
	rewrite (?!^/backend/web)^/admin(/.+)$ /backend/web$1 break;

	fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
	fastcgi_param PATH_INFO $fastcgi_path_info;
	fastcgi_pass "unix:///var/www/vhosts/system/YOURDOMAIN/php-fpm.sock";
	include /etc/nginx/fastcgi.conf;
}

location ~ /\. {
	deny all;
}

If you want you can enable nginx caching

Press “OK” and enjoy

Angular 6 – ADAL Dynamic Parameter initialization

We have seen in the previous article, how to implement the ADAL Authentication in Angular 6.

Now we can see, how to do, for init the ADAL Module with dynamic parameter, for example we can take them from database, or json file configuration.

We must to open the app.module.ts
Search the “imports” line, where we have write:

@NgModule({
declarations: [
AppComponent
],
imports: [
MsAdalAngular6Module.forRoot({
instance: 'https://adal.resource.com/',
tenant: '',
clientId: '',
redirectUri: window.location.origin,
navigateToLoginRequestUrl: false,
cacheLocation: 'localStorage'
}),
RouterModule.forRoot(
appRoutes,
{ enableTracing: true }
),
BrowserModule,
],
providers: [
AuthenticationGuard
]
});

As we can see, the parameter are static, now we want to take them from a web service.

We must to change the “forRoot” function, and pass a function that return the object with parameter configuration

@NgModule({
declarations: [
AppComponent
],
imports: [
    MsAdalAngular6Module.forRoot(function () {
      var request = new XMLHttpRequest();
      request.open('GET', '/api/getParameterADAL', false);
      request.send(null);

      if (request.status === 200) {
        console.log(request.responseText);
        var parameter = JSON.parse(request.responseText);
        return {
          instance: parameter.adfs_instance,
          tenant: parameter.adfs_tenant,
          clientId: parameter.adfs_client_id,
          redirectUri: parameter.adfs_redirect_uri,
          navigateToLoginRequestUrl: false,
          cacheLocation: 'localStorage',
        }
      }
    }()),
RouterModule.forRoot(
appRoutes,
{ enableTracing: true }
),
BrowserModule,
],
providers: [
AuthenticationGuard
]
});

If you have compile error build for example:
Function expressions are not supported in decorators in ‘ɵ0’

Build with:

ng build --optimization=true --outputHashing=a

Enjoy!

Angular 6 – ADAL Authentication

Today i want to talk to you about Microsoft ADAL (Azure Active Directory Authentication Library).
ADAL allows users to authenticate in Active Directory (AD) local or in the cloud and take token to protect the API.

How can i do to integrate it in a Angular 6 app?

1) Install the js library microsoft-adal-angular6

npm i microsoft-adal-angular6

2) Open app.component.ts
2.1) Import the microsoft adal

import { MsAdalAngular6Service } from 'microsoft-adal-angular6';

2.2) In the export class AppComponent change the constructor

export class AppComponent {
title = 'APP Title';
constructor(private adalSvc: MsAdalAngular6Service) {
console.log(this.adalSvc.userInfo);
var token = this.adalSvc.acquireToken('http://adal.resource.com').subscribe((token: string) => {
console.log(token);
});
}
}

3) Open app.module.ts
3.1) Import the microsoft adal

import { MsAdalAngular6Module, AuthenticationGuard } from 'microsoft-adal-angular6';

3.2) We must to change our routes

const appRoutes: Routes = [
{ path: '', component: AppComponent, pathMatch: 'full', canActivate: [AuthenticationGuard] }
];

3.3) In NgModule import library

@NgModule({
declarations: [
AppComponent
],
imports: [
MsAdalAngular6Module.forRoot({
instance: 'https://adal.resource.com/',
tenant: '',
clientId: '',
redirectUri: window.location.origin,
navigateToLoginRequestUrl: false,
cacheLocation: 'localStorage'
}),
RouterModule.forRoot(
appRoutes,
{ enableTracing: true }
),
BrowserModule,
],
providers: [
AuthenticationGuard
]
});

If you want an example Angular 6 ADAL App click here.

Angular 6 Material – MatDatePicker italian format dd/MM/yyyy

Material Angular is very very useful library to generate beautiful app with material design and use all the power of angular.
Today we can see how to set the format for the MatDatePicker with dd/MM/yyyy so how to customize it, then you can change it.

In our Angular 6 project we must to install moment.
So execute in our project directory:

npm i @angular/material-moment-adapter
npm add moment

Then we must to open our
app.module.ts

//Some import before, add this
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material';
import { MomentDateModule, MomentDateAdapter } from '@angular/material-moment-adapter';

//create our cost var with the information about the format that we want
export const MY_FORMATS = {
  parse: {
    dateInput: 'DD/MM/YYYY',
  },
  display: {
    dateInput: 'DD/MM/YYYY',
    monthYearLabel: 'MM YYYY',
    dateA11yLabel: 'DD/MM/YYYY',
    monthYearA11yLabel: 'MM YYYY',
  },
};

//in our ngmodule providers add the provide for the date
@NgModule({
imports: [
............
],
providers: [
    { provide: MAT_DATE_LOCALE, useValue: 'it' }, //you can change useValue
    { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
    { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS }
  ],
bootstrap: [AppComponent]
});

export class AppModule { }

At the end all the date in our project became with the format dd/mm/yyyy!!
Some question contact me.

Angular 6 – IE 11 method fill not supported

You have created your angular app and now you have some error about method fill, for example: “Object doesn’t support property or method ‘fill'”.
Line that fail: var HEADER_FILLER = new Array(HEADER_OFFSET).fill(null); (Angular core).

Don’t worry the solution is easy. You must open your file on: src/polyfill.ts
At line 21 of the file you see:

/** IE9, IE10 and IE11 requires all of the following polyfills. **/

and many “import ‘core-js/es6/BLABLA’” commented.

You must to uncomment all:

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';

Build and fun!

Complete Guide Ionic 3 Firebase with cordova plugin firebase

Okay let’s start to integrate in our Ionic 3 app the Firebase Google Cloud Message with the cordova plugin firebase.
In the Ionic 3 we can found the native integration with this plugin. For the documentation click here.
It work with IOS 10 and IOS 11 and latest version of Android, i have tested it.

In this guide we can see:
Install cordova plugin firebase on Ionic app
Setting cordova plugin firebase on Ionic app
Setting Firebase Cloud Message

 

Install the Ionic Firebase module

We must to install the npm library and the cordova plugin so let’s start to execute this command:

$ ionic cordova plugin add cordova-plugin-firebase
$ npm install --save @ionic-native/firebase

Then we must to use it on our app, so let’s start to include it in our app.module.ts, import it and then add into “providers” section.

import { Firebase } from '@ionic-native/firebase';

@NgModule({
  declarations: [
    MyApp
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: (createTranslateLoader),
        deps: [HttpClient]
      }
    }),
    IonicModule.forRoot(MyApp,{
      menuType: 'push'
    }),
    IonicStorageModule.forRoot()
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp
  ],
  providers: [
    Api,
    Items,
    User,
    Camera,
    SplashScreen,
    StatusBar,
    Firebase,
    IonicErrorHandler,
    { provide: Settings, useFactory: provideSettings, deps: [Storage] },
    // Keep this to enable Ionic's runtime error handling during development
    { provide: ErrorHandler, useClass: MyErrorHandler }
  ]
})

 

Setting cordova plugin firebase on Ionic app

Now we can use it in our app.component.ts, for the grant permission, registration of token.
This is a simplest installation, import it, add in the constructor, and then use this.firebase to attach at the event.

For IOS is very important the method “grantPermission”

import { Firebase } from '@ionic-native/firebase';

constructor(platform: Platform, private statusBar: StatusBar, private splashScreen: SplashScreen, private firebase: Firebase) {
    platform.ready().then(() => {

      this.statusBar.styleDefault();

      this.splashScreen.hide();

      this.firebase.grantPermission();
      this.firebase.getToken()
  .then(token => console.log('The token is ${token}')) // save the token server-side and use it to push notifications to this device
  .catch(error => console.error('Error getting token', error));

this.firebase.onTokenRefresh()
  .subscribe((token: string) => console.log('Got a new token ${token}'));
      });
  }

Now we must to setting up the account on the firebase cloud messaage, so we can generate two files:
google-services.json (Android)
GoogleService-Info.plist (IOS)

We can add this file in the root directory, with the config.xml and package.json file.

Setting Firebase Cloud Message

To setting up the firebase account remind to this guide: https://engineering.hexacta.com/managing-push-notifications-with-ionic2-3698249c07a

Remember, is very important that you upload you APN CERTIFICATE IOS, if you not load it the notifications not work.
This guide: https://firebase.google.com/docs/cloud-messaging/ios/certs

 

If you have some question write me.

ElasticSearch 5 – NEST Dynamic QueryContainer with QueryContainerDescriptor

How can i create a dynamic QueryContainer with many QueryContainerDescriptor?
How to dynamically build up a Bool query using the NEST client?

I will teach you how to create a dynamic nest query with and logic.

You must to write your QueryContainer:

QueryContainer filters_complete = null;

Then we must to attach to them the many filters that we want

var dateFilter = new QueryContainerDescriptor<OBJTYPE>().DateRange(t => t.Field("student.age").GreaterThanOrEquals(DateTime.Min).LessThanOrEquals(DateTime.Max));
filters_complete &= (new QueryContainerDescriptor<OBJTYPE>().Nested(n => n.Path("student").Query(q2 => q2.Bool(bq => bq.Filter(dateFilter)))));

Add in and another filter to out QueryContainer. Just need to create the other QueryContainerDescriptor

var partial = new QueryContainerDescriptor<OBJTYPE>().Range(t => t.Field("school.alumn_number").GreaterThan(0));
filters_complete &= (new QueryContainerDescriptor<OBJTYPE>().Nested(n => n.Path("school").Query(q2 => q2.Bool(bq => bq.Filter(partial)))));

We have created a query to extract: (student with age >= XX && age <= YY) && (school with alumn number > 0)

Now we must to use it:

string _urlServerElasticSearch = WebConfigurationManager.AppSettings["ElasticSearch_Server"];
var node = new Uri(_urlServerElasticSearch);
var client = new ElasticClient(node);

var response1 = client.Search<OBJTYPE>(s => s
.Index("index")
.Type("mapping")
.Query(_ => filters_complete).Scroll("60s").From(0).Size(100)
);

Use the _ in the lambda expressions, because we don’t care about the parameter!
I use the Scroll() method in my query, if you want to know how to manage the Scroll, see this guide.

 

Do you know a simplest method?
There is some error in my article?
Or if you have a question write me!