質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • ASP.NET

    530questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • MVC

    224questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

  • Razor

    19questions

    RazorはASP.NET Web PagesとASP.NET MVCで使われているビュー・エンジンです。HTMLマークアップとC#またはVisual Basicのコードに対応しています。マークアップとコードの間の切り替えは"@"で記されています。

ASP.NET で Razor 記述部において表示と値を異なるものにする方法について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 306

nanairo_7_

score 12

質問
Modelと連結したViewの値について、int型の値を値に応じてstring型の異なる値で表示することはできないのだろうか、と思い質問投稿しました。

現在の状況
Modelを作成しデータベースと接続。その後、Scaffolding機能を用いてViewとModelを作成しました。

以下、具体的に質問内容を記します。
例えば、Viewに記された次の行について、(modelItem => item.AreaId)の値がModelで定義したデータモデルクラスAreaでデータベーステーブルに保存したIdと合致したAreaNameを表示するように変更したいです。

図をもって説明すると、現在「地域」「カテゴリー」「ユーザー名」で表示されているこれらの項目について、地域(1=>福岡)、カテゴリー(2=>車)、ユーザー名(高坂京介)のような感じで表示したいです。

![イメージ説明](c3085d4817b301e93b2462f21f4cbf02.png)

@Html.DisplayFor(modelItem => item.AreaId)
   public class Area
    {
        public int Id { get; set; }
        public int AreaName { get; set; }
    }

Modelの全体は以下の様に定義してあります。

using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace ForumMVC.Models.Forum
{
    class ForumModels
    {
    }

    public class Area
    {
        public int Id { get; set; }
        public int AreaName { get; set; }
    }

    public class Topic
    {
        public int Id { get; set; }
        [Required]
        [Display(Name = "地域")]
        public int AreaId { get; set; }
        [Required]
        [Display(Name = "カテゴリー")]
        public int CategoryId { get; set; }
        [Required]
        [Display(Name = "タイトル")]
        public string Title { get; set; }
        [Required]
        [Display(Name = "本文")]
        public string Contents { get; set; }
        [Required]
        [Display(Name = "ユーザー名")]
        public int TopicOwnerId { get; set; }
    }

    public class ForumConnection : DbContext
    {
        public DbSet<Topic> Topics { get; set; }
    }
}

Viewの全体は以下の様に定義してあります。

@model IEnumerable<ForumMVC.Models.Forum.Topic>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.AreaId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.CategoryId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Title)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Contents)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.TopicOwnerId)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.AreaId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.CategoryId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Contents)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TopicOwnerId)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}

</table>

Controllerは以下の様に定義してあります。(必要そうな所だけ抜粋)

        // GET: NewTopic
        public ActionResult Index()
        {
            return View(db.Topics.ToList());
        }

自分でも解決を試みようとは思ったのですが、データセットクラスを複数のテーブルから作成するなどで対処するのではないかと考えたのですが、手が付けられない状態です。
長文の質問投稿になり申し訳ありませんが、宜しくお願いします。

使用環境等
Windows7
VS2017
ASP.NET MVC5
Net Framework 4.6.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • SurferOnWww

    2018/06/26 07:45

    データベースに「トピックス」「地域」「カテゴリー」「ユーザー」と言うテーブルを作る必要があるはずですが、それらはどうなってますか? 今のコードを見ると EF Code First で作るにしても「トピックス」テーブルしか生成されないように見えますが? 追加するとして、ナビゲーションプロパティはどうしますか?

    キャンセル

  • nanairo_7_

    2018/06/27 06:44

    回答にも記したので再三になり申し訳ありませんが、「ナビゲーションプロパティ」とはなんなのか、ということです躓いてしまっているので、少し触り方を調べてからまた質問欄に投稿します。もしよろしければ再度ご教授いただけたらとても嬉しいです。

    キャンセル

回答 2

checkベストアンサー

+1

質問に対する私のコメントへの返答をもらってませんので、質問者さんの都合はちょっと置いといての一方的な話ですが、こうすれば望むことはできるということを書いておきます。

Modelを作成しデータベースと接続。その後、Scaffolding機能を用いてViewとModelを作成しました。

データーベースが基になっているようですので、最初にデータベースの構造をきちんと設計するところから始めてください。

きちんと設計というのは、データベースに「トピックス」「地域」「カテゴリー」「ユーザー」と言うテーブルを作って、必要な外部キー制約を張ることです。

その上で、Visual Studio を利用してそのデーターベースを元に Entity Data Model を作れば、必要なコンテキストクラスや、ナビゲーションプロパティが定義されたテーブルのクラスが生成されます。そこまでが上の質問者さんの言う「Modelを作成」になるべきです。

Model がきちんとできていれば、それをベースに Visual Studio のスキャフォールディング機能を利用すれば、自動的に Model を通じてデーターベースへの接続が行われ、 Create, Read, Update, Delete (CRUD) 操作を行うために必要な Controller と View のコードが一式自動生成されます。

