c#- Display error message if there is no issue permission - c#

I have a program in c# that allow users to issue events ( think of it like different vouchers from different category). In the program, there is a function called promotion permission to set access to the event. The two access are view permission and issue permission. View permission allow user to view the event and issue permission allow user to issue (print) out the event. For example, if the event is set to as view permission: yes and issue permission : no , then user cannot issue the event but could view it. If both cases are yes then user may issue the event.
Now I have another function in program to issue the event(voucher). In that program, it shows a list of events (when user enter their id) and are able to tick(checkbox) the event they wish to issue. What I need is if the event does not have issue permission but view permission, it should not allowed user to tick the checkbox and if they try to do so, it should throw a error message informing user of the restriction.
This is my code:
private void lisVieBenefits_ItemChecked(object sender, ItemCheckedEventArgs e)
{
RestartAutoLogoffTimer();
DataSet dsData = oBSPromoPermission.GetBrowseData();
if (e.Item.Checked && !IsEnoughtToRedeemPointEarnReward())
{
// Uncheck previous item
e.Item.Checked = false;
return;
}
if (panBenefitSelection.Enabled)
{
int intTotal = 0;
for (int intCounter = 0; intCounter < lisVieBenefits.Items.Count; intCounter++)
{
if (lisVieBenefits.Items[0].ListView.Items[intCounter].Checked)
intTotal += 1;
}
if (intTotal > intMaxBenefitSelection)
{
lisVieBenefits.Items[0].ListView.Items[e.Item.Index].Checked = false;
SetErrorHint("Please select not more than (" + intMaxBenefitSelection + ") benefit selection");
}
if (dsData.Tables[0].Columns[3].ToString() == "True" && dsData.Tables[0].Columns[4].ToString() == "False")
{
// lisVieBenefits.Items[0].ListView.Items[e.Item.Index].Checked = false;
SetErrorHint("This event does not have an issue permission");
}
}
I declared and call the class:
private BSPromoPermission oBSPromoPermission = new BSPromoPermission();
So,dsData is a dataset variable declared to call the database that have view permission and issue permission. As shown in the code, column[3] is set to true for view permission and column[4] is set to false for issue permission.
Somehow this isn't working. Any help would be appreciated.

Related

Change Buttons to visible after a User logs in

I made an SQL database with a connection and a table with user and password. I managed to create a login following a guide. The code is working fine to login, but what I want to do is to show all other Buttons on the main Form after a user logs in.
I am using a Panel in the main Form to show the second Form. Clicking Buttons show a UserControl in the middle Panel.
I just want to update the Button.Visible value from false to true without opening a new main Form.
I can make the Buttons visible when the Form loads but not when I try to set a condition. I can't figure out how to set a condition that when a user logs in successfully, the other Buttons are set to visible and the login Button is hidden.
Part of code in the MainLogin UserControl.
The MainMenu.UserAutherised I added was to pass the userID from a TextBox to the UserAutherised() method in the MainMenu Form when the login is successful.
if (mread.Read() == true)
{
MessageBox.Show("Login successfull");
this.Hide();
MainMenu.UserAutherised(text_userID.Text);
}
Part of code in MainMenu: I did this trying to solve the problem.
I thought that setting a bool to true when a user successfully logs in, I could have then called the ShowButtons() method to set Buttons to visible:
public static bool UserAutherised(string user)
{
bool returnValue;
string _user ="true";
string _noUser ="false";
bool _userID = bool.Parse(_user);
bool _noUserID = bool.Parse(_noUser);
}
if (user == "")
{
returnValue = _noUserID;
return returnValue;
}
else
{
returnValue = _userID;
return returnValue;
}
I get the bool value as far as I can understand from debugging, but when I try to use the if statement in the ShowButtons() method, I can't figure out how to get the bool value from UserAutherised() to if(UserAutherised()) to show the Buttons when the value is true.
I hope I described the problem well enough.
EDIT 1:
I tried the same event Action syntax to get the position and access for the user logging in. In the MainLogin form i added the following:
public event Action<string> ACCESS;
public event Action<string> POSITION;
string userAccess, userPosition;
and then i added the following in the mread.Read if-statement:
Sqlcommand cmd_get_position_Access = new SqlCommand (
"SELECT, Access FROM Users WHERE position = #position AND Access = #Access", dataconnection);
SqlParameter _position = new SqlParameter("#position",
SqlDbType.NVarchar);
SqlParameter _access = new SqlParameter("#Access", SqlDbType.NChar);
cmd.Parameters.Add(_position);
cmd.Parameters.Add(_access);
userPosition = mread["position"].ToString();
userAccess = mread["Access"].ToString();
I get a NullReferenceException when trying to Invoke the new events so i added the following if-else statement to fix it:
if (ACCESS == null || POSITION == null)
{
return;
}
else
{
ACCESS.Invoke(userAccess);
POSITION.Invoke(userPosition);
}
In the MainMenu button click event:
var userLogin = new MainLogin();
panel_Main.controls.Add(userLogin);
userLogin.userLogged += UserLogged;
userLogin.ACCESS += UserAccess;
userlogin.POSITION += Position;
userLogin.Show();
When debugging i can see that i get the Access value from database table. But when i try to use a method with if-statements but the conditions are skipped even when true. I also tried the switch-statement but same thing happens to cases. They are skipped. For example if admin login i get access yellow but case is skipped. Same thing happens to the if-statements conditions. Access is yellow and condition is true but if-statement is skipped. Why are they skipped when conditions are true?
private void UserAccess(string access)
{
switch (access)
{
case: "yellow":
userAdmin();
break;
case: "green":
userGreen();
break;
default:
break;
}
}
EDIT 2:
I found the problem. It turns out to be in the User table. Access was set to nchar data type which add spaces to the value. Access was getting the string "yellow ". I changed data type to varchar and it solved the issue.
Why are you using static method to access MainMenu?
I think it would be better to declare event in MainLogin form like:
public event Action<string> userLogged;
and invoke it after this.hide:
userLogged.Invoke(text_userID.Text);
And in MainMenu form create a handler for this event:
void UserLogged(string user)
{
if (user != "")ShowButtons();
}
And subscribe to userLigged event before showing MainLogin form like:
MainLogin loginForm = new MainLogin();
loginForm.userLigged += UserLogged;
loginForm.Show();

How to stop Windows Form program execution until text box input is given?

I'm building a windows form application that stores employee information records in a database, including SSN. Next to the textbox where the SSN is input is requested, I have a checkbox that when clicked, shows me the full SSN instead of the last four digits. To ensure that only an administrator is accessing this information, I created a prompt form connected to a MS SQL DB that stores an admin password and would like to ask the user for a password for security purposes. Also, i'd like to be able to call this form whenever needed. I successfully implemented it but would like to add a feature that allows for 3 tries. Is there a way to stop the program execution and keep prompting the user for input in a textBox?
output is a variable that stores the result of the 'SELECT' query that gets the password.
confirmation is the Accept Button.
The only option i could think of forcing input was calling a new form. Only problem is, this code is inside the form and my gut tells me that's not the answer to this problem. I must be missing something.
confirmation.Click += (sender, e) => {
//If Password is correct.
if (textBox.Text == output)
{
isCorrect = true;
Pprompt.Close();
}
else
{
isCorrect = false;
//While the password is incorrect.
while (isCorrect == false)
{
//textBox.Text = "";
if (textBox.Text == output)
{
isCorrect = true;
Pprompt.Close();
break;
}
tryCount++;
if (tryCount == 3)
{
MessageBox.Show("Access Denied.");
break;
}
}
}
}
What I'd like to happen is for the form to keep asking me for input until the try limit is exceeded.
You cannot have the loop inside the click handler, because the UI freezes while it is running and the user does not get the opportunity make any entries.
Process only one entry and process the next when the user clicks the button again.
confirmation.Click += (sender, e) => {
if (textBox.Text == output) // Password is correct.
{
isCorrect = true;
Pprompt.Close();
}
else
{
isCorrect = false;
textBox.Text = "";
tryCount++;
if (tryCount == 3)
{
MessageBox.Show("Access Denied.");
Pprompt.Close();
}
}
}
Unless you are using multi-threading or async/await, the following is true:
Winforms is event based. I.e., if no event handler is running, no code is running.
If code (i.e. an event handler) is running, the user interface (UI) is frozen and the user cannot make any input. He cannot enter text or click any buttons, cannot scroll lists and cannot resize or move the window.
While an event handler is running, no other event handler will ever be called. I.e., an event handler will never be interrupted by another one. This prevents you from having to deal with multi-threading issues unless you are using multi-threading explicitly.
If an event should be fired (e.g. a timer tick) while an event handler (e.g. a button click handler) is running, the execution of the event handler associated to this new event will be deferred until after the first event handler returns.

errorprovider or message box?

I have a simplr windows form input(student name,studentid) to display to a listbox.
I need to check for duplicate student id in listbox before i add a value.
Can I use error provider on student id text box to do this?
any help much appreciated
please check last bit of my code below -is for/foreach loop required?
Thanks
private void txtSid_Validating(object sender, CancelEventArgs e)
{
bool can = false;
int sid = 0;
if (string.IsNullOrEmpty(txtSid.Text))
{
ep1.SetError(txtSid, "Please Enter Student ID");
can = true;
}
else if (!int.TryParse(txtSid.Text, out sid))
{
ep1.SetError(txtSid, "Student ID must be a number");
can = true;
}
else
for (int i = 0; i < lstDisplay.Items.Count; i++)
{
if (lstDisplay.Items[i].ToString().Contains(txtSid.Text))
{
ep1.SetError(txtSid, "Student ID already added");
can = true;
}
{
}
e.Cancel = can;
}
Yes, you can use Error Provider. In fact, for in-place validation such as you are doing, I tend to prefer them. I try to limit pop-up boxes, as they can be annoying to the user. Error providers, coupled with disabling a Save button, for instance, can provide a block to continuing as well as information as to why, all without annoying pop-ups.
As for checking against items already in the list box, yes, I would loop over them checking one at a time. If there are a lot of them, or if performance is highly critical, then you could implement a custom comparer for the items you add to the list box. They could also be of a custom class to facilitate the mechanics of it all.

How can I count a specific session variable?

I want to know if i can count a specific session variable.
I want to make a count of how many users are currenty logged in to the site and how many users are visiting the site right now.
Here is what i did (code)
public void Session_OnStart()
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
Application.UnLock();
}
public void Session_OnEnd()
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] - 1;
Application.UnLock();
}
This code works fine, But now I got no idea how to count users that are logged in. I want to do something like that:
public void Session_OnStart()
{
if (Session["IsLoggedIn"] == "true")
{
Application.Lock();
Application["UsersLoggedIn"] = (int)Application["UsersLoggedIn"] + 1;
Application.UnLock();
}
}
and then if the session is closed it will subtract 1 from the Application["UsersLoggedIn"]. My problem is that I cant count the 'IsLoggedIn' session on session start, because it is null and hence it wont work. So now we get to my quistion, Is there anyway to trigger the count of that application variable? Like to create an event when that session is true and then tell the application to add +1 to the counter on that event? Im sorry if my quistion wasnt clear, Please ask me for more deatils if its not clear and you just had no idea what i want from you.
Thank you for your help!
Dirty, hacky, inefficient, solution (assumes use of forms authentication):
public void Global_BeginRequest(object sender, EventArgs e)
{
if(
Context.User != null &&
!String.IsNullOrWhiteSpace(Context.User.Identity.Name) &&
Context.Session != null &&
Context.Session["IAMTRACKED"] == null
)
{
Context.Session["IAMTRACKED"] = new object();
Application.Lock();
Application["UsersLoggedIn"] = Application["UsersLoggedIn"] + 1;
Application.UnLock();
}
}
At a high level, this works by, on every request, checking if the user is logged in and, if so, tags the user as logged in and increments the login. This assumes users cannot log out (if they can, you can add a similar test for users who are logged out and tracked).
This is a horrible way to solve your problem, but it's a working proto-type which demonstrates that your problem is solvable.
Note that this understates logins substantially after an application recycle; logins are much longer term than sessions.
I think the session items are client sided.
You can create a query to count the open connections (hence you're working with a MySQL database.)
Another option is to use external software (I use the tawk.to helpchat, which shows the amount of users visiting a page in realtime).
You could maybe use that, making the supportchat invisible, and only putting it on paging which are accesible for loggedin users.
OR
Execute an update query which adds/substracts from a column in your database (using the onStart and OnEnd hooks).
That is the problem that you cannot do it using Session[] variables. You need to be using a database (or a central data source to store the total number of active users). For example, you can see in your application, when the application starts there is no Application["UsersOnline"] variable, you create it at the very instance. That is why, each time the application is started, the variable is initialized with a new value; always 1.
You can create a separate table for your application, and inside it you can then create a column to contain OnlineUsers value. Which can be then incremented each time the app start event is triggered.
public void Session_OnStart()
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
// At this position, execute an SQL command to update the value
Application.UnLock();
}
Otherwise, for every user the session variable would have a new value, and you would not be able to accomplish this. Session variables were never designed for such purpose, you can access the variables, but you cannot rely on them for such a task. You can get more guidance about SQL commands in .NET framework, from MSDN's SqlClient namespace library.
Perhaps I am missing something, but why not something like this:
public void Session_OnStart()
{
Application.Lock();
if (Application["UsersOnline"] == null )
{
Application["UsersOnline"] = 0
}
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
Application.UnLock();
}
Maybe I'm missing something, but is there a reason you don't just want to use something like Google Analytics?
Unless you're looking for more queryable data, in which case I'd suggest what others have; store the login count to a data store. Just keep in mind you also have to have something to decrement that counter when the user either logs out or their session times out.
Try this. It may help you.
void Application_Start(object sender, EventArgs e)
{
Application["cnt"] = 0;
Application["onlineusers"] = 0;
// Code that runs on application startup
}
void Session_Start(object sender, EventArgs e)
{
Application.Lock();
Application["cnt"] = (int)Application["cnt"] + 1;
if(Session["username"] != null)
{
Application["onlineusers"] = (int)Application["onlineusers"] + 1;
}
else
{
Application["onlineusers"] = (int)Application["onlineusers"] - 1;
}
Application.UnLock();
// Code that runs when a new session is started
}
now you can display the number of users(Without Loggedin):
<%=Application["cnt"].ToString()%>
and number of online users:
<%=Application["onlineusers"].ToString()%>

