How to pass values to DataAccess Layer for storing into database in asp.net MVC5 API? - api

In my API application, I field values coming from registration view which I want to store into the database. On AccountController.cs, I have collected these values using the following code.
[Route("Register")]
public async Task<object> Register(UserDetails data)
{
var userRegister = new IdentityUser
{
FirstName = data.FirstName,
LastName = data.LastName,
UserName = data.Email,
Email = data.Email,
PhoneNumber = data.PhoneNumber,
PasswordHash = data.Password
};
UserManager<IdentityUser> _manager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(new TachusApi.DBContext.AuthDbContext()));
string pHash = _manager.PasswordHasher.HashPassword(data.Password);
DBAccess dbaccess = new DBAccess();
dbaccess.SaveAdmin(userRegister, pHash);
return data;
}
What I want to do is to pass these values to the SaveAdmin method in DBAccess.cs for storing into the database. Here is my SaveAdmin method:
#region Save Admin User
public void SaveAdmin(string userRegister, string hash)
{
SqlConnection conn = null;
SqlCommand command = null;
int retValue;
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
conn.Open();
command = conn.CreateCommand();
command.CommandText = "RequestedServiceUserDataInsert";
command.CommandType = CommandType.StoredProcedure;
...
}
#endregion
I can't pass a valid format of the values to my SaveAdmin method where I can save them into the database. Is there anyone who may advise an effective way that can help me pass these values as an object for using them in my save method? Please advice

Since you define the userRegister object as an IdentityUser object
var userRegister = new IdentityUser
{
FirstName = data.FirstName,
LastName = data.LastName,
UserName = data.Email,
Email = data.Email,
PhoneNumber = data.PhoneNumber,
PasswordHash = data.Password
};
And then pass it to the SaveAdmin function of your dbaccess class
dbaccess.SaveAdmin(userRegister, pHash);
The SaveAdmin method needs to be set up to accept the userRegister of type IdentityUser. Right now it expects a plain string.
So, instead of having your SaveAdmin function declared as this:
public void SaveAdmin(string userRegister, string hash)
You need to have it declared like this:
public void SaveAdmin(IdentityUser userRegister, string hash)
That way the method gets the data it expects and you can access all properties of that object and insert them into SQL server.

Related

How can i check if the password i add to the textbox, is same as the password in database using mvc

I have a login form where all of the user's data are displayed when you click the login button. When the data are displayed in the form fields, I have an old password, new password and confirm password field, where the user can change his password. Now, when the user puts his old password, I want to check if it is the same password as the password stored in database.
This is how I get the data from database :
[HttpGet]
public ActionResult Edit(int? id, UpdateModel updatemodel)
{
id = 1;
SqlConnection cn = new SqlConnection("#")
SqlCommand cmd1 = new SqlCommand(
"Select Username , Password From BS_Users Where IDBS_Persons=" + id, cn);
cn.Open();
SqlDataReader dr = cmd.ExecuteReader();
SqlDataReader dr1 = cmd1.ExecuteReader();
if (dr1.Read())
{
updatemodel.Username = dr1["Username"].ToString();
updatemodel.Password = dr1["Password"].ToString();
}
else
{
dr.Close();
}
dr.Close();
cn.Close();
return View(updatemodel);
}
and this is how I post them :
[HttpPost]
public ActionResult Edit(UpdateModel p, FormCollection form, int? id)
{
id = 1;
SmartFinanceContext db = new SmartFinanceContext();
if (ModelState.IsValid)
{
int users = p.UpdateUser(p.Username, Crypto.Hash(p.Password), id = 1);
if (_records > 0 && users > 0)
{
db.SaveChanges();
return RedirectToAction("Edit", "Home");
}
{
ModelState.AddModelError("", "Can Not Update");
}
}
return View(p);
}
It would be something like this:
//Get from database, which would be an encrypted string
var pw = dr1["Password"].ToString();
//Encrypt password sent in by user
var pwCheck = Crypto.Hash(p.Password)
//Check encrypted password from database against encrypted passed-in password
if (pw == pwCheck){
//do something
}

How to convert SQL to LINQ?