その中で一覧を表示する Index の Controller, View のコードでは、ナビゲーションプロパティを使って、数字ではなく名前(例えば、地域では 1 ⇒ 福岡)を表示するようになります。

その具体例は以下の記事を見てください。

スキャフォールディング機能
http://surferonwww.info/BlogEngine/post/2017/07/23/creating-controller-and-view-in-mvc-using-scaffolding-function.aspx

記事では、Microsoft が提供するサンプルデータベース Northwind の Products, Catagories, Suppliers を使っています。質問者さんの例で言うと「トピックス」「カテゴリー」「ユーザー」に該当するという感じです。Products テーブルから、Catagories, Suppliers テーブルの主キーに外部制約がかかっています。

それをベースに Visual Studio で Entity Data Model を生成すると(方法は上に紹介した記事を読んでください)、以下のコンテキストクラスとターブルクラスが生成されます。Products.cs の中のナビゲーションプロパティ Categoties, Suppliers に注目してください。

NorthwindEdm.Context.cs

namespace Mvc5App
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;

    public partial class NORTHWINDEntities : DbContext
    {
        public NORTHWINDEntities()
            : base("name=NORTHWINDEntities")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public virtual DbSet<AspNet_SqlCacheTablesForChangeNotification> AspNet_SqlCacheTablesForChangeNotification { get; set; }
        public virtual DbSet<Categories> Categories { get; set; }
        public virtual DbSet<CustomerDemographics> CustomerDemographics { get; set; }
        public virtual DbSet<Customers> Customers { get; set; }
        public virtual DbSet<Employees> Employees { get; set; }
        public virtual DbSet<Order_Details> Order_Details { get; set; }
        public virtual DbSet<Orders> Orders { get; set; }
        public virtual DbSet<Products> Products { get; set; }
        public virtual DbSet<Region> Region { get; set; }
        public virtual DbSet<Shippers> Shippers { get; set; }
        public virtual DbSet<Suppliers> Suppliers { get; set; }
        public virtual DbSet<Territories> Territories { get; set; }
    }
}

Products.cs

namespace Mvc5App
{
    using System;
    using System.Collections.Generic;

    public partial class Products
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Products()
        {
            this.Order_Details = new HashSet<Order_Details>();
        }

        public int ProductID { get; set; }
        public string ProductName { get; set; }
        public Nullable<int> SupplierID { get; set; }
        public Nullable<int> CategoryID { get; set; }
        public string QuantityPerUnit { get; set; }
        public Nullable<decimal> UnitPrice { get; set; }
        public Nullable<short> UnitsInStock { get; set; }
        public Nullable<short> UnitsOnOrder { get; set; }
        public Nullable<short> ReorderLevel { get; set; }
        public bool Discontinued { get; set; }

        public virtual Categories Categories { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<Order_Details> Order_Details { get; set; }
        public virtual Suppliers Suppliers { get; set; }
    }
}

Categories.cs

namespace Mvc5App
{
    using System;
    using System.Collections.Generic;

    public partial class Categories
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Categories()
        {
            this.Products = new HashSet<Products>();
        }

        public int CategoryID { get; set; }
        public string CategoryName { get; set; }
        public string Description { get; set; }
        public byte[] Picture { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<Products> Products { get; set; }
    }
}

Suppliers.cs

namespace Mvc5App
{
    using System;
    using System.Collections.Generic;

    public partial class Shippers
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Shippers()
        {
            this.Orders = new HashSet<Orders>();
        }

        public int ShipperID { get; set; }
        public string CompanyName { get; set; }
        public string Phone { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<Orders> Orders { get; set; }
    }
}

上の Entity Data Model をベースにスキャフォールディング機能を利用して Controller と View を生成すれば、自力では一行もコードを書かずに望むことができるはずです。

一覧 (Index) 画面用の Controller と View コードを以下にアップしておきます。CatrgoryID, SupplierID(数字)ではなく、ナビゲーションプロパティをたどって CategoryName, CompanyName を取得してそれが表示されるようになっています。さらに、Linq 式に Include メソッドを使いプロパティを先読みするという配慮もされています。

Controller

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Mvc5App;

namespace Mvc5App.Controllers
{
    public class ProductsController : Controller
    {
        private NORTHWINDEntities db = new NORTHWINDEntities();

        // GET: Products
        public ActionResult Index()
        {
            var products = db.Products.Include(p => p.Categories).Include(p => p.Suppliers);
            return View(products.ToList());
        }
    }
}

View

@model IEnumerable<Mvc5App.Products>

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.ProductName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.QuantityPerUnit)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.UnitPrice)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.UnitsInStock)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.UnitsOnOrder)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ReorderLevel)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Discontinued)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Categories.CategoryName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Suppliers.CompanyName)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ProductName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.QuantityPerUnit)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.UnitPrice)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.UnitsInStock)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.UnitsOnOrder)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ReorderLevel)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Discontinued)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Categories.CategoryName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Suppliers.CompanyName)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ProductID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ProductID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ProductID })
        </td>
    </tr>
}

</table>

本題とは関係ない話ですが、もし LocalDB で Northwind を使いたいという場合は以下の記事を参考にしてください。

