Korzystanie z SimpleMembership z modelem EF-najpierw

Czy SimpleMembership może być używany z EF model-first? Kiedy próbuję, dostaję "nie można znaleźć żądanego dostawcy danych. NET Framework", gdy wywołuję WebSecurity.InitializeDatabaseConnection.

By ująć to inaczej: nie mogę uzyskać wywołania WebSecurity.InitializeDatabaseConnection do pracy, gdy łańcuch połączenia używa dostawcy System.Data.EntityClient (Jak to robi, gdy używa paradygmatu model-first ).

Aby ponownie rozwiązać problem, utwórz aplikację MVC 4 i zamień code-first UserProfile entity class (która otrzymujesz za darmo szablon MVC 4) z model-pierwsza klasa Użytkownika, którą utworzyłeś w encji Designer:

  1. Utwórz aplikację MVC 4 w VS 2012 i dodaj nowe, puste dane encji Model.
  2. Dodaj do modelu nową jednostkę o nazwie User z polami dla Id, UserName, and FullName. Zatem w tym momencie podmiot User danych jest mapowane do tabeli Users i jest dostępne za pomocą funky connection string, który używa dostawcy System.Data.EntityClient.
  3. sprawdź, czy EF może uzyskać dostęp do podmiotu User. Jeden łatwy sposób czyli rusztowanie kontrolera Users w oparciu o tabelę User i związany z nim DbContext.
  4. Edytuj plik AccountModels.cs, aby usunąć klasę UserProfile i jego powiązana Klasa UsersContext. Zastąp odniesienia do (obecnie brak) UserProfile i UsersContext klasy z referencjami do nowej klasy użytkownika i powiązanej z nią klasy DbContext.
  5. Przenieś wywołanie do InitializeDatabaseConnection z InitializeSimpleMembershipAttribute Klasa filtra do Application_Start method in Global.asax.cs. While you ' re at it, zmodyfikuj argumenty, aby użyć połączenia nowej jednostki użytkownika ciąg znaków, nazwa tabeli i nazwa kolumny UserId.
  6. Usuń (już nie używany) InitializeSimpleMembershipAttribute klasa i odniesienia do niej.
Kiedy uruchomisz repro, otrzymasz wyjątek przy wywołaniu InitializeDatabaseConnection.

Bob

Author: Irfan, 2012-09-25

5 answers

SimpleMembership może najpierw pracować z modelem. Oto rozwiązanie.

1.InitializeSimpleMembershipAttribute.cs szablon aplikacji internetowej MVC 4 powinien wyglądać tak

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.Delete CodeFirst Classes from AcountModel.cs

3.Fix AccountCotroler.cs do pracy z Modelem - pierwsza metoda DbContext (ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl))

4.Zdefiniuj swój łańcuch połączeń "ConnStringForWebSecurity", który nie jest taki sam jak łańcuch połączeń dla pierwszego dostępu db, zauważ, że używamy provider System.Data.SqlClient, a nie 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>
 24
Author: Mario Zderic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-23 19:33:55

To błąd w MVC 4. jest obejście w tym poście na blogu .

Jako filtr akcji, InitializeSimpleMembershipAttribute zaczepia się do OnActionExecuting, aby wykonać leniwą pracę inicjalizacyjną, ale może to być zbyt późno w cyklu życia. Atrybut Authorize będzie wymagał, aby dostawcy byli gotowi wcześniej, jeśli będą musieli sprawdzić dostęp w oparciu o role (podczas OnAuthorization). Innymi słowy, jeśli pierwsze żądanie do witryny trafi w akcję kontrolera, taką jak:

[Authorize(Roles="Sales")]

.. wtedy będziesz mieć wyjątek, ponieważ filtr sprawdza rolę użytkownika, ale dostawcy nie są inicjowani.

Zalecam usunięcie ISMA z projektu i zainicjowanie WebSecurity podczas zdarzenia start aplikacji.

 12
Author: Craig Stuntz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-25 13:48:46

1 - Musisz włączyć migracje, najlepiej z EntityFramework 5

2-Przenieś swoje

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

Do metody Seed w YourMvcApp / Migrations / Configuration.Klasa cs

    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"});
    }

Teraz EF5 będzie odpowiedzialny za tworzenie tabeli UserProfile, po zrobieniu tego wywołasz WebSecurity.InitializeDatabaseConnection rejestruje tylko SimpleMembershipProvider z już utworzoną tabelą UserProfile (w Twoim przypadku możesz zastąpić parametr "UserProfile" wartość z niestandardową nazwą tabeli) , również mówi SimpleMembershipProvider, która kolumna jest UserId i UserName. Pokazuję również przykład, w jaki sposób można dodać użytkowników, role i powiązać te dwa w swojej metodzie zalążkowej z niestandardowymi właściwościami/polami UserProfile, np.

3-Teraz, gdy uruchomisz update-database z konsoli Menedżera pakietów, EF5 udostępni Twoją tabelę ze wszystkimi własnymi właściwościami

Aby uzyskać dodatkowe odniesienia, zapoznaj się z tym artykuł z kodem źródłowym: http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/

 10
Author: LeLong37,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-29 23:47:33

Ten problem spowodowany przez WebSecurity.InitializeDatabaseConnection nie może używać łańcucha połączenia z nazwą dostawcy System.Data.EntityClient.

Zapewnienie ciągu podwójnego połączenia nie brzmi dobrze, więc możesz wygenerować Łańcuch Połączenia dla modelu EF najpierw w konstruktorze w klasie częściowej.

Kod wygląda jak poniżej

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)) { }
}

Dzięki tej sztuczce możesz użyć pojedynczego ciągu połączenia w konfiguracji web, ale jeden problem nie możesz użyć domyślnego konstruktora w datacontext, zamiast tego powinieneś zalać łańcuch połączenia wymień wszędzie, gdy tworzysz instancję datacontext. ale nie jest to duży problem, gdy używasz wzorca wtrysku zależności.

 1
Author: ktutnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-13 23:30:20

Im nie może pracować z klasą EF i WebMatrix webSecurity, więc aby uniknąć tego problemu i iść do przodu:

Zmień najpierw mój model Ef na kod.

Zmień łańcuch połączeń na providerName= " System.Data.SqlClient " (usuwanie wszystkich informacji metadanych) lub użyj połączenia EF

W moim przypadku model, Dane i web są różne proyects więc dla mnie nie jest problemem, aby usunąć te informacje z sieci.config w sieci.projekt.

Obecnie websecuroty.initializedatabase nie uruchamia się z łańcuchem połączeń EF.

I wish this helps

 0
Author: jlsfernandez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-01 07:34:01