Created class is not appearing in other class files asp.net/visual basic - asp.net

Very basic explanation: I have created a "User" class in a ConnectionClass.cs file and need to use it elsewhere (see below, it's a login button).
The code I'm trying to type is: `
namespace Vehicle_Website.Pages.Account
{
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnLogin_Click(object sender, EventArgs e)
{
User user = ConnectionClass.LoginUser(txtLogin.Text, txtPassword.Text);
if (user != null)
{
//Store login variables to session
Session["login"] = user.Name;
Session["type"] = user.Type;
Response.Redirect("~/Pages/Home.aspx");
}
else
{
lblError.Text = "Login Failed";
}
}
}
}`
The "User" should be highlighting in "blue" if you like, recognizing that it's an already created class elsewhere, except is isn't and I' getting an error
"type or namespace "User" could not be found"
The exact same applies to the "ConnectionClass" line.. It should be highlighting but again says not recognized.
I have created a public class User and a public static User LoginUser(string login, string password) elsewhere and they work fine without errors. I cant understand why, in plain English, the words "User" and "ConnectionClass" are not "highlighting/changing colour" and being recognised.
I have tried changing properties to compile but seems to have done nothing.
Whatever other information you need I'll be happy to share.
UPDATE***
This is my ConnectionClass.cs file (which is working fine):
namespace Vehicle_Website.App_Code
{
public static class ConnectionClass
{
private static SqlConnection conn;
private static SqlCommand command;
static ConnectionClass()
{
string connectionString = ConfigurationManager.ConnectionStrings["DataConnection"].ToString();
conn = new SqlConnection(connectionString);
command = new SqlCommand("", conn);
}
public static User LoginUser(string login, string password)
{
//Check if user exists
string query = string.Format("SELECT COUNT (*) FROM WebsiteDB.dbo.users WHERE name = '{0}'", login);
command.CommandText = query;
try
{
conn.Open();
int amountOfUsers = (int)command.ExecuteScalar();
if(amountOfUsers == 1)
{
//User exists, check if passwords match
query = string.Format("SELECT password FROM users WHERE name = '{0}'", login);
command.CommandText = query;
string dbPassword = command.ExecuteScalar().ToString();
if(dbPassword == password)
{
//Passwords match, retrieve further information.
query = string.Format("SELECT email, user_type FROM users WHERE name = '{0}'", login);
command.CommandText = query;
SqlDataReader reader = command.ExecuteReader();
User user = null;
while (reader.Read())
{
string email = reader.GetString(0);
string type = reader.GetString(1);
user = new User(login, password, email, type);
}
return user;
}
else
{
//Passwords do not match.
return null;
}
}
else
{
//User exists
return null;
}
}
finally
{
conn.Close();
}
}
}
}
UPDATE
So i think i may have found the problem but no idea how to fix:
Basically my login.aspx.cs page isnt being "linked" to my ConnectionClass.cs
By this, i mean, I have created the below line on the login.aspx.cs page :
Session["login"] = user.Name;
When i try and use ".Name" on my ConnectionClass.cs file, it isnt recognised :
user.Name);
Any idea on how to ensure both pages are communicating? I have tried correcting the namespace so they both match with no luck...

Do you have your ConnectionClass in the same project as the login button? If not you have to add a reference to the project that contains the ConnectionClass.
Also, is your ConnectionClass static? If it is not you will not be able to use it without creating first an instance of a class like this:
ConnectionClass myClass = new ConnectionClass();
User user = myClass.LoginUser(txtLogin.Text, txtPassword.Text);

You have to use full name of the class . That is ConnectedClass.User when accessing the nested class. By default nested class is private so also make sure you are using the correct access modifier

See to that the namespace Vehicle_Website.App_Code is included
in the aspx.cs which contains the button click method
Clearly see this line
public static class ConnectionClass
As per the code it is a static class and also see this constructor!
static ConnectionClass()
{
string connectionString = ConfigurationManager.ConnectionStrings["DataConnection"].ToString();
conn = new SqlConnection(connectionString);
command = new SqlCommand("", conn);
}
When is the constructor called during instanciating an object. Is
it possible instanciate the ConnectionClass? As per OOPs
programming concepts, you cannot do it. Then how will the connection
string and command will be assigned!!
Try fixing this first.

Related

Secure website from SQL Injection ' using ASP.net and an Access database

I currently have a website with a normal registration and login, coded with ASP.net.
I am using an Access database, while using a C# class my friend wrote for handling most of the database actions (executeQuery, executeRead, isExits...).
Now that I've almost finished building my website, I want to start adding security - mostly to my database. I have searched for a while now for a tutorial on the subject, but I could not find anything good exept an old microsoft msdn article which I couldn't realy get its code to work.
The furthest I've got now is just no allowing any dangerous characters in the username and password, (such as ',--,;), but it kind of feels as if it is the worse solution that i can use (why shouldn't my users use this characters?).
I think that the best solution I've found is somehow insertion the variables into the query string after declaring it (something to do with "WHERE username=#user" or something like that), but i couldn't get it to work with Access and with my oleDBManager.
here is my current registration code. handle() is removing all ' from the string, and Validate() checks for dangerous parts in the string.
string username = user.Text;
string password = pass.Text;
bool isThingy = false;
if (handle(ref password)) isThingy = true;
if (handle(ref username)) isThingy = true;
if (username != "" && username != null)
{
if (password != "" && password != null)
{
if (Validate(username, password))
{
if ((db.IsExist("SELECT * FROM Table1 WHERE username='" + username + "'") == false))
{
int a = db.ExecuteQuery("INSERT INTO `Table1`(`username`, `password`, `logins`, `email`, `fname`, `lname`, `country`, `city`, `birthday`, `userid`) VALUES ('" + username + "', '" + password + "', '0', '', '', '', '', '', '', '" + Convert.ToString(Convert.ToInt32(db.ExecuteCellRead("SELECT MAX(userid) FROM Table1")) + 1) + "');");
if (!isThingy) errorLabel.Text = "Your user has been successfully registered";
else errorLabel.Text = "The ' token is invalid. your user was registered absence the '.";
}
else
errorLabel.Text = "This username is already taken";
}
else errorLabel.Text = "Invalid name format";
}
else errorLabel.Text = "Please enter a password";
}
else errorLabel.Text = "Please enter a user name";
as for the oleDBManager (named db in my code):
private OleDbConnection link; // The link instance
private OleDbCommand command; // The command object
private OleDbDataReader dataReader; // The data reader object
private OleDbDataAdapter dataAdapter; // the data adapter object
private DataTable dataTable; // the data table object
private string dbName; // the Database filename
private int version; // the usersTableG office version
private string connectionString; // the connection string for the database connection
private string provider; // the matching driver string for the connection string
private string path; // the path to the database file
...
public int ExecuteQuery(string query)
{
this.link.Open();
int rowsAffected;
// ---
this.command = new OleDbCommand(query, this.link);
try
{
rowsAffected = this.command.ExecuteNonQuery();
}
catch (InvalidOperationException e)
{
if (e.Data == null)
throw;
else
rowsAffected = -1;
}
finally
{
this.command.Dispose();
this.link.Close();
}
// ---
return rowsAffected;
}
public bool IsExist(string query)
{
this.link.Open();
// ---
this.command = new OleDbCommand(query, this.link);
this.dataReader = this.command.ExecuteReader();
bool a = this.dataReader.Read();
// ---
this.command.Dispose();
this.link.Close();
// ---
return a;
}
public string ExecuteCellRead(string query)
{
string output = "";
this.dataTable = this.ExcecuteRead(query);
foreach (DataRow row in this.dataTable.Rows)
{
foreach (object obj in row.ItemArray)
{
output += obj.ToString();
}
}
return output;
}
So, as you might see, the main problem is that the user now can not use characters as '.
It suppose the best solution would be using the # variables in the SQL queries, but I have no idea how.
[thanks for your help]
PS. i HAVE changed my tables' name ;)
edit: most of you are telling me to use these parameterized queries, but it would be great if you could give me an example of how to use them, since i've never done that
So, thanks to #Remou, my FINAL code is:
db.DoWeirdStackOverFlowStuff(
"INSERT INTO `Table1`(`username`, `password`, `logins`) VALUES (#username, #password, '0');"
, new string[] { "#username", "#password" }
, new string[] { username, password });
and
public int DoWeirdStackOverFlowStuff(string query, string[] vars, string[] reps)
{
this.link.Open();
int rowsAffected;
// ---
this.command = new OleDbCommand();
this.command.CommandText = query;
this.command.CommandType = System.Data.CommandType.Text;
this.command.Connection = this.link;
//Parameters in the order in which they appear in the query
for (int i = 0; i < vars.Length; i++)
this.command.Parameters.AddWithValue(vars[i], reps[i]);
try
{
rowsAffected = this.command.ExecuteNonQuery();
}
catch (InvalidOperationException e)
{
if (e.Data == null)
throw;
else
rowsAffected = -1;
}
finally
{
this.command.Dispose();
this.link.Close();
}
// ---
return rowsAffected;
}
for whoever needs this =]
Some notes
In MS Access, I have a saved query called UpdateUser, it looks like this:
UPDATE INTERNETSETTINGS
SET url = [#url],
databasename = [#databasename],
port = [#port],
username = [#username],
[password] = [#password]
I can refer to this query by name in my code, using a command object:
OleDbCommand Command = new OleDbCommand();
Command.CommandText = "UpdateUser"; //saved query
Command.CommandType = System.Data.CommandType.StoredProcedure;
Command.Connection = cn; //a connection to the database
//Parameters in the order in which they appear in the query
Command.Parameters.AddWithValue("#url", "a"); //a,b,c etc for my test run
Command.Parameters.AddWithValue("#databasename", "b");
Command.Parameters.AddWithValue("#port","c");
Command.Parameters.AddWithValue("#username", "d");
Command.Parameters.AddWithValue("#password", "e");
Command.ExecuteNonQuery();
I don't remember whether Access does the same thing as SQL Server here, but in SQL Server you can escape the single quote mark by doubling it:
username = username.Replace("'", "''");
So you can include single-quote marks in the string, you can store them in the database, and they can't be used as malicious string terminators.

Object reference not set to an instance of an object ERROR

I have few textboxes whose values are to be inserted into SQl table on Submit button click. But it gives me "Object reference not set to an instance of an object" Exception. Below is the code I have written for this. Please do help me in this.
contact_new.aspx.cs
protected void btnSubmit_Click(object sender, EventArgs e)
{
DateTime dtime;
dtime = DateTime.Now;
string ocode = offercode.Text;
string firstname = firstnamepreapp.Text;
string lastname = lastnamepreapp.Text;
string email = emailpreapp.Text;
string phoneno = phonepreapp.Text;
string timetocall = besttimepreapp.SelectedItem.Value;
string time = dtime.ToString();
//Insert the data into autoprequal table
<--- GIVES ME AN ERROR ON THIS LINE --->
Insert.insertINTOautoprequal(ocode, time, firstname, lastname, email, phoneno, timetocall);
}
Insert.cs (App_code class)
namespace InsertDataAccess
{
public class Insert
{
public Insert()
{
//
// TODO: Add constructor logic here
//
}
public static bool insertINTOautoprequal(string code, string time, string first, string last, string email, string phoneno, string timetocall)
{
bool success = false;
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["connstring"].ConnectionString);
conn.Open();
string query = "Insert INTO autoprequal(offercode, timeofday, firstname, lastname, emailID, phone, besttimetocall) Values(#offercode, #time, #first, #last, #email, #phoneno, #timetocall);";
SqlCommand cmd = new SqlCommand(query, conn);
try
{
cmd.Parameters.AddWithValue("#offercode", code);
cmd.Parameters.AddWithValue("#time", time);
cmd.Parameters.AddWithValue("#first", first);
cmd.Parameters.AddWithValue("#last", last);
cmd.Parameters.AddWithValue("#email", email);
cmd.Parameters.AddWithValue("#phoneno", phoneno);
cmd.Parameters.AddWithValue("#timetocall", timetocall);
if (cmd.ExecuteNonQuery() == 1) success = true;
else success = false;
return success;
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
}
}
Step through the code, as the error is most likely bubbling up from the SQL insert routine. I woulud guess the connection string is not being pulled from the configuration file, but without stepping through that is a wild guess. I would take time to learn how to debug in Visual Studio, as it will help you easily spot what cannot be a problem so you can focus on what is likely to be the problem.

Question about inserting Users/Members into a database table!

My registration form has got a CreateUserWizard. I used its event that is fired after the user is created.
Then I obtain the users identity and key. In the last line, I send the unique key to a function inside a class that should insert the key into the Users table (the field is a primary key and is unique).
public partial class Registration : System.Web.UI.Page
{
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
MembershipUser CurrentUser = Membership.GetUser(User.Identity.Name);
int i =(int) CurrentUser.ProviderUserKey;
RegisterAdo.InsertUsers(i);
}
}
Below, I execute the query with the value that I passed and insert the user into a database
class RegisterAdo
{
public static void InsertUsers(int UsersIDentity)
{
string myConnectionString = WebConfigurationManager.ConnectionStrings["YourGuruDB"].ConnectionString;
SqlConnection sqlConnect = new SqlConnection(myConnectionString);
SqlCommand sqlCommand = new SqlCommand(RegisterAdo.insertCommand(UsersIDentity), sqlConnect);
try
{
sqlConnect.Open();
sqlCommand.ExecuteNonQuery();
}
catch (Exception x)
{
}
finally
{
sqlConnect.Close();
}
}
public static String insertCommand(int UsersIdentityToinsert)
{
string insertCommand="INSERT INTO Users(";
insertCommand += "UserID)";
insertCommand += "VALUES('";
insertCommand += UsersIdentityToinsert+"')";
return insertCommand;
}
My question is whether it is the best way to insert UserID into a table, and whether I do it right at all. I need the UserID to be unique, and the whole command executed with no fail...(just after the user was created and the whole UserCreateUser finished validating the user!!!
I would change two things mainly:
don't concatenate together your SQL statement - this opens doors to SQL injection attacks. Use parametrized queries instead - they are both safer, and they perform better (since only a single copy of the query's execution plan needs to be created and cached and will be reused over and over again)
put your SqlConnection and SqlCommand objects into using blocks so that they'll be automatically freed / disposed when the using blocks ends (and you can save yourself the finally block of the try...catch construct, too!).
So my code would look like this
public static void InsertUsers(int UsersIDentity)
{
string myConnectionString = WebConfigurationManager.ConnectionStrings["YourGuruDB"].ConnectionString;
string insertStmt =
"INSERT INTO dbo.Users(UserID) VALUES(#UserID)";
using(SqlConnection _con = new SqlConnection(myConnectionString))
using(SqlCommand _cmd = new SqlCommand(insertStmt, sqlConnect))
{
_cmd.Parameters.Add("#UserID", SqlDbType.Int).Value = UsersIDentity;
try
{
_con.Open();
_cmd.ExecuteNonQuery();
_con.Close();
}
catch (Exception x)
{
// do something if error occurs
}
}

How to close executereader in asp.net?

I am using more then one repeater on same page. But when I use Execute reader for 2nd repeater then it gives exception that there is already execute reader running.. so close it. I put ExecuteReader(CommandBehavior.CloseConnection) but it give error that command behaviour doesn't exists... Any idea about this issue?
You need to explicitly close the DataReader if you specify that CommandBehavior, it will not do it for you.
http://msdn.microsoft.com/en-us/library/y6wy5a0f.aspx
Personally I would bind UI controls to strongly typed objects. So for example I would define a Product model:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
then a method to read products from the database:
public static IEnumerable<Product> GetProducts()
{
using (var conn = new SqlConnection("Some connection string"))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT prod_id, prod_name FROM products";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return new Product
{
Id = reader.GetInt32(reader.GetOrdinal("prod_id")),
Name = reader.GetString(reader.GetOrdinal("prod_name")),
};
}
}
}
}
and in the web tier I would call this method to fetch my products and bind them to some UI controls:
protected void Page_Load(object sender, EventArgs e)
{
var products = Db.GetProducts().ToArray();
repeater1.DataSource = products;
repeater2.DataSource = products;
gridView.DataSource = products;
...
}
And when you get sick of writing those SQL queries you might take a look at an ORM, such as Entity Framework for example.

IsAuthenticated is false! weird behaviour + review question

This is the login function (after I validate user name and password, I load user data into "user" variable and call Login function:
public static void Login(IUser user)
{
HttpResponse Response = HttpContext.Current.Response;
HttpRequest Request = HttpContext.Current.Request;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
user.UserId.ToString(), DateTime.Now, DateTime.Now.AddHours(12), false,
UserResolver.Serialize(user));
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(ticket));
cookie.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(cookie);
string redirectUrl = user.HomePage;
Response.Redirect(redirectUrl, true);
}
UserResolver is the following class:
public class UserResolver
{
public static IUser Current
{
get
{
IUser user = null;
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
user = Desrialize(ticket.UserData);
}
return user;
}
}
public static string Serialize(IUser user)
{
StringBuilder data = new StringBuilder();
StringWriter w = new StringWriter(data);
string type = user.GetType().ToString();
//w.Write(type.Length);
w.WriteLine(user.GetType().ToString());
StringBuilder userData = new StringBuilder();
XmlSerializer serializer = new XmlSerializer(user.GetType());
serializer.Serialize(new StringWriter(userData), user);
w.Write(userData.ToString());
w.Close();
return data.ToString();
}
public static IUser Desrialize(string data)
{
StringReader r = new StringReader(data);
string typeStr = r.ReadLine();
Type type=Type.GetType(typeStr);
string userData = r.ReadToEnd();
XmlSerializer serializer = new XmlSerializer(type);
return (IUser)serializer.Deserialize(new StringReader(userData));
}
}
And the global.asax implements the following:
void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
IPrincipal p = HttpContext.Current.User;
if (p.Identity.IsAuthenticated)
{
IUser user = UserResolver.Current;
Role[] roles = user.GetUserRoles();
HttpContext.Current.User = Thread.CurrentPrincipal =
new GenericPrincipal(p.Identity, Role.ToString(roles));
}
}
First question:
Am I do it right?
Second question - weird thing!
The user variable I pass to Login has 4 members: UserName, Password, Name, Id.
When UserResolver.Current executed, I got the user instance.
I descided to change the user structure - I add an array of Warehouse object.
Since that time, when UserResolver.Current executed (after Login), HttpContext.Current.User.Identity.IsAuthenticated was false and I couldn't get the user data.
When I removed the Warehouse[] from user structure, it starts to be ok again and HttpContext.Current.User.Identity.IsAuthenticated become true after I Login.
What is the reason to this weird behaviour?
First, you don't need to do an HttpContext.Current from Global.asax. Global.asax derives from HttpApplication. So all you need to do is to get the Context property. This might help make that code a little cleaner.
//this is all you need in your global.asax
void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if(Context.User.Identity.IsAuthenticated)
{
var user = UserResolver.Current;
Context.User = Thread.CurrentPrincipal = new UserWrapperPrincipal(user, Context.User.Identity);
}
}
//this helper class separates the complexity
public class UserWrapperPrincipal: IPrincipal, IUser
{
private readonly IUser _user;
private readonly IIdentity _identity;
public UserWrapperPrincipal(IUser user, IIdentity identity)
{
_user = user;
_identity = identity;
}
private IList<string> RoleNames
{
get { return _user.GetUserRoles().Select(role => role.ToString()); }
}
public IIdentity Identity { get { return _identity; } }
public bool IsInRole(string role) { return RoleNames.Contains(role); }
}
Based on your error, it seems like the issue is that either your serializing function or your deserializing function corrupts the data. However, the problem area is probably not those functions. Either there is an issue in serializing the Warehouse object (serializing complex types can sometimes be tricky), or in the serialization of the actual array. Since you are using the default .NET XmlSerializer, There is a good article on customizing and controlling the way different objects are handled available at http://www.diranieh.com/NETSerialization/XMLSerialization.htm .
On another note, are you sure that this is the best way for you to store this data in your application? Storing a user-id and name makes sense. When you start storing serialized arrays of complex objects in your cookie, it might indicate you are not approaching the problem correctly to begin with.
I am guessing that your code is in a log on event somewhere and your building a custom forms auth.
You also need to then build the User object from the cookie on every page request
public class AuthHttpModule : IHttpModule {
public virtual void Init(HttpApplication app) {
app.AuthenticateRequest += new EventHandler(app_AuthenticateRequest);
}
private void app_AuthenticateRequest(object source, EventArgs e) {
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null) {
HttpContext.Current.User = null;
} else {
cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]);
}
bool result = HttpContext.Current.Request.IsAuthenticated;
}
}
EDIT
Try adding this to your global
void Application_AuthenticateRequest(Object sender, EventArgs e)
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null) {
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]);
}
}

Resources