Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Automapper to map from dynamic/JObject to arbitrary types without creating multiple maps

In an ASP.NET Core controller method, which has a parameter of type dynamic, I would like to map using Automapper as shown below. The method looks like this:

public IActionRsult Post([FromBody] dynamic model) {
  // Skip validation
  switch(model.src) {
    case "employer"
      var employerVM = _mapper.Map<EmployerViewModel>(model.data);
      // Work with mapped object
    break;
    case "employee"
      var employeeVM = _mapper.Map<EmployeeViewModel>(model.data);
      // Work with mapped object
    break;
  }
}

where EmployerViewModel looks like this:

public class EmployerViewModel {
   public string CompanyName {get; set;}
   public string CompanyAddress {get; set;}
}

and EmployeeViewModel looks like this:

public class EmployeeViewModel {
   public string FirstName {get; set;}
   public string LastName {get; set;}
   public bool Ready {get; set;} 
}

It receives JSON data from the client side, which may look like this:

{
  "src": "employer",
  "data": {
    "CompanyName": "Pioneers Ltd.",
    "CompanyAddress": "126 Schumacher St., London" 
  }
}

or this:

{
  "src": "employee",
  "data": {
    "FirstName": "John",
    "LastName": "Doe",
    "Ready": true
  }
}

Now everything works fine except for boolean properties, which are always set to false no matter what the value in JSON is. I have JSON input formatter, which constructs the instances in the parameter. I've checked the type of the instances and found them to be Newtonsoft.Json.Linq.JObject

Any idea how I can get bools to behave correctly?

I would like to continue supporting mapping an arbitrary number of destination classes using the TDestination IMapper.Map<TDestination>(object source) (see here) without having to explicitly construct AutoMapper maps for each. Any hint how this can be achieved?

P.S. I'm using AutoMapper 6.2.1 and ASP.NET Core 1.1.3

like image 858
Bahaa Avatar asked Sep 15 '25 12:09

Bahaa


1 Answers

The problem is that JObject wraps its content in JValue, so it cannot work by default with AM which of course expects the actual values. So you have to let AM know how to map a JValue:

cfg.CreateMap<JValue, object>().ConvertUsing(source => source.Value);
like image 86
Lucian Bargaoanu Avatar answered Sep 18 '25 08:09

Lucian Bargaoanu