24

SimpleMembershipはEFモデルファーストで使用できますか?試してみると、電話をかけると「要求された.NETFrameworkデータプロバイダーが見つかりません」と表示されます。WebSecurity.InitializeDatabaseConnection.

別の言い方をすれWebSecurity.InitializeDatabaseConnectionば、接続文字列がSystem.Data.EntityClientプロバイダーを使用している場合(モデルファーストパラダイムを使用している場合のように)、呼び出しを機能させることができません。

問題を再現するには、MVC 4アプリを作成し、コードファーストのUserProfileエンティティクラス(MVC 4テンプレートで無料で入手できます)を、エンティティデザイナーで作成したモデルファーストのユーザークラスに置き換えます。

  1. VS2012でMVC4アプリを作成し、新しい空のエンティティデータモデルを追加します。
  2. Userのフィールドを使用して、モデルに名前が付けられた新しいエンティティを追加しますId, UserName, and FullName。したがって、この時点で、Userデータエンティティはテーブルにマップされ、プロバイダーUsersを使用するファンキーな接続文字列を介してアクセスされます。System.Data.EntityClient
  3. EFUserがエンティティにアクセスできることを確認します。これを行う簡単な方法の1つは、Userテーブルとそれに関連付けられたDbContextに基づいてUsersコントローラーをスキャフォールディングすることです。
  4. ファイルを編集して、クラスとそれに関連するクラスAccountModels.csを削除します。(現在欠落している)クラスへの参照を、新しいUserクラスとそれに関連するクラスへの参照に置き換えます。UserProfileUsersContextUserProfileUsersContextDbContext
  5. InitializeDatabaseConnectionの呼び出しをInitializeSimpleMembershipAttributeフィルタークラスからGlobal.asax.csのApplication_Startメソッドに移動します。その間に、新しいUserエンティティの接続文字列、テーブル名、およびUserId列名を使用するように引数を変更します。
  6. (使用されなくなった)InitializeSimpleMembershipAttribute クラスとそのクラスへの参照を削除します。

再現を実行すると、への呼び出し時に例外が発生しますInitializeDatabaseConnection.

ボブ

4

5 に答える 5

24

SimpleMembershipは、最初にモデルを操作できます。これが解決策です。

1.MVC4InitializeSimpleMembershipAttribute.csインターネットアプリケーションテンプレートからは次のようになります

namespace WebAndAPILayer.Filters
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
    {
        private static SimpleMembershipInitializer _initializer;
        private static object _initializerLock = new object();
        private static bool _isInitialized;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Ensure ASP.NET Simple Membership is initialized only once per app start
            LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
        }

        private class SimpleMembershipInitializer
        {
            public SimpleMembershipInitializer()
            {
                try
                {
                    WebSecurity.InitializeDatabaseConnection("ConnStringForWebSecurity", "UserProfile", "Id", "UserName", autoCreateTables: true);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException("Something is wrong", ex);
                }
            }
        }
    }
}

2.CodeFirstクラスをから削除しますAcountModel.cs

3.モデルファーストのDbContext AccountCotroler.csExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)メソッド)で動作するように修正

"ConnStringForWebSecurity"4.モデルファーストのdbアクセス用のファンキーなconn文字列とは異なる接続文字列を定義します。プロバイダーでSystem.Data.SqlClientはなくプロバイダーを使用していることに注意してください。System.Data.EntityClient

 <connectionStrings>
         <add name="ModelFirstEntityFramework" connectionString="metadata=res://*/Context.csdl|res://*/Context.ssdl|res://*/Context.msl;provider=System.Data.SqlClient;provider
 connection string=&quot;data source=.\SQLEXPRESS;Initial
 Catalog=aspnet-MVC4;Integrated
 Security=SSPI;multipleactiveresultsets=True;App=EntityFramework&quot;"
 providerName="System.Data.EntityClient" />
         <add name="ConnStringForWebSecurity" connectionString="data source=.\SQLEXPRESS;Initial Catalog=aspnet-MVC4;Integrated
 Security=SSPI" providerName="System.Data.SqlClient" />
       </connectionStrings>
于 2012-10-23T19:33:55.213 に答える
12

これはMVC4のバグです。このブログ投稿には回避策があります。

