ASP.NET MVC 5 - Identity. Cara mendapatkan ApplicationUser saat ini


237

Saya memiliki entitas Artikel di proyek saya yang memiliki ApplicationUserproperti bernama Author. Bagaimana saya bisa mendapatkan objek lengkap dari yang saat ini dicatat ApplicationUser? Saat membuat artikel baru, saya harus mengatur Authorproperti Articleke saat ini ApplicationUser.

Dalam mekanisme Keanggotaan lama itu sederhana, tetapi dalam pendekatan Identitas baru saya tidak tahu bagaimana melakukan ini.

Saya mencoba melakukannya dengan cara ini:

  • Tambahkan menggunakan pernyataan untuk ekstensi Identity: using Microsoft.AspNet.Identity;
  • Lalu saya mencoba untuk mendapatkan pengguna saat ini: ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == User.Identity.GetUserId());

Tapi saya mendapatkan pengecualian berikut:

LINQ ke Entitas tidak mengenali metode metode 'System.String GetUserId (System.Security.Principal.IIdentity)', dan metode ini tidak dapat diterjemahkan ke dalam ekspresi toko. Sumber = EntityFramework

Jawaban:


448

Anda tidak perlu menanyakan database secara langsung untuk ApplicationUser saat ini.

Itu memperkenalkan ketergantungan baru untuk memiliki konteks tambahan sebagai permulaan, tetapi ke depan tabel database pengguna berubah (3 kali dalam 2 tahun terakhir) tetapi API konsisten. Misalnya userstabel sekarang disebut AspNetUsersdalam Kerangka Identitas, dan nama-nama beberapa bidang kunci utama terus berubah, sehingga kode dalam beberapa jawaban tidak lagi berfungsi sebagaimana adanya .

Masalah lain adalah bahwa akses OWIN yang mendasari ke database akan menggunakan konteks yang terpisah, sehingga perubahan dari akses SQL yang terpisah dapat menghasilkan hasil yang tidak valid (misalnya tidak melihat perubahan yang dibuat ke database). Sekali lagi solusinya adalah bekerja dengan API yang disediakan dan tidak mencoba untuk mengatasinya .

Cara yang benar untuk mengakses objek pengguna saat ini dalam identitas ASP.Net (seperti pada tanggal ini) adalah:

var user = UserManager.FindById(User.Identity.GetUserId());

atau, jika Anda memiliki tindakan async, sesuatu seperti:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

FindByIdmengharuskan Anda memiliki pernyataan menggunakan berikut ini agar metode non-async UserManagertersedia (mereka adalah metode ekstensi untuk UserManager, jadi jika Anda tidak menyertakan ini Anda hanya akan melihat FindByIdAsync):

using Microsoft.AspNet.Identity;

Jika Anda tidak berada di pengontrol sama sekali (misalnya Anda menggunakan injeksi IOC), maka id pengguna diambil dari:

System.Web.HttpContext.Current.User.Identity.GetUserId();

Jika Anda tidak berada di pengontrol Akun standar, Anda harus menambahkan yang berikut ini (sebagai contoh) ke pengontrol Anda:

1. Tambahkan dua properti ini:

    /// <summary>
    /// Application DB context
    /// </summary>
    protected ApplicationDbContext ApplicationDbContext { get; set; }

    /// <summary>
    /// User manager - attached to application DB context
    /// </summary>
    protected UserManager<ApplicationUser> UserManager { get; set; }

2. Tambahkan ini dalam konstruktor Pengendali:

    this.ApplicationDbContext = new ApplicationDbContext();
    this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));

Pembaruan Maret 2015

Catatan: Pembaruan terbaru untuk Kerangka kerja identitas mengubah salah satu kelas dasar yang digunakan untuk otentikasi. Anda sekarang dapat mengaksesnya dari Konteks Owin dari HttpContent saat ini.

ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());

Tambahan:

Saat menggunakan EF dan Identity Framework dengan Azure, melalui koneksi basis data jarak jauh (mis. Pengujian host lokal ke database Azure), Anda dapat secara acak menekan "kesalahan: 19 - Koneksi fisik tidak dapat digunakan". Karena penyebabnya terkubur di dalam Kerangka Identitas, tempat Anda tidak dapat menambahkan percobaan ulang (atau yang tampaknya hilang .Include(x->someTable)), Anda perlu menerapkan kebiasaan SqlAzureExecutionStrategydi proyek Anda.


5
@TBA - terima kasih, saya menyadari nanti ini adalah metode ekstensi. Perlu menambahkan Microsoft.AspNet.Identity menggunakan. terima kasih lagi
Sentinel

2
Jenis atau namesapce UserStore tidak dapat ditemukan. Saya menambahkan menggunakan Microsft.AspNet.Indentity
Wasfa

2
@Zapnologica: Kedengarannya seperti pertanyaan baru (sarankan Anda mempostingnya). Anda dapat memperluas ApplicationUserkelas (khusus aplikasi) dan AspNetUserstabel secara paralel dan mereka akan memberikan bidang baru. Sekali lagi: Jangan tekan database secara langsung! :)
Hilang Coding

