Resting a private variable that should not happen - c#

I have a strange problem I'm checking in my code behind the user if he is active or not with as simple if .. in my Page_Load method as you can see here
private TimeReport paramTR;
private ZevUser zevUser;
protected void Page_Load(object sender, EventArgs e)
{
ZevUser user = ZevUser.GetById(Int32.Parse(Session["SessionId"].ToString()));
if (user == null)
{
this.Response.Redirect("~/About.aspx");
}
this.getParameters();
if (!this.IsPostBack)
{
if (paramTR.ZevUser.Active == 0)
{
this.Response.Redirect("~/TimeReporting/TimeReportPanel.aspx");
}
this.bindData();
}
}
But when I make a go throw to this method I get allays nullreferenceexception why so ever .. but the private ZevUser variable is not null it's full..
I really don't have a clue why is this happing, it would be really cool if someone could explain me this why this is happening
Thanks for help and fast answer

You need to break your code down so you can debug it easier or add logging if you cannot debug this code locally.
Remember that when debugging something, the worse mistake you can make is to make assumptions. Start from the beginning and follow the process through. Don't assume that the problem is something and don't assume that the problem can't be something:
I've included a broken down, more readable version below. You can now add logging around this or easily add breakpoints:
private TimeReport paramTR;
private ZevUser zevUser;
protected void Page_Load(object sender, EventArgs e)
{
this.getParameters();
if (!this.IsPostBack)
{
if ((this.paramTR != null) &&
(this.paramTR.ZevUser != null) &&
(this.paramTR.ZevUser.Active == 0))
{
this.Response.Redirect("~/TimeReporting/TimeReportPanel.aspx");
}
this.bindData();
}
string sessionId = Session["SessionId"] as string;
if (sessionId != null)
{
int session = int32.Parse(sessionId);
ZevUser user = ZevUser.GetById(session);
if (user == null)
{
this.Response.Redirect("~/About.aspx");
}
}
}
Why are you passing the session id to ZevUser.GetById()? I would expect this to take a user id, or for the method to be called something like ZevUser.GetBySessionId(). At the moment it's quite confusing.

