UmbracoMapper custom mapping not working with Umbraco 7.4.1
Hi.
I am trying to get UmbracoMapper to work with mapping a related links data type using a custom mapping. My code is as follows:
Models:
public class HomeViewModel
{
public IEnumerable<NavLink> NavigationLinks { get; set; }
}
public class NavLink
{
public string Title { get; set; }
public string Caption { get; set; }
[JsonProperty("type")]
public string LinkType { get; set; }
public bool NewWindow { get; set; }
public bool IsInternal { get; set; }
public string Link { get; set; }
public string InternalName { get; set; }
}
Mapper use:
var mapper = new UmbracoMapper();
mapper.AddCustomMapping(typeof(IEnumerable<NavLink>).FullName, MapRelatedLinksContent);
var viewModel = new HomeViewModel();
mapper.Map(CurrentPage, viewModel);
This works perfectly well using Umbraco 7.3.4, but when I try the same code in Umbraco 7.4.1 the following exception is thrown on the mapper.Map() line:
An exception of type 'System.ArgumentException' occurred in mscorlib.dll but was not handled in user code
Additional information: Object of type 'Newtonsoft.Json.Linq.JArray'
cannot be converted to type
'System.Collections.Generic.IEnumerable`1[Test_UmbracoMapper.Models.NavLink]'.
Any help with resolving this issue or a working example for Umbraco 7.4.1 would be appreciated.
The JsonConvert operation works fine with IEnumerable as just running the following results in a properly deserialised collection (I have tested this in isolation):
string relatedLinks = CurrentPage.GetPropertyValue<string>("navigationLinks");
var result = JsonConvert.DeserializeObject<IEnumerable<NavLink>>(relatedLinks);
Not sure is the quick but not very useful reply Al. But just wanted to respond to say I'll take a look at this later this week, as am away at the moment. Wasn't aware of any compatibility changes with Umbraco 7.4 but could be you've found one.
If it's any use, I also tried mapping an Archetype property following the method detailed in this article
I got a similar exception thrown when calling the Map method. It didn't even get into the custom mapping method as I put a breakpoint in the method which was never hit.
I've figured out the issue now Al, it's due to the fact that with Umbraco 7.4 we now have the "Models Builder" shipped with the core product and enabled by default. You should be able to get things working again just by disabling this, via the following web.config setting:
The reason this being enabled is causing a problem for Umbraco Mapper is that this package is all about mapping from IPublishedContent items. It looks first for any native properties - existing strongly typed fields (e.g. Id, Name, Url) - and maps those. And then it handles the custom fields you've created on the document type.
With models builder set up, then you would already have strongly typed fields being generated, and Umbraco Mapper is then attempting to map those as if they were all native properties. For primitive types like strings and numbers it would do so successfully, but for related links (and others like Archetype where a chunk of JSON is used), it's trying to map a JArray to an IEnumerable and not succeeding.
So could this be made to work? Possibly, but I'm not sure it's a good idea - though would be interested in others opinions on this.
I would suggest Umbraco Mapper (or I imagine Ditto which I believe is similar in it's approach to mapping to view models) can certainly still be used with Umbraco 7.4 onwards, but I'm not convinced it makes sense to use them as well as Models Builder.
For me I'd suggest one of two approaches should be used.
Turn Models Builder off and continue using Umbraco Mapper or Ditto to map from IPublishedContent to strongly typed view models. I still like this approach over Models Builder on it's own as then our views are working with true view models and not just representations of a single document type (which are strongly typed, but don't account for anything else we might want in the view, like information drawn from other content nodes). For me this would be the equivalent in a standard MVC application of passing our "domain" model to our view, which is often considered something best avoided.
Decide we like the strongly typed content models over IPublishedContent but then still maintain a distinction between these and the view models. We then need a method of mapping from one strongly typed model to the other, for which I'd likely look to use AutoMapper, which is much better established in this space and by this point there's nothing Umbraco specific that needs doing.
I discussed this distinction a couple of years back in this blog post if interested in reading further.
I'll probably expand on this at some point in another blog post or something - and as I say, interested in other opinions on this - but meantime, the short answer is I don't suspect if you are using Umbraco Mapper you are also using Models Builder, and if not, you can just turn the latter off.
I would certainly like to use Umbraco Mapper as we want to go down the strongly typed view route with our Umbraco projects. I'll discuss with our team here but will most likely disable Models Builder as suggested.
Many thanks for the swift reply, it's good that there looks to be a resolution for this.
UmbracoMapper custom mapping not working with Umbraco 7.4.1
Hi.
I am trying to get UmbracoMapper to work with mapping a related links data type using a custom mapping. My code is as follows:
Models:
Mapper use:
Mapping method:
This works perfectly well using Umbraco 7.3.4, but when I try the same code in Umbraco 7.4.1 the following exception is thrown on the mapper.Map() line:
Any help with resolving this issue or a working example for Umbraco 7.4.1 would be appreciated.
Many thanks.
Hi,
Have you tried deserializing to a List<> instead?
Could be that newtonsoft json cannot convert to an interface (IEnumerable<>) and need the implemented class (List or equal)
/Martin
Hi Martin.
The JsonConvert operation works fine with IEnumerable as just running the following results in a properly deserialised collection (I have tested this in isolation):
Not sure is the quick but not very useful reply Al. But just wanted to respond to say I'll take a look at this later this week, as am away at the moment. Wasn't aware of any compatibility changes with Umbraco 7.4 but could be you've found one.
Andy
OK, great. Thanks Andy.
If it's any use, I also tried mapping an Archetype property following the method detailed in this article
I got a similar exception thrown when calling the Map method. It didn't even get into the custom mapping method as I put a breakpoint in the method which was never hit.
Al
I've figured out the issue now Al, it's due to the fact that with Umbraco 7.4 we now have the "Models Builder" shipped with the core product and enabled by default. You should be able to get things working again just by disabling this, via the following web.config setting:
The reason this being enabled is causing a problem for Umbraco Mapper is that this package is all about mapping from IPublishedContent items. It looks first for any native properties - existing strongly typed fields (e.g. Id, Name, Url) - and maps those. And then it handles the custom fields you've created on the document type.
With models builder set up, then you would already have strongly typed fields being generated, and Umbraco Mapper is then attempting to map those as if they were all native properties. For primitive types like strings and numbers it would do so successfully, but for related links (and others like Archetype where a chunk of JSON is used), it's trying to map a JArray to an IEnumerable and not succeeding.
So could this be made to work? Possibly, but I'm not sure it's a good idea - though would be interested in others opinions on this.
I would suggest Umbraco Mapper (or I imagine Ditto which I believe is similar in it's approach to mapping to view models) can certainly still be used with Umbraco 7.4 onwards, but I'm not convinced it makes sense to use them as well as Models Builder.
For me I'd suggest one of two approaches should be used.
Turn Models Builder off and continue using Umbraco Mapper or Ditto to map from IPublishedContent to strongly typed view models. I still like this approach over Models Builder on it's own as then our views are working with true view models and not just representations of a single document type (which are strongly typed, but don't account for anything else we might want in the view, like information drawn from other content nodes). For me this would be the equivalent in a standard MVC application of passing our "domain" model to our view, which is often considered something best avoided.
I discussed this distinction a couple of years back in this blog post if interested in reading further.
I'll probably expand on this at some point in another blog post or something - and as I say, interested in other opinions on this - but meantime, the short answer is I don't suspect if you are using Umbraco Mapper you are also using Models Builder, and if not, you can just turn the latter off.
Andy
Hi Andy.
I would certainly like to use Umbraco Mapper as we want to go down the strongly typed view route with our Umbraco projects. I'll discuss with our team here but will most likely disable Models Builder as suggested.
Many thanks for the swift reply, it's good that there looks to be a resolution for this.
Al
is working on a reply...