代码之家  ›  专栏  ›  技术社区  ›  Matt Hamilton

我可以将匿名类型传递给我的ASP.NET MVC视图吗?

  •  40
  • Matt Hamilton  · 技术社区  · 17 年前

    我刚刚开始使用ASP.NETMVC,现在它已经是beta版了。在我的代码中,我正在运行一个简单的LINQ到SQL查询,以获取结果列表并将其传递给我的视图。这类事情:

    var ords = from o in db.Orders
               where o.OrderDate == DateTime.Today
               select o;
    
    return View(ords);
    

    然而,在我看来,我意识到我需要访问每个订单的客户名称。我开始使用 o.Customer.Name 但我相当确定这是对每个订单执行一个单独的查询(因为LINQ的延迟加载)。

    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);
    

    但现在我的“ords”变量是匿名类型的IEnumerable。

    11 回复  |  直到 17 年前
        1
  •  25
  •   Haacked    14 年前

    你能把它传给观景台吗?是的,但是您的视图不会是强类型的。但是帮手会起作用的。例如:

    public ActionResult Foo() {
      return View(new {Something="Hey, it worked!"});
    }
    
    //Using a normal ViewPage
    
    <%= Html.TextBox("Something") %>
    

    那么,您可以定义一个视图,其中T是由从控制器传递给它的内容定义的吗?是的,但显然不是在编译时。

    想一想。当您为一个视图声明一个模型类型时,这样您就可以获得该视图的intellisense。这意味着类型必须在编译时确定。但问题是,我们能否根据运行时提供给它的内容来确定类型。当然可以,但不保留强类型。

    对于一种你还不知道的类型,你如何获得智能感知?控制器可能会在运行时向视图传递任何类型。我们甚至不能分析代码和猜测,因为动作过滤器可以改变传递给视图的对象。

    我希望这能澄清问题的答案,而不会使之更加混淆

        2
  •  16
  •   Lasse Skindstad Ebert    15 年前

    可以 将匿名类型传递给视图,只需记住将模型强制转换为动态类型。

    您可以这样做:

    return View(new { 
        MyItem = "Hello", 
        SomethingElse = 42, 
        Third = new MyClass(42, "Yes") })
    

    在视图的顶部,您可以执行此操作(此处使用razor)

    @{
        string myItem = (dynamic)Model.MyItem;
        int somethingElse = (dynamic)Model.SomethingElse;
        MyClass third = (dynamic)Model.Third;
    }
    

    也可以从ViewData中按如下方式强制转换它们:

    @{
        var myItem = ViewData.Eval("MyItem") as string
        var somethingElse = ViewData.Eval("SomethingElse") as int?
        var third = ViewData.Eval("Third") as MyClass 
    }
    
        3
  •  8
  •   Community Mohan Dere    9 年前

    退房 here

        4
  •  4
  •   Matt Hamilton    17 年前

    值得一提的是,今晚我发现了 DataLoadOptions LoadWith 方法我能够告诉我的LINQ to SQL DataContext在检索订单行时始终加载客户行,因此原始查询现在一次就可以获得我需要的所有内容。

        5
  •  4
  •   Baby Groot Duleendra    12 年前

    Here

    谢谢

        6
  •  1
  •   zadam    17 年前

    post 显示如何从方法返回匿名类型,但它不符合您的要求。

    另一种选择可能是将匿名类型转换为JSON(JavaScriptSerializer将执行此操作),然后将该JSON返回到视图,然后需要一些jQuery等来处理它。

    我一直在使用Linq将我的数据“塑造”成JSON格式,我的视图非常成功地需要这种格式。

        7
  •  1
  •   Alper    16 年前

    您可以使用匿名类型的相同属性编写类,并且可以将匿名类型强制转换为手写类型。缺点是在linq查询中进行投影更改时必须更新类。

        8
  •  1
  •   AlexMelw    6 年前

    anonymous

    你最好通过 dynamic 对象(而不是 匿名的 一)你的 View 通过转换 ,使用扩展方法。

    public class AwesomeController : Controller
    {
        // Other actions omitted...
        public ActionResult SlotCreationSucceeded(string email, string roles)
        {
            return View("SlotCreationSucceeded", new { email, roles }.ToDynamic());
        }
    }
    

    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;
        }
    }
    

    然而你是 通过 匿名的 一个以后。

    public class AwesomeController : Controller
    {
        // Other actions omitted...
        public ActionResult SlotCreationSucceeded(string email, string roles)
        {
            return View("SlotCreationSucceeded", new { email, roles });
        }
    }
    

    @{
        var anonymousModel = DynamicUtil.ToAnonymous(Model, new { email = default(string), roles = default(string) });
    }
    
    <h1>@anonymousModel.email</h1>
    <h2>@anonymousModel.roles</h2>
    

    助手方法如下所示:

    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);
        }
    }
    
        9
  •  0
  •   John Boker    17 年前

        10
  •  0
  •   Mitch    17 年前

    如果我没有弄错的话,匿名类型会在编译时转换为强类型对象。不过,强类型对象对于视图数据是否有效是另一个问题。

        11
  •  0
  •   Davi F Davi F    16 年前