This line is causing the issue:
ZevUser user = ZevUser.GetById(Int32.Parse(Session["SessionId"].ToString()));
This is because Session["SessionId"] can be null, and is null in this case.
If you are looking to get the SessionId that is set by ASP.net, then use this.Session.SessionID (source).
If you are storing a value in Session["SessionId"] that you are trying to retrieve, then do a null-check first:
if (Session["SessionId"] != null) { ...

You should consider testing the SessionId variable before using it by doing something like that :
if (!string.IsNullOrEmpty(Session["SessionId"].ToString()))
ZevUser user = ZevUser.GetById(Int32.Parse(Session["SessionId"].ToString()));

The best way to debug your exception is to enable debug when the exception is thrown.
For this, go to Debug>>Exceptions
and then enable first four checkboxes (maybe) and then try debugging the project. You will be halted at the position from where the exception will be thrown.

Related

How to exit a non void method in c#

I have a method that returns an ItemCollection, I want to stop the function early if there is no information provided. I would normally do this with a return; however as my method expects an ItemCollection it fails. I have this as a work around but it seems frankly hacky. Is there something I am missing. I tried just return; and I would prefer not throw an exception.
private ItemCollection loadLeft_Click(object sender, RoutedEventArgs e)
{
var leftUser = UsrLeft.Text;
if (leftUser == "")
{
MessageBox.Show("No User Entered");
GroupListLeft.Items.Add("");
var fail = GroupListLeft.Items;
return fail;
}
//Succesful test do stuff
var leftItems = GroupListLeft.Items;
return leftItems;
}
You have few options:
throw a new Exception (maybe even a custom one like NoUserEnteredException("someText")).
return null
return an empty collection or dummy object (see Null-object pattern)
The last one is better choice, in this case you don't need write a null-check or a try-catch section in client code.
You will need to return something that equates to an ItemCollection, depending on how you may want the calling procedures to handle such a return you could use a null return:
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return null;
}
Or return a new ItemCollection e.g.
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return new ItemCollection();
}
You will need to return null, like
private ItemCollection loadLeft_Click(object sender, RoutedEventArgs e)
{
var leftUser = UsrLeft.Text;
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return null;
}
//Succesful test do stuff
var leftItems = GroupListLeft.Items;
return leftItems;
}
You can use "return null" which I do from time to time, but its not a good coding convention. Another option is to throw an exception and then catch it. Both is bad coding conventions and makes the code that uses this button add some rather obscure logic and dependencies.
From studying SOLID principles I would argue a better solution is to make a new type of object to return. f.ex. one that holds a list, but also a status message and then make it react a bit like when you have an HTTP request that depends on a success and otherwise cannot expect to have any content. This way, the object makes it clearer what to expect.
A fourth option, since this sounds UI related, is to possible have the click callback somehow and either update the collection, or update with an error message directly. But this might also be a bad coding convention that has impractical dependencies in the code.
Your code seems to return an object when you click on something.
(I am no expert in WPF, i don't know if this is possible).
I would encapsulate the function that returns the ItemCollection in a separate function and check whether the User is valid BEFORE calling this function.
This way you ensure that the ItemCollection is always valid (because you don't even try to retrieve it with an invalid user). Something like this:
private void loadLeft_Click(object sender, RoutedEventArgs e) {
var leftUser = UsrLeft.Text;
if(leftUser != "") {
ItemCollection coll = getItemCollectionForUser(leftUser);
}else {
//Error Handling
}
}
private ItemCollection getItemCollectionForUser(string user) {
//return ItemCollection here
}
Note how I wrote a separate function that returns the ItemCollection and the Click function returns nothing.

Acumatica - Require File be Attached

In Bills and Adjustments, an error message "Please upload invoice" needs to display if user tries to save without attaching/uploading a document.
I created a bool field, UsrFilesAttached, that does not persist. On Rowselected event, i get a count, set bool if 0 or not.
I tried updating AP.APRegister DAC to [PXUIRequired(typeof(Where>))]
I tried something else in the BLC but I can't find it now.
//in APInvoiceEntry
protected void APInvoice_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
var inv = (APInvoice)e.Row;
bool attachedFiles = PXNoteAttribute.GetFileNotes(cache, cache.Current).Length != 0;
cache.SetValueExt<APRegisterExt.usrFilesAttached>(inv, attachedFiles);
}
// in DAC AP.APRegister
[PXBool]
[PXUIField(DisplayName="UsrFilesAttached")]
[PXDefault]
[PXUIRequired(typeof(Where<usrFilesAttached, Equal<False>>))]
I expect that if UsrFilesAttached is false an error will appear. I am able to save record whether UsrFilesAttached is true or false. Also, how do I add a custom error message?
This morning, I had a different thought about how to tackle this and it worked. I started over with this and it works:
protected void APInvoice_Hold_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var inv = (APInvoice)e.Row;
if (inv == null)
return;
bool attachedFiles = PXNoteAttribute.GetFileNotes(cache, cache.Current).Length != 0;
if (attachedFiles == false)
{
cache.RaiseExceptionHandling<APRegister.hold>(inv, null, new PXSetPropertyException("Please attach invoice", PXErrorLevel.Error));
inv.Hold = true;
}
}
It makes better sense to do the check when trying to release the hold anyway. It can probably be improved on, so please teach me if you know a cleaner way. :)

C# Function calls using Services

I am debugging a code that uses Services to execute Stored Procedures. The code is as follows:
void serviceClient_EvaluateScoresCompleted(object sender, EvaluateScoresCompletedEventArgs e)
{
if (e.Error == null)
{
this.GenerateExcelFiles(e.Result as System.Data.DataSet);
}
else
{
Response.Write(e.Error.Message);
Response.Write(e.Error.InnerException);
Response.Write(e.Error.StackTrace);
}
}
And the button click code is as follows:
protected void btnSubmit_Click(object sender, EventArgs e)
{
System.Collections.Generic.List<ConsultantShares> consultantShareList = this.GetConsultantShareList();
if (consultantShareList == null)
{
Response.Write("Please fix the Metioned Errors to Continue");
return;
}
CIServiceClient serviceClient = new CIServiceClient();
serviceClient.EvaluateScoresAsync(consultantShareList, this.ddlTargetProject.SelectedValue.Split(new char[] { '-' })[0], this.txtWorkclass.Text, this.ddlTargetProject.SelectedValue.Split(new char[] { '-' })[1]);
serviceClient.EvaluateScoresCompleted += new EventHandler<EvaluateScoresCompletedEventArgs>(serviceClient_EvaluateScoresCompleted);
}
There is no stored procedure named Evaluate Scores or Evaluate Scores Completed. The problem is with the e.Result as System.Data.DataSet above, as in the data in the DataSet is not correct and I want to see where this is calculated. Any help would be appreciated.
unless CIServiceClient is also developed by your group you likely won't be able to debug it. That's part of the reason to use web services, you keep the logic tucked away so the consumer has no need to see it.