アクションフィルターとして、怠惰な初期化作業を実行するためにInitializeSimpleMembershipAttributeフックしOnActionExecutingますが、これはライフサイクルの遅すぎる可能性があります。Authorize属性は、役割ベースのアクセスチェックを実行する必要がある場合(の間にOnAuthorization)、プロバイダーがより早く準備ができている必要があります。つまり、サイトへの最初のリクエストが次のようなコントローラーアクションにヒットした場合:

[Authorize(Roles="Sales")]

..次に、フィルターがユーザーの役割をチェックしますが、プロバイダーが初期化されていないため、例外が発生します。

プロジェクトからISMAを削除し、アプリケーション開始イベント中にWebSecurityを初期化することをお勧めします。

于 2012-09-25T13:48:46.880 に答える
10

1-できればEntityFramework5を使用して移行を有効にする必要があります

2-移動します

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true); 

YourMvcApp / Migrations/Configuration.csクラスのSeedメソッドに

    protected override void Seed(UsersContext context)
    {
        WebSecurity.InitializeDatabaseConnection(
            "DefaultConnection",
            "UserProfile",
            "UserId",
            "UserName", autoCreateTables: true);

        if (!Roles.RoleExists("Administrator"))
            Roles.CreateRole("Administrator");

        if (!WebSecurity.UserExists("lelong37"))
            WebSecurity.CreateUserAndAccount(
                "lelong37",
                "password",
                new {Mobile = "+19725000000", IsSmsVerified = false});

        if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
            Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
    }

これで、EF5がUserProfileテーブルの作成を担当します。その後、WebSecurity.InitializeDatabaseConnectionを呼び出して、SimpleMembershipProviderを作成済みのUserProfileテーブルにのみ登録します(この場合、「UserProfile」パラメーター値をカスタムテーブルに置き換えることができます)。 name)、また、どの列がUserIdとUserNameであるかをSimpleMembershipProviderに通知します。また、ユーザー、ロールを追加し、Seedメソッドで2つをカスタムUserProfileプロパティ/フィールド(ユーザーのモバイル(番号)など)に関連付ける方法の例も示しています。

3-パッケージマネージャーコンソールからupdate-databaseを実行すると、EF5はすべてのカスタムプロパティを使用してテーブルをプロビジョニングします

その他の参考資料については、ソースコードを含むこの記事を参照してください:http: //blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom -user-properties /

于 2012-09-28T17:50:02.367 に答える
1

この問題は、プロバイダー名WebSecurity.InitializeDatabaseConnectionで接続文字列を使用できないことが原因で発生します。System.Data.EntityClient

二重接続文字列を提供するのは適切ではないため、部分クラスのコンストラクターで最初にEFモデルの接続文字列を生成できます。

コードは次のようになります

public partial class MyDataContext 
{
    private static string GenerateConnectionString(string connectionString)
    {
        var cs = System.Configuration.ConfigurationManager
                     .ConnectionStrings[connectionString];

        SqlConnectionStringBuilder sb = 
             new SqlConnectionStringBuilder(cs.ConnectionString);
        EntityConnectionStringBuilder builder = 
             new EntityConnectionStringBuilder();
        builder.Provider = cs.ProviderName;
        builder.ProviderConnectionString = sb.ConnectionString;
        builder.Metadata = "res://*/MyDataContext.csdl|" +
              "res://*/MyDataContext.ssdl|res://*/MyDataContext.msl";
        return builder.ToString();
    }

    public MyDataContext(string connectionName) : 
          base(GenerateConnectionString(connectionName)) { }
}

このトリックを使用すると、Web構成で単一の接続文字列を使用できますが、データコンテキストでデフォルトのコンストラクターを使用できないという問題があります。代わりに、データコンテキストをインスタンス化するときに接続文字列名をどこにでもシードする必要があります。しかし、依存性注入パターンを使用する場合、それは大きな問題ではありません。

于 2013-01-13T23:30:20.633 に答える
0

EFおよびWebMatrixwebSecurityクラスを使用できないため、この問題を回避して先に進んでください。

最初にEfモデルを最初にコードに変更します。

接続文字列を変更してproviderName="System.Data.SqlClient"(すべてのメタデータ情報を削除)を使用するか、EF接続を使用します

私の場合、モデル、データ、およびWebは異なるプロジェクトであるため、web.projectのweb.configからこの情報を削除することは問題ではありません。

現在、websecuroty.initializedatabaseはEF接続文字列では実行されません。

これがお役に立てば幸いです

于 2012-09-30T21:02:37.587 に答える