views:

253

answers:

3

Update: I can't delete this question, because the answer has been upvoted, yet it is not at all the answer to what I'm asking. I'd like to delete this, as it has been a week with no answer, and it's just dragging down my accept %. Thanks.

I have a strongly typed master page that includes information that is based on the currently authenticated user's UserId:

(Guid)Membership.GetUser().ProviderUserKey

Every other normal action/view would require the user to be authenticated prior to it being viewed, which means the user's information is guaranteed to be available.

The problem is, I'm only getting null reference exceptions when I attempt to access the user's info. from the site's master page. I'm guessing this is because there isn't such thing as an [Authorize] attribute that applies to master pages.

Do I have this wrong? Is there another possible cause?

Simple example:

My site's various pages all use a view model object that inherits the master page view model:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<Models.MasterViewModel>" %>

the authenticated user object is a property of this base view model. All pages require authentication, so anyone who isn't is redirected to the login view, which has been working flawlessly. So a simple attempt to make use of a user's property in a view is thus:

<%= Model.UserName %>

which I'll put in one of the views, as well as in the site's master view.

When the user is already authenticated, all works as it should, with the UserName being printed twice on the page. When the auth ticket is expired, or a new user comes along however, the page will not redirect to the login, but instead generate an exception that complains of a null reference coming from the <%= Model.UserName %> in the master view.

When I remove the <%= Model.UserName %> from the master view, and leave it in the normal view, it redirects as it should, without throwing the error.

I hope this is somewhat more clear.

Edit:

Maybe someone could offer a better way to access the authenticated user's information in the master page?

Edit #2:

I would be very interested to see any example of an authenticated user's info being accessed in the master page...this is a real head-scratcher for me.

Update:

I haven't accepted the answer because I'm quite familiar with how I can test whether or not a user is authenticated. I am curious to know why no redirection to the login page is taking place.

+2  A: 

It's not because of the master page.

Membership.GetUser() will return the current logged-on membership user. If no user is logged in it will return null and that's what is causing your problem.

you can use an if statement in your master page to check if the user is logged in or not before using any user's info.

if(Membership.GetUser() != null )
{
    // Use User Info.
}
Manaf Abu.Rous
Thank you. The thing is, normally if the user hasn't authenticated yet, he will be redirected to the login page, whereas this just throws an exception and doesn't bother redirecting.
PolishedTurd
If you are using your master page in other pages that unauthenticated users have access to (login page for example) then yes you will need to check.
Manaf Abu.Rous
If you think that checking for users info in your view would complicate things then you could create a Helper to make your life easier. also another solution is having two master pages. one for pages accessed by authenticated users which contains the users info. and another one for pages that unauthenticated users have access to which doesn't contain the users info.
Manaf Abu.Rous
That's just it--everything requires authentication. Everything was redirecting as expected, until I tried to access user info. in the master page, at which point it generated an exception instead of redirecting to the login page first.
PolishedTurd
It's as though the master page is the only one that fails to redirect an unauthenticated user, and instead first looks for the user's properties, which of course are null when they aren't even logged in.
PolishedTurd
A: 

not sure if this still applies in mvc2, but have you tried defining the loginUrl attribute in your web.config?

<authentication mode="Forms"> 
 <forms loginUrl="/user/login" />
</authentication>

<authorization>
 <deny users="?" />
</authorization>
Andrew dh
I have, but thank you anyway.
PolishedTurd
+1  A: 

The only way i manage to reproduce this error is if i add the violating codeblock to a masterpage that is referenced from pages that does not require auth, then look at'em without signing in.

If your masterpage is not used on your logon-page, it could indicate something else is not entirely in place. How's your routing and authentication set up? If your View gets instantiated before the redirect, so will your masterpage, which could provoke this behaviour.

David L
I have an [Authorize] attribute on a base controller from which all other controllers inherit, and I believe my routing is sound. "Something else is not entirely in place," was, and still is what I suspect is the cause--I just can't find it. Thanks.
PolishedTurd
In the offending masterpage, add the line <%= this.ViewContext %>, then rightclick and "Breakpoint" -> "Insert breakpoint". Then inspect ViewContext, should give you pointers on which View has been loaded etc
David L
I can't figure this out to save my life, but I'm going to mark this as an "answer," and move on. Thanks for the help.
PolishedTurd