1

I have run into some code that calls Controller.Execute, via a derived controller class. The derived class, ErrorController doesn't override Execute though, and the RequestContext parameter passed in is not null, although several of its properties are. How can I determine which part of RequestContext is the problem that makes 'Execute' throw NullReferenceException?

Here is the code that calls Execute:

public class AuthenticationManager : ClaimsAuthenticationManager
{
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        try
        {
            throw new Exception();
            if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated)
            {
                signInClient.TransformClaimsBasedOnUserRole(incomingPrincipal.Identity.AsClaimsBasedIdentitiy());
            }
            return base.Authenticate(resourceName, incomingPrincipal);
        }
        catch (Exception e)
        {

        var context = HttpContext.Current; 
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "Index");
            routeData.Values.Add("errorId", logId);
            routeData.Values.Add("exceptionMessage", "");
            IController controller = new ErrorController();
            var ctx = new RequestContext(new HttpContextWrapper(context), routeData);
            controller.Execute(ctx);
        }
    }
}

I had to slip in the throw to reproduce the Execute exception. The other auth code only throws on very rare occasions.

As requested:

public class ErrorController: Controller
{
    public ActionResult Index(Guid? errorId, string exceptionMessage)
    {
        ErrorModel resultModel;
        try
        {
            resultModel = new ErrorModel
            {
                ErrorId = errorId==null ? Guid.NewGuid() : Guid.Parse(errorId.ToString()) ,
                ErrorMessage = (string.IsNullOrEmpty(exceptionMessage)) ? ConfigurationManager.AppSettings["GenericError"] : exceptionMessage,
            };

            if (User.IsInRole(RoleIdentifiers.InActive))
            {
               Authentication.AuthenticationManager.SignOut();
            }
        }
        catch (Exception e)
        {
            LogProvider.Current.LogError(LogLevel.Fatal, e, "Error constructing error result model for error Id [{0}]", errorId);
            return new HttpNotFoundResult();
        }
        return View(resultModel);
    }

    public ActionResult SessionTimeOut(string rtnController = "Home", string rtnAction="Index")
    {
        return View(new SessionTimeOutViewModel { RedirectAction = rtnAction, RedirectController = rtnController });
    }

    public ActionResult LogonAgain()
    {
        return null;
    }
}

And, the much awaited stack trace:

   at System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext)
   at System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
   at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
   at MyCompany.Authentication.AuthenticationManager.Authenticate(String resourceName, ClaimsPrincipal incomingPrincipal) in c:\Development\Give4GoodGallery\ThreeFifteen.Plexus.Web\Authentication\AuthenticationManager.cs:line 63

On closer inspection, I see this looks to be about the AuthorizeAttribute - that might requite some sort of context not present when the Execute is directly called.

15
  • 3
    Do you have a stack trace associated with the exception? That will tell where in the code the NRE is being raised. Commented Nov 28, 2014 at 9:32
  • 1
    I don't have a stack trace, and the implementation of ErrorController shouldn't matter, as the exception is being thrown by base class Controller, not by ErrorController. Commented Nov 28, 2014 at 9:36
  • 6
    The stack trace matters a lot. The information in a stack trace would point to exactly where in the code the NRE is being thrown. I've taken a look at IController.Execute() in dotPeek. That method is being used by ControllerBase, and there is a lot of places where an NRE could be thrown. Getting a stack trace would help immensely. Commented Nov 28, 2014 at 9:53
  • 1
    Exactly. The stack trace is always important. It can narrow down the issue to something more specific. Without it we are just shooting in the dark. Commented Nov 28, 2014 at 9:53
  • 1
    @ProfK : Can you put try..catch around the error throwing code and post if you see any InnerException/StackTrace object within the thrown exception object? You may replace any confidential object names etc., in the trace to something meaningful. Commented Nov 28, 2014 at 10:28

4 Answers 4

2

Looking at the stack trace it can be seen that the exception is thrown in AuthorizeAttribute.AuthorizeCore. This is a simple method that will access the User property of the HttpContextBase and also the Identity property of this user property. As far as I can see one of these properties must be null for the NullReferenceException to be thrown.

Most likely the User property of HttpContext.Current is null. This does not seem surprising as you are invoking the ErrorController in AuthenticationManager which I assume is part of the authentication process. Before this process is complete the user is not known.

So you could fix your problem by making sure that the user is known before invoking the ErrorController but the real question is why do you require authorization on ErrorController? The best solution is probably to make sure that ErrorController does not require authorization. This will allow you to invoke the controller also when errors occur before or during authorization.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @Martin. The auth on the ErrorController is just the result of a global filter. I will be sure to remove it.
1
+100

Are u trying to call this method from a running application? or from a unit test or anything else besides asp.net mvc runtime? if the first is true than here is nothing I can think of that could cause the NRE, but if the second is true then make sure User property is provider with value.

HttpContextBase GetContext(string userName) 
{
    var user = new GenericPrincipal(new GenericIdentity(userName, "Forms"), new string[] {});

    var contextMock = new Mock<HttpContextBase>();
    contextMock.Setup(context => context.User).Returns(user);
    contextMock.Setup.....
    return contextMock.Object;
}

1 Comment

It is being called in a running application, but with a null user - the user hasn't logged in yet. Bonus points for the test tip - I can maybe mock the user in the calling code as well.
1

I am able to execute your code without any exception though the exact scenario in your case could be different.

I am not sure, if you did it already, and if you are doing this in Visual Studio then:

1) Wrap the code: controller.Execute(ctx); in a try...catch block so that you should be able to see the exception detail. You can click the "View Detail" at the bottom of exception window so that you can see complete exception details like InnerException,StackTrace etc., within a new window. They may help you to narrow down on the exception.

2) Put a break-point in Index action of ErrorController so that you can step line-by-line by hitting 'F10' to check: If the ErrorController is called or not in first place and also to check, if any of that code throwing exception.

However the basic areas you can cross check are:

1) The code within the "Index" action [you are setting this via:

routeData.Values.Add("action", "Index"); ] might have some uninitialized object that could be throwing.

2) The View you are returning from Index action of ErrorController is existing in a proper View folder.

3) If the Error View is existing as expected, then check within the view if it is not referencing any uninitialized object.

4 Comments

The Index method isn't reached at all. I added an override for Execute, and base.Execute() throws before anything else runs.
So the route may have some problem. Also since the Index is a 'GET' action, can put relevant url within browser to see if the breakpoint is hitting?
1+ on the wondering on the IDE and pointing to inner exception i think that will answer his problem
@Liran , Thank you and lets see how that goes for him.
1

How can I determine which part of RequestContext is the problem that makes 'Execute' throw NullReferenceException?

  • Put a breakpoint on the Execute call line
  • Enable auto breaking on exception in visual studio (Debug -> Exceptions... -> Common Language Runtime Exceptions -> System -> System.NullReferenceException -> 'check the thrown checkbox')
  • Press F5 to continue program execution and wait for the exception to be raise
  • Get the stack strace of the exception or open the call stack window (Debug -> Windows -> Call stack)
  • From the topmost call, you have to isolate the variable that is not initialized on which you are trying to perform an operation. To do this you can use the Auto window (Debug -> Windows -> Auto) or the Watch window (Debug -> Windows -> Watch) to inspect the content of your current variables (not lambdas though) and find which one is null.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.