Можно ли передать анонимный тип моему представлению ASP.NET MVC? - PullRequest
41 голосов
/ 22 октября 2008

Я только начал работать с ASP.NET MVC сейчас, когда он находится в бета-версии. В моем коде я выполняю простой запрос LINQ to SQL, чтобы получить список результатов и передать его на мой взгляд. Такого рода вещи:

var ords = from o in db.Orders
           where o.OrderDate == DateTime.Today
           select o;

return View(ords);

Однако в своем View я понял, что мне нужно будет получить доступ к имени клиента для каждого заказа. Я начал использовать 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 анонимного типа.

Можно ли объявить ASP.NET MVC View таким образом, чтобы он принимал IEnumerable в качестве данных своего представления, где T определяется тем, что передается из контроллера, или мне нужно будет определить конкретный тип для заполнения из моего запроса?

Ответы [ 11 ]

22 голосов
/ 22 октября 2008

Можете ли вы передать его на вид? Да, но ваше мнение не будет строго напечатано. Но помощники будут работать. Например:

public ActionResult Foo() {
  return View(new {Something="Hey, it worked!"});
}

//Using a normal ViewPage

<%= Html.TextBox("Something") %>

Это текстовое поле должно отображать "Эй, это сработало!" как значение.

Так вы можете определить представление, где T определяется тем, что передается ему от контроллера? Ну да, но не во время компиляции, очевидно.

Подумайте об этом на мгновение. Когда вы объявляете тип модели для представления, это значит, что вы получаете intellisense для представления. Это означает, что тип должен быть определен во время компиляции. Но возникает вопрос, можем ли мы определить тип из чего-то, данного ему во время выполнения. Конечно, но не с сильной типизацией.

Как бы вы получили Intellisense для типа, который вы еще даже не знаете? Контроллер может в конечном итоге передать любой тип в представление во время выполнения. Мы даже не можем анализировать код и догадываться, потому что фильтры действий могут изменить объект, переданный в представление, для всего, что мы знаем.

Надеюсь, это проясняет ответ, не запутывая его больше. :)

11 голосов
/ 13 января 2011

Вы можете передавать анонимные типы в представление, просто не забудьте преобразовать модель в динамический.

Вы можете сделать так:

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

В верхней части окна вы можете сделать это (используя бритву здесь)

@{
    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 
}
7 голосов
/ 15 апреля 2011

В .NET 4.0 анонимные типы могут быть легко преобразованы в ExpandoObjects, и, таким образом, все проблемы устраняются с помощью издержек самого преобразования. Проверьте здесь

4 голосов
/ 22 октября 2008

Сегодня вечером я обнаружил класс DataLoadOptions и его метод LoadWith . Я смог указать своему LINQ to SQL DataContext всегда загружать строку «Клиенты» при получении строки «Заказы», ​​поэтому исходный запрос теперь получает все, что мне нужно, за одно нажатие.

3 голосов
/ 12 ноября 2013

Здесь - статья, объясняющая передачу анонимного типа в Views и привязку данных.

Спасибо

1 голос
/ 25 июня 2009

Вы можете написать класс с теми же свойствами, что и у вашего анонимного типа, и вы можете привести свой анонимный тип к вашему рукописному типу. Недостатком является необходимость обновления класса при внесении изменений проекции в запрос linq.

1 голос
/ 22 октября 2008

Эта запись показывает, как вы можете вернуть анонимный тип из метода, но он не будет соответствовать вашим требованиям.

Другой вариант может заключаться в том, чтобы вместо этого преобразовать анонимный тип в JSON (JavaScriptSerializer сделает это), а затем вернуть этот JSON в представление, тогда вам потребуется jQuery и т. Д., Чтобы делать то, что вам нравится с ним.

Я использовал Linq для «преобразования» моих данных в формат JSON, который необходим моему представлению с большим успехом.

0 голосов
/ 21 мая 2018

Помните: anonymous типы являются внутренними, что означает, что их свойства не могут быть видны вне определяющей сборки.

Вам лучше передать объект dynamic (вместо anonymous one) в View, преобразовав тип anonymous в dynamic, используя метод расширения.

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

Тем не менее, вы все еще можете передать объект anonymous, но вам придется преобразовать его и dynamic один.

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);
    }
}
0 голосов
/ 23 июля 2009

У меня такая же проблема ... Подумав немного, я пришел к выводу, что самое правильное и наиболее масштабируемое решение - сериализация этого анонимного типа перед отправкой в ​​View. Таким образом, вы можете использовать тот же метод, чтобы заполнить страницу с помощью кода View и заполнить вашу страницу с помощью JSON

0 голосов
/ 22 октября 2008

Если я не ошибаюсь, анонимные типы преобразуются в строго типизированные объекты во время компиляции. Вопрос о том, является ли строго типизированный объект допустимым для данных представления, - это другой вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...