View model for custom Userdata on the Layout page

823 views Asked by At

My user is Authenticated but has extra information stored in a FormsAuthenticationTicket then a cookie.

// Custom UserData will contain the following | seperated values:
// [ FullName | ContactNumber1 | ContactNumber2 ]
string userData = fullName + "|" + contactNumber1 + "|" + contactNumber2

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                                                1,
                                                userName,
                                                DateTime.Now,
                                                DateTime.Now.AddMinutes(20),
                                                false,
                                                userData,
                                                FormsAuthentication.FormsCookiePath);

Create Cookie etc etc

All this is working fine.

Im using mvc 3 and Razor

I have a foo.Layout.cshtml that displays the Fullname / ContactNumber etc etc at the top of the page.

I could include code at the top of the foo.Layout.cshtml to extract an display these values:

@{

    FormsAuthenticationTicket ticket = ( (FormsIdentity)User.Identity ).Ticket;

    // Custom UserData will contain the following | seperated values:

    // [ FullName | ContactNumber1 | ContactNumber2 ]

    string[] userData = ticket.UserData.Split(new char[] { '|' });

    string fullName = userData[0];

    string contactNumber1 = userData[1];

    string contactNumber2 = userData[2];

}

<div>@fullName</div>

<div>@contactNumber1</div>

<div>@contactNumber2</div>

This means I dont have to include this code in my controllers but to be honest I dont like it and in my actual app (different values) I need the values in the majority of my views including the layout.

So I have debated including the code inside my controller:

Create a viewmodel:

public class UserViewModel {

    public string FullName { get; set; }

    public string ContactNumber1 { get; set; }

    public string ContactNumber2 { get; set; }

}

Create Controller

public class FooController : Controller {

    private readonly _userViewModel = null;

    public FooController( ) {

      // NOTE this would actually be behind an interface in some type of 
      //      repository / service pattern and injected but for the sake 
      //      of easy conversation ive put it here.

      FormsAuthenticationTicket ticket = ( (FormsIdentity)User.Identity ).Ticket;

      // Custom UserData will contain the following | seperated values:
      // [ FullName | ContactNumber1 | ContactNumber2 ]
      string[] userData = ticket.UserData.Split(new char[] { '|' });

      _userViewModel = new UserViewModel();

      userViewModel.FullName = userData[0];
      userViewModel.ContactNumber1 = userData[1];
      userViewModel.ContactNumber2 = userData[2];

    }

    public ActionResult Index() {

        (HOWEVER_SET_ON_LAYOUT_PAGE) = userViewModel.FullName;

        // If not posting ViewModel            
        (HOWEVER_SET_ON_THIS_PAGE) = userViewModel.FullName;

        // If posting ViewModel
        return View(_userViewModel);

    }

Maybe some of this could be put inside the controller factory.

Im just looking for discussion or ideas of how other people are approaching this quite common setup.

My actual task is to display the Users Full Name at the top of each page via the Layout and display the Full Name (and other data) at the bottom of various forms that are being filled in then submitted. After postback the Full Name will then be re read from cookie and sent to be stored with the other form fields. Does that make sense and is it really that time :-/

1

There are 1 answers

1
James Nail On

I've addressed this exact thing a couple times in recent projects.

Even better than putting this in the controller would be to create an Authentication service that wraps your FormsAuthentication-specific code, then inject that service via IoC where ever you may need it. Pretty much any IoC container should be able to also specify that your Authentication service could be cached per-http request, so you can take advantage of that to help conserve resources / enhance performance.

Now if you need to display this user info in lots of places, I would encourage you to create a separate UserController and do a RenderAction call to it wherever the User info is needed in your views, instead of making your user view model a part of a bunch of other view models (unless it's actually needed by the other models/views to satisfy some business conditions, etc.). This way you can have a standard, "canonical" view of the user info, as a component, and you'll get lots of reuse out of it.