locked
Using starter site - authenticating with username and password RRS feed

  • Question

  • User-1370183403 posted

    Hi, I am working with the starter site and would like to authenticate users using a username and password rather than email and password.

    Is it a matter of adding a username column to the UserProfile table and then just updating all the Websecurity methods to use username instead of email.?

    As this happens in the background I am guessing if it will then query this field.

    I have tried

    Websecurity.CreateAccount(username, password, requireEmailConfirmation);

    But this doesn't work

    However, documentation does indicate this is possible to use username

    http://msdn.microsoft.com/en-us/library/webmatrix.webdata.websecurity.createaccount%28v=vs.111%29.aspx

    So I must be doing something wrong, if anyone can guide me how to change the starter site to register and authenticate on username it would be appreciated

    cheers

    Monday, September 1, 2014 6:38 PM

Answers

  • User1292124637 posted

    Ok, this assumes you haven't made any changes to the membership system and you're starting with a clean starter template. THIS IS TESTED 100% WORKING ON WEBMATRIX. Here goes.

    FIRST, here's how your _AppStart.cshtml page should look like:

    @{
        WebSecurity.InitializeDatabaseConnection("StarterSite", "UserProfile", "UserId", "Email", autoCreateTables: true);
    
        //CUSTOM
    
        //create username column in Membership database
        var db =  Database.Open("StarterSite");
        var select =  db.Query("SELECT userName FROM UserProfile");
        if(select == null) {
                var dbCommand = "ALTER TABLE UserProfile ADD userName nvarchar(50)";
                db.Execute(dbCommand);
            }
        else {
            //do nothing
        }
        
        //END CUSTOM
    
    
        // To let users of this site log in using their accounts from other sites such as Microsoft, Facebook, Twitter,
        // you must update this site. For more information visit http://go.microsoft.com/fwlink/?LinkID=226949
    
        //OAuthWebSecurity.RegisterMicrosoftClient(
        //    clientId: "",
        //    clientSecret: "");
    
        //OAuthWebSecurity.RegisterTwitterClient(
        //    consumerKey: "",
        //    consumerSecret: "");
    
        //OAuthWebSecurity.RegisterFacebookClient(
        //    appId: "",
        //    appSecret: "");
    
        //OAuthWebSecurity.RegisterGoogleClient();
    
        //WebMail.SmtpServer = "mailserver.example.com";
        //WebMail.EnableSsl = true;
        //WebMail.UserName = "username@example.com";
        //WebMail.Password = "your-password";
        //WebMail.From = "your-name-here@example.com";
    
        // To learn how to optimize scripts and stylesheets in your site go to http://go.microsoft.com/fwlink/?LinkID=248973
    }

    The above inserts a 3rd column after UserId in UserProfile table in StarterSite.sdf database.

    SECOND, here's how your register.cshtml should look like:

    @using System.Data.SqlServerCe
    
    @* Remove this section if you are using bundling *@
    @section Scripts {
        <script src="~/Scripts/jquery.validate.min.js"></script>
        <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    }
    
    @{
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Register";
    
        // Initialize general page variables
        //CUSTOM
        var username = "";
        //END CUSTOM
        var email = "";
        var password = "";
        var confirmPassword = "";
    
        // Setup validation
        Validation.RequireField("username", "You must specify desired username.");
        Validation.RequireField("email", "You must specify an email address.");
        Validation.RequireField("password", "Password cannot be blank.");
        Validation.Add("confirmPassword",
            Validator.EqualsTo("password", "Password and confirmation password do not match."));
        Validation.Add("password",
            Validator.StringLength(
                maxLength: Int32.MaxValue,
                minLength: 6,
                errorMessage: "Password must be at least 6 characters"));
    
        // If this is a POST request, validate and process data
        if (IsPost) {
            AntiForgery.Validate();
            //CUSTOM
            username = Request.Form["username"];
            //END CUSTOM
            email = Request.Form["email"];
            password = Request.Form["password"];
            confirmPassword = Request.Form["confirmPassword"];
    
            // Validate the user's captcha answer
            // if (!ReCaptcha.Validate("PRIVATE_KEY")) {
            //     ModelState.AddError("recaptcha", "Captcha response was not correct");
            // }
    
            // If all information is valid, create a new account
            if (Validation.IsValid()) {
                // Insert a new user into the database
                var db = Database.Open("StarterSite");
    
                // Check if user already exists
                var user = db.QuerySingle("SELECT Email FROM UserProfile WHERE LOWER(Email) = LOWER(@0)", email);
                if (user == null) {
                    
                    //CUSTOM
                    // Insert email & username into the profile table
                    db.Execute("INSERT INTO UserProfile (Email, userName) VALUES (@0, @1)", email, username);
                    //END CUSTOM
    
                    // Create and associate a new entry in the membership database.
                    // If successful, continue processing the request
                    try {
                        bool requireEmailConfirmation = !WebMail.SmtpServer.IsEmpty();
                        var token = WebSecurity.CreateAccount(email, password, requireEmailConfirmation);
                        if (requireEmailConfirmation) {
                            var hostUrl = Request.Url.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);
                            var confirmationUrl = hostUrl + VirtualPathUtility.ToAbsolute("~/Account/Confirm?confirmationCode=" + HttpUtility.UrlEncode(token));
    
                            WebMail.Send(
                                to: email,
                                subject: "Please confirm your account",
                                body: "Your confirmation code is: " + token + ". Visit <a href=\"" + confirmationUrl + "\">" + confirmationUrl + "</a> to activate your account."
                            );
                        }
    
                        if (requireEmailConfirmation) {
                            // Thank the user for registering and let them know an email is on its way
                            Response.Redirect("~/Account/Thanks");
                        } else {
                            // Navigate back to the homepage and exit
                            WebSecurity.Login(email, password);
    
                            Response.Redirect("~/");
                        }
                    } catch (System.Web.Security.MembershipCreateUserException e) {
                        ModelState.AddFormError(e.Message);
                    }
                } else {
                    // User already exists
                    ModelState.AddFormError("Email address is already in use.");
                }
            }
        }
    }
    
    <hgroup class="title">
        <h1>@Page.Title.</h1>
        <h2>Create a new account.</h2>
    </hgroup>
    
    <form method="post">
        @AntiForgery.GetHtml()
        @* If at least one validation error exists, notify the user *@
        @Html.ValidationSummary("Account creation was unsuccessful. Please correct the errors and try again.", excludeFieldErrors: true, htmlAttributes: null)
    
        <fieldset>
            <legend>Registration Form</legend>
            <ol>
                <!-- CUSTOM -->
                <li class="email">
                    <label for="username" @if(!ModelState.IsValidField("username")){<text>class="error-label"</text>}>Username</label>
                    <input type="text" id="username" name="username" value="@username" @Validation.For("username") />
                    @* Write any email validation errors to the page *@
                    @Html.ValidationMessage("username")                
                </li>
                <!-- END CUSTOM -->
    
                <li class="email">
                    <label for="email" @if(!ModelState.IsValidField("email")){<text>class="error-label"</text>}>Email address</label>
                    <input type="text" id="email" name="email" value="@email" @Validation.For("email") />
                    @* Write any email validation errors to the page *@
                    @Html.ValidationMessage("email")
                </li>
                <li class="password">
                    <label for="password" @if(!ModelState.IsValidField("password")) {<text>class="error-label"</text>}>Password</label>
                    <input type="password" id="password" name="password" @Validation.For("password") />
                    @* Write any password validation errors to the page *@
                    @Html.ValidationMessage("password")
                </li>
                <li class="confirm-password">
                    <label for="confirmPassword" @if(!ModelState.IsValidField("confirmPassword")) {<text>class="error-label"</text>}>Confirm password</label>
                    <input type="password" id="confirmPassword" name="confirmPassword" @Validation.For("confirmPassword") />
                    @* Write any password validation errors to the page *@
                    @Html.ValidationMessage("confirmPassword")
                </li>
                <li class="recaptcha">
                    <div class="message-info">
                        <p>
                            To enable CAPTCHA verification, <a href="http://go.microsoft.com/fwlink/?LinkId=204140">install the 
                            ASP.NET Web Helpers Library</a> and uncomment ReCaptcha.GetHtml and replace 'PUBLIC_KEY'
                            with your public key. At the top of this page, uncomment ReCaptcha. Validate and
                            replace 'PRIVATE_KEY' with your private key.
                            Register for reCAPTCHA keys at <a href="http://recaptcha.net">reCAPTCHA.net</a>.
                        </p>
                    </div>
                    @*
                    @ReCaptcha.GetHtml("PUBLIC_KEY", theme: "white")
                    @Html.ValidationMessage("recaptcha")
                    *@
                </li>
            </ol>
            <input type="submit" value="Register" />
        </fieldset>
    </form>

    Take note of the CUSTOM comments I've added. Those are the sections I've modified in the Starter Template files to have this work for you. The above basically inserts selected username in the register page into the UserProfile table associating it with the registration e-mail.

    THIRD, you need to modify your Login.cshtml page to look like this:

    @* Remove this section if you are using bundling *@
    @section Scripts {
        <script src="~/Scripts/jquery.validate.min.js"></script>
        <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    }
    
    @{
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Log in";
    
        // Initialize general page variables
        //CUSTOM
        var username = "";
        //END CUSTOM
        var email = "";
        var password = "";
        var rememberMe = false;
            
        var returnUrl = Request.QueryString["ReturnUrl"];
        if (returnUrl.IsEmpty()) {
            // Some external login providers always require a return URL value
            returnUrl = Href("~/");
        }
    
        // Setup validation
        //CUSTOM
        Validation.RequireField("username", "You must specify a username.");
        //END CUSTOM
        Validation.RequireField("password", "You must specify a password.");
        Validation.Add("password",
            Validator.StringLength(
                maxLength: Int32.MaxValue,
                minLength: 6,
                errorMessage: "Password must be at least 6 characters"));
    
        // If this is a POST request, validate and process data
        if (IsPost) {
            AntiForgery.Validate();
            // is this an external login request?
            string provider = Request.Form["provider"];
            if (!provider.IsEmpty()) {
                OAuthWebSecurity.RequestAuthentication(provider, Href("~/Account/RegisterService", new { returnUrl }));
                return;
            } else if (Validation.IsValid()) {
                //CUSTOM
                username = Request.Form["username"];
                //END CUSTOM
                password = Request.Form["password"];
                rememberMe = Request.Form["rememberMe"].AsBool();
                //CUSTOM
                //get email based on password
                var db = Database.Open("StarterSite");
                email = db.QueryValue("SELECT Email FROM UserProfile WHERE userName=@0", username);
                //END CUSTOM
                if (WebSecurity.UserExists(email) && WebSecurity.GetPasswordFailuresSinceLastSuccess(email) > 4 && WebSecurity.GetLastPasswordFailureDate(email).AddSeconds(60) > DateTime.UtcNow) {
                    Response.Redirect("~/Account/AccountLockedOut");
                    return;
                }
    
                // Attempt to log in using provided credentials
                if (WebSecurity.Login(email, password, rememberMe)) {
                    Context.RedirectLocal(returnUrl);
                    return;
                } else {
                    ModelState.AddFormError("The user name or password provided is incorrect.");
                }
            }
        }
    }
    
    <hgroup class="title">
        <h1>@Page.Title.</h1>
    </hgroup>
    
    <section id="loginForm">
        <h2>Use a local account to log in.</h2>
        <form method="post">
            @AntiForgery.GetHtml()
            @* If one or more validation errors exist, show an error *@
            @Html.ValidationSummary("Log in was unsuccessful. Please correct the errors and try again.", excludeFieldErrors: true, htmlAttributes: null)
    
            <fieldset>
                <legend>Log in to Your Account</legend>
                <ol>
                    <!-- CUSTOM -->
                    <li class="username">                                                                    
                        <label for="username" @if (!ModelState.IsValidField("username"))
                                           {<text>class="error-label"</text>}>Username</label>
                        <input type="text" id="username" name="username" value="@username" @Validation.For("username")/>
                        @* Write any user name validation errors to the page *@
                        @Html.ValidationMessage("username")
                    </li>
                    <!-- END CUSTOM -->
                    <li class="password">
                        <label for="password" @if (!ModelState.IsValidField("password")) {<text>class="error-label"</text>}>Password</label>
                        <input type="password" id="password" name="password" @Validation.For("password")/>
                        @* Write any password validation errors to the page *@
                        @Html.ValidationMessage("password")
                    </li>
                    <li class="remember-me">
                        <input type="checkbox" id="rememberMe" name="rememberMe" value="true" checked="@rememberMe" />
                        <label class="checkbox" for="rememberMe">Remember me?</label>
                    </li>
                </ol>
                <input type="submit" value="Log in" />
            </fieldset>
        </form>
        <p>
            <a href="~/Account/Register">Don't have a Account?</a>
            <a href="~/Account/ForgotPassword">Did you forget your password?</a>
        </p>
    </section>
    
    <section class="social" id="socialLoginForm">
        <h2>Use another service to log in.</h2>
        @RenderPage("~/Account/_ExternalLoginsList.cshtml")
    </section>
    

    Again, take note of the modifications I have made tagged with //CUSTOM comment. The above basically, allows you to log in with username instead of e-mail, by selecting email from database based on username input and logging in with e-mail in the back-end.

    FINALLY, to show username as logged in instead of e-mail, modify your _SiteLayout.cshtml to look like this:

    @{
        //CUSTOM
        var email = "";
        email = WebSecurity.CurrentUserName;
        var db = Database.Open("StarterSite");
        var showUserName =  db.QueryValue("SELECT userName FROM UserProfile WHERE Email=@0", email);
        //END CUSTOM
    }
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>@Page.Title - My ASP.NET Web Page</title>
            <link href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css" />
            <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
            <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
            <script src="~/Scripts/jquery-1.8.2.min.js"></script>
            <script src="~/Scripts/jquery-ui-1.8.24.js"></script>
            <script src="~/Scripts/modernizr-2.6.2.js"></script>
            <meta name="viewport" content="width=device-width" />
        </head>
        <body>
            <header>
                <div class="content-wrapper">
                    <div class="float-left">
                        <p class="site-title"><a href="~/">your logo here</a></p>
                    </div>
                    <div class="float-right">
                        <section id="login">
                            @if (WebSecurity.IsAuthenticated) {
                                <text>
                                    <!-- CUSTOM -->
                                    Hello, <a class="email" href="~/Account/Manage" title="Manage">@showUserName</a>
                                    <form id="logoutForm" action="~/Account/Logout" method="post">
                                        @AntiForgery.GetHtml()
                                        <a href="javascript:document.getElementById('logoutForm').submit()">Log out</a>
                                    </form>
                                    <!-- END CUSTOM -->
                                </text>
                            } else {
                                <ul>
                                    <li><a href="~/Account/Register">Register</a></li>
                                    <li><a href="~/Account/Login">Log in</a></li>
                                </ul>
                            }
                        </section>
                        <nav>
                            <ul id="menu">
                                <li><a href="~/">Home</a></li>
                                <li><a href="~/About">About</a></li>
                                <li><a href="~/Contact">Contact</a></li>
                            </ul>
                        </nav>
                    </div>
                </div>
            </header>
            <div id="body">
                @RenderSection("featured", required: false)
                <section class="content-wrapper main-content clear-fix">
                    @RenderBody()
                </section>
            </div>
            <footer>
                <div class="content-wrapper">
                    <div class="float-left">
                        <p>&copy; @DateTime.Now.Year - My ASP.NET Web Page</p>
                    </div>
                </div>
            </footer>
            @RenderSection("Scripts", required: false)
        </body>
    </html>

    The above ensures your username is displayed once logged in, and not your e-mail.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, September 2, 2014 11:42 AM

