asp.net-mvc 我可以将匿名类型传递给我的 ASP.NET MVC 视图吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/223713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I pass an anonymous type to my ASP.NET MVC view?
提问by Matt Hamilton
I've just started working with ASP.NET MVC now that it's in beta. In my code, I'm running a simple LINQ to SQL query to get a list of results and passing that to my view. This sort of thing:
我刚刚开始使用 ASP.NET MVC,现在它处于测试阶段。在我的代码中,我正在运行一个简单的 LINQ to SQL 查询来获取结果列表并将其传递给我的视图。这种事情:
var ords = from o in db.Orders
where o.OrderDate == DateTime.Today
select o;
return View(ords);
However, in my View, I realised that I'd need to access the customer's name for each order. I started using o.Customer.Namebut I'm fairly certain that this is executing a separate query for each order (because of LINQ's lazy loading).
但是,在我的视图中,我意识到我需要访问每个订单的客户姓名。我开始使用,o.Customer.Name但我相当确定这是为每个订单执行单独的查询(因为 LINQ 的延迟加载)。
The logical way to cut down the number of queries would be to select the customer name at the same time. Something like:
减少查询数量的合乎逻辑的方法是同时选择客户名称。就像是:
var ords = from o in db.Orders
from c in db.Customers
where o.OrderDate == DateTime.Today
and o.CustomerID == c.CustomerID
select new { o.OrderID, /* ... */, c.CustomerName };
return View(ords);
Except now my "ords" variable is an IEnumerable of an anonymous type.
除了现在我的“ords”变量是匿名类型的 IEnumerable。
Is it possible to declare an ASP.NET MVC View in such a way that it accepts an IEnumerable as its view data where T is defined by what gets passed from the controller, or will I have to define a concrete type to populate from my query?
是否可以声明一个 ASP.NET MVC 视图,它接受一个 IEnumerable 作为它的视图数据,其中 T 由从控制器传递的内容定义,或者我是否必须定义一个具体的类型来填充我的查询?
采纳答案by Haacked
Can you pass it to the view? Yes, but your view won't be strongly typed. But the helpers will work. For example:
你能把它传递给视图吗?是的,但您的视图不会是强类型的。但帮手会工作。例如:
public ActionResult Foo() {
return View(new {Something="Hey, it worked!"});
}
//Using a normal ViewPage
<%= Html.TextBox("Something") %>
That textbox should render "Hey, it worked!" as the value.
该文本框应该呈现“嘿,它起作用了!” 作为价值。
So can you define a view where T is defined by what gets passed to it from the controller? Well yes, but not at compile time obviously.
那么您能否定义一个视图,其中 T 由控制器传递给它的内容定义?嗯,是的,但显然不是在编译时。
Think about it for a moment. When you declare a model type for a view, it's so you get intellisense for the view. That means the type must be determined at compile time. But the question asks, can we determine the type from something given to it at runtime. Sure, but not with strong typing preserved.
想一想。当您为视图声明模型类型时,您就可以获得视图的智能感知。这意味着必须在编译时确定类型。但问题是,我们能否从运行时提供给它的东西中确定类型。当然,但不保留强类型。
How would you get Intellisense for a type you don't even know yet? The controller could end up passing any type to the view while at runtime. We can't even analyze the code and guess, because action filters could change the object passed to the view for all we know.
您将如何为您还不知道的类型获得智能感知?控制器最终可能会在运行时将任何类型传递给视图。我们甚至无法分析代码和猜测,因为动作过滤器可以更改传递给视图的对象,因为我们知道所有这些。
I hope that clarifies the answer without obfuscating it more. :)
我希望这能澄清答案,而不会对其进行更多的混淆。:)
回答by Lasse Skindstad Ebert
You canpass anonymous types to a view, just remember to cast the model to a dynamic.
您可以将匿名类型传递给视图,只需记住将模型转换为动态。
You can do like this:
你可以这样做:
return View(new {
MyItem = "Hello",
SomethingElse = 42,
Third = new MyClass(42, "Yes") })
In the top of the view you can then do this (using razor here)
在视图的顶部,您可以执行此操作(此处使用剃刀)
@{
string myItem = (dynamic)Model.MyItem;
int somethingElse = (dynamic)Model.SomethingElse;
MyClass third = (dynamic)Model.Third;
}
Or you can cast them from the ViewData like this:
或者你可以像这样从 ViewData 投射它们:
@{
var myItem = ViewData.Eval("MyItem") as string
var somethingElse = ViewData.Eval("SomethingElse") as int?
var third = ViewData.Eval("Third") as MyClass
}
回答by Adaptabi
回答by Raja
回答by Matt Hamilton
For what it's worth, tonight I discovered the DataLoadOptionsclass and its LoadWithmethod. I was able to tell my LINQ to SQL DataContext to always load a Customers row whenever an Orders row is retrieved, so the original query now gets everything I need in one hit.
无论如何,今晚我发现了DataLoadOptions类及其LoadWith方法。我能够告诉我的 LINQ to SQL DataContext 在检索 Orders 行时始终加载 Customers 行,因此原始查询现在可以一次性获得我需要的所有内容。
回答by Alper Ozcetin
You can write a class with the same properties of your anonymous type's, and you can cast your anonymous type to your hand-written type. The drawback is you have to update the class when you make projection changes in your linq query.
您可以编写一个与匿名类型具有相同属性的类,并且可以将匿名类型转换为手写类型。缺点是在 linq 查询中进行投影更改时必须更新类。
回答by AlexMelw
Remember:anonymoustypes are internal, which means their properties can't be seen outside their defining assembly.
请记住:anonymous类型是内部的,这意味着在定义程序集之外无法看到它们的属性。
You'd better pass dynamicobject (instead of anonymousone) to your Viewby converting anonymoustype to dynamic, using an extension method.
您最好使用扩展方法将类型转换为,从而将dynamic对象(而不是anonymous一个)传递给您。Viewanonymousdynamic
public class AwesomeController : Controller
{
// Other actions omitted...
public ActionResult SlotCreationSucceeded(string email, string roles)
{
return View("SlotCreationSucceeded", new { email, roles }.ToDynamic());
}
}
The extension method would look like this:
扩展方法如下所示:
public static class DynamicExtensions
{
public static dynamic ToDynamic(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
return (ExpandoObject) expando;
}
}
Nevertheless you are still ableto pass an anonymousobject, but you'll have to convert it to a dynamicone later on.
尽管如此,您仍然可以传递一个anonymous对象,但您必须稍后将其转换为一个对象dynamic。
public class AwesomeController : Controller
{
// Other actions omitted...
public ActionResult SlotCreationSucceeded(string email, string roles)
{
return View("SlotCreationSucceeded", new { email, roles });
}
}
View:
看法:
@{
var anonymousModel = DynamicUtil.ToAnonymous(Model, new { email = default(string), roles = default(string) });
}
<h1>@anonymousModel.email</h1>
<h2>@anonymousModel.roles</h2>
The helper method would look like this:
辅助方法如下所示:
public class DynamicUtil
{
public static T ToAnonymous<T>(ExpandoObject source, T sample)
where T : class
{
var dict = (IDictionary<string, object>) source;
var ctor = sample.GetType().GetConstructors().Single();
var parameters = ctor.GetParameters();
var parameterValues = parameters.Select(p => dict[p.Name]).ToArray();
return (T) ctor.Invoke(parameterValues);
}
}
回答by zadam
This postshows how you can return an anonymous type from a method, but it is not going to suit your requirements.
这篇文章展示了如何从方法返回匿名类型,但它不符合您的要求。
Another option may be to instead convert the anonymous type into JSON (JavaScriptSerializer will do it) and then return that JSON to the view, you would then need some jQuery etc to do what you like with it.
另一种选择可能是将匿名类型转换为 JSON(JavaScriptSerializer 会这样做),然后将该 JSON 返回到视图,然后您将需要一些 jQuery 等来执行您喜欢的操作。
I have been using Linq to 'shape' my data into a JSON format that my view needs with great success.
我一直在使用 Linq 将我的数据“塑造”成我的视图需要的 JSON 格式,并取得了巨大的成功。
回答by John Boker
you may be able to pass an Object and use reflection to get your desired results. Have a look at ObjectDumper.cs (included in csharpexamples.zip) for an example of this.
您可以传递一个对象并使用反射来获得所需的结果。请查看 ObjectDumper.cs(包含在 csharpexamples.zip 中)以获取示例。
回答by Mitch
If I'm not mistaken, anonymous types are converted into strongly typed objects at compile time. Whether the strongly typed object is valid for view data is another question though.
如果我没记错的话,匿名类型会在编译时转换为强类型对象。强类型对象是否对视图数据有效是另一个问题。

