On one of my ASP.NET MVC websites I occassionally get a NPE in production that I'm having trouble understanding root cause. I'm using ELMAH for tracing errors.
The full stacktrace is here (not much to it:
System.NullReferenceException: Object reference not set to an instance of an object.
at PG.Controllers.FooController.FooActionName(FooModel model) in
{REMOVED}\web\www\Controllers\FooController.cs:line 622
Here's line 622:
if(UserCanEditFoo(out result))
Here's the "UserCanEditFoo listing:
private bool UserCanEditFoo(out ActionResult result)
{
String email = User != null && User.Identity != null ? User.Identity.Name : String.Empty;
UserAccount user = String.IsNullOrEmpty(email) ? null : this.accountServices.GetUserAccount(email);
bool canEditFoo = false;
result = null;
// Don't know this user
if(user == null)
{
FormsAuthentication.SignOut();
Session.Abandon();
result = RedirectToAction(Routes.Actions.Index, Routes.Controllers.Home);
}
// Only admins and foo profile can edit foo
else if(user.Role != Types.UserRole.Admin && user.Role != Types.UserRole.Foo)
{
result = new HttpUnauthorizedResult("Oops! Only administrators and foo users can edit foo.");
}
else
{
result = null;
canEditFoo = true;
}
return canEditFoo;
}
I'm assuming the exception is actually raised in the "UserCanEditFoo" private method but I don't understand why the line number is not being reported as such. On the flipside, if the exception is truly being raised at line 622 I don't understand how that can be given it is a simple function call.
Any help will be much appreciated. Thanks in advance.
Assuming this.accountServices cannot be null, your code looks fine to me, so I would suggest that the exception is actually happening elsewhere (perhaps due to inlining).
Take a look at this question for details on displaying correct line numbers in Release mode.
Related
When I try to access my classic ASP application I get a random error of "Invalid Procedure Call or Argument". The line that causes this error calls a method from a C# component.
Here is the line that breaks in vbscript :
tmpArray2 = session.get(arrName) 'where arrName is a string
Also it cracks at this kind of line too :
if UBound(session.get("RTT_ID")) <> "-1" then
And here is the component code for the get method :
public object get(string key)
{
if (key == null || IsExpired)
{
return null;
}
if (!SessionData.ContainsKey(key))
{
var sessionData = GetDbSessionData(key);
var cachedValue = default(object);
if (sessionData == null || sessionData.Value == null || sessionData.ValueType == null)
{
LogManager.Instance.LogFormat(this, LogLevel.Warning, "Session data not found. SessionId: '{0}'; Key: '{1}'.", this.SessionInfo.Id, key);
cachedValue = null;
}
else
{
cachedValue = SessionDataSerializer.Instance.DeserializeSessionData(sessionData.Value, sessionData.ValueType);
}
var cachedSessionData = new CachedSessionData();
cachedSessionData.CachedValue = cachedValue;
cachedSessionData.DbEntity = sessionData;
SessionData.Add(key, cachedSessionData);
}
RefreshExpirationDate();
return SessionData[key].CachedValue;
}
Also, what I noticed and I do not know if it is relevant or not, this code cracks a lot on an environment that has 2 servers and makes a balancing between them when the first one is too busy. If I try it on a single server, I managed to broke it only once.
Any ideas?
Thank you for your answers. The problem was that because we wanted to increase our performance we had to serialize every object that was send to the component and deserialize it when we returned it to the vbscript. The issue was that we had one array that was containing other arrays and when we deserialize the array we could not return also the child arrays and that was causing the problem. We used for deserialization the MessageBox library.
Another thing to mention is that on our environment we had 2 servers and we are doing some balancing between them. When the application runs only on one server, the deserialization was ok and we had no problems, but when we switched to the other server we encountered this problem.
Maybe this answer will help others understand what could happen if you receive this type of error.
I created session to move data between pages using c# asp.net but the result does not appear and the program does not give me error in the code
first page code:
Session["New1"] = desc1.Text;
to send data to Label in Second page
code:
var userType = (string)Session["New1"];
if (userType != null)
{
Label1.Text = userType.ToString() ;
}
else
{
// test "2" etc
}
Try this,
if (Session["New1"]!= null)
{
Label1.Text = Session["New1"].ToString() ;
}
else
{
// test "2" etc
}
Try explicitly checking of your Session variable exists before attempting to use it to avoid any null-reference issues :
// Explicitly check that it exists
if (Session["New1"] != null)
{
// Then grab it (if it is a non-string type, then you can use as to cast it
// (e.g. a List might use Session["List"] as List<Widget>;)
Label1.Text = Convert.ToString(Session["New1"]);
}
else
{
// Do something here
}
This assumes that your value will be set prior to this code getting called. Additionally, any hiccups to the web server (e.g. timeouts, restarts, major exceptions, etc.) will clear all of the values within the Session.
I have the following action:
public async Task<ActionResult> Cart(bool refresh = false, bool mobile = false)
{
var user = await Auth.GetUserAsync();
//rest of the code
}
Which is being called twice by 2 AJAX calls at the same time (one to render mobile partial, other normal page).
$(document).ready(function () {
$("basket").html('<i class="fa fa-spinner fa-spin"></i>');
$('basket').load(PartialURL + "/Cart");
$('MobileBasket').load(PartialURL + "/Cart?mobile=true");
});
The real problem occurs in Auth.GetUserAsync() function.
Code:
public static async Task<User> GetUserAsync()
{
if (HttpContext.Current == null || HttpContext.Current.Request == null
|| HttpContext.Current.User == null || HttpContext.Current.Request.IsAuthenticated == false)
return null;
//if session does not exist, but user is logged in, fill session information
if (HttpContext.Current.Session[sessionKey] == null && HttpContext.Current.Request.IsAuthenticated)
using (var dal = new DAL.DAL())
{
//load user from DB
var user = await dal.SingleOrDefaultAsync<User>(m => m.Email == HttpContext.Current.User.Identity.Name);
HttpContext.Current.Session[sessionKey] = user;
}
return HttpContext.Current.Session[sessionKey] as User;
}
In one of those calls, the function returns user normally, but the other call produces following error (screenshot from fiddler). Notice how the first call was successful.
Code for SingleOrDefaultAsync is following:
public Task<T> SingleOrDefaultAsync<T>(Expression<Func<T, bool>> predicate) where T : class
{
return _context.Set<T>().SingleOrDefaultAsync(predicate);
}
I have checked while debugging, and email is present in both of the requests, _context is not null, and the user with requested email exists, but one of those always returns an error. Error is returned randomly. Sometimes in first, sometimes in second AJAX call.
Can someone please tell me what is causing this error? Any help is greatly appreciated.
I would assume, because of the other checks you have in place, that HttpContext.Current.User.Identity.Name (or even HttpContext.Current.User.Identity) is null, and that that's what's causing the error.
This might be so if the first request has caused the authentication process to start, but that process is not yet complete - so that the null checks you have succeed, but the subsequent member access fails. In other words, you have a timing issue / race condition. That's just a guess, though.
Update: following my suggestion to store the name in a variable and use the variable in the lambda, everything worked. But why?
My theory is that the expression passed to your SingleOrDefaultAsync method included the expression HttpContext.User.Identity.Name, rather than the value of that expression.
This expression was then evaluated in your DAL, where HttpContext.Current was (presumably) null (assuming your DAL is not in your web project). QED?
I have a several methods in controller:
public ActionResult Issue()
{
var message = WSFederationMessage.CreateFromUri(HttpContext.Request.Url);
// sign in
var signinMessage = message as SignInRequestMessage;
if (signinMessage != null)
{
return ProcessWSFederationSignIn(signinMessage, ClaimsPrincipal.Current);
}
// sign out
var signoutMessage = message as SignOutRequestMessage;
if (signoutMessage != null)
{
return ProcessWSFederationSignOut(signoutMessage);
}
return View("Error");
}
And the most valuable for me in this question:
private ActionResult ProcessWSFederationSignOut(SignOutRequestMessage message)
{
FederatedAuthentication.SessionAuthenticationModule.SignOut();
var mgr = new SignInSessionsManager(HttpContext, _cookieName);
// check for return url
if (!string.IsNullOrWhiteSpace(message.Reply) && mgr.ContainsUrl(message.Reply))
{
ViewBag.ReturnUrl = message.Reply;
}
return View("Signout");
}
All works fine, but, there are interesting moment.
This thing works in both cases, if I ended session by myself, or session simply expired. Its fine but actually, I need to tell the difference between those cases, write in ViewBag something like "You are singed out" or "Session expired" depends on result and show it oy the View.
Is there are some kind of way to detect session expired situations or should it be something different?
P.S Sorry for my bad English.
Since you changed the topic I will update my answer. I haven't used WSFederatinSession but maybe you could store the inf about how session ended (in a cookie for example) and during the next request (in a global asax for example) read this inf and do what you want to do.
// EWS Microsoft.Exchange.WebServices.Data.Folder
private Folder _historyFolder;
_historyFolder = GetHistroyFolder(exchangeService) ?? CreateHistortFolder(exchangeService);
public Folder GetHistroyFolder(ExchangeService service)
{
//if found the folder I want - return it , otherwise returns null
}
public Folder CreateHistortFolder(ExchangeService service)
{
var folder = new Folder(service);
folder.DisplayName = _historyFolderName; // "who cares" :)
folder.FolderClass = _historyFolderClass; // "IPF.Note"
folder.Save(WellKnownFolderName.MsgFolderRoot);
return folder;
}
For some reason _historyFolder is always null, although GetHistroyFolder(exchangeService) does return a folder. Why is that?
UPDATE I
I have updated proof for the unbelievers !
If I separate it to 2 lines (without ??) it's OK! but I still wanna understand why the first approach doesn't work...
why down vote? mean ppl..
UPDATE II
Thanks for the all warm people who down vote the question / vote for "close" this thread.
And Thanks for the true warm people who are trying ...
I used the workaround approach, split it to 2 lines
_historyFolder = GetHistroyFolder(exchangeService);
if (_historyFolder == null) _historyFolder = CreateHistortFolder(exchangeService);
you know what funny? Resharper suggests me to return it to how it was before...
Yea , this is a workaround and not real answer for WHY and WTF ... ( .net 4.5 )
UPDATE III
if GetHistroyFolder(..) is return null ( when foreach doesn't find ... ) , CreateHistoryFolder does return Folder object , and _historyFolder is getting the value
Instead of a field why dont you use a property with a backing field. This doesn't exactly solve the problem but at least this makes it easier to debug.
Folder historyFolder
{
get{
if(_historyFolder != null)
return _historyFolder;
_historyFolder = GetHistroyFolder(exchangeService);
if(_historyFolder == null)
_historyFolder = CreateHistortFolder(exchangeService)
if(_historyFolder == null)
throw new NullReferenceException("history folder still null");
return _historyFolder;
}
}
There's no reason for _historyFolder to be NULL, if GetHistroyFolder() is returning an object e.g.
namespace ConsoleApplication1
{
class Program
{
// EWS Microsoft.Exchange.WebServices.Data.Folder
private static object _historyFolder;
static void Main(string[] args)
{
_historyFolder = GetHistroyFolder(null) ?? CreateHistortFolder(null);
Console.WriteLine(_historyFolder == null);
}
public static object GetHistroyFolder(object service)
{
return new object();
//if found the folder I want - return it , otherwise returns null
}
public static object CreateHistortFolder(object service)
{
return null;
}
}
}
I can only imagine that _historyFolder is being set to NULL after GetHistroyFolder() has been called. Your code looks incomplete, are you running in an ASP.NET or something?
EDIT:
In your code, where you call FindFolders(new FolderView()) do this:
FindFolders(new FolderView()).ToList()
Because FindFolders returns an IEnumerable, I think you should call ToList() to ensure that all the folders are returned in one go, not just yielded.
may be "CreateHistoryFolder" return null