In my web app the admin can assign a web page to a specific user, therefore that user can only access that specific page.
So to give an idea of how this works:
in my database I have a table with the web pages in, Webpage1.aspx, Webpage2.aspx etc.
The admin can create an user assign Webpage1.aspx to that user
Then when that user logs in they can only see the link to their page (all other links are hidden)
This is now the problem I have:
This works on a DataTable row number so when adding a new web form it re-arranges the DataTable row numbers which then when the user logs in again they can see all other links cause the table numbers have changed.
So to give a visual idea:
if (Session["Privilege"] != null)
{
DataTable dtPrivilege = (DataTable)Session["Privilege"];
/* Dashboard */
if (bool.Parse(dtPrivilege.Rows[1]["Read"].ToString()) == false && dtPrivilege.Rows[1]["FormName"].ToString() == "dashboard.aspx")
lnkDashboard.Visible = false;
/* Settings */
if (bool.Parse(dtPrivilege.Rows[2]["Read"].ToString()) == false && dtPrivilege.Rows[2]["FormName"].ToString() == "general.aspx")
lnkSettings.Visible = false;
/* Web Pages */
if (bool.Parse(dtPrivilege.Rows[0]["Read"].ToString()) == false)
lnkWebpages.Visible = false;
else
{
if (bool.Parse(dtPrivilege.Rows[0]["Read"].ToString()) == false && dtPrivilege.Rows[0]["FormName"].ToString() == "Webpage1.aspx")
lnkWebpage1.Visible = false;
}
So it reads by row number so when you add another page it messes up the row number and the 1st users saved in the database then gets the wrong link assigned to their privilege, because it moved the row number to 1 or 2 depending on how many web forms have been added.
So my question is, how can I make it so that it reads the string instead of the row number? So for example
if (Session["Privilege"] != null)
{
DataTable dtPrivilege = (DataTable)Session["Privilege"];
/* Web Pages */
if (bool.Parse(dtPrivilege.Rows[0]["Read"].ToString()) == false)
lnkWebpages.Visible = false;
else
{
if (bool.Parse(dtPrivilege.Rows[**Webpage1.aspx**]["Read"].ToString()) == false && dtPrivilege.Rows[0]["FormName"].ToString() == "Webpage1.aspx")
lnkWebpage1.Visible = false;
}
Is this possible and if so how can I achieve my goal?
Please let me know if you need more info or I haven't explained properly :-)
Thanks
You can use Linq to achieve this.
Add using System.Linq; at the top of your .cs page.
Then add below line to generate IEnumerable(Array) of all rows inside dtPrivilege DataTable,
DataRow[] allRows = dtPrivilege.Select();
And finally, add if blocks like below for all your webpages.
if (allRows.Any(x => x["FormName"].ToString() == "Webpage1.aspx" &&
x["Read"].ToString().ToLower() == "false"))
{
lnkWebpage1.Visible = false;
}
What above if block says:
It checks if there exists Any row in allRows, which has FormName = "Webpage1.aspx" and Read = "false". And if it exist, just set lnkWebpage1.Visible = false
Related
I have created a vsto application that calls a webservice. everything seems to work just fine, but i would like to extend the functionality to call the test service version of my production service.
code snippet that works that calls my test service.
//how do i change here to be dynamic?
npfunctions.finfunctions service = new npfunctions.finfunctions();
var Results = service.ValidateFoapal(index.ToArray(), fund.ToArray(), org.ToArray(), prog.ToArray(), acct.ToArray(), row.ToArray());
/* if their are no error then return a "Y" for success.*/
if (Results.Count() < 0) { return LocallErrorInd; }
/*well we have encountered errors lets adjust the spreadsheet to notify the user.*/
else{
//REMOVE ANY VISUAL ERRORS
Microsoft.Office.Interop.Excel.Range delRng = Globals.ThisAddIn.Application.Range["R:S"];
delRng.Delete(XlDeleteShiftDirection.xlShiftToLeft);
for (int i = 0; i < Results.Count(); i++)
{//set the error indicator
LocallErrorInd = "Y";
//account error:
if (Results[i].FVALJOR_FUND_WARNING == "Y")
{
Microsoft.Office.Interop.Excel.Range WrkRng = Globals.ThisAddIn.Application.Range[Results[i].FVALJOR_ROW];
WrkRng.Offset[0, 17].Value2 = "Invalid Account";
}
i have seen this post How can I dynamically switch web service addresses in .NET without a recompile?
but it requires me to change my config file i would really like to change the service variable to point to another location based on a variable and basically flip from prod to test on my command. as i see it right now it appears that i would have to duplicate the code but i know there has got to be a better way. i like it to be something like.
if (TestBtn.Checked == true)
{
npfunctions.finfunctions service = new npfunctions.finfunctions();
Results = service.ValidateFoapal(index.ToArray(), fund.ToArray(), org.ToArray(), prog.ToArray(), acct.ToArray(), row.ToArray());
}
if (PrdBtn.Checked == true)
{
prdFunctions.finfunctions service = new prdFunctions.finfunctions();
Results = service.ValidateFoapal(index.ToArray(), fund.ToArray(), org.ToArray(), prog.ToArray(), acct.ToArray(), row.ToArray());
}
/* if their are no error then return a "Y" for success.*/
if (Results.Count() < 0) { return LocallErrorInd; }
Does your service object not have a URL property?
2nd option, you can use a config file transformation so you do not need to manually change the settings(after the intial setup of course).
npfunctions.finfunctions service = new npfunctions.finfunctions();
if (TestBtn.Checked == true)
{
service.url="<testurl>";
}
else
{
service.url="<produrl>";
}
Results = service.ValidateFoapal(index.ToArray(), fund.ToArray(), org.ToArray(), prog.ToArray(), acct.ToArray(), row.ToArray());
In our test client we have a drop-down to select between dev or tst. We also have buttons to select proxy or net.tcp. (We have many different people using our service using different methods).
In the app.config the names of the endpoints correlate with different selectable options.
Eg. name="BasicHttpBinding_IInterface_PROXY_DEV"
You can then dynamically build up which endpoint you would like to use and go with that.
thanks for reading my post, i am from yesterday trying with this code to lock the function "secundario" and bring always the same info until i totalize or cancel that order.
Is working fine with "index" Function, but not with "secundario" function
[AuthorizeRoles(Modulo = "4310")]
public ActionResult Index()
{
/* Lot of Code Here */
var pedido_1 = dc.SAFACTs.FirstOrDefault(b => b.CodUsua == User.Identity.Name && b.SAFACT_01.Estado == "0");
if (pedido_1 != null)
{
Session["pedido1"] = pedido_1;
/* Lot of Code Here */
}
/* If order "pedido1" does not exist, we create a new order */
return View(pedido_1); //Load the view with the data and here works the lock. View Data with the data of pedido_1 until the user totalize or cancel this order
}
[AuthorizeRoles(Modulo = "4310")]
public ActionResult secundario()
{
if (Session["pedido1"] != null) //I check if the first order "pedido1" exists, if exists i do the second order
{
/* Lot of Code Here */
var pedido_2 = dc.SAFACTs.Skip(1).Take(1).FirstOrDefault(b => b.CodUsua == User.Identity.Name && b.SAFACT_01.Estado == "0");
if (Session["pedido2"] != null)
{
pedido_2 = (PRINCIPAL.Areas.VENTAS.Models.SAFACT)Session["pedido2"];
//Session["pedido2"] = pedido_2;
}
if (pedido_2 != null)
{
/* Lot of Code Here */
}
/* If order "pedido2" does not exist, we create a new order */
return View(pedido_2); /* Load the view with the data and here DOES NOT work the lock and i can make n orders
I should View Data with the data of pedido_2 until the user totalize or cancel this order
*/
}
else // If first order "pedido1" does not exist i redirect the user to index function
{
return RedirectToAction("Index", "PROG_4310"); //Redirect to Index
}
}
If you wish have a look at full code you can refer at this question i did yesterday -> link
Thanks in Advance, any help would be appreciated
I have an issue, where by each user in my user list is showing as on-line when I know they're not.
When the page is loaded, they show as offline, but if I refresh the page, they all show as on-line. I'm assuming this is because I'm programmatically accessing their profile information (CommonProfile) to get the data to show on the gridview?
Is there any way to get the profile information without triggering the IsOnline property to be true?
Update:
Sorry, code is here. Please be gentle, I'm relatively new to c# & asp.net and I'm still learning.
The code is collecting information from Membership user and the common profiles and adding the fields to a datatable so that i can display the results in a gridview.
MembershipUserCollection usersList = Membership.GetAllUsers();
MembershipUserCollection filteredUsers = new MembershipUserCollection();
foreach (MembershipUser user in usersList)
{
if (!Roles.IsUserInRole(user.UserName, "Admin") && !Roles.IsUserInRole(user.UserName, "Engineering"))
{
if (txtFilterCustomerNo.Text.Length > 0)
{
ProfileCommon PC = Profile.GetProfile(user.UserName);
if (PC.CompanyAccountNo == txtFilterCustomerNo.Text.ToUpper())
{
filteredUsers.Add(user);
}
}
else
{
filteredUsers.Add(user);
}
}
}
txtFilterCustomerNo.Text = null;
foreach (MembershipUser user in filteredUsers)
{
userProfile = Profile.GetProfile(user.UserName);
string[] userRoles = Roles.GetRolesForUser(user.UserName);
DataRow orderLine = dataSet.Tables["UserAccounts"].NewRow();
orderLine["USER_NAME"] = user.UserName;
orderLine["CREATED"] = user.CreationDate;
orderLine["LAST_LOGIN"] = user.LastLoginDate;
orderLine["PASSWORD_CHANGED"] = user.LastLoginDate;
orderLine["ACTIVE"] = user.IsApproved;
orderLine["ONLINE"] = user.IsOnline;
orderLine["LOCKED"] = user.IsLockedOut;
orderLine["CUSTOMER_NO"] = userProfile.CompanyAccountNo;
orderLine["HAS_INVENTORY"] = userProfile.HasOwnInventory;
orderLine["ORDER"] = userRoles.Contains("Order");
orderLine["REPAIR"] = userRoles.Contains("Repair");
orderLine["WARRANTY"] = userRoles.Contains("Warranty");
orderLine["COMMISSIONING"] = userRoles.Contains("Commissioning");
orderLine["ACCOUNT"] = userRoles.Contains("Account");
dataSet.Tables["UserAccounts"].Rows.Add(orderLine);
}
if (dataSet.Tables.Contains("UserAccounts"))
{
GridView1.DataSource = dataSet.Tables["UserAccounts"];
}
If you simply looked at the different overloads of GetUser, you would see that some of them take a Boolean called userIsOnline. If you specify this as false, it will not update the last online timestamp, and will not list them as online.
var user = Membership.GetUser(userid, false);
EDIT:
I see you are using GetAllUsers() rather than GetUser(). There are some problems with GetAllUsers() and you cannot rely on the IsOnline property. Instead, you need to check the LastActivityDate field and figure out the difference between that and the current DateTime. If the amount of time is greater than what you consider "Online" to be, then they are offline, otherwise online.
Hi having abit of a problem with my code it refuses to do my else statement have a global variable set to say attempts = 3
runs the while loop but when i put an invalid pin it basically just doesnt run anything i would appreciate any help possible thanks
while (read.Read())
{
if (read.HasRows)
{
}
//If the card isnt confiscated then do this:
if (((Boolean)(read["confiscated"]) == false))
{
string cardnum = read["cardNumber"].ToString();
string pinnum = read["PIN"].ToString();
//Compare the results in the table against those put in by the customer
if (string.Equals(cardnum, cardBox.Text) && string.Equals(pinnum, pinNumber.Text))
{
MessageBox.Show("Welcome customer");
MessageBox.Show("Card Number " + cardnum + " PIN " + pinnum);
//if the login details match and everything is correct then bring the next form up
MessageBox.Show("Details are correct");
pinNumber.Clear();
//open the options form
Form optionForm = new optionForm();
optionForm.Show();
//hide this form
this.Hide();
break;
}
else
{
if (attempts == 1)
{
sqlCommandATM.Parameters["#cardNum"].Value = cardBox.Text;
sqlCommandATM.Parameters["#confiscated"].Value = true;
MessageBox.Show("Your card has been confiscated please contact The bank of Glamorgan to resolve the issue");
pinNumber.Clear();
}
EDIT
I've tried to understand what you're doing. I assume you're trying to authenticate a person by credit card number and PIN against a database, and you're doing it by getting all the entries from a database table and looping over them to find the one that matches the user input. You want to allow the user to do that three times before locking the credit card.
I see more than one issue with that: The task of finding the correct row in the table for the user should be left to the database. This is much quicker and less error prone. So if you'd like to do it right, then you should have an SQL statement like:
int attempts = 0;
bool success = false;
while (!success && attempts < 3)
{
using (SQLCommand exists = new SQLCommand("SELECT ID FROM ... WHERE CCardNo = #cardNo AND PIN = #pin", conn))
{
exists.Parameters.AddWithValue("#cardNo", cardNum);
exists.Parameters.AddWithValue("#PIN", pinnum);
object idObject = (int)exists.ExecuteScalar();
if (idObject == null || idObject == DBNull.Value)
{
attemps++;
}
else
{
success = true;
}
if (attempts >= 3)
{
// Lock out the user
}
}
}
if (success)
{
...
}
If you really insist on doing it your way, then please make sure that attempts is initialized properly and is incremented on each login attempt - in your current code, you'd increment it on every row you're validating against, so you'd lock out every customer who's not within the first three rows you're getting from the database.
Original reply
OK, you're reading all data from a DataReader in a while loop:
while (read.Read())
{
Then what do the following three lines do? You wouldn't be here if read.HasRows was false, because read.Read() would have returned false already. The following three lines are pointless and can be removed, leaving only what's inside the block.
if (read.HasRows)
{
}
The usual way would be:
if (read.HasRows)
{
while (read.Read())
{
...
}
}
More is hard to tell as you're not showing us the complete code - what value does attempts have before the while loop, for example?
Ignoring the syntax errors in your posted code, my first guess is that your attempts variable is not set to 1 when control goes inside the else statement so, based on your posted code, nothing should happen. Could you show us where this attempts variable is declared/changed?
From the code supplied you have not incremented attempts on each attempt the user trys to enter a pin. where teh code is;
string pinnum = read["PIN"].ToString();
attempts++;
Something like that. Its hard to tell what you have in total as its obviously snipped code.
You said the global attempts = 3.
If that's the case, you should check if the failed attempts is >= 3.
if (string.Equals(cardnum, cardBox.Text) && string.Equals(pinnum, pinNumber.Text))
{
// Load account
}
else if (attempts >= 3)
{
// Confiscate card
}
else
{
attempts ++;
}
can anyone help me how to resolve the out of memory error on my asp page? im using linq to sql.. after adding data several data.. like more than 10 rows. in the grid. an out of memory error occurs.. attached herewith is my add function..
public ServiceDetail checkservicedetailid()
{
string ServiceName = ViewState["Tab"].ToString();
ServiceDetail checkservicedetailid = ServiceDetails_worker.get(a => a.ServiceName == ServiceName && a.MarginAnalysisID == checkmarginanalysisid().MarginAnalysisID).SingleOrDefault();
return checkservicedetailid;
}
public IEnumerable<ServiceDetail> get(Expression<Func<ServiceDetail, Boolean>> express)
{
return ServiceDetailsDB.ServiceDetails.Where(express);
}
protected void btnSaveEmptyOC_Click(object sender, EventArgs e)
{
try
{
if (checkservicedetailid() != null)
{
CashExpense tblCashExpenses = new CashExpense();
Guid CashExpensesID = Guid.NewGuid();
tblCashExpenses.CashExpensesID = CashExpensesID;
tblCashExpenses.ServiceDetailsID = checkservicedetailid().ServiceDetailsID;
tblCashExpenses.Description = txtDescriptionEmptyOC.Text;
tblCashExpenses.Quantity = Decimal.Parse(txtQTYEmptyOC.Text);
tblCashExpenses.UnitCost = Decimal.Parse(txtUnitCostEmptyOC.Text);
tblCashExpenses.CreatedBy = User.Identity.Name;
tblCashExpenses.DateCreated = DateTime.Now;
tblCashExpenses.CashExpensesTypeID = "OTHER";
CashExpenses_worker.insert(tblCashExpenses);
CashExpenses_worker.submit();
//Clear items after saving
txtDescriptionEmptyOC.Text = "";
txtQTYEmptyOC.Text = "";
txtUnitCostEmptyOC.Text = "";
ValidationMessage.ShowValidationMessage(MessageCenter.CashExpenseMaintenace.InsertOC2, "SaveEmptyOC", this.Page);
MyAuditProvider.Insert(this.GetType().ToString(), ViewState["MarginAnalysisID"].ToString(), MessageCenter.Mode.ADD, MessageCenter.CashExpenseMaintenace.InsertOC2, Page.Request, User);
divOtherCost.Visible = false;
grd_othercost.Visible = true;
btnaddothercost.Visible = true;
}
else
{
//Displays a Message on the Validation Summary (Service Id does not exist)
ValidationMessage.ShowValidationMessage(MessageCenter.CashExpenseMaintenace.SaveServiceDetailOC, "SaveEmptyOC", this.Page);
}
}
catch
{
//Displays a Message on the Validation Summary (Error on Saving)
ValidationMessage.ShowValidationMessage(MessageCenter.CashExpenseMaintenace.InsertOCError, "SaveEmptyOC", this.Page);
}
finally
{
//Rebinds the Grid
populategrd_othercost();
}
}
I'm guessing from your code here:
ServiceDetail checkservicedetailid = ServiceDetails_worker.get(
a => a.ServiceName == ServiceName &&
a.MarginAnalysisID == checkmarginanalysisid().MarginAnalysisID
).SingleOrDefault();
that .get() is taking a Func<SomeType, bool>, and you are doing something like:
var row = dbCtx.SomeTable.Where(predicate);
(please correct me here if I'm incorrect)
This, however, is using LINQ-to-Objects, meaning: it is loading every row from the table to the client and testing locally. That'll hurt memory, especially if a different db-context is created for each row. Additionally, the checkmarginanalysisid() call is being executed per row, when presumably it doesn't change between rows.
You should be testing this with an Expression<Func<SomeType, bool>> which would be translated to TSQL and executed at the server. You may also need to remove untranslatable methods, i.e.
var marginAnalysisId = checkmarginanalysisid().MarginAnalysisID;
ServiceDetail checkservicedetailid = ServiceDetails_worker.get(
a => a.ServiceName == ServiceName &&
a.MarginAnalysisID == marginAnalysisId
).SingleOrDefault();
where that is get(Expression<Func<SomeType, bool>>).
I tried all of the solution given to me both by my peers as well as the solution provided here, from GC.Collect, to disposing linq datacontext after use etc. however the error keeps on occurring, i then tried to remove the update panel, Ive read a site that showed how ridiculous update panel when it comes to handling data esp when a function is done repeatedly. And poof! the memory problem is gone!