Here is my IsValid user login code in MVC4 model.
I'm trying to have my SQL command convert to LINQ.
How can I convert it to LINQ way?
public bool IsValid(string _username, string _password)
{
using (var cn = new SqlConnection(#"Data Source=(LocalDB)\v11.0;AttachDbFilename" +
#"='C:\Tutorials\1 - Creating a custom user login form\Creating " +
#"a custom user login form\App_Data\Database1.mdf';Integrated Security=True"))
{
string _sql = #"SELECT [Username] FROM [dbo].[System_Users] " +
#"WHERE [Username] = #u AND [Password] = #p";
var cmd = new SqlCommand(_sql, cn);
cmd.Parameters
.Add(new SqlParameter("#u", SqlDbType.NVarChar))
.Value = _username;
cmd.Parameters
.Add(new SqlParameter("#p", SqlDbType.NVarChar))
.Value = Helpers.SHA1.Encode(_password);
cn.Open();
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Dispose();
cmd.Dispose();
return true;
}
else
{
reader.Dispose();
cmd.Dispose();
return false;
}
}
}
After you've LINQ or any ORM setup for your application, it can be converted to simple LINQ statement.
return _dbContext.Users.Any(c=>c.UserName == _username && c.Password == Helpers.SHA1.Encode(_password));
I would first look at using an Entity Data Model like the ones in Entity Framework (http://msdn.microsoft.com/en-gb/data/ef.aspx) to model your database objects in C# and add one to your project.
Then I would create a Stored Procedure in your DB to handle the execution of the SQL statement, passing in the parameters you want to test against.
Then, I would import the stored procedure into the Data Model and run a LINQ query against it.
Something along the lines of:
var valid = (from users in context.CheckUserMembership(userName: userName, password: password)
select new User
{
UserId = users.UserId,
UserName = users.Username
}).Count() > 0;
Where context is a reference to the Data Context generated by the Entity Data Model wizard and CheckUserMembership is the imported stored procedure containing your SQL statement.

Returning a specific value from a database ASP.NET/C#

My question involves returning a specific value from a table in a database. I want to have it where after you login, it displays the name of the user's first and last name.
The table looks like this.
Person
UID(PK), FName, LName, Uname, Upass
How do I return just the Fname and LName so I can place it in a label?
Here is my current code. Keep in mind this is for the master page.
string strConn = WebConfigurationManager.ConnectionStrings["cloud2"].ConnectionString;
protected void btnlogin2_Click(object sender, EventArgs e)
{
string strCmd = "Select * From Person Where uname = #uname and upass = #upass";
SqlConnection objConn = new SqlConnection(strConn);
SqlCommand objCmd = new SqlCommand(strCmd, objConn);
objCmd.Parameters.AddWithValue("#uname", txtusername.Text);
objCmd.Parameters.AddWithValue("#upass", txtpassword.Text);
using (objConn)
{
objConn.Open();
SqlDataReader objDR = objCmd.ExecuteReader();
if (objDR.HasRows)
{
btnlogin2.Visible = false;
txtusername.Visible = false;
txtpassword.Visible = false;
Response.Redirect("member.aspx");
lblLogin.Text = "Logged in as: Test " ; //Display login name?
}
else
{
btnlogin2.Text = "Failed";
}
}
}
First I'd refactor your logic a bit to maintain UI VS database calls a bit separate. Secondly refactor your code to retrieve first and last name that uses code for your connection string, username, password, and outputs firstname and lastname.
string firstName, lastName;
if(ValidateUser(txtusername.Text, txtpassword.Text, out firstName, out lastName)
{
//put your UI Logic and redirect in here
lblLogin.Text = "Welcome: " + firstName + " " + " lastName;
}
else
{
//login faild code
}
private bool ValidateUser(string strConn, string username, string password, out string firstName, out string lastName)
{
firstName = string.Empty;
lastName = string.Empty;
using (var con = new SqlConnection(strConn))
using (var cmd = con.CreateCommand())
{
cmd.CommandText = "Select * From Person Where uname=#uname and upass=#upass";
cmd.Parameters.AddWithValue("#uname", username);
cmd.Parameters.AddWithValue("#upass", password);
con.Open();
using (var r = cmd.ExecuteReader())
{
if (r.Read())
{
firstName = r["FName"].ToString();
lastName = r["LName"].ToString();
return true;
}
else
{
return false;
}
}
}
}
I would do three things:
separate your UI logic from the database logic - don't access your database directly in the middle of a button_Click event handler......
if you only need first and last name, then only select those two columns from the table!
put all the disposable objects like SqlConnection, SqlCommand, SqlDataReader into using(...) {...} blocks so that they will be properly disposed after use
So my code would look something like this:
UI layer:
protected void btnlogin2_Click(object sender, EventArgs e)
{
// call the database layer to get the first and last name
FirstAndLastName data = GetFirstAndLastName(txtusername.Text, txtpassword.Text);
if (data != null) // something was returned - show it
{
lblLogin.Text = string.Format("You're logged in as {0} {1}",
data.FirstName, data.LastName);
}
else
{
lblLogin.Text = "Not logged in....";
}
}
Database layer:
string strConn = WebConfigurationManager.ConnectionStrings["cloud2"].ConnectionString;
internal class FirstAndLastName
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
protected FirstAndLastName GetFirstAndLastName(string userName, string password)
{
FirstAndLastName result = null;
// if you only need FName und LName - then only select those two columns!
// don't just use SELECT * all the time because it's easy and because you're lazy
string strCmd = "SELECT FName, LName FROM dbo.Person WHERE uname = #uname AND upass = #upass";
// wrap everything into using blocks
using(SqlConnection objConn = new SqlConnection(strConn))
using(SqlCommand objCmd = new SqlCommand(strCmd, objConn))
{
objCmd.Parameters.AddWithValue("#uname", userName);
objCmd.Parameters.AddWithValue("#upass", password);
objConn.Open();
using(SqlDataReader objDR = objCmd.ExecuteReader())
{
if (objDR.Read())
{
result = new FirstAndLastName();
result.FirstName = objDR.GetString(objDR.GetOrdinal("FName"));
result.LastName = objDR.GetString(objDR.GetOrdinal("LName"));
}
}
}
return result;
}
string Name=objDR ["FName"].ToString() + ["LName"].ToString()
lblLogin.Text = "Logged in as:"+Name
You can read the instance of SqlDataReader in following way:
WebConfigurationManager.ConnectionStrings["cloud2"].ConnectionString; protected void btnlogin2_Click(object sender, EventArgs e) {
string strCmd = "Select * From Person Where uname=#uname and upass=#upass";
SqlConnection objConn = new SqlConnection(strConn);
SqlCommand objCmd = new SqlCommand(strCmd, objConn);
objCmd.Parameters.AddWithValue("#uname", txtusername.Text);
objCmd.Parameters.AddWithValue("#upass", txtpassword.Text);
using (objConn)
{
objConn.Open();
SqlDataReader objDR = objCmd.ExecuteReader();
if (objDR.Read())
{
string fName= (string)objDR["FName"];
string lName= (string)objDR["LName"];
btnlogin2.Visible = false;
txtusername.Visible = false;
txtpassword.Visible = false;
Response.Redirect("member.aspx");
lblLogin.Text = "Logged in as: Test "+fName+" "+lName; //Display login name?
}
else
{
btnlogin2.Text = "Failed";
}
}
}
Is your question how to return just the data you want from the query, or how to access it from the datareader?
It sounds like you might want ExecuteScalar(), and you can combine the fname and lastname fields in the query so you can just pull the one result:
string strCmd = "Select Fname + ' ' + LName From Person Where uname=#uname and upass=#upass";
SqlConnection objConn = new SqlConnection(strConn);
SqlCommand objCmd = new SqlCommand(strCmd, objConn);
objCmd.Parameters.AddWithValue("#uname", txtusername.Text);
objCmd.Parameters.AddWithValue("#upass", txtpassword.Text);
using (objConn)
{
objConn.Open();
var username = objConn.ExecuteScalar() as string;
if (!string.IsNullOrEmpty())
{
btnlogin2.Visible = false;
txtusername.Visible = false;
txtpassword.Visible = false;
Response.Redirect("member.aspx");
lblLogin.Text = "Logged in as: " + username ; //Display login name?
}
Edit: Just noticed a detail... you're setting lblLogin.Text after redirecting... so not thinking anyone's going to see it anyway. Could add it to the querystring though and display it on member.aspx...
You can do something like
lblLogin.Text = "Logged in as: " + objDR.GetString(dr.GetOrdinal("FName")) + " " + objDR.GetString(dr.GetOrdinal("LName"));
If memory serves, you probably also need to first call objDR.Read(); to start iterating over the datareader.

reporting service network credentials

receiving the error:
"Property or indexer
'Microsoft.Reporting.WebForms.IReportServerCredentials.NetworkCredentials'
cannot be assigned to-- it is read only"
within this line:
reportviewer1.ServerReport.ReportServerCredentials.NetworkCredentials
= new System.Net.NetworkCredential("someaccount",
"somepassword");
When I hover the cursor on NetworkCredentials, it says: "Gets or sets the network credentials that are used for authentication with report server"..
what the heck is going on here?
thanks
this.rpv.ServerReport.ReportServerCredentials is not read-only. Read this post:
http://www.visualstudiodev.com/visual-studio-report-controls/reportviewerserverreportreportservercredentialsnetworkcredentials-readonly-24629.shtml
it is still read only, that ReportServerCredentials field is still read only, it has only getter but not a setter !
add this class to the same namespace:
public class CustomReportCredentials : IReportServerCredentials
{
private string _UserName;
private string _PassWord;
private string _DomainName;
public CustomReportCredentials(string UserName, string PassWord, string DomainName)
{
_UserName = UserName;
_PassWord = PassWord;
_DomainName = DomainName;
}
public System.Security.Principal.WindowsIdentity ImpersonationUser
{
get { return null; }
}
public ICredentials NetworkCredentials
{
get { return new NetworkCredential(_UserName, _PassWord, _DomainName); }
}
public bool GetFormsCredentials(out Cookie authCookie, out string user,
out string password, out string authority)
{
authCookie = null;
user = password = authority = null;
return false;
}
}
Then set your credentials like this:
IReportServerCredentials Creds = new CustomReportCredentials("Administrator", "password", "domain"); //to actual values
myReportViewer.ServerReport.ReportServerCredentials = Creds;
in .NET core as well in .NET 5.0 replace "reportViewer.ServerReport.ReportServerCredentials" with "reportViewer.ServerReport.ReportServerCredentials.NetworkCredentials = new System.Net.NetworkCredential(Username,Password,Domain);"
also you Should install "Microsoft.Reporting.WinForms" NuGet

Rhino Mocks Assert Property Setter was called with correct object type

I have a method that sets a property
public void SetNetworkCredential(string userName, string password, string domain)
{
_reportExecutionService.Credentials = new NetworkCredential(userName, password, domain);
}
how do I verify that Credentials was called with a valid NetworkCredential?
I tried this TestMethod but it fails because the NetworkCredential objects are different references
[TestMethod]
public void TestTest()
{
const string userName = "userName";
const string password = "password";
const string domain = "domain";
var mock = MockRepository.GenerateMock<IReportExecutionService>();
var rptService= new ReportService(mock);
rptService.SetNetworkCredential(userName, password, domain);
mock.AssertWasCalled(x => x.Credentials = new System.Net.NetworkCredential(userName, password, domain));
}
Is there a way to validate that the setter was called with an object of type NetworkCredential and with the correct parameters?
I fixed it by making the ReportService accept a Network Credential instead of the username, password, domain
public void SetNetworkCredential(NetworkCredential networkCredential)
{
_reportExecutionService.Credentials = networkCredential;
}
so my test was much easier
[TestMethod]
public void TestTest()
{
const string userName = "userName";
const string password = "password";
const string domain = "domain";
var mock = MockRepository.GenerateMock<IReportExecutionService>();
var rptService= new ReportService(mock);
var networkCredential = new System.Net.NetworkCredential(userName, password, domain);
rptService.SetNetworkCredential(networkCredential);
mock.AssertWasCalled(x => x.Credentials = networkCredential);
}
Edit: Rethinking this problem, my previous suggested answer would probably not work. Here's why:
Essentially, you are attempting to verify that the dependency of a dependency has been set up correctly. That is probably why you are having problems writing a unit test for this. You probably want to consider whether it would make sense for you to move the SetNetworkCredential method into the class that implements IReportExecutionService instead.
And if you do, the unit test for that method would be simple enough:
[Test]
public void TestSetNetworkCredential()
{
const string userName = "userName";
const string password = "password";
const string domain = "domain";
var rptService= new ReportExecutionService();
rptService.SetNetworkCredential(userName, password, domain);
Assert.AreEqual(userName, rptService.Credentials.UserName);
Assert.AreEqual(password, rptService.Credentials.Password);
Assert.AreEqual(domain, rptService.Credentials.Domain);
}