1

I am creating web app in MVC 4 that is require custom Login, authentication and role based system. My intention is to use SimpleMembership and SimpleRole but struggling to start with and grasp its basic implication within my app.

I have already database say for example DB1.mdf and have created Users table with userId and UserName. I believe i need to initialize simplemembership with existing database??? and i dont want system create database itself if it doesn't find, as it is doing in default internet template created by visual studio 2012.

many thanks in advanced...

tereško
  • 58,060
  • 25
  • 98
  • 150
K.Z
  • 5,201
  • 25
  • 104
  • 240

2 Answers2

-1

You need to use WebSecurity.InitializeDatabaseFile tell MVC.NET that you already have a database and a Users table. Then, make sure that the provider uses it upon initialization. So create an ActionFilterAttribute that ensures the Simple Membership provider is initialized, for example:

[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
        {
          if (!WebSecurity.Initialized)
          {
            WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "UserId", "UserName", autoCreateTables: true);
          }
        }
        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);
        }
      }
    }
  }

Then you will need to register the filter:

public class FilterConfig
  {
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
      filters.Add(new HandleErrorAttribute());
      filters.Add(new InitializeSimpleMembershipAttribute());
    }
  }

EDIT: Thanks to constructive criticism I've removed the code that decorates controllers with the attribute since adding it globally already takes care of the problem. If you decide not to use it globally you will need to decorate other controllers with it since, as explained on this question, you will notice that users may be authenticated with cookies and redirected to other controllers without passing first by your AccountController.

Also, Jon Galloway shows in this post how you can point to your existing database by using:

WebSecurity.InitializeDatabaseFile("SecurityDemo.sdf", "Users", "UserID", "Username", true);
Community
  • 1
  • 1
Ulises
  • 13,229
  • 5
  • 34
  • 50
  • MVC4 automatically creates this filter for you, and puts it on the AccountController so it's automatically initialized. You also do NOT want to both put it on the AccountController and add it as a global filter, then it will run twice. You haven't really addressed his question either, so downvote -1 – Erik Funkenbusch Dec 14 '12 at 18:47
  • @MystereMan Got it, you don't want to run things twice unnecessarily so I'll remove the last piece regarding the controller. However, you do use this approach above to reuse an existing database. How this does not address the OP's question? I was looking to read yours but I didn't find it. – Ulises Dec 14 '12 at 19:14
  • thanks for your guideline Ulises, I followed as you said and it works. however i have initialized 'InitializeSimpleMembership' in my controller class by calling initialize class instead of registering in Global .... – K.Z Dec 14 '12 at 20:16
  • @khurram That's great! As you will see in the linked question (http://stackoverflow.com/questions/12257232/role-based-authentication-in-the-new-mvc-4-internet-template-using-simplemembers), avoiding the global registration implies adding the attribute to any controller that may be executed first. This problem arises when they are logged in with a cookie and redirected straight to another controller. I'll expand my answer to include this info – Ulises Dec 14 '12 at 20:24
-1

SimpleMembership was not developed for extensive customization or integrating to existing databases. To use an existing database you want to create your own membership provider just like you always have in ASP.NET. You can find direction on creating your own membership provider here.

Community
  • 1
  • 1
Kevin Junghans
  • 17,475
  • 4
  • 45
  • 62
  • I'm not sure I agree with that, in fact Simple Membership was designed to be able to use an arbitrary users table. – Erik Funkenbusch Dec 14 '12 at 18:46
  • I'm currently working on a project where we have our SimpleMembership tables along with our domain tables so we indeed reuse the same database. I didn't have to do much customization, it was straightforward, see my answer's references. – Ulises Dec 14 '12 at 19:21
  • 1
    Not sure what it means to say, "...was designed to be able to use an arbitrary users table. SimmpleMembership uses EF code-first model so you can extend it by modifying the entities it is using in the code. And it looks like you can do some tricks to make it work with an existing database, but that was not what it was designed for. If you do a search on SimpleMembership in SO you will find a lot of people hitting walls with SimpleMembership, which the name implies is simple. What value do you get out of shoehorning a more advance authentication/authorization scheme with SimpleMembership? – Kevin Junghans Dec 17 '12 at 14:05