Context.Items clears during page refresh/transfer

I am working on a class project and I've run into a problem I can't figure out. I have a feeling it's actually pretty easy, but I've been working on stuff so long I can't think straight anymore.
I have a login page that allows a user to login and pass 2 data items to the next page using Context.Items and Server.Transfer. Here is the code snippet:
Context.Items["preferred"] = true;
Context.Items["pageNum"] = 1;
Server.Transfer("ProductsShelf.aspx");
On the "ProductsShelf" page I can access those two items and use the data like so:
pageNumber = (int)Context.Items["pageNum"];
I am then using a switch-statement with pageNumber to display certain information:
switch (pageNumber)
{
case 1:
imgProd.ImageUrl = "assets/laptop.bmp";
lbl_Name.Text = "Laptop";
lbl_desc.Text = "This is a cheap laptop!";
lbl_price.Text = "199.99";
break;
}
Obviously there's other entries I'm omitting. What I want to do is click a next or previous button and use the event to change the Context.Items["pageNum"] data so the Page_Load() event uses different data in the switch-statement. Hope that makes sense. Here is one of the button click events:
protected void btn_Prev_Click(object sender, EventArgs e)
{
if (pageNumber == 1 || pageNumber == 2)
{
Context.Items["pageNum"] = 1;
}
else if (pageNumber == 3)
{
Context.Items["pageNum"] = 2;
}
Context.Items["preferred"] = preferredCustomer;
Server.Transfer("ProductsShelf.aspx");
}
The problem is that before the button click event fires, the form posts and clears the Context.Items and pageNumber values. This means that the button event if-statements never fire and it results in:
pageNumber = (int)Context.Items["pageNum"];
Being null, throwing an exception and making me very sad. So my question is, how can I go about retaining the values? Should I switch to Response.Redirect and have something like ?page=1 in the URL? Or will that clear too when the form posts? Hopefully I'm not doing this completely wrong.
If TL;DR, here's a quick summary:
Context.Items has 2 values passed with Server.Transfer
These values determine what's shown on the next page
The form clears Context.Items and variables before button click event fires
The values are null, the if-statement doesn't run, and the app throws an exception
Question: how should I go about retaining those values?
Thanks a lot. :)
HttpContext items can be used within one request only - it will be recreated for next request so your values are bound to lose. You should use view-state to preserve data across post-backs. In page load, you should check if data exists in context and then copy it to view-state. Then in button click events, you can read the data from view-state, put into the context items and do server.transfer.
Here's simple sample code:
private int PageNumber
{
get
{
var value = ViewState["pageNum"];
return null == value? 1: (int)value;
}
set
{
ViewState["pageNum"] = value;
}
}
private bool IsPreferredCustomer
{
get
{
var value = ViewState["preferred"];
return null == value? false: (bool)value;
}
set
{
ViewState["preferred"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
var preferred = Context.Items["preferred"];
if (null != preferred)
{
IsPreferredCustomer = (bool)preferred;
}
var pageNum = Context.Items["pageNum"];
if (null != pageNum )
{
PageNumber = (int)Context.Items["pageNum "];
}
}
Use the same PageNumber property in event code.

Categories

Resources