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

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

新規登録して質問してみよう
ただいま回答率
85.37%
MVC

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

Razor

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

ASP.NET

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

Q&A

解決済

2回答

24456閲覧

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

pomu.pomupomu

総合スコア18

MVC

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

Razor

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

ASP.NET

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

0グッド

0クリップ

投稿2018/06/25 10:26

編集2018/06/25 10:29

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

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

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

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

イメージ説明

C#

1@Html.DisplayFor(modelItem => item.AreaId)

C#

1 public class Area 2 { 3 public int Id { get; set; } 4 public int AreaName { get; set; } 5 }

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

C#

1using System.ComponentModel.DataAnnotations; 2using System.Data.Entity; 3 4namespace ForumMVC.Models.Forum 5{ 6 class ForumModels 7 { 8 } 9 10 public class Area 11 { 12 public int Id { get; set; } 13 public int AreaName { get; set; } 14 } 15 16 public class Topic 17 { 18 public int Id { get; set; } 19 [Required] 20 [Display(Name = "地域")] 21 public int AreaId { get; set; } 22 [Required] 23 [Display(Name = "カテゴリー")] 24 public int CategoryId { get; set; } 25 [Required] 26 [Display(Name = "タイトル")] 27 public string Title { get; set; } 28 [Required] 29 [Display(Name = "本文")] 30 public string Contents { get; set; } 31 [Required] 32 [Display(Name = "ユーザー名")] 33 public int TopicOwnerId { get; set; } 34 } 35 36 public class ForumConnection : DbContext 37 { 38 public DbSet<Topic> Topics { get; set; } 39 } 40}

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

C#

1@model IEnumerable<ForumMVC.Models.Forum.Topic> 2 3@{ 4 ViewBag.Title = "Index"; 5} 6 7<h2>Index</h2> 8 9<p> 10 @Html.ActionLink("Create New", "Create") 11</p> 12<table class="table"> 13 <tr> 14 <th> 15 @Html.DisplayNameFor(model => model.AreaId) 16 </th> 17 <th> 18 @Html.DisplayNameFor(model => model.CategoryId) 19 </th> 20 <th> 21 @Html.DisplayNameFor(model => model.Title) 22 </th> 23 <th> 24 @Html.DisplayNameFor(model => model.Contents) 25 </th> 26 <th> 27 @Html.DisplayNameFor(model => model.TopicOwnerId) 28 </th> 29 <th></th> 30 </tr> 31 32@foreach (var item in Model) { 33 <tr> 34 <td> 35 @Html.DisplayFor(modelItem => item.AreaId) 36 </td> 37 <td> 38 @Html.DisplayFor(modelItem => item.CategoryId) 39 </td> 40 <td> 41 @Html.DisplayFor(modelItem => item.Title) 42 </td> 43 <td> 44 @Html.DisplayFor(modelItem => item.Contents) 45 </td> 46 <td> 47 @Html.DisplayFor(modelItem => item.TopicOwnerId) 48 </td> 49 <td> 50 @Html.ActionLink("Edit", "Edit", new { id=item.Id }) | 51 @Html.ActionLink("Details", "Details", new { id=item.Id }) | 52 @Html.ActionLink("Delete", "Delete", new { id=item.Id }) 53 </td> 54 </tr> 55} 56 57</table>

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

C#

1 // GET: NewTopic 2 public ActionResult Index() 3 { 4 return View(db.Topics.ToList()); 5 }

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/06/25 22:45

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

2018/06/26 21:44

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

回答2

0

ベストアンサー

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

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/26 03:39

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pomu.pomupomu

2018/06/26 21:42

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

退会済みユーザー

2018/06/27 01:45

上の回答にも書きましたが、virtual キーワードのついている Categoties, Suppliers がナビゲーションプロパティです。 DB First で、既存の DB の外部キー制約の付与されているテーブルをベースに EDM を生成すると、自動的にコードにナビゲーションプロパティが含まれるようになります。 逆に、Code First でナビゲーションプロパティを定義して DB を生成すると、生成される DB のテーブルに定義に従って外部キー制約が付与されます。 外部キー制約は SQL Server などの DB の、ナビゲーションプロパティは Entity Framework の基本のキに近いことですので、ググるなどすれば十分な情報は得られると思いますので調べてみてください。
退会済みユーザー

退会済みユーザー

2018/06/27 01:50

ちなみに、既存の DB のテーブルに外部キー制約が付与されてない場合(そういうのはきちんと設計されているとは言えないと思いますが)とか、データソースが異なるのでそういうことが不可能な場合は、クエリで結合して望む結果を得ることができます。具体例は以下の記事を見てください。 異なるデータソースの結合と表示 http://surferonwww.info/BlogEngine/post/2017/11/26/how-to-join-and-show-the-records-from-different-data-sources.aspx
pomu.pomupomu

2018/07/02 08: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])
guest

0

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

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

投稿2018/06/25 23:39

編集2018/06/25 23:41
f_horizon

総合スコア163

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/06/26 01:29

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

2018/06/26 04:58

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

退会済みユーザー

2018/06/26 05:12

質問者さんの過去スレッドを見ると初学者の方のようですので、まずは ASP.NET MVC でごく一般的な方法をベースに話を進めるべきだと思います。でないと、ミスリードすることになるかもしれません。 そもそも、どこにどのような形で必要な情報を保持しておくか、それからどのように取得するかは提案されてないようですが、それはどうするつもりだったのでしょう? DB 以外に適当&現実的な場所があるのでしょうか?
f_horizon

2018/06/26 07:08

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

2018/06/26 21:40

お二方ともに丁寧な解説をありがとうございます。御察しの通り、開発(?)そのものも未経験で独学でやってる初学者です。 ToricクラスにIDに対応したものをstring型で呼び出す方法があることも知らなかったので模索してみます。今回は他のテーブルとの連携が必要な場面になりそうですが、intをstringに置き換えたい場面は今後来るはずなので今習得します。本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問