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

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

ただいまの
回答率

90.33%

  • C#

    7750questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • ASP.NET MVC Framework

    69questions

    ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

ActiveDirectory情報の一覧表示

解決済

回答 1

投稿 編集

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

Man-drill

score 1

こんにちは。
ASP.NET MVC でC#を使って社内Webシステムの構築を始めました。
以前はVB.NETでWindowsアプリケーションの開発をしていましたが、
今回、WebシステムということでASP.NET MVCとC#に挑戦してみました。
MVCの概念やC#ならではの記述などは素人です。
開発環境:VS2015、.NET 4.5.2、MVC 5.2.3.0

目的

ActiveDirectoryからワイルドカード検索をして、取得した複数のデータをViewで一覧表示する。

できたこと

ユーザーIDを直接指定して、1件だけのデータを表示。

AdController.cs

namespace Web1.Models
{
    public class AdController : Controller
    {
        // GET: Ad
        public ActionResult Index()
        {
            var directoryEntry = new DirectoryEntry();
            var directorySearcher = new DirectorySearcher(directoryEntry);

            // ユーザーID
            var samAccountName = "ABC123";

            // LDAP設定、検索
            directoryEntry.Path = "LDAP://xxx";
            directorySearcher.Filter = String.Format("(&(objectClass=user)(samAccountName={0}))", samAccountName);

            var result = directorySearcher.FindOne();
            var entry = result.GetDirectoryEntry();

            // メールアドレス
            var mailAddress = (string)entry.Properties["mail"].Value;

            ViewBag.Mail = mailAddress;
            return View();
        }
    }
}

Ad/Index.cshtml

    <tr>
        <td>メールアドレス</td>
        <td>@ViewBag.Mail</td>
    </tr>

やりたいこと

  • 検索条件をワイルドカード指定(samAccountName = "ABC12*")
  • directorySearcher.FindAll()で複数のデータをViewへ渡す(↓View画面のイメージ)
cn name mail department
ABC121 suzuki suzuki@jp 営業
ABC122 sato sato@jp 総務
ABC123 tanaka tanaka@jp 経理

質問

値が一つの場合は上記のようにFindOneで取得してViewBag変数で渡していましたが、複数だとどのようになるのでしょうか?
View側ではforeachで回すのだとは思うのですが、Controller側で取得した値を格納する型がわかりません。
また、このような事をしたい場合、Modelの定義は必要でしょうか?
不慣れなので具体的なコードがあると助かります。

よろしくお願いします。


追記

AdInfo.cs

namespace Web1.Models
{
    public class AdInfo
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Mail { get; set; }
        public string Department { get; set; }

        // 追加:引数を取るコンストラクタを実装
        public AdInfo (string Id1, string Name1, string Mail1, string Department1)
        {
            Id = Id1;
            Name = Name1;
            Mail = Mail1;
            Department = Department1;
        }
    }
}


AdController.cs

using System.DirectoryServices;

namespace Web1.Models
{
    public class AdController : Controller
    {
        public ActionResult UserList()
        {
            var directoryEntry = new DirectoryEntry();
            var directorySearcher = new DirectorySearcher(directoryEntry);

            // ユーザーID
            var samAccountName = "ABC12*";

            // LDAP設定、検索
            directoryEntry.Path = "LDAP://xxx";
            directorySearcher.Filter = String.Format("(&(objectClass=user)(samAccountName={0}))", samAccountName);
            var result = directorySearcher.FindAll();    // FindOneからFindAllに変更

            // ここから修正
            List<AdInfo> model = new List<AdInfo>();

            foreach (var user in result
                    .Cast<SearchResult>()
                    .Select(x => x.GetDirectoryEntry()))
            {
                var id = (string)user.Properties["sAMAccountName"].Value;
                var name = (string)user.Properties["name"].Value;
                var mail = (string)user.Properties["mail"].Value;
                var department = (string)user.Properties["department"].Value;

                model.Add(new AdInfo(id, name, mail, department));
            }

            return View(model);
        }
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • SurferOnWww

    2018/12/04 12:15

    質問は AD 情報の所得方法なのか、所得した情報を ASP.NET MVC を使ってブラウザに表示することなのか、どちらですか?

    キャンセル

  • SurferOnWww

    2018/12/04 12:18

    前者は自分は答えられませんが、後者なら多分分かります。後者であれば、取得する情報がどういうものか詳しく書いてください。

    キャンセル

  • Man-drill

    2018/12/04 13:11

    後者です。コードに書いたように"mail"などのADSI属性を指定してフィルターをかけて値を取得表示したいです。一件だけの取得はできています。