LocalDB で Northwind と Pubs を利用
http://surferonwww.info/BlogEngine/post/2017/05/16/use-northwind-and-pubs-on-localdb-2016.aspx

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/27 06:42

    返信が遅くなり申し訳ありません。
    ナビゲーションプロパティという単語を初めて見聞きし、概念はおそらく理解できているのですが記述方法等のアプローチの理解にしばらくの時間を要しそうなので、教えていただいた参考urlを元に再度手をつけてみようと思います。
    自分では絶望的な状況でしたのでとてもありがたいです。
    ありがとうございます!

    キャンセル

  • 2018/06/27 10:45

    上の回答にも書きましたが、virtual キーワードのついている Categoties, Suppliers がナビゲーションプロパティです。

    DB First で、既存の DB の外部キー制約の付与されているテーブルをベースに EDM を生成すると、自動的にコードにナビゲーションプロパティが含まれるようになります。

    逆に、Code First でナビゲーションプロパティを定義して DB を生成すると、生成される DB のテーブルに定義に従って外部キー制約が付与されます。

    外部キー制約は SQL Server などの DB の、ナビゲーションプロパティは Entity Framework の基本のキに近いことですので、ググるなどすれば十分な情報は得られると思いますので調べてみてください。

    キャンセル

  • 2018/06/27 10:50

    ちなみに、既存の DB のテーブルに外部キー制約が付与されてない場合(そういうのはきちんと設計されているとは言えないと思いますが)とか、データソースが異なるのでそういうことが不可能な場合は、クエリで結合して望む結果を得ることができます。具体例は以下の記事を見てください。

    異なるデータソースの結合と表示
    http://surferonwww.info/BlogEngine/post/2017/11/26/how-to-join-and-show-the-records-from-different-data-sources.aspx

    キャンセル

  • 2018/07/02 17:08

    いきなり複雑な形態で試して意味わからなすぎて混乱したので、とりあえず以下の簡単なものから始めてみたところ、ようやく以下の3テーブルで上手くいって理解できました。
    これから質問時のテーブルに外部キーを組み込み再挑戦します。ありがとうございました!

    Areas
    -Id
    Name

    Users
    -Id
    -Name

    Topics
    -Id
    -AreaId
    -UserId
    -TopicTitle
    外部キー
    CONSTRAINT[FK_Topics_Area] FOREIGN KEY ([AreaId]) REFERENCES [dbo].[Areas]([Id]),
    CONSTRAINT[FK_Topics_Users] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users]([Id])

    キャンセル

0

Topicsクラスに名称が必要な各IDに対応するstring型のプロパティを定義する方法はいかがでしょうか。
TopicOwnerIdに対応する名称があるならば、string型のTopicOwnerNameのようなプロパティを定義して、表示に使います。

編集処理等でデータを送信する際にTopicOwnerIdが必要な場合、hiddenにセットしておけば画面に見えませんが、IDを持たせておくこともできます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/26 10:29

    データーベースが基になっているようですので、最初にデータベースの構造をきちんと設計するところから話を始めるべきだと思います。きちんとできていれば、DB First でも Code First でもナビゲーションプロパティが定義されるはずですので、それを使って取得するのが、ASP.NET MVC + Linq to Entiries では普通のやりかたです。(だから上のコメントで質問しているのですが)

    キャンセル

  • 2018/06/26 13:58

    ここではDBの設計ではなく、あくまでご質問内容の仕様で、IDに応じた名称をどうやって表示させるかということと認識しましたので、上記で回答した次第です。

    キャンセル

  • 2018/06/26 14:12

    質問者さんの過去スレッドを見ると初学者の方のようですので、まずは ASP.NET MVC でごく一般的な方法をベースに話を進めるべきだと思います。でないと、ミスリードすることになるかもしれません。

    そもそも、どこにどのような形で必要な情報を保持しておくか、それからどのように取得するかは提案されてないようですが、それはどうするつもりだったのでしょう? DB 以外に適当&現実的な場所があるのでしょうか?

    キャンセル

  • 2018/06/26 16:08

    質問内容から、DBから任意のデータの取得やプロパティへのセット等は行えるものと解釈しております。
    が、おっしゃる通り、質問者さんの背景や質問内容以外のことを考慮すると、この限りではありませんね。

    キャンセル

  • 2018/06/27 06:40

    お二方ともに丁寧な解説をありがとうございます。御察しの通り、開発(?)そのものも未経験で独学でやってる初学者です。

    ToricクラスにIDに対応したものをstring型で呼び出す方法があることも知らなかったので模索してみます。今回は他のテーブルとの連携が必要な場面になりそうですが、intをstringに置き換えたい場面は今後来るはずなので今習得します。本当にありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • ASP.NET

    530questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • MVC

    224questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

  • Razor

    19questions

    RazorはASP.NET Web PagesとASP.NET MVCで使われているビュー・エンジンです。HTMLマークアップとC#またはVisual Basicのコードに対応しています。マークアップとコードの間の切り替えは"@"で記されています。