It is a basic topic and there are many answers in the topic, but I cannot see why my case does not work as it is expected.
The problem: moduleContract variable always null and exception is thrown.
What I did so far:
- read as much answers here as possible to find the solution - no success
 - check my other solution, which is working fine, and compare to this - there is no difference, or I haven't find the difference
 - request help from my supersmart dev peers - the couldn't help
 - checking official tutorials - no success
 
The controller:
[HttpPost]
[Route("add")]
public string AddModuleScreen([FromBody] KendoModuleScreenViewModel moduleContract)
{
    if (moduleContract == null)
    {
        throw new ArgumentNullException();
    }
    //return _digitalLibraryApplication.AddNewModuleScreen(moduleContract);
    return "asd";
}
The WebApiConfig:
public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
    // Web API routes
    config.MapHttpAttributeRoutes();
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
    var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
    config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
The ViewModel: (don't ask why the ModuleId is an object, it is due to Kendo UI)
public class KendoModuleScreenViewModel
{
    public int ModuleScreenId { get; set; }
    public int ModuleScreenIsEnabled { get; set; }
    public string ModuleScreenName { get; set; }
    public string ModuleScreenRoute { get; set; }
    public string ModuleScreenDesc { get; set; }
    public int ModuleScreenSortNo { get; set; }
    public KendoModuleViewModel ModuleId { get; set; }
}
The request:
Request URL:http://dilib.local/services/webapi/administration/modulescreens/add
Request Method:POST
Status Code:500 Internal Server Error
Remote Address:127.0.0.1:80
Request URL:http://dilib.local/services/webapi/administration/modulescreens/add
Request Method:POST
Status Code:500 Internal Server Error
Remote Address:127.0.0.1:80
POST /services/webapi/administration/modulescreens/add HTTP/1.1
Host: dilib.local
Connection: keep-alive
Content-Length: 322
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://dilib.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
Authorization: Bearer z1rjKoxXM2BjuJXpEWMN3hi4FRFIkh1Qy4U4NSfhkZ52d8lLHEBVkk-ILJ4QVYlXlIV_gNbFPI0ys91CFMytGs9pppIxbFLpStaq4pwm8PhIeOIXhIuhpC0XEQegNyMhYCj0EBQ5rdBiQIApBcUh4MvIfpCadOcrQChTUs2emKPmFYbEgSE-c6vRdLBe8HYwyYJgOndYHiVdQQsoNKd6rQ
Content-Type: application/json;charset=UTF-8
DNT: 1
Referer: http://dilib.local/ui.spa/administration/modules_screens
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,hu;q=0.6
{
    "moduleScreenId": 0,
    "moduleScreenName": "asdasd",
    "moduleScreenDesc": "asdasd",
    "moduleScreenSortNo": 0,
    "moduleScreenRoute": "asdasd",
    "moduleScreenIsEnabled": true,
    "moduleId": {
        "moduleName": "Blog",
        "moduleDesc": "Publish your thoughts",
        "moduleRoute": "blog",
        "moduleSortNo": 2,
        "moduleScreenDtos": null,
        "moduleIsEnabled": 1,
        "moduleId": 2
    }
}