2
@ LifeH2O: ApplicationUser yang dikembalikan oleh FindById adalah kelas Anda , lengkap dengan properti tambahan Anda . Silakan dicoba.
Hilang Coding

1
Menunggu Penanganan Masalah baru Anda: P
Anup Sharma

60

Kesalahan saya, saya seharusnya tidak menggunakan metode di dalam permintaan LINQ.

Kode yang benar:

using Microsoft.AspNet.Identity;


string currentUserId = User.Identity.GetUserId();
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);

2
User.Identiy.GetUserId tidak ada untuk saya. Apakah itu metode khusus? Saya hanya bangun untuk User.Identity
Gerrie Pretorius

9
Nevermind ... Anda memerlukan "using Microsoft.AspNet.Identity;" untuk metode itu ada di sana.
Gerrie Pretorius

4
Sekedar catatan, objek Pengguna hanya terlihat di Pengontrol.
Miro J.

8
Tentunya Anda harus menggunakan UserManagermetode dan tidak memukul database secara langsung?
Lewat Coding

3
@Josh Bjelovuk: Jangan pernah menekan database secara langsung ketika API tersedia. Itu memperkenalkan ketergantungan baru untuk memiliki konteks tambahan sebagai permulaan, tetapi ke depan tabel database pengguna berubah (3 kali dalam 2 tahun terakhir) tetapi API konsisten.
Hilang Coding

33

Itu di komentar dari jawaban tetapi tidak ada yang memposting ini sebagai solusi yang sebenarnya.

Anda hanya perlu menambahkan pernyataan menggunakan di atas:

using Microsoft.AspNet.Identity;

2
Saya datang ke sini dengan pengecualian itu, saya menyelesaikannya dengan itu using. Melihat 15k orang telah mengunjungi pertanyaan yang saya pikir itu adalah jawaban yang membantu :)
rtpHarry

2
@ TrueBlueAussie, meskipun tidak menjadi jawaban langsung untuk pertanyaan OP, saya merasa menyebutkan menyebutkan penggunaan adalah tambahan yang sangat berguna.
StuartQ

1
Untuk kejelasan, itu karena .GetUserId()merupakan metode ekstensi
FSCKur

11

Kode Ellbar berfungsi! Anda hanya perlu menambahkan menggunakan.

1 - using Microsoft.AspNet.Identity;

Dan ... kode Ellbar:

2 - string currentUserId = User.Identity.GetUserId(); ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);

Dengan kode ini (dalam currentUser), Anda mengerjakan data umum dari pengguna yang terhubung, jika Anda ingin data tambahan ... lihat tautan ini


5
Ini mungkin "berfungsi", tetapi tentu saja tidak disarankan untuk mem-bypass API yang disediakan dan langsung menekan database. Jika Anda memang menggunakan API, Anda tidak perlu kerja ekstra untuk mendapatkan data tambahan karena sudah ada di ApplicationUserobjek
Goding Coding

Saya setuju! Namun, terpaksa dengan cara ini karena saya sudah memiliki sistem di tempat hari ini, dengan menjalankan dalam database dan saya memerlukan solusi sederhana untuk menyelesaikan masalah ini! Tentu saja, dalam sistem awal, saya akan meletakkan objek di kelas dan identitas yang tepat.
Diego Borges

6

Pada ASP.NET Identity 3.0.0, Ini telah direactored menjadi

//returns the userid claim value if present, otherwise returns null
User.GetUserId();

6
ApplicationDbContext context = new ApplicationDbContext();
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
ApplicationUser currentUser = UserManager.FindById(User.Identity.GetUserId());

string ID = currentUser.Id;
string Email = currentUser.Email;
string Username = currentUser.UserName;

3

Untuk MVC 5 lihat saja metode EnableTwoFactorAuthentication dari ManageController di scaffold template WebApplication, sedang dilakukan di sana:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> EnableTwoFactorAuthentication()
        {
            await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
            var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
            if (user != null)
            {
                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
            }
            return RedirectToAction("Index", "Manage");
        }

Jawabannya ada di sana seperti yang disarankan oleh Microsoft sendiri:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

Ini akan memiliki semua properti tambahan yang Anda tetapkan di kelas ApplicationUser.


5
Sudah tertutup. Harap periksa bahwa jawaban yang identik belum diposkan (atau tambahkan komentar ke jawaban yang ada) :)
Hilang Pengkodean

3

Saat ini template proyek asp.mvc membuat pengontrol akun yang membuat pengelola akun ini dengan cara ini:

HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>()

Berikut ini berfungsi untuk saya:

ApplicationUser user = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(User.Identity.GetUserId());

0

Saya berhasil mendapatkan Pengguna Aplikasi Dengan Mengikuti Sepotong Kode

var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
            var user = manager.FindById(User.Identity.GetUserId());
            ApplicationUser EmpUser = user;

0

Jika seseorang bekerja dengan Identitypengguna web forms, saya membuatnya bekerja dengan melakukannya:

var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindById(User.Identity.GetUserId());
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.