Sunday, November 6, 2016

How To Stop The Asp.Net Identity Service From Continuing To Create The AspNetUsers Table After Changing The TableNames

I came across something while using the latest version of Asp.Net Identity that will likely save someone out there some time. It was a simple thing, but might not be readily apparent.


By default, when you use the AspNet Identity service, it creates the following set of tables:
  • dbo.AspNetRoles
  • dbo.AspNetUserClaims
  • dbo.AspNetUserLogins
  • dbo.AspNetUserRoles
  • dbo.AspNetUsers
The default schema is dbo and the table names are the default names created by the AspNet Identity service.

To change the default schema, you can do one of a couple of things.
You can add the schema to the OnModelCreating method like so:

  protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
   {
      base.OnModelCreating(modelBuilder);
           
      //your default schema would be a string of your choosing
      modelBuilder.HasDefaultSchema("YourDefaultSchemaHere");
   }

or you can change the schema as you rename the table in the OnModelCreating method

   modelBuilder.Entity<IdentityUser>().ToTable("Users", "YourDefaultSchemaHere");
 

Either of these methods change your tables to:


  • YourDefaultSchemaHere.AspNetRoles
  • YourDefaultSchemaHere.AspNetUserClaims
  • YourDefaultSchemaHere.AspNetUserLogins
  • YourDefaultSchemaHere.AspNetUserRoles
  • YourDefaultSchemaHere.AspNetUsers

  • If you want to change the default AspNet Identity table names, you can do it in the following way:


    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {   base.OnModelCreating(modelBuilder);

       //this is the default schema that will be used in the system.
       //I have the schema value stored in the app settings area of my web.config 

       modelBuilder.HasDefaultSchema(ConfigurationManager.AppSettings 
       ["DefaultDatabaseSchema"]);

       //the renamed tables

       modelBuilder.Entity<ApplicationUser>().ToTable("Users");

       modelBuilder.Entity<IdentityRole>().ToTable("Roles");

       modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles");

       modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims");

       modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins");
    }



    Using either your new schema name or dbo, you add a field to ApplicationUser like this:


    public class ApplicationUser : IdentityUser
    {
       [Required]
       public string WebsiteUrl { get; set; }


          //...other stuff here
    }


    That field, in this case WebsiteUrl, will be added to the AspNetUsers table.
    That is what you would expect to happen.
    Now, here is where things might get strange for you.
    There is a situation where you can rename the default table and add that field, but the field will NOT be added to the new table name! It will STILL be added to the database, but in the AspNetUsers table! That is NOT what you would expect right? Well here is a little bit of news for you, there is a simple fix for this if this behavior is not what you want.


    If this is happening to you, it is likely happening because you are identifying the IdentityUser table INSTEAD of the ApplicationUser table when you rename your tables.


    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {
       base.OnModelCreating(modelBuilder);


       //this is the default schema that will be used in the system to separate the

       modelBuilder.HasDefaultSchema(ConfigurationManager.AppSettings 
       ["DefaultSchemaToBeUsedToPrefaceCreatedDatabaseTables"]);


       //the renamed tables

       modelBuilder.Entity<ApplicationUser>().ToTable("Users");

       modelBuilder.Entity<IdentityRole>().ToTable("Roles");

       modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles");

       modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims");

       modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins");
    }


    Notice the highlighted field. If you have IdentityUser in that field instead of ApplicationUser, the IdentityUser table and its associated fields will be renamed to Users, however, IdentityUser doesn't know anything about the extra field or fields you might have added in ApplicationUser. ApplicationUser incorporates the IdentityUser fields AND your added field. In my example above, that field is the WebsiteUrl. So, if your system is creating the database tables and STILL creating the AspNetUsers table AFTER you have renamed the table names, check the entity name you are using for the Users table. Remember that it should be ApplicationUser - NOT IdentityUser.


    Smooches!
    Kila



















    Monday, April 4, 2016

    How To Solve Website Errors: 503 Service Temporarily Unavailable While Using WordPress With A Windows Shared Hosting Accounts

    OK. This is an error that will likely have you pulling your hair out (if you have hair :-)). Here is the scenario.

    I have several website hosting accounts. One of those accounts is a Windows account that allows me to host multiple website (Deluxe Shared Hosting). I have MANY domains hosted on this account and the websites are a mixture of Asp.Net MVC, Asp.Net Webforms (yes...webforms still work :-)) and WordPress sites. I noticed an odd thing happening with the WordPress sites. From time to time, as I was working in the WordPress admin area, the sites would produce a 503 Service Unavailable error. Sometimes I would be editing a menu and click the Update button and would get the error. Sometimes I would make a change and try to visit the site and get the error. Sometimes I would make a theme edit and save and get the error. It happened at very random moments when some action was initiated on the server.

    Initially, I thought it was the version of PHP being used for the shared hosting account, so I upgraded to version 5.4 (I was using 5.2). Nope! That did NOT solve the problem at all. OK. What next? I upgraded WordPress for one of the accounts and started hammering it. No resolution! I kept getting the intermittent 503 errors. OK. So now what? Next I started hammering my Asp.Net MVC websites to try to produce the error. Nope! Couldn't reproduce the 503 error on ANY of those sites. I did the same for the Webforms sites and could not reproduce the 503 error there either. So I realized the first fact about this error -

    FACT #1 - The 503 Service Temporarily Unavailable error was ONLY happening on my Windows hosted accounts that had WordPress installed in their folders.

    Interesting....

    After realizing fact #1, I started to pay very close attention to what was happening when the error happened. I realized something. The error seemed to happen when some function had to be performed - ie. when something had to be saved. It didn't seem to happen on navigation only actions like going from page to page. However, I did notice that if the error happened when I was trying to perform an action in the admin panel, then I would also get the error on the website if I tried to bring that up at that moment. It was like the server was hanging on any server function other than serving pages and would get "stuck" for a few moments. It felt like the request for processing was happening too fast for the server to handle it so it would produce an error. Basically, the request for a function was coming in and being routed, but the underlying process could not move quickly enough to process it.

    Since Google is my friend, I started researching the issue. I saw that many people had the 503 error on shared hosting accounts, but no one had a real solution - including the hosting companies! Now I'm no server expert, but this isn't rocket science either. How hard can it be for some of these hosting companies to examine their logs and come up with a solution? Based on what I read, it must be VERY hard for them to do that! Anywho.....I decided to keep researching.

    I came across this from Microsoft -
    https://support.microsoft.com/en-us/kb/2619402

    That article gave me some great information. Since the Windows Deluxe shared hosting account allowed me to interact with IIS in a very limited way, I decided to see if I could tweak some settings in their to prevent, help, solve or stop the 503 errors from continuing to happen. By the way, my hosting account is using IIS 7.0. The IIS area provided by the website was very limited. However, it did allow me to switch from Integrated to Classic Pipeline mode. In integrated mode, all requests are handled in a unified pipeline. However, in classic mode, there are two pipelines. One is for native code applications and one is for managed code applications. You can look up the differences between native code and managed code, but essentially managed code needs a runtime to handle its execution. Native code executes on a particular processor and it takes it's instructions on how to run from the OS it is running on.

    So, here is what I did. The IIS 7.0 pipeline was set to Integrated mode. I changed this to Classic. Then I recycled the App Pool. The combination of these two things stopped the 503 errors from happening. This should help you get your websites running if you are on a Windows shared hosting account with limited access to IIS. Do not forget to recycle the app pool.

    I will keep you updated on how this "fix" holds. I have tested it quite a bit and haven't received a 503 error again....YET :-)!

    If you are experiencing this issue on your shared Windows hosting account with WordPress, try this and let me know how it works for you.

    Smooches,

    Kila Morton