Dynamic Mapping Api responses to Hypermedia inside a ResultFilter

21 views
Skip to first unread message

Bruno Mendonça

unread,
Feb 28, 2023, 8:22:08 AM2/28/23
to AutoMapper-users
I have a requirement to create a library that will be consumed by a set of Api's that will enhance the responses with Hypermedia metadata.

I have implemented an IAsyncResultFilter for the purpose of manipulating the responses. I have created a class that extends DynamicObject. This class, HypermediaResponse will be instantiated with all the relevant hypermedia metadata we want to add each particular hypermedia response. Then, I need to add to it the fields from the filter's context.Result.Value (for example an Order with Id, ProductId and Quantity, for simplicity). I thought of using AutoMapper to do that.

The Api's may already have Automapper configured. Something like ```services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());```. In that case they will also have some Profiles created.

However, I don't want developers to have to create new Profiles to map to the HypermediaResponse DynamicObject. The Hypermedia mapping should be as transparent as possible, with little to no intervention from the developers in most cases. Developers don't even need to know of HypermediaResponse. That will be encapsulated inside the library I am creating, that they will consume in the Api's.

My initial approach was to do this inside the filter's OnResultExecutionAsync method, after injecting the mapper through the filter's constructor:

```var response = _mapper.Map(result.Value, hypermediaResponse);```

However, I get ```Cannot implicitly convert type 'string' to 'System.Uri'```

Clearly, I need to setup some sort of mapping rules. So far I have only done so with profiles, but I really don't want to have to create individual profiles for each possible response.

Is there a way to create mapping rules/configuration on the fly for this purpose (that would not impact the rules/configuration/profiles the Api's may already have)?

I've also thought of creating a more generic Profile within the library that would map HypermediaResponse to object or some base class that the Api response classes would have to extend. However, I would prefer the solution above if it is achievable.

Any help would be appreciated.

Jimmy

unread,
Feb 28, 2023, 8:44:51 AM2/28/23
to automapp...@googlegroups.com

That specific exception just means there’s no mapping from “string” to “System.Uri”. If you create a type converter, it applies to ALL mappings (any CreateMap is global to a mapping configuration, profiles are for organization and common mapping rules).

 

There is no dynamic creation of maps on the fly. This is because AutoMapper does not validate maps at runtime. Without this runtime validation, members that don’t match will silently skipped. So you need to create maps once at startup.

--
You received this message because you are subscribed to the Google Groups "AutoMapper-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to automapper-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/automapper-users/ce99ca0e-07b8-4150-bfdc-4c842d7a48bbn%40googlegroups.com.

 

Bruno Mendonça

unread,
Feb 28, 2023, 12:09:58 PM2/28/23
to AutoMapper-users
Doesn't look like I would want to use a type converter. So, can I create a new mapping configuration on the IMapper I injected into my filter class? Or should I not inject the mapper and just do something like:

var config = new MapperConfiguration(cfg => cfg.CreateMap<MyObjectBaseClass, HypermediaResponse>());
var mapper = config.CreateMapper();var response = mapper.Map(result.Value, hypermediaResponse);

Jimmy

unread,
Feb 28, 2023, 12:14:54 PM2/28/23
to automapp...@googlegroups.com

If you do that, don’t use AutoMapper. AutoMapper is meant for one-time startup configuration, validating all mappings in a unit test. If you have more dynamic needs, don’t use AutoMapper.

Sunny

unread,
Feb 28, 2023, 12:41:36 PM2/28/23
to automapp...@googlegroups.com
While probably it can be done with automapper, you will need to resort to reflection in order ro enumerate the properties of the source. Maybe consider using Json.Net - serialize your metadata and source, and merge the result: https://www.newtonsoft.com/json/help/html/MergeJson.htm.



--
Svetoslav Milenov (Sunny)

Artificial Intelligence is no match for natural stupidity.
Reply all
Reply to author
Forward
0 new messages