7

NRE

Why is VS 2012 showing the Type variable as an NullReferenceException when it also shows that it's value = "Retailer".

enter image description here

I've got a newborn, and I'm working on limited sleep, so I apologize if I'm missing something obvious here. The LoggedInUser.Employer object has been instantiated and this line works fine 1/2 of the time. But then it starts breaking. Not sure if this helps - need sleep...

 private string _type;
    public string Type
    {
        get { return _type; }
        set
        {
            if (value != null)
            {
                TypeEnum = (Constants.BusinessType)Enum.Parse(typeof(Constants.BusinessType), value, true);
                _type = value;
            }
        }
    }

enter image description here I'm starting to wonder if it's a cross-thread issue...

enter image description here

Jeff Borden
  • 1,369
  • 1
  • 19
  • 30
  • 4
    Can you provide the code for each relevant part? IE: The `Employer` class' `Type` property? – Simon Whitehead Feb 18 '13 at 01:34
  • 1
    You probably have not properly initialized `LoggedinUser` properly but can't tell without you proiding relevant code.. what if you cast the type in your if statement will this help `if(string.IsNullOrEmpty((string)LoggedInUser.Employer.Type))){ }` – MethodMan Feb 18 '13 at 01:35
  • Can you provide a [SSCCE](http://sscce.org/)? – congusbongus Feb 18 '13 at 01:37
  • Check the accessor logic in `LoggedInUser.Employer`; if I had to guess, it's returning `null` the first time (when you're getting the `.Type` and calling `String.IsNullOrEmpty`), and then returning a valid object later (when you're inspecting it in the debugger). – Adam Maras Feb 18 '13 at 01:49
  • `Employer.Type` a property of field? – Parimal Raj Feb 18 '13 at 01:49
  • 2
    Can you show us some actual code and not just blurred screenshots? Our debugging power is extremely limited with what you've given us.. – Simon Whitehead Feb 18 '13 at 01:50
  • Check the line above/before it, in VS2010 after an exception is thrown it may highlight the line after. – Monso Feb 18 '13 at 01:51
  • @SimonWhitehead I understand that what I've provided is limited and probably not all too useful. I'm confused because it is a simple String.IsNullOrEmpty on a string that is clearly showing it has a value. – Jeff Borden Feb 18 '13 at 01:54
  • FWIW this does not start happening until I open a 2nd browser (incognito) and login as a different user. – Jeff Borden Feb 18 '13 at 01:55
  • 1
    @JeffBorden - paste the stacktrace! – Parimal Raj Feb 18 '13 at 02:00
  • @AppDeveloper stacktrace per your request. – Jeff Borden Feb 18 '13 at 02:07
  • @SimonWhitehead thanks, looks like I have some reading to do. Is just strange b/c I've been devving in the 2 browsers w/ 2 diff users logged in for weeks w/o issue. – Jeff Borden Feb 18 '13 at 02:12
  • i am almost sure that, `_type` field is either null or empty! – Parimal Raj Feb 18 '13 at 02:12
  • Does this happen if you open a second browser not incognito? – Ryan Byrne Feb 18 '13 at 02:14
  • @AppDeveloper Even so.. when called it is wrapped in `IsNullOrEmpty`.. which happily accepts a `null` parameter. – Simon Whitehead Feb 18 '13 at 02:14
  • @AppDeveloper _type has a value. Image posted. – Jeff Borden Feb 18 '13 at 02:16
  • @RyanByrne I opened a new tab in Chrome (non-incognito) and it ran as expected – Jeff Borden Feb 18 '13 at 02:18
  • @JeffBorden then I would place a breakpoint where LoggedInUser is getting set each request. Cookie information is most likely not getting passed to the site. – Ryan Byrne Feb 18 '13 at 02:21
  • Can you clean your solution, close Visual Studio, Reboot and try again. Also debug it by attaching to the Process when you open a 2nd browser and step thru the code. You mention multi-threaded issue, is this a multithreaded asp.net site? Are you using Sessions or how are you persisting state? otherwise smells like some sort of corruption in the IDE.... This is the main Stackoverflow Q & A for NullRefExceptions: http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net – Jeremy Thompson Feb 18 '13 at 02:48
  • I think your Type.set is throwing that excetion. As you know, Visual Studio evaluates properties when developers hover mouse on properties. I suspect of your Enum.Parse has something null. Also you can configure Visual Studio with Menu -> Debug -> Exceptions... and check in Common Language Runtime Exceptions, Thrown flag, so that Visual Studio can break the execution when exception raises. – oarrivi Feb 18 '13 at 13:56
  • How about splitting the expression and adding a few `Assert`s? And please post the code for getters of `LoggedInUser` and `Employer`. Perhaps one of them uses broken lazy initialization. – CodesInChaos Feb 18 '13 at 20:44
  • 1
    *"I'm starting to wonder if it's a cross-thread issue"* - That would offer an explanation why the debugger has no problem seeing the variable. How is LoggedInUser and its properties set? Does it depend at all on HttpContext? (which doesn't get flowed across threading contexts). – Snixtor Feb 18 '13 at 22:04
  • @Snixtor Yes it does depend on HttpContext. Business business = (Business)HttpContext.Current.Session["user-business"] ?? null; – Jeff Borden Feb 19 '13 at 18:31
  • If you comment out line TypeEnum = (Constants.BusinessType)Enum.Parse(typeof(Constants.BusinessType), value, true); in your settter, do you still get this exception. – Raghu Feb 19 '13 at 22:07

3 Answers3

2

The ASP.NET ExecutionContext, responsible for storing the HttpContext.Current instance, won't naturally "flow" to other threads. Judging by your error stack trace, you're working in ASP.NET MVC, a framework that abstracts away the use of HttpContext. You've perhaps come from a WebForms background, where its direct use is common?

SynchronizationContext

This article offers much more detail than I can reasonably go into. Some of the points most relevant to your situation though are:

"ExecutionContext is all about “ambient” information, meaning that it stores data relevant to the current environment or “context” in which you’re running."

This "ambient" information being... HttpContext.Current and its various properties (including Session).

"This means that this ambient context we’ve come to rely on for controlling details of our execution is no longer viable, because TLS doesn’t “flow” across these async points."

TLS being thread-local-storage (HttpContext.Current, etc.) In short, async = potentially lose HttpContext.Current.

The MVC way

Remember I said MVC mostly abstracts away HttpContext?

Session is in Controller.Session. (I'm sorry to say that as yet I have not tested this in an async controller action, so can't verify it's suitability for your needs as yet, or whether you will need additional work to make it cooperate.)

Request is in Controller.Request

User is in Controller.User

There are others... check them out.

Session Alternatives?

Have you considered alternatives? You don't have to look far to find articles suggesting that Session + ASP.NET MVC is a bad idea. I'm not going to weigh in on something as generalised as whether or not it's a "bad thing", but looking at your example, it seems to me you're dealing with user profile data, not "session" data.

Session isn't really the right place to be caching user profile information. For that matter, is it appropriate to cache it at all? Could a users profile change during a session? If they changed it themselves, would you reset the session? What if a separate admin user changed their profile while they were logged in?

Exploring alternatives are beyond the scope of this question, but just be wary that you may be trying to solve the wrong problem here.

Snixtor
  • 4,239
  • 2
  • 31
  • 54
  • Thank you for compiling this thoughtful answer. Your assumption is correct, that I have a WebForms background and this is my first crack at an MVC app. – Jeff Borden Feb 20 '13 at 01:48
  • The LoggedInUser class is stored in session because its properties are frequently accessed throughout the lifetime of the application. Why did I do this? First, because it's what I know (not a great reason, but it is a reason). Second, I wanted to avoid hitting the database everytime I needed the class. I considered storing this in a cache like memcache, but did not. If they change their data themselves then I update the session data accordingly. I have no great answer as what would happen if their profile info was changed by an external source (admin). – Jeff Borden Feb 20 '13 at 02:00
  • I haven't googled yet, but if you have any good links for learning a better approach, please share. ty – Jeff Borden Feb 20 '13 at 02:00
  • 1
    A common pattern is to use ASP.NET Profile Providers - http://msdn.microsoft.com/en-us/library/014bec1k(v=vs.100).aspx - You may find the framework a little *heavy* though (just a fore-warning). Regarding "hitting the database every time", it's a balancing act. Keep a cache too long and you run the risk of dirty data, no cache and you may increase load. Do you *have* a load problem though? Don't pre-optimise a problem that doesn't exist. This is an issue beyond the scope of this comments discussion, so get googling, and raise a new question if needed. – Snixtor Feb 20 '13 at 02:08
1

String.IsNullOrEmpty won't throw this exception on a string, even if it's null so the Type property is not the issue. LoggedInUser is used 2 lines before without error, so that leaves the Employer property as the culprit (unless String isn't the built in String).

You can add a check for null on that to confirm:

if (LoggedInUser.Employer != null) 
{
    if (String.IsNullOrEmpty(LoggedInUser.Employer.Type))
    {
        ...  
    }
}
else
{
    // debug output
}

Assuming Employer is null, you'll need to provide that property definition here. Because you only see this when multiple users are logged in, I'm suspecting a static declaration somewhere it shouldn't be.

Mufaka
  • 2,333
  • 1
  • 18
  • 25
0

My Guess would be that you somewhere declared a field named "String" - try using the lower case "string.IsNullOrEmpty" or "System.String.IsNullOrEmpty" for one....

Roman Gruber
  • 1,411
  • 11
  • 16
  • If that was his error then it wouldn't compile, as opposed to throwing a NRE. – Servy Feb 18 '13 at 20:31
  • @Servy It would compile, since the C# compiler figures out if you're talking about the type or variable. But it still wouldn't throw a NRE, unless the field has a really weird type. – CodesInChaos Feb 18 '13 at 20:36
  • @CodesInChaos No, in C# calling a static method on an instance of a type. It will generate this error: `"Member 'string.IsNullOrEmpty(string)' cannot be accessed with an instance reference; qualify it with a type name instead"` This differs from say JAVA where it would be valid to call a static method from an instance of the type. – Servy Feb 18 '13 at 20:38
  • @Servy Try it, it works. Probably because (as long as you have proper `using`s) `String` refers to both the type and the field. You only get that error when trying to call `IsNullOrEmpty` on a string field that's not called `String`. – CodesInChaos Feb 18 '13 at 20:40
  • @CodesInChaos Then it would work, and it wouldn't matter whether or not there was a variable named `String` since it couldn't mask it. The point remains that it's not the OP's problem. – Servy Feb 18 '13 at 20:48