    キャンセル

回答 1

checkベストアンサー

+1

今スマホからなので、コードが書けませんが・・・

情報を格納するクラスを Model に定義してください。そのクラスを、例えば AdInfo とすると、取得した複数のユーザーの AD 情報を、Controller で List<AdInfo> というオブジェクトを作って格納します。それを Model として View に渡すのが基本になります。

【追伸】

PC からアクセスできるようになったので、コードを書いて説明しておきます。

↓View画面のイメージ

そう表示したいのであれば、cn, name, mail, department のすべてが AdInfo クラスにないとダメでは? であれば、以下のように Model に AdInfo クラスを定義して:

Model

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

namespace Mvc5App.Models
{
    public class AdInfo
    {
        public string Cn { get; set; }
        public string Name { get; set; }
        public string Mail { get; set; }
        public string Department { get; set; }
    }
}

Controller / Action Method 

上記をベースに Controller / Action Method を作って(注: List<AdInfo> model は実際は AD 情報から取得するとしてサンプルでは以下のように簡略化)、

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using Mvc5App.Models;

namespace Mvc5App.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult AdInfo()
        {
            List<AdInfo> model = new List<AdInfo>
            {
                new AdInfo { Cn = "ABC121", Name = "suzuki", Mail = "suzuki@jp", Department = "営業" },
                new AdInfo { Cn = "ABC122", Name = "sato", Mail = "sato@jp", Department = "総務" },
                new AdInfo { Cn = "ABC123", Name = "tanaka", Mail = "tanaka@jp", Department = "経理" }
            };

            return View(model);
        }
    }
}

スキャフォールディング機能を利用して、

イメージ説明

View を生成すると以下のようになって、(追伸: @model ... がキモです。スキャフォールディングで適切にパラメータを設定すれば自動生成されます)

View

@model IEnumerable<Mvc5App.Models.AdInfo>

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

<h2>AdInfo</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Cn)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Mail)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Department)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Cn)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Mail)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Department)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr>
}

それを実行すると以下のようになります。これで分かりますか?

イメージ説明

分からないということなら本を買って読んで体系的に勉強しないと、話が通じないので、ここのような掲示板でのやり取りで解決するのは難しいと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/04 13:36

    ご回答ありがとうございます。試してみます。ひとまずお礼まで。

    キャンセル

  • 2018/12/04 15:20

    不明点がありましたら質問してください。PC が使えるようになったらコードを書いて説明します。

    キャンセル

  • 2018/12/04 21:42

    回答欄にコードを書いて説明しておきます。

    キャンセル

  • 2018/12/05 10:11

    丁寧なご回答ありがとうございます。

    > そう表示したいのであれば、cn, name, mail, department のすべてが AdInfo クラスにないとダメでは?
    これはイメージ説明のために書いたもので実際とは異なります。わかりにくくてすみません。修正しました。

    Model で AdInfo クラスを定義して、Controller でインスタンス化し、View の @model で受け取るまでの流れ、大変参考になりました。

    一番知りたかったのは、サンプル Controller では簡略化されている、 AD 情報を List<AdInfo> model に入れる部分です。
    「できたこと」に書いた Index を基に、検索結果が複数帰ってくる(はずの) UserList アクションメソッドを追記しました。
    foreach の中で1件ごとに new するのでしょうか?

    キャンセル

  • 2018/12/05 10:49

    > 一番知りたかったのは、サンプル Controller では簡略化されている、 AD 情報を List<AdInfo> model に入れる部分です。

    質問に対する 2 番目のコメントで「前者(AD 情報の所得方法)は自分は答えられませんが・・・」とお伝えしたはずです。

    追記したコードの user というのが何で、それからどのように cn, name, mail, department という情報を取得できるのかを書いていただければ答えられると思いますが。

    キャンセル

  • 2018/12/05 14:34

    解決しました!
    コードを修正しました。

    > 追記したコードの user というのが何で、それからどのように cn, name, mail, department という情報を取得できるのかを書いていただければ答えられると思いますが。
    foreach の中の Cast や Select のくだりはAD関係のサイトを参考にしたので説明できるほど詳しくないのですが、
    このようにすると directorySearcher.FindAll() で取得した値が result に入り、user.Properties で各属性を取れるようです。

    解決方法
    1.SurferOnWww さんのサンプルコードをほぼそのまま実行 → 動いた
    2.result の内容を foreach で全件 List<AdInfo> model に入れれば動くはず
    3.サンプルでは new した時点で初期データを入れているが、本番では foreach で回すため独自クラスへのデータ追加の仕方を調査
    4.AdInfo クラスに引数ごとにコンストラクタを実装
    5.model.Add(new AdInfo(id, name, mail, department)); ← このAddの中でnewする記述の仕方が分からなかった

    という具合にやったら動きました。
    SurferOnWww さん、非常に助かりました。ありがとうございました。

    キャンセル

  • 2018/12/05 18:03 編集

    AD 情報は (string)user.Properties["属性名"].Value で取得できるのですね。

    それを、C# 3.0 で導入されたオブジェクト初期化子(私がサンプルに書いたものです)を利用して代入しながら初期化すると、コンストラクタを追加しなくても書けるようになるはずです。

    詳しくは以下の記事を見てください。

    オブジェクト初期化子とコレクション初期化子 (C# プログラミング ガイド)
    https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers

    さらに進めて、Linq を使ってもっと簡略化できるかもしれませんが、それはまた別の機会に・・・

    キャンセル

  • 2018/12/07 08:54

    > コンストラクタを追加しなくても
    おそらくそうかなとは思っていましたが、見つけた参考例がこのような記述でしたので。
    次回は教わった方法で試してみようと思います。

    C#自体の習熟度がまだまだ素人同然なので、面倒でも一番基本的な記述方式で覚えていこうと思います。
    ラムダ式、Linq など使いこなせば便利そうなのでいずれは・・・。

    キャンセル

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

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

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

  • C#

    7750questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • ASP.NET MVC Framework

    69questions

    ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。