ASP.NET MVC2 Homepage Login Form

I am trying to find an elegant way to have a login form on the main page. This means that if the user does not log in, a login form should appear on each page. (This is very common these days)

Taking an example with an MVC2 application in Visual Studio, I created this:

public class MasterViewModel { public string User { get; set; } // omitted validation attributes public string Pass{ get; set; } public bool RememberMe { get; set; } } 

Each view model inherits from MasterViewModel

 public class RegisterViewModel : MasterViewModel { public string UserName { get; set; } public string Email { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } } 

My main page displays a partial view

 <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<MyLogon.ViewModels.MasterViewModel>" %> ..... <div id="logindisplay"> <% Html.RenderPartial("LogOn"); %> </div> ...... 

Strongly typed partial view:

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyLogon.ViewModels.MasterViewModel>" %> <% if (Request.IsAuthenticated) { %> Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>! <div>[ <%= Html.ActionLink("Change Password", "ChangePassword", "Account") %> ]</div> <div>[ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]</div> <% } else { %> <%= Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") %> <% using (Html.BeginForm("LogOn", "Account",FormMethod.Post)) { %> <div> <fieldset> <legend>Account Information</legend> <div class="editor-label"> <%= Html.LabelFor(m => m.User) %> </div> <div class="editor-field"> <%= Html.TextBoxFor(m => m.User) %> <%= Html.ValidationMessageFor(m => m.User) %> </div> <div class="editor-label"> <%= Html.LabelFor(m => m.Pass) %> </div> <div class="editor-field"> <%= Html.PasswordFor(m => m.Pass) %> <%= Html.ValidationMessageFor(m => m.Pass) %> </div> <div class="editor-label"> <%= Html.CheckBoxFor(m => m.RememberMe) %> <%= Html.LabelFor(m => m.RememberMe) %> </div> <p> <input type="submit" value="Log On" /> </p> </fieldset> </div> <% } %> <% } %> 

Registration Page:

 <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyLogon.Models.RegisterViewModel>" %> ... <h2>Create a New Account</h2> <p> Use the form below to create a new account. </p> <p> Passwords are required to be a minimum of <%= Html.Encode(ViewData["PasswordLength"]) %> characters in length. </p> <% using (Html.BeginForm("Register", "Account" ,FormMethod.Post)) { %> <%= Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.") %> <div> <fieldset> <legend>Account Information</legend> <div class="editor-label"> <%= Html.LabelFor(m => m.UserName) %> </div> <div class="editor-field"> <%= Html.TextBoxFor(m => m.UserName) %> <%= Html.ValidationMessageFor(m => m.UserName) %> </div> <div class="editor-label"> <%= Html.LabelFor(m => m.Email) %> </div> <div class="editor-field"> <%= Html.TextBoxFor(m => m.Email) %> <%= Html.ValidationMessageFor(m => m.Email) %> </div> <div class="editor-label"> <%= Html.LabelFor(m => m.Password) %> </div> <div class="editor-field"> <%= Html.PasswordFor(m => m.Password) %> <%= Html.ValidationMessageFor(m => m.Password) %> </div> <div class="editor-label"> <%= Html.LabelFor(m => m.ConfirmPassword) %> </div> <div class="editor-field"> <%= Html.PasswordFor(m => m.ConfirmPassword) %> <%= Html.ValidationMessageFor(m => m.ConfirmPassword) %> </div> <p> <input type="submit" value="Register" /> </p> </fieldset> </div> <% } %> </asp:Content> 

Since all view models inherited from the partial view of MasterViewModel LogOn are always satisfied, but I find this solution very inelegant. Is there any other way to achieve this?

+4
source share
1 answer

Use a partial view because you have different views based on login status. Return one view for anonymous users with the / lunk login form to the registration page and a second view for registered users.

Partial views can have their own models that do not need to inherit from the main view model.

Inherited models can cause problems later (this makes using html.EditForModel() or .DisplayForModel() difficult, as they also display common fields of the main view).

Oh, and generally, for bad vision practice, relying on anything outside the model is your Test on Request.IsAuthenticated can be fine, but if you want to be absolutely correct, you must have the model.IsAuthenticated property that is set by the action. However, switching views will completely fix this problem.

Edit: Last improvement. In lines like this:

 Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>! 

Instead, run:

 Welcome <b><%: Page.User.Identity.Name %></b>! 

In fact, it would be even better to hit only the model:

 Welcome <b><%: model.Username %></b>! 

(Note the <%: not <%= ). This tag form indicates that the content should be encoded in HTML. What's even better, if it encounters a string , it will encode it. If he encounters an HTMLString , he will not. All .Net MVC functions return an HTML string or string if necessary, so you can do this:

 <%: html.EditFor(x => x.fieldname) %> <%: model.somefield %> 

The first will NOT be html encoded as EditFor() returns an HTMLString . The second WILL will be encoded (if somefield is the standard string)

This will make your code tidier and more reliable. You can also use this to dynamically generate HTML code if you need to code it / not appropriate. For example, we have some helper functions for processing, including CSS / JS. They return HTMLStrings ...

 <%: Helper.IncludeCSS("SomeCSS.css") %> 
+2
source

All Articles