All replies

  • User1292124637 posted

    Ok, this assumes you haven't made any changes to the membership system and you're starting with a clean starter template. THIS IS TESTED 100% WORKING ON WEBMATRIX. Here goes.

    FIRST, here's how your _AppStart.cshtml page should look like:

    @{
        WebSecurity.InitializeDatabaseConnection("StarterSite", "UserProfile", "UserId", "Email", autoCreateTables: true);
    
        //CUSTOM
    
        //create username column in Membership database
        var db =  Database.Open("StarterSite");
        var select =  db.Query("SELECT userName FROM UserProfile");
        if(select == null) {
                var dbCommand = "ALTER TABLE UserProfile ADD userName nvarchar(50)";
                db.Execute(dbCommand);
            }
        else {
            //do nothing
        }
        
        //END CUSTOM
    
    
        // To let users of this site log in using their accounts from other sites such as Microsoft, Facebook, Twitter,
        // you must update this site. For more information visit http://go.microsoft.com/fwlink/?LinkID=226949
    
        //OAuthWebSecurity.RegisterMicrosoftClient(
        //    clientId: "",
        //    clientSecret: "");
    
        //OAuthWebSecurity.RegisterTwitterClient(
        //    consumerKey: "",
        //    consumerSecret: "");
    
        //OAuthWebSecurity.RegisterFacebookClient(
        //    appId: "",
        //    appSecret: "");
    
        //OAuthWebSecurity.RegisterGoogleClient();
    
        //WebMail.SmtpServer = "mailserver.example.com";
        //WebMail.EnableSsl = true;
        //WebMail.UserName = "username@example.com";
        //WebMail.Password = "your-password";
        //WebMail.From = "your-name-here@example.com";
    
        // To learn how to optimize scripts and stylesheets in your site go to http://go.microsoft.com/fwlink/?LinkID=248973
    }

    The above inserts a 3rd column after UserId in UserProfile table in StarterSite.sdf database.

    SECOND, here's how your register.cshtml should look like:

    @using System.Data.SqlServerCe
    
    @* Remove this section if you are using bundling *@
    @section Scripts {
        <script src="~/Scripts/jquery.validate.min.js"></script>
        <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    }
    
    @{
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Register";
    
        // Initialize general page variables
        //CUSTOM
        var username = "";
        //END CUSTOM
        var email = "";
        var password = "";
        var confirmPassword = "";
    
        // Setup validation
        Validation.RequireField("username", "You must specify desired username.");
        Validation.RequireField("email", "You must specify an email address.");
        Validation.RequireField("password", "Password cannot be blank.");
        Validation.Add("confirmPassword",
            Validator.EqualsTo("password", "Password and confirmation password do not match."));
        Validation.Add("password",
            Validator.StringLength(
                maxLength: Int32.MaxValue,
                minLength: 6,
                errorMessage: "Password must be at least 6 characters"));
    
        // If this is a POST request, validate and process data
        if (IsPost) {
            AntiForgery.Validate();
            //CUSTOM
            username = Request.Form["username"];
            //END CUSTOM
            email = Request.Form["email"];
            password = Request.Form["password"];
            confirmPassword = Request.Form["confirmPassword"];
    
            // Validate the user's captcha answer
            // if (!ReCaptcha.Validate("PRIVATE_KEY")) {
            //     ModelState.AddError("recaptcha", "Captcha response was not correct");
            // }
    
            // If all information is valid, create a new account
            if (Validation.IsValid()) {
                // Insert a new user into the database
                var db = Database.Open("StarterSite");
    
                // Check if user already exists
                var user = db.QuerySingle("SELECT Email FROM UserProfile WHERE LOWER(Email) = LOWER(@0)", email);
                if (user == null) {
                    
                    //CUSTOM
                    // Insert email & username into the profile table
                    db.Execute("INSERT INTO UserProfile (Email, userName) VALUES (@0, @1)", email, username);
                    //END CUSTOM
    
                    // Create and associate a new entry in the membership database.
                    // If successful, continue processing the request
                    try {
                        bool requireEmailConfirmation = !WebMail.SmtpServer.IsEmpty();
                        var token = WebSecurity.CreateAccount(email, password, requireEmailConfirmation);
                        if (requireEmailConfirmation) {
                            var hostUrl = Request.Url.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);
                            var confirmationUrl = hostUrl + VirtualPathUtility.ToAbsolute("~/Account/Confirm?confirmationCode=" + HttpUtility.UrlEncode(token));
    
                            WebMail.Send(
                                to: email,
                                subject: "Please confirm your account",
                                body: "Your confirmation code is: " + token + ". Visit <a href=\"" + confirmationUrl + "\">" + confirmationUrl + "</a> to activate your account."
                            );
                        }
    
                        if (requireEmailConfirmation) {
                            // Thank the user for registering and let them know an email is on its way
                            Response.Redirect("~/Account/Thanks");
                        } else {
                            // Navigate back to the homepage and exit
                            WebSecurity.Login(email, password);
    
                            Response.Redirect("~/");
                        }
                    } catch (System.Web.Security.MembershipCreateUserException e) {
                        ModelState.AddFormError(e.Message);
                    }
                } else {
                    // User already exists
                    ModelState.AddFormError("Email address is already in use.");
                }
            }
        }
    }
    
    <hgroup class="title">
        <h1>@Page.Title.</h1>
        <h2>Create a new account.</h2>
    </hgroup>
    
    <form method="post">
        @AntiForgery.GetHtml()
        @* If at least one validation error exists, notify the user *@
        @Html.ValidationSummary("Account creation was unsuccessful. Please correct the errors and try again.", excludeFieldErrors: true, htmlAttributes: null)
    
        <fieldset>
            <legend>Registration Form</legend>
            <ol>
                <!-- CUSTOM -->
                <li class="email">
                    <label for="username" @if(!ModelState.IsValidField("username")){<text>class="error-label"</text>}>Username</label>
                    <input type="text" id="username" name="username" value="@username" @Validation.For("username") />
                    @* Write any email validation errors to the page *@
                    @Html.ValidationMessage("username")                
                </li>
                <!-- END CUSTOM -->
    
                <li class="email">
                    <label for="email" @if(!ModelState.IsValidField("email")){<text>class="error-label"</text>}>Email address</label>
                    <input type="text" id="email" name="email" value="@email" @Validation.For("email") />
                    @* Write any email validation errors to the page *@
                    @Html.ValidationMessage("email")
                </li>
                <li class="password">
                    <label for="password" @if(!ModelState.IsValidField("password")) {<text>class="error-label"</text>}>Password</label>
                    <input type="password" id="password" name="password" @Validation.For("password") />
                    @* Write any password validation errors to the page *@
                    @Html.ValidationMessage("password")
                </li>
                <li class="confirm-password">
                    <label for="confirmPassword" @if(!ModelState.IsValidField("confirmPassword")) {<text>class="error-label"</text>}>Confirm password</label>
                    <input type="password" id="confirmPassword" name="confirmPassword" @Validation.For("confirmPassword") />
                    @* Write any password validation errors to the page *@
                    @Html.ValidationMessage("confirmPassword")
                </li>
                <li class="recaptcha">
                    <div class="message-info">
                        <p>
                            To enable CAPTCHA verification, <a href="http://go.microsoft.com/fwlink/?LinkId=204140">install the 
                            ASP.NET Web Helpers Library</a> and uncomment ReCaptcha.GetHtml and replace 'PUBLIC_KEY'
                            with your public key. At the top of this page, uncomment ReCaptcha. Validate and
                            replace 'PRIVATE_KEY' with your private key.
                            Register for reCAPTCHA keys at <a href="http://recaptcha.net">reCAPTCHA.net</a>.
                        </p>
                    </div>
                    @*
                    @ReCaptcha.GetHtml("PUBLIC_KEY", theme: "white")
                    @Html.ValidationMessage("recaptcha")
                    *@
                </li>
            </ol>
            <input type="submit" value="Register" />
        </fieldset>
    </form>

    Take note of the CUSTOM comments I've added. Those are the sections I've modified in the Starter Template files to have this work for you. The above basically inserts selected username in the register page into the UserProfile table associating it with the registration e-mail.

    THIRD, you need to modify your Login.cshtml page to look like this:

    @* Remove this section if you are using bundling *@
    @section Scripts {
        <script src="~/Scripts/jquery.validate.min.js"></script>
        <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    }
    
    @{
        Layout = "~/_SiteLayout.cshtml";
        Page.Title = "Log in";
    
        // Initialize general page variables
        //CUSTOM
        var username = "";
        //END CUSTOM
        var email = "";
        var password = "";
        var rememberMe = false;
            
        var returnUrl = Request.QueryString["ReturnUrl"];
        if (returnUrl.IsEmpty()) {
            // Some external login providers always require a return URL value
            returnUrl = Href("~/");
        }
    
        // Setup validation
        //CUSTOM
        Validation.RequireField("username", "You must specify a username.");
        //END CUSTOM
        Validation.RequireField("password", "You must specify a password.");
        Validation.Add("password",
            Validator.StringLength(
                maxLength: Int32.MaxValue,
                minLength: 6,
                errorMessage: "Password must be at least 6 characters"));
    
        // If this is a POST request, validate and process data
        if (IsPost) {
            AntiForgery.Validate();
            // is this an external login request?
            string provider = Request.Form["provider"];
            if (!provider.IsEmpty()) {
                OAuthWebSecurity.RequestAuthentication(provider, Href("~/Account/RegisterService", new { returnUrl }));
                return;
            } else if (Validation.IsValid()) {
                //CUSTOM
                username = Request.Form["username"];
                //END CUSTOM
                password = Request.Form["password"];
                rememberMe = Request.Form["rememberMe"].AsBool();
                //CUSTOM
                //get email based on password
                var db = Database.Open("StarterSite");
                email = db.QueryValue("SELECT Email FROM UserProfile WHERE userName=@0", username);
                //END CUSTOM
                if (WebSecurity.UserExists(email) && WebSecurity.GetPasswordFailuresSinceLastSuccess(email) > 4 && WebSecurity.GetLastPasswordFailureDate(email).AddSeconds(60) > DateTime.UtcNow) {
                    Response.Redirect("~/Account/AccountLockedOut");
                    return;
                }
    
                // Attempt to log in using provided credentials
                if (WebSecurity.Login(email, password, rememberMe)) {
                    Context.RedirectLocal(returnUrl);
                    return;
                } else {
                    ModelState.AddFormError("The user name or password provided is incorrect.");
                }
            }
        }
    }
    
    <hgroup class="title">
        <h1>@Page.Title.</h1>
    </hgroup>
    
    <section id="loginForm">
        <h2>Use a local account to log in.</h2>
        <form method="post">
            @AntiForgery.GetHtml()
            @* If one or more validation errors exist, show an error *@
            @Html.ValidationSummary("Log in was unsuccessful. Please correct the errors and try again.", excludeFieldErrors: true, htmlAttributes: null)
    
            <fieldset>
                <legend>Log in to Your Account</legend>
                <ol>
                    <!-- CUSTOM -->
                    <li class="username">                                                                    
                        <label for="username" @if (!ModelState.IsValidField("username"))
                                           {<text>class="error-label"</text>}>Username</label>
                        <input type="text" id="username" name="username" value="@username" @Validation.For("username")/>
                        @* Write any user name validation errors to the page *@
                        @Html.ValidationMessage("username")
                    </li>
                    <!-- END CUSTOM -->
                    <li class="password">
                        <label for="password" @if (!ModelState.IsValidField("password")) {<text>class="error-label"</text>}>Password</label>
                        <input type="password" id="password" name="password" @Validation.For("password")/>
                        @* Write any password validation errors to the page *@
                        @Html.ValidationMessage("password")
                    </li>
                    <li class="remember-me">
                        <input type="checkbox" id="rememberMe" name="rememberMe" value="true" checked="@rememberMe" />
                        <label class="checkbox" for="rememberMe">Remember me?</label>
                    </li>
                </ol>
                <input type="submit" value="Log in" />
            </fieldset>
        </form>
        <p>
            <a href="~/Account/Register">Don't have a Account?</a>
            <a href="~/Account/ForgotPassword">Did you forget your password?</a>
        </p>
    </section>
    
    <section class="social" id="socialLoginForm">
        <h2>Use another service to log in.</h2>
        @RenderPage("~/Account/_ExternalLoginsList.cshtml")
    </section>
    

    Again, take note of the modifications I have made tagged with //CUSTOM comment. The above basically, allows you to log in with username instead of e-mail, by selecting email from database based on username input and logging in with e-mail in the back-end.

    FINALLY, to show username as logged in instead of e-mail, modify your _SiteLayout.cshtml to look like this:

    @{
        //CUSTOM
        var email = "";
        email = WebSecurity.CurrentUserName;
        var db = Database.Open("StarterSite");
        var showUserName =  db.QueryValue("SELECT userName FROM UserProfile WHERE Email=@0", email);
        //END CUSTOM
    }
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>@Page.Title - My ASP.NET Web Page</title>
            <link href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css" />
            <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
            <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
            <script src="~/Scripts/jquery-1.8.2.min.js"></script>
            <script src="~/Scripts/jquery-ui-1.8.24.js"></script>
            <script src="~/Scripts/modernizr-2.6.2.js"></script>
            <meta name="viewport" content="width=device-width" />
        </head>
        <body>
            <header>
                <div class="content-wrapper">
                    <div class="float-left">
                        <p class="site-title"><a href="~/">your logo here</a></p>
                    </div>
                    <div class="float-right">
                        <section id="login">
                            @if (WebSecurity.IsAuthenticated) {
                                <text>
                                    <!-- CUSTOM -->
                                    Hello, <a class="email" href="~/Account/Manage" title="Manage">@showUserName</a>
                                    <form id="logoutForm" action="~/Account/Logout" method="post">
                                        @AntiForgery.GetHtml()
                                        <a href="javascript:document.getElementById('logoutForm').submit()">Log out</a>
                                    </form>
                                    <!-- END CUSTOM -->
                                </text>
                            } else {
                                <ul>
                                    <li><a href="~/Account/Register">Register</a></li>
                                    <li><a href="~/Account/Login">Log in</a></li>
                                </ul>
                            }
                        </section>
                        <nav>
                            <ul id="menu">
                                <li><a href="~/">Home</a></li>
                                <li><a href="~/About">About</a></li>
                                <li><a href="~/Contact">Contact</a></li>
                            </ul>
                        </nav>
                    </div>
                </div>
            </header>
            <div id="body">
                @RenderSection("featured", required: false)
                <section class="content-wrapper main-content clear-fix">
                    @RenderBody()
                </section>
            </div>
            <footer>
                <div class="content-wrapper">
                    <div class="float-left">
                        <p>&copy; @DateTime.Now.Year - My ASP.NET Web Page</p>
                    </div>
                </div>
            </footer>
            @RenderSection("Scripts", required: false)
        </body>
    </html>

    The above ensures your username is displayed once logged in, and not your e-mail.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, September 2, 2014 11:42 AM
  • User-1370183403 posted

    Wow...many thanks for the very detailed answer. Just one thing in the register.cshtml file should the check on the email prior to insert into UserProfile, should this be a check on username?

    A check on email would allow more than 1 account with the same username and password but differing email addresses to exist.

    But when logging in...as we are checking only username and password this would return more than 1 record when only 1 should exist

    many thanks

                // Check if user already exists
                var user = db.QuerySingle("SELECT Email FROM UserProfile WHERE LOWER(Email) = LOWER(@0)", email);

    to

    var user = db.QuerySingle("SELECT userName FROM UserProfile WHERE LOWER(userName ) = LOWER(@0)", username);
    Tuesday, September 2, 2014 7:16 PM
  • User1292124637 posted

    Easy fix for that.

    In your register.cshtml page, locate the following code section:

            // If all information is valid, create a new account
            if (Validation.IsValid()) {
                // Insert a new user into the database
                var db = Database.Open("StarterSite");
    
                // Check if user already exists
                var user = db.QuerySingle("SELECT Email FROM UserProfile WHERE LOWER(Email) = LOWER(@0)", email);
                if (user == null) {
                    
                    //CUSTOM
                    // Insert email & username into the profile table
                    db.Execute("INSERT INTO UserProfile (Email, userName) VALUES (@0, @1)", email, username);
                    //END CUSTOM

    Now  make it look like this:

            // If all information is valid, create a new account
            if (Validation.IsValid()) {
                // Insert a new user into the database
                var db = Database.Open("StarterSite");
    
                // Check if user already exists
                var user = db.QuerySingle("SELECT Email FROM UserProfile WHERE LOWER(Email) = LOWER(@0)", email);
                var checkUser = db.QuerySingle("SELECT userName FROM UserProfile WHERE userName= @0", username);
                if (user == null && checkUser == null) {
                    
                    //CUSTOM
                    // Insert email & username into the profile table
                    db.Execute("INSERT INTO UserProfile (Email, userName) VALUES (@0, @1)", email, username);
                    //END CUSTOM
    
                    // Create and associate a new entry in the membership database.
                    // If successful, continue processing the request

    Notice, I've added a second query var:

    var checkUser = db.QuerySingle("SELECT userName FROM UserProfile WHERE userName= @0", username);

    and am now checking to see if that username is associated with any e-mails. Like this:

                if (user == null && checkUser == null) {

    So if both email query returns nothing, and username query returns nothing, only then create user. Else, if email returns nothing but username returns something alert that e-mail is already in user, and vice versa.

    I've tested this and it works. It answers your question.

    Tuesday, September 2, 2014 7:54 PM
  • User-1370183403 posted

    Thanks for all your help..it is very appreciated

    Tuesday, September 2, 2014 8:16 PM