4

私は、ViewBag.productsオブジェクトに渡すためにLinqからSQLへのクエリを構築しているコントローラーを持っています。問題は、予想どおりにforeachを使用してループできないことです。

.ToList()関数が適用された、クエリを構築するコントローラーのコードは次のとおりです。

var products = from bundles in db.Bundle
    join bProducts in db.BundleProducts on bundles.bundleId equals bProducts.bundleID
    join product in db.Products on bProducts.productID equals product.productID
    join images in db.Images on product.productID equals images.productID
    where bundles.bundleInactiveDate > DateTime.Now
          select new {
              product.productName,
              product.productExcerpt,
              images.imageID,
              images.imageURL
           };
ViewBag.products = products.ToList();

Index.cshtmlで必要な他のアイテムに別のモデルを使用しているので、単純なHtml.Partialを使用してビューバッグループを含めることができると思いました。パーシャルを使用する場合と使用しない場合で、index.cshtmlのforeachを使用するだけで、同じ結果で試してみました。パーシャルを含むスニペットは以下のとおりです。

<div id="bundle_products">
<!--build out individual product icons/descriptions here--->
@Html.Partial("_homeBundle")
</div>

私の_homeBundle.cshtmlファイルには、次のものがあります。

@foreach (var item in ViewBag.products)
{ 
    @item
}

ViewBagデータを取得していますが、リスト全体を出力として取得しています。

{ productName = Awesomenes Game, productExcerpt = <b>Awesome game dude!</b>, imageID = 13, imageURL = HotWallpapers.me - 008.jpg }{ productName = RPG Strategy Game, productExcerpt = <i>Test product excerpt</i>, imageID = 14, imageURL = HotWallpapers.me - 014.jpg }

私にできると思ったのは:

@foreach(var item in ViewBag.Products)
{
    @item.productName
}

ご覧のとおり、出力では、productName =AwesomenesGameです。ただし、これを実行しようとすると、「object」に「productName」の定義が含まれていないというエラーが表示されます。

ページに必要な適切なHTMLタグとスタイルを適用できるように、ループ内で個別に言うように、各「フィールド」を出力するにはどうすればよいですか?

これを行うには、まったく新しいViewModelを作成してから、ここで参照されているように表示テンプレートを作成する必要がありますか?'object'には'X'の定義が含まれていません

または、ここで試みていることを実行できますか?

*****アップデート*****

私のコントローラーには、次のものがあります。

        var bundle = db.Bundle.Where(a => a.bundleInactiveDate > DateTime.Now);
        var products = from bundles in db.Bundle
                       join bProducts in db.BundleProducts on bundles.bundleId equals bProducts.bundleID
                       join product in db.Products on bProducts.productID equals product.productID
                       join images in db.Images on product.productID equals images.productID
                       where bundles.bundleInactiveDate > DateTime.Now
                       select new {
                           product.productName,
                           product.productExcerpt,
                           images.imageID,
                           images.imageURL
                       };
        var bundleContainer = new FullBundleModel();

        bundleContainer.bundleItems = bundle;

        return View(bundleContainer);

私はモデル、FullBundleModelを持っています

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace JustBundleIt.Models
{
    public class FullBundleModel
    {
        public IQueryable<Bundles> bundleItems { get; set; }
        public IQueryable<Images> imageItems { get; set; }
    }
}

そして私のビューは今持っています

@model IEnumerable<JustBundleIt.Models.FullBundleModel>

@foreach (var item in Model) 
{
<div class="hp_bundle">

    <h3>@Html.Display(item.bundleName)</h3>
    </div>
}       

モデル参照からIEnumerableを削除すると、foreachは、列挙子のパブリック定義がないというエラーを出します。

@ Html.Display(item.bundleName)で、モデルにbundleNameの定義がないというエラーが発生します。しようとしたら

@foreach(var item in Model.bundleItems)

bundleItemsがモデルで定義されていないというエラーが表示されます。

では、組み合わせたモデルを使用するために正しく配線されていないのは何ですか?

4

2 に答える 2

2

これを行うには、まったく新しい ViewModel を作成し、ここで参照されているように表示テンプレートを作成する必要がありますか?

リンクしたDarin の回答には、重要な概念が記載されています。匿名型は、アセンブリの境界を越えて使用するためのものではなく、Razor では使用できません。匿名オブジェクトを直接のコンテキストの外に公開することは、めったに良い考えではないと付け加えておきます。

ビューの消費専用のビュー モデルを作成することは、ほとんどの場合、正しいアプローチです。同様のデータを表示している場合、ビュー モデルはビュー間で再利用できます。

表示テンプレートを作成する必要はありませんが、表示ロジックを再利用する場合に役立ちます。HTML ヘルパーも、再利用可能な表示ロジックを提供する同様の機能を果たすことができます。

とはいえ、匿名型をビューに渡したり、匿名型のメンバーを読み取ったりすることは不可能ではありません。ARouteValueDictionaryは (アセンブリ間でも) 匿名型を取り、そのプロパティを読み取ることができます。リフレクションにより、可視性に関係なくメンバーを読み取ることができます。これには用途がありますが、ビューにデータを渡すことはその用途の 1 つではありません

もっと読む:

于 2012-09-18T02:22:16.140 に答える
0

必要なすべてのデータを含む新しいモデルを作成してみませんか?

例1:

public class ContainerModel
{
    public IQueryable<T> modelOne;
    public IQueryable<T> modelTwo;
}

これにより、Razorのクエリのいずれかにアクセスできるようになります。

@model SomeNamespace.ContainerModel

@foreach (var item in Model.modelOne)
{
    //Do stuff
}

私は個人的にViewBagの使用をまったく避け、必要なものはすべてそのようなモデルに保存します。これは動的ではなく、すべてを強く型付けする必要があるためです。また、これにより明確に定義された構造/意図が得られると思います。

そして、わかりやすくするために:

public ViewResult Index()
{
    var queryOne = from p in db.tableOne
                   select p;

    var queryTwo = from p in db.tableTwo
                   select p;

    var containerModel = new ContainerModel();
    containerModel.modelOne = queryOne;
    containerModel.modelTwo = queryTwo;

    return View(containerModel);
}

例2:

public class ContainerModel
{
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] //Format: MM/dd/yyyy (Date)
    public Nullable<DateTime> startDate { get; set; }
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] //Format: MM/dd/yyyy (Date)
    public Nullable<DateTime> endDate { get; set; }
    public SelectList dropdown { get; set; }
    public IQueryable<T> modelOne { get; set; }
    public IQueryable<T> modelTwo { get; set; }
}

この場合、2つのクエリを使用してモデルに他の3つのアイテムを保存しました。Htmlヘルパーを使用して、Razorでドロップダウンリストを作成できます。

@Html.DropDownList("dropdown", Model.dropdown)

また、DisplayForヘルパーを使用して、データ注釈を使用してモデルで定義された日付を表示できます。

@Html.DisplayFor(a => a.startDate)

これは、ビューで使用するすべてのデータと、そのデータを1か所でフォーマットする方法を定義できるため、有利なIMOです。コントローラにはすべてのビジネスロジックが含まれ、モデルにはすべてのデータ/フォーマットが含まれ、ビューはページのコンテンツのみに関係します。

于 2012-09-18T02:47:55.153 に答える