0

I am using EF6 and doing some LINQ joins and then passing new structures to the view. Problem is it then throws Microsoft.CSharp.RuntimeBinder.RuntimeBinderException since these new joined structures are internal.

C#

 var carMains = this.DatabaseManager.carClaims.Join(this.DatabaseManager.carConvictions, l => l.request_id, r => r.request_id, (l, r) => new { l.claim_amount, r.conviction_driver }).Take(10);
 return View("CarJoin", carMains.ToList());

view

@model dynamic
@foreach (var m in Model)
{
    <br>
    <div>@(m.claim_amount ?? "")</div>
     <br>
    <div>@(m.conviction_driver ?? "")</div>
     <br>
}

The way I see it solution is to create object for each join and have strongly typed views which would be extremely time consuming as we are talking multiple db models with 200+ entities.

I am sure someone has already been in this situation by now and probably found some less time consuming solution. How can I pass structures to views without having to explicitly define them?

Community
  • 1
  • 1
Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265

1 Answers1

0

Sorted myself

After enumerating one can cast it to ExpandoObject and then view will be glad to handle dynamic

Expando extension in C#

public static class ExtensionMethods
{
    public static ExpandoObject ToExpando(this object obj)
    {
        IDictionary<string, object> expando = new ExpandoObject();
        foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(obj))
        {
            var value = propertyDescriptor.GetValue(obj);
            expando.Add(propertyDescriptor.Name, value == null || new[]
            {
                typeof (Enum),
                typeof (String),
                typeof (Char),
                typeof (Guid),
                typeof (Boolean),
                typeof (Byte),
                typeof (Int16),
                typeof (Int32),
                typeof (Int64),
                typeof (Single),
                typeof (Double),
                typeof (Decimal),
                typeof (SByte),
                typeof (UInt16),
                typeof (UInt32),
                typeof (UInt64),
                typeof (DateTime),
                typeof (DateTimeOffset),
                typeof (TimeSpan),
            }.Any(oo => oo.IsInstanceOfType(value))
                ? value
                : value.ToExpando());
        }

        return (ExpandoObject)expando;
    }
}

then query gets additional .ToList().Select(o => o.ToExpando()); like:

var carMains =
            this.DatabaseManager.GetEntities<carClaims>()
                .Join(this.DatabaseManager.GetEntities<carConvictions>(), l => l.request_id, r => r.request_id, (l, r) => new {l.claim_amount, r.conviction_driver})
                .Take(10)
                .ToList()
                .Select(o => o.ToExpando());
        return View("CarJoin", carMains.ToList());

view code does not change at all.

Hope this saves you some time.

Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265