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

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

ただいまの
回答率

90.35%

  • C#

    9666questions

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

  • VB.NET

    1124questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

  • ASP.NET MVC Framework

    109questions

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

  • Entity Framework

    58questions

.net Identity に登録した自分の情報(追加分)を 画面に表示したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,282

pcb

score 5

前提

Visual studio 2013 for webで開発をしております。 
VB/C#いずれでもかまいません(実際にはVBで開発しています)。

新しくMVC5アプリケーションをテンプレートから生成したあと、 
以下の拡張を行いました:

/models/ientityModel.vb

....(imports省略)....

' ApplicationUser クラスにプロパティを追加することでユーザーのプロファイル データを追加できます。詳細については、http://go.microsoft.com/fwlink/?LinkID=317594 を参照してください。
Public Class ApplicationUser
    Inherits IdentityUser

''' <summary>
''' 登録連番
''' </summary>
<Required>
<Display(Name:="登録連番")>
<DatabaseGenerated(DatabaseGeneratedOption.Identity)>
<Column("ID_NUM", Order:=0)>
Public Property Id_Num As Integer

 Public Async Function GenerateUserIdentityAsync(manager As UserManager(Of ApplicationUser)) As Task(Of ClaimsIdentity)
....


こうすると、ApplicationUserManager(UserManager)において、登録連番が定義されると思います。
また、標準では ほかに、 PhoneNumber属性も持っています。

実現したいこと

1)アカウントを生成した後、dbを調整して、以下とします:

  • PhoneNumber属性に適当なstringが入っている(例として:"0120-000-000")
  • Id_Num属性に、登録連番(DBから振られる連番) が入っている

2)1の状態で、生成したアカウントにサインインします。

3)ページには電話番号と連番が表示されるようにしたいです。

ソース、試したこと

以下のソースを書きましたが、IDE画面のオートコンプリートに、メソッドが出てきません。
また、クラス継承がうまくいっていないのか、

 'getPhoneNumber''System.Security.Principal.IIdentity' のメンバーではありません。    
 'getIdNum''System.Security.Principal.IIdentity' のメンバーではありません。    

というエラーがでて表示がうまくできません

VB.net / modules/test.vb

Module Extensions

    <System.Runtime.CompilerServices.Extension>
    Public Function GetIdNum(This As System.Security.Principal.IIdentity) As Integer?
        Dim userIdentity = TryCast(This, ApplicationUser)
        If userIdentity IsNot Nothing Then
            Return userIdentity.Id_Num()
        Else
            Return Nothing
        End If
    End Function

    <System.Runtime.CompilerServices.Extension>
    Public Function GetPhoneNumber(This As System.Security.Principal.IIdentity) As String
        Dim userIdentity = TryCast(This, ApplicationUser)
        If userIdentity IsNot Nothing Then
            Return userIdentity.PhoneNumber()
        Else
            Return Nothing
        End If
    End Function


End Module

/views/index.vbhtml

@Imports Microsoft.AspNet.Identity
@Imports System.Security.Principal
@ModelType ApplicationUser

@Code
End Code
...

ログインしているとあなたのIDと電話番号が表示されます
[ @User.Identity.getId_Num : @User.Identity.getPhoneNumber ]

...

具体的なゴール

@User.Identity.getPhoneNumber @User.Identity.GetIdNum を、
ログインしていればビューから呼び出せればOkです。

なお現時点で、以下は表示できています: 

  • @User.Identity.GetUserName
  • @User.Identity.GetUserId
  • @User.Identity.Name
  • @HttpContext.Current.User.Identity.GetUserName

補足情報(言語/FW/ツール等のバージョンなど)

VisualStudio 2013 VB / C# , SQLserver 2014

上記、どうぞよろしくお願い申し上げます。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

3)ページには電話番号と連番が表示されるようにしたいです。

先のスレッドで紹介した記事(URL 下記)の 3 ページ目にある「リスト3」のようにして取得できませんか?

ASP.NET Identityのプロファイル情報のカスタマイズ 
https://codezine.jp/article/detail/7845

上記の記事はたぶん 1.0 のもので、2.0 では多少違うかもしれませんが、基本は同じではないかと思います。

ただ、検証はしていませんのでハズレでしたらすみません・・・

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/04/07 13:46

    はい、MVC + Identity でのモデルを無視する方法では実現可能です:

    [VB]
    ```
    @*'//(↓IdentityModels.vbで定義されている)*@
    @ModelType ApplicationUser

    @Code
    Dim currentUser As ProjectName.ApplicationUser
    If (User.Identity.IsAuthenticated) Then
    Dim userStore = New UserStore(Of ApplicationUser)(New ApplicationDbContext())
    Dim manager = New UserManager(Of ApplicationUser)(userStore)

    currentUser = manager.FindById(User.Identity.GetUserId())
    End If

    End Code
    IdNumは: @currentUser.IdNum <br />
    電話は: @currentUser.PhoneNumber <br />
    ```

    [C#]
    ```
    @{
    ProjectName.ApplicationUser currentUser = default(ProjectName.ApplicationUser);
    if ((User.Identity.IsAuthenticated)) {
    dynamic userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());
    dynamic manager = new UserManager<ApplicationUser>(userStore);

    currentUser = manager.FindById(User.Identity.GetUserId());
    }
    }
    IdNumは: @currentUser.IdNum <br />
    電話は: @currentUser.PhoneNumber <br />
    ```

    毎回 viewの先頭に上記のような定義をすると、モデルオブジェクト責任において
    都度検索を回すことが可能です(別解としてはきっと当たり回答です)。

    今回は ExtendsしたうえでUser.Identityのメンバーに加えることがゴールとなります。

    キャンセル

  • 2017/04/07 15:04

    > 今回は ExtendsしたうえでUser.Identityのメンバーに加えることがゴールとなります。

    どういう意味でしょう? 質問文では登録済みの情報を表示できれば良いというように読めますが?

    キャンセル

  • 2017/04/07 15:36

    確かに実現できていることは同じなのですが、Userオブジェクトがあるのにも関わらずcurrentUserオブジェクト作るためにDBをviewで呼んでいる(modelの仕事をViewで直書きして実行している)問題と、1オブジェクトで済むはずのログイン中Userのオブジェクトが2つ、かつDB呼出しが別途起きてしまうなど、その後の事故原因になりそうな状況となっているので、Identity本来の呼出し手順を実現したく存じます...

    キャンセル

  • 2017/04/07 17:14 編集

    > Userオブジェクトがあるのにも関わらずcurrentUserオブジェクト作るためにDBをviewで呼んでいる

    User プロパティで取得できるのは System.Security.Claims.ClaimsPrincipal オブジェクト、User.Identity プロパティで取得できるのは System.Security.Claims.ClaimsIdentity オブジェクトです。

    ClaimsIdentity クラスの拡張メソッドとして GetIdNum() とか GetPhoneNumber() を実装できるのかどうか知りませんが(無理なような気がしますが)、仮にできたとしても ClaimsIdentity オブジェクトには IdNum, PhoneNumber の情報はないので、User.Identity.GetIdNum() とかした時点で結局 DB にアクセスして情報を取得せざるを得ないはずです。

    あまり意味のないことではありませんか?

    キャンセル

check解決した方法

0

どうにか自力で答えにたどり着けたため、記録しておきます:
vbにおいてまともな日本語文献が存在しなかったので、これで皆様の助けになれば幸いです。

VB.netでClaimで追加情報を持ちまわし、User.identityを拡張してviewに出せるようにする方法:

「毎回ユーザーストアとユーザーマネージャを呼び出しDBを叩く」をしなくてもよくなるため、パフォーマンスが向上します。

クレームにほしい情報を追加する

クレームを追加します。このクレームはログイン時または標準では30分に再取得しようとします。ログインしていない場合は値がありません。つまり、ログインしたときの情報をもちまわしてくれることになります。
質問欄に定義してあるId_numと、MVC5テンプレートで標準の電話番号をここでは取得できるようにクレームに追加しています。

/models/ientityModels.vb

...(略)...

    Public Async Function GenerateUserIdentityAsync(manager As UserManager(Of ApplicationUser)) As Task(Of ClaimsIdentity)
        ' authenticationType が CookieAuthenticationOptions.AuthenticationType で定義されているものと一致している必要があります
        Dim userIdentity = Await manager.CreateIdentityAsync(Me, DefaultAuthenticationTypes.ApplicationCookie)
        ' ここにカスタム ユーザー クレームを追加します
        userIdentity.AddClaim(New Claim("PhoneNumber", Me.PhoneNumber))
        userIdentity.AddClaim(New Claim("Id_Num", Me.Id_Num))

        Return userIdentity
    End Function

...(略)...

 User.Identity を拡張して、標準実装と同じやり方でメソッドを追加する

ここがハマりどころでした。Razor で @User.Identity.GetPhoneNumber のように、拡張したメソッドを開発環境に認知させるためには、module を publicで宣言する必要があります

/models/User_Claim_Extends.vb

Imports System.Security.Claims
Public Module IdentityExtensions

    <System.Runtime.CompilerServices.Extension>
    Public Function GetIdNum(User As System.Security.Principal.IIdentity) As Integer?
        If (User.IsAuthenticated) Then
            Dim claim = DirectCast(User, ClaimsIdentity).FindFirst("Id_Num")
            Return If((claim IsNot Nothing), claim.Value, Nothing)
        Else
            Return Nothing
        End If
    End Function

    <System.Runtime.CompilerServices.Extension>
    Public Function GetPhoneNumber(User As System.Security.Principal.IIdentity) As String
        If (User.IsAuthenticated) Then
            Dim claim = DirectCast(User, ClaimsIdentity).FindFirst("PhoneNumber")
            Return If((claim IsNot Nothing), claim.Value, Nothing)
        Else
            Return Nothing
        End If
    End Function

End Module

 ビューに表示したい情報を足す

IdNumは: @User.Identity.GetIdNum <br />
電話は: @User.Identity.GetPhoneNumber <br />


↓ 実行例)

IdNumは: 2 
電話は: 0120-000-000 

 追加情報:

ログイン中の再取得タイミング変更を、以下の時間をサーバに負荷にならない程度に短く変更するとよいかもしれません。

/App_Start/Startup.Auth.vb 

validateInterval:=TimeSpan.FromMinutes(30),


validateInterval:=TimeSpan.FromSeconds(20),


具体的には、Startup.Auth.vb にあるパラメータを、上記のように変更すると、ログイン後、または最後にGenerateUserIdentityAsyncを訪れてクレーム周りを更新(たいていはページ読み込みと同義)したあと指定時間が経過したら、GenerateUserIdentityAsyncを巡回するようになります。

これにより上記の例ですと、Administratorを想定したアカウントが変更を掛けると遅くとも20秒以内で、自動で情報が更新できるを実現することが可能になります。

なお、moduleのほう、namespaceで囲っていないので、どこからでも見られるようになっていますが、可能で居あればnamespaceで囲って、Importsできるようにするほうが無難(スマート)です。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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

  • C#

    9666questions

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

  • VB.NET

    1124questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

  • ASP.NET MVC Framework

    109questions

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

  • Entity Framework

    58questions