Je développe une application Web de code de code dans Visual Studio 2012 Express.
J'utilise cette chaîne de connexion dans le web.config: p> J'utilise SimpleMembership . P> J'essaie de semer 1 administrateur de filtres / initialisiseimplememberthipattribute.cs:
... p> using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Web.Mvc;
using WebMatrix.WebData;
using System.Web.Security;
using myapPMVC4.Models;
namespace myapPMVC4.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)
{
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
//WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
if (!WebSecurity.Initialized)
{
WebSecurity.InitializeDatabaseConnection("myapPMVC4DBContext", "Users", "UserId", "Email", autoCreateTables: true);
}
// Create Admin user
if (!WebSecurity.ConfirmAccount("admin@myapp.com"))
{
//WebSecurity.CreateUserAndAccount("admin", "pass", new { email = "a@b.com" });
WebSecurity.CreateUserAndAccount("admin@myapp.com", "pass");
}
// Create admin role if not exist
if (!Roles.RoleExists("Administrator"))
{
Roles.CreateRole("Administrator");
Roles.AddUserToRole("admin@myapp.com", "Administrator");
}
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
}
5 Réponses :
S'il est déjà initialisé, assurez-vous que votre premier appel: De cette façon, vous serez sûr de ne pas répéter le processus d'initialisation. P> P >
Cela ne semble pas aider - voir ci-dessus. FYI, ma méthode de semences SampleData.cs dérive de 'DropcreateDatabaseways): Classe publique SampleData: DropcreateDatabaseways
J'ai essayé d'envelopper LAZYYLOader (voir AccountController.cs ci-dessus) dans ceci - N'a pas aidé.
Avez-vous également l'attribut d'initialisationImplemEnplemEship sur votre classe de comptyController? (Ceci est la valeur par défaut). Si tel est le cas, vous initialisez deux fois. P>
"Vous devez appeler la méthode" WebSecurity.InitializedAbaseconnection "avant d'appeler toute autre méthode de la classe" Websecurity ". Cet appel doit être placé dans un fichier _Appstart.cshtml à la racine de votre site."
@ user2254951 - Vous êtes absolument sûr que c'est le seul endroit où est la méthode initaliséatabaseconnection? Vous êtes sûr de ne pas avoir l'attribut dans plus d'un endroit?
Non, comme je dis ci-dessus - si je supprimais [Intialiszeimplememembervership] dans AccountController.cs - I Obtenir l'erreur ci-dessus (ce qui l'implique qu'il n'a pas été initialisé du tout
@ user2254951 - non? Tu n'es pas sûr?
@ user2254951 - Vous devez fournir tout le code source de votre version d'initialisationImplememberShipAttribute, en offrant uniquement une petite partie, nous ne pouvons pas voir ce que vous pourriez faire d'autre.
@ user2254951 - Il y a quelque chose qui se passe ici que vous ne nous montrez pas .. Vous devez l'appeler deux fois en quelque sorte.
@ user2254951 - Vous n'avez pas de fichier _Appstart.cshtml. Est-ce que cela a un appel d'initialiséeAbaseconnection? Avez-vous
Je n'ai pas de code dans _appstart.cshtml, seulement des informations de mise en page (un pendage de l'ancienne webmatrix, je pense?) - Et pas de référence web.config
Je pense que je l'ai réduit à la réduction - il semble fonctionner si je commencez ces lignes: [Code] (// Créer un utilisateur administrateur si (! Websecurity.confirmaccount ("admin@mydom.com")) {// Websecurity. CreateUserAndAccount ("admin", "Pass", nouveau {email = "a@b.com"}); Websecurity.createUserandAccount ("admin@mydom.com", "Pass");} // Créer un rôle d'administrateur sinon existent if (! roles.roleexists ("administrateur")) {roles.criptionaleole ("administrateur"); roles.addusertorole ("admin@mydom.com", "administrateur");} est quelque chose qui ne va pas avec eux? Si oui, quel est le meilleur moyen de semer les administrateurs?
Code formaté: Je pense que je l'ai réduit - il semble fonctionner si je commencez ces lignes: '// Créer un utilisateur administrateur si (! Websecurity.confirmaccount ("admin@mydom.com")) {// Websecurity. CreateUserandAccount ("admin", "Pass", nouveau {email = "a@b.com"}); Websecurity.createUserandAccount ("admin@mydom.com", "Pass"); } // Créer un rôle d'administration s'il n'existe pas si (! Roles.RoleExists ("Administrateur")) {Roles.Createrole ("Administrateur"); Roles.adduSertorole ("admin@mydom.com", "administrateur"); } '
est que Semencage (pour les migrations) signifie que votre Mettre le code d'initialisation dans plusieurs endroits également. Brise votre Dry NESS P> Assurez-vous que vos appels d'initialisation sont à thread-coffre-fort et ne se produisent qu'une fois par exemple d'une appdomaine. Utilisez une classe Singleton Singleton sur le fil pour le faire; et réduire la duplication du code. P> Appelez la méthode Voici un exemple simple Singleton: P> initialisatabaseconnection code> appels
Websecurity.initializeProviders code> interne et cette méthode
Websecurity.Initialisé code> et
WebSecurity.initializedAbaseconnection code> ne sont pas thread-sûrs lorsqu'ils sont utilisés ensemble EM> - Ils créent une condition de course typique. P>
Websecurity code> peut être initialisé plus d'une fois, car vous devrez peut-être également l'initialiser à Global. ASAX.cs Pour les déploiements avec semis éteint, et votre
initialisiseimplemembeShipAttribute code> peut potentiellement être appelé plusieurs fois simultanée par les demandes HTTP dans des déploiements en direct, etc. P>
La solution ... h3 >
SINGLETON ''S> EURISITIALISE CODE> à partir de tout / Tout ce qui suit, selon le cas possible pour votre application: P>
application_start code> méthode avant tout autre) li>
graines code> (avant de créer les utilisateurs) li>
SimplemembershipInitializer code> après le contexte est initialisé) LI>
ul>
// Call this with WebSecurityInitializer.Instance.EnsureInitialize()
public class WebSecurityInitializer {
private WebSecurityInitializer() { }
public static readonly WebSecurityInitializer Instance = new WebSecurityInitializer();
private bool isNotInit = true;
private readonly object SyncRoot = new object();
public void EnsureInitialize() {
if (isNotInit) {
lock (this.SyncRoot) {
if (isNotInit) {
isNotInit = false;
WebSecurity.InitializeDatabaseConnection("MyContextName",
userTableName: "UserProfile", userIdColumn: "UserId", userNameColumn: "UserName",
autoCreateTables: true);
}
}
}
}
}
Merci - ça a l'air vraiment intéressant. Rapportera l'ASAP (hors ligne pendant une journée)
En mettant en œuvre ceci maintenant - pouvez-vous recommander des exemples d'applications que je peux télécharger intégrer les meilleures pratiques - comme celle-ci. Je suis nouveau à MVC et ce serait très utile. Mvcmusicstore ne va pas presque assez loin ...
@ user2254951. En tant que sa propre classe, cela peut aller n'importe où, tant qu'il est accessible par tous les points que j'ai mentionnés qui doivent l'appeler. Je ne suis pas sûr de l'échantillon d'applications - les modèles fournis par VS sont un bon début, mais je n'ai trouvé aucun bien, grand, des exemples de meilleures pratiques encore.
Essayer de mieux comprendre la situation. J'ai ceci dans la première ligne d'application_start (): 'if (! Websecurity.Initialisé) {System.Data.entity.database.setinity.database.setinitializer (nouveau myappmvc4.models.sampledata ()); } 'J'ai aussi cela, dans les initialesImsizeImplememberShipAttribute.cs: si (! Websecurity.initialisé) {Websecurity.InitializedAbaseconnection ("MyAppmVC4DBContext", "Utilisateurs", "Courriel", "email", autocréate: true); } Ce que vous dites, c'est qu'ils conflit et ont besoin de passer au même endroit dans le code qui est exécuté une seule fois?
Je pense qu'il y a un écart sur le marché - je paierais certainement 5 $? 20 $? ou plus pour une application complète d'échantillons clairs ....
@ user2254951. Votre première ligne a l'air étrange pour moi, je ne l'ai jamais fait comme ça, ou le lier à Websecurity code> (voir endroit pour mettre de la base de données.Setinitializer et Chirurgie de fusil de chasse ). J'utilise assez séparément mon
S'assurez-existialiser code> dans les deux endroits sans aucun "si Websec ... init .." Tests pour permettre à divers scénarios de déploiement.
Merci - j'ai aussi trouvé ce message très utile: blog.longle.net/2012/09/25/...
Merci beaucoup pour cela. Je pourrais obtenir mon site pour courir et semer localement, mais je continue à courir dans la question lors de la publication d'Azure. J'ai toujours besoin de grokser complètement les concepts, mais samedi après-midi sauvé! :)
Ajouter ce code à global.asax.cs code>. Cela veillera à ce que votre base de données soit toujours initialisée avant toute autre exécution. Assurez-vous également que c'est la première inscription dans
Application_Start () CODE>
if (!WebSecurity.Initialized)
WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
Pour vous assurer que le Websecurity.InitializedAbaseconnection n'est pas appelé deux fois utilisez simplement le Websecurity.Initialisé pour vérifier s'il était déjà appelé. Ce Publication du blog fournit des instructions détaillées sur l'ensemencement et la personnalisation de SimpleMembership a>. Il y a une série dans ce blog sur l'utilisation de SimpleMembership et je recommanderais également à regarder Découplage SimpleMembership de votre application ASP.NET MVC . Vous pouvez obtenir le code source complet de ces exemples ici . P>
Montrez-nous votre code. Quelle est la trace de la pile?
Dupliqué possible de La méthode WebSecurity.InitializedAbaseconnection ne peut être appelée qu'une fois
pas dupliquer - vu ça, ne m'a pas aidé
Ajout de la trace de la pile ci-dessus