Difference between LoadState and navigationHelper_LoadState

I am new to windows store app development. Currently I am looking into passing and receiving parameter between xamls, using c#.
Can someone help explain difference between LoadState() and navigationHelper_LoadState() with some examples? Which should I go for receiving parameter?
So, NavigationHelper.LoadState requires two things:
OnNavigatedTo Invoked when this page is about to be displayed in a Frame.
NavigationMode.New Navigation is to a new instance of a page (not forward or back)
MSDN says:
In addition to providing the implementations described earlier, NavigationHelper also needs to be called from the OnNavigatedTo() and OnNavigatedFrom() event handlers that are implemented on each page. When these events occur, NavigationHelper calls a page-specific implementation of LoadState() and SaveState(). You can customize the implementation of these functions on each page. They should be used in place of OnNavigatedTo() and OnNavigatedFrom() respectively.
The raw code is:
public void OnNavigatedTo(NavigationEventArgs e)
{
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
this._pageKey = "Page-" + this.Frame.BackStackDepth;
if (e.NavigationMode == NavigationMode.New)
{
var nextPageKey = this._pageKey;
int nextPageIndex = this.Frame.BackStackDepth;
while (frameState.Remove(nextPageKey))
{
nextPageIndex++;
nextPageKey = "Page-" + nextPageIndex;
}
if (this.LoadState != null)
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, null));
}
}
else
{
if (this.LoadState != null)
{
this.LoadState(this, new LoadStateEventArgs(e.Parameter, (Dictionary<String, Object>)frameState[this._pageKey]));
}
}
}
For the sake of your question, there is no LoadState() override unless you define your own like this blog. He simply does this:
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
LoadState(e);
}
private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
{
SaveState(e);
}
protected virtual void LoadState(LoadStateEventArgs e) { }
protected virtual void SaveState(SaveStateEventArgs e) { }
See, they are identical. Nothing different between them except the execution pipeline which might impact timing a little, but not likely. In the end, no real difference. People who need to use one over the other... they have to be mistaken, attributing a cause where something else is the influence.
Best of luck.
There are a lot of example online. You might be better off going through those and then coming back here for more specific questions.
http://marcominerva.wordpress.com/2013/10/10/a-base-page-class-for-windows-8-1-store-apps-with-c-and-xaml/

Why is my ASP.NET Web Page not Getting or Setting my Session Variable?

I've added bits of debug code in an attempt to figure out what is going on with my Session variable, and it appears that it is always empty.
Could someone tell me what I am doing wrong?
This is probably some noobie mistake, because I don't do much web development.
private const string PASSWORD = "PASSWORD";
protected void Page_Load(object sender, EventArgs e) {
if (String.IsNullOrEmpty(password)) {
lblMessage.Text = !IsPostBack ? "Not a PostBack!" : "A PostBack.";
} else {
ShowData(IsPostBack);
}
}
private string password {
get { return Session[PASSWORD] as string; }
set { Session[PASSWORD] = value; }
}
protected void Password_Click(object sender, EventArgs e) {
string val = txtPassword.Text.Trim();
if (val == ConfigurationManager.ConnectionStrings[PASSWORD].ConnectionString) {
password = val;
txtPassword.Text = null;
} else {
Response.Redirect(val);
}
}
private void ShowData(bool postType) {
// I would display my data here if it ever got to this point!
}
EDIT: When the Password_Click event fires, all I ever see is "Not a PostBack!" or "A PostBack." So, my Session variable must not be getting set.
Unless you have specifically disabled sessionstate (which I don't think you did), your code looks OK.
The only thing I can think of is that your method Password_Click doesn't get called.
Please put a breakpoint there and see whether the variable actually gets set.
If not show us the ASP.NET markup so we can see why it's not firing the event
Looking at your code, the only "issue" I see which can create this behaviour is this line:
Response.Redirect(val);
I would say that your are getting a redirect, because otherwise your code seems right to me.
In this scenario the only way Session[PASSWORD] (effectively Session["PASSWORD"]) gets set is if there is an entry in your web.config:
<configuration>
<connectionStrings>
<add name="PASSWORD" connectionString="xxx" providerName="<Some Provider>" />
</connectionStrings>
</configuration>
And you type a string in txtPassword control that matches the string in connectionString attribute of the PASSWORD entry in the section of your web.config

Categories