ViewComponent View() fails on CoreCLR with IEnumerable<> passed in #1354
Comments
Do you know how model metadata is supposed to behave in this case? |
This seems to be less related to view components and more related to passing an IEnumerable to a View. |
It doesn't matter what the view is. You can just have an empty one. |
@BrennanConroy - I am not able to repro this scenario. [ViewComponent(Name = "Test")]
public class TestViewComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
var kk = new List<Person>()
{
new Person() { Name = "Hello" },
new Person() { Name = "World" }
};
return View(kk as IEnumerable<Person>);
}
} My View calls this like: @await Component.InvokeAsync("Test") The build I am using is - |
Change the |
So, the scenario which was pointed out does not work only for Anonymous objects. And we are not currently planning to support binding Anonymous objects. Please refer this issue - #1484 - for more details. |
Could you please explain your comment about Anonymous objects? The scenario I am pointing out doesn't involve anonymous objects that I can see and it is an issue of something that works in Desktop CLR but not Core CLR |
So, when you do a |
Actually, I am wrong. |
This seems to be a bug in CoreCLR. I have contacted the CoreCLR team with this repro: public class Program
{
public void Main(string[] args)
{
var range = Enumerable.Range(0, 10).Select(x => x);
var prop = range.GetType().GetProperty("Current");
var propertyGetterAsFunc = prop.GetMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(range.GetType(), typeof(int)));
Console.WriteLine(propertyGetterAsFunc);
}
} Will follow up. |
…passed in. Fix - When the model is passed in to a View, ViewDataDictionary sets it. During this process, we recurse through all the properties and create FastPropertyGetters for each of them. In this case, since it is an enumerable, the properties which we recurse through are not the elements of the collection but the properties of the Enumerable instead. i.e - Enumerable.Current. Creating getters for these properties are not necessary. The fix moves the property iteration step to a place where the properties are actually requested.
…passed in. Fix - When the model is passed in to a View, ViewDataDictionary sets it. During this process, we recurse through all the properties and create FastPropertyGetters for each of them. In this case, since it is an enumerable, the properties which we recurse through are not the elements of the collection but the properties of the Enumerable instead. i.e - Enumerable.Current. Creating getters for these properties are not necessary. The fix moves the property iteration step to a place where the properties are actually requested.
…passed in. Fix - When the model is passed in to a View, ViewDataDictionary sets it. During this process, we recurse through all the properties and create FastPropertyGetters for each of them. In this case, since it is an enumerable, the properties which we recurse through are not the elements of the collection but the properties of the Enumerable instead. i.e - Enumerable.Current. Creating getters for these properties are not necessary. The fix moves the property iteration step to a place where the properties are actually requested. - Splitting TypeInformation class into two and separating their caches appropriately.
This is checked in - 07043ce |
I have a ViewComponent and on InvokeAsync I grab some data from a database and give it to the View.
var query = Context.SomeTable.ToArray();
return View(query.Select(e => new Model
{
Value = e.Val;
Count = e.Count;
}));
A stack trace is at the bottom for the above.
If I Instead do:
var temp = query.Select(e => new Model
{
Value = e.Val;
Count = e.Count;
}).ToArray();
return View(temp);
That will work on Core now.
Stack trace:
System.MethodAccessException: Attempt by method 'Microsoft.AspNet.Mvc.PropertyHelper.MakeFastPropertyGetter(System.Reflection.PropertyInfo)' to access method 'System.Linq.Enumerable+Iterator
1<System.__Canon>.get_Current()' failed. at System.Delegate.BindToMethodInfo(Object target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags) at System.Delegate.UnsafeCreateDelegate(RuntimeType rtType, RuntimeMethodInfo rtMethod, Object firstArgument, DelegateBindingFlags flags) at System.Delegate.CreateDelegateInternal(RuntimeType rtType, RuntimeMethodInfo rtMethod, Object firstArgument, DelegateBindingFlags flags, StackCrawlMark& stackMark) at System.Reflection.RuntimeMethodInfo.CreateDelegateInternal(Type delegateType, Object firstArgument, DelegateBindingFlags bindingFlags, StackCrawlMark& stackMark) at System.Reflection.RuntimeMethodInfo.CreateDelegate(Type delegateType) at Microsoft.AspNet.Mvc.PropertyHelper.MakeFastPropertyGetter(PropertyInfo propertyInfo) at Microsoft.AspNet.Mvc.PropertyHelper..ctor(PropertyInfo property) at Microsoft.AspNet.Mvc.PropertyHelper.CreateInstance(PropertyInfo property) at Microsoft.AspNet.Mvc.PropertyHelper.<>c__DisplayClass0.<GetProperties>b__3(PropertyInfo p) at System.Linq.Enumerable.WhereSelectArrayIterator
2.MoveNext()at System.Linq.Buffer
1..ctor(IEnumerable
1 source)at System.Linq.Enumerable.ToArray[TSource](IEnumerable
1 source) at Microsoft.AspNet.Mvc.PropertyHelper.GetProperties(Type type, Func
2 createPropertyHelper, ConcurrentDictionary2 cache) at Microsoft.AspNet.Mvc.PropertyHelper.GetProperties(Type type) at Microsoft.AspNet.Mvc.ModelBinding.AssociatedMetadataProvider
1.CreateTypeInformation(Type type, IEnumerable1 associatedAttributes) at Microsoft.AspNet.Mvc.ModelBinding.AssociatedMetadataProvider
1.GetTypeInformation(Type type, IEnumerable1 associatedAttributes) at Microsoft.AspNet.Mvc.ModelBinding.AssociatedMetadataProvider
1.GetMetadataForType(Func1 modelAccessor, Type modelType) at Microsoft.AspNet.Mvc.ViewDataDictionary.SetModel(Object value) at Microsoft.AspNet.Mvc.ViewDataDictionary
1.SetModel(Object value)at Microsoft.AspNet.Mvc.ViewDataDictionary`1.set_Model(TModel value)
at Microsoft.AspNet.Mvc.ViewComponent.View[TModel](String viewName, TModel model)
at Microsoft.AspNet.Mvc.ViewComponent.View[TModel](TModel model)
at Namespace.Component.MyCompComponent.d__1.MoveNext() in FileName\Components\MyComp.cs:line 80
The text was updated successfully, but these errors were encountered: