ExpandoObject、匿名类型和Razor

5

我想在类型为ViewPage<dynamic>的Razor视图中使用ExpandoObject作为视图模型。但是这样做会出现错误。

ExpandoObject o = new ExpandoObject();
o.stuff = new { Foo = "bar" };
return View(o);

我应该怎么做才能让这个工作起来?

4个回答

15

你可以使用在这个问题中提到的扩展方法来实现:

Dynamic Anonymous type in Razor causes RuntimeBinderException

因此,你的控制器代码应该如下所示:

dynamic o = new ExpandoObject();
o.Stuff = new { Foo = "Bar" }.ToExpando();

return View(o);

然后是你的视图:

@model dynamic

@Model.Stuff.Bar

2
最终这个方法成功了。第一次尝试时它并没有起作用,因为我实际上是在做像 ctx.Foo.Select(x => new { Foo = "bar" }.ToExpandoObject()).SingleOrDefault() 这样的事情,而我应该做的是 ctx.Foo.Select(x => new { Foo = "bar" }).SingleOrDefault().ToExpandoObject() - kenwarner

4

使用开源 Dynamitey(在NuGet中)可以使用非常简洁的语法制作ExpandoObjects图表;

  dynamic Expando = Build<ExpandoObject>.NewObject;

  var o = Expando (
      stuff: Expando(foo:"bar")
  );

  return View(o);

1

我必须纠正一下,@gram的想法是正确的。然而,这仍然是修改您概念的一种方法。

编辑

您必须给.stuff一个类型,因为dynamic必须知道它正在处理什么类型的对象。

.stuff在设置为匿名类型时变为internal,因此@model dynamic在这里对您没有帮助

ExpandoObject o = new ExpandoObject();
o.stuff = MyTypedObject() { Foo = "bar" };
return View(o);

当然,还有MyTypedObject

public class MyTypedObject
{
    public string Foo { get; set; }
}

是的,这基本上就是我在这里提问之前所达到的地步。如果我需要创建MyTypedObject,最好放弃动态使用并回到强类型的视图模型:\ - kenwarner
@qntmfred 我认为 @gram 的想法是正确的。我测试了代码,它似乎能够解决问题。它肯定更接近于具体回答你的问题。 - David Fox
是的,他的方法有效。我也在他的答案下发表了评论 - 我第一次尝试时只是稍微做错了。 - kenwarner

0
尝试将类型设置为dynamic
dynamic o = new ExpandoObject();
o.stuff = new { Foo = "bar" };
return View(o);

请参阅关于ExpandoObject的优秀文章

1
虽然这样可以解决编译错误,但是在视图中如何访问@Model.stuff.Foo呢?dynamic对象必须知道其处理的对象类型。 - David Fox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接