SimpleMembershipはEF model-firstと一緒に使用できますか?試してみると、WebSecurity.InitializeDatabaseConnection.
を呼び出すと、「要求された.NET Frameworkデータプロバイダーが見つかりません」と表示されます。
別の言い方をすると、接続文字列がWebSecurity.InitializeDatabaseConnection
プロバイダーを使用している場合、System.Data.EntityClient
への呼び出しが機能しません(model-firstを使用する場合のように)パラダイム)。
問題を再現するには、MVC 4アプリを作成し、code-first UserProfileエンティティークラス(MVC 4テンプレートで無料で入手できます)をmodel-firstに置き換えます。 =エンティティデザイナーで作成したユーザークラス:
Id,
UserName, and FullName
のフィールドを使用して、User
という名前の新しいエンティティをモデルに追加します。したがって、この時点で、User
データエンティティはUsers
テーブルにマップされ、System.Data.EntityClient
プロバイダーを使用するファンキーな接続文字列を介してアクセスされます。User
エンティティにアクセスできることを確認します。これを行う簡単な方法の1つは、Userテーブルとそれに関連付けられたDbContextに基づいて、Usersコントローラーをスキャフォールドすることです。AccountModels.cs
ファイルを編集して、UserProfile
クラスとそれに関連するUsersContext
クラスを削除します。 (現在欠落している)UserProfile
およびUsersContext
クラスへの参照を、新しいUserクラスおよび関連するDbContext
クラスへの参照に置き換えます。InitializeSimpleMembershipAttribute
クラスとその参照を削除します。リプロを実行すると、InitializeDatabaseConnection.
の呼び出し時にExceptionが取得されます
ボブ
SimpleMembershipは最初にモデルを操作できます。これが解決策です。
1 ._InitializeSimpleMembershipAttribute.cs
_ MVC 4インターネットアプリケーションのテンプレートは次のようになります。
_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. _AcountModel.cs
_からCodeFirstクラスを削除する
3. _AccountCotroler.cs
_を修正して、モデルファーストDbContext(ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
メソッド)で動作するようにします。
4.モデルファーストデータベースアクセス用のファンキーなconn文字列とは異なる_"ConnStringForWebSecurity"
_接続文字列を定義します。プロバイダーは_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="data source=.\SQLEXPRESS;Initial
Catalog=aspnet-MVC4;Integrated
Security=SSPI;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
<add name="ConnStringForWebSecurity" connectionString="data source=.\SQLEXPRESS;Initial Catalog=aspnet-MVC4;Integrated
Security=SSPI" providerName="System.Data.SqlClient" />
</connectionStrings>
_
これはMVC 4のバグです このブログ投稿には回避策があります 。
アクションフィルターとして、
InitializeSimpleMembershipAttribute
はOnActionExecuting
にフックして遅延初期化作業を実行しますが、これはライフサイクルの後半では遅すぎる可能性があります。 Authorize属性は、ロールベースのアクセスチェック(OnAuthorization
中)を実行する必要がある場合、プロバイダーを早期に準備する必要があります。つまり、サイトへの最初のリクエストが次のようなコントローラーアクションにヒットした場合:
[Authorize(Roles="Sales")]
..すると、フィルターがユーザーの役割をチェックするがプロバイダーは初期化されないため、例外が発生します。
私の推奨は、プロジェクトからISMAを削除し、アプリケーション開始イベント中にWebSecurityを初期化することです。
1-できればEntityFramework 5で移行を有効にする必要があります
2-移動
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true);
your 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」パラメータ値とカスタムテーブル名)。また、SimpleMembershipProviderに、どの列がUserIdとUserNameであるかを伝えます。また、ユーザー、ロールを追加する方法の例と、2つをSeedメソッドをユーザーのモバイル(番号)などのカスタム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 /
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構成で単一の接続文字列を使用できますが、データコンテキストでデフォルトコンストラクターを使用できない1つの問題です。代わりに、データコンテキストをインスタンス化するときにどこにでも接続文字列名をシードする必要があります。しかし、依存関係注入パターンを使用する場合、それは大きな問題ではありません。
この問題を回避して先に進むために、EFおよびWebMatrix webSecurityクラスを操作することはできません。
Efモデルを最初にコードに変更します。
接続文字列を変更して、providerName = "System.Data.SqlClient"(すべてのメタデータ情報を削除)を使用するか、EF接続を使用します。
私の場合、モデル、データ、Webは異なるプロジェクトであるため、web.projectのweb.configからこの情報を削除しても問題はありません。
現在、websecuroty.initializedatabaseはEF接続文字列で実行されません。
これが役に立てば幸い