Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
How to save history of user last login and display right after user login in login screen.
I have shared the code in which I have implemented for the user session login. I am checking for any help with explanation will be appreciated.
User Login and Validation Code:
public ActionResult Login(LoginViewModel login)
{
if (ModelState.IsValid)
{
if (new UserEntity().isValidUser(login.EmailId, login.Password))
{
Session["login"] = login;
//Redirect to Employee Controller after Validation
return RedirectToAction("Index", "Employee");
}
else
{
ViewBag.InvalidUser = "Invalid User Name or
Password";
return View(login);
}
}
return View(login);
}
public Boolean isValidUser(string emailId, string password)
{
Boolean isValid = false;
try
{
sqlConnection = new SqlConnection(ConnectionString);
string query = #"Select * from UserProfile
where EmailID='" + emailId + "' and
Password = '"+password+"'";
cmd = new SqlCommand(query, sqlConnection);
sqlConnection.Open();
SqlDataReader dataReader = cmd.ExecuteReader();
if (dataReader.Read())
{
isValid = true;
}
}
catch (Exception exp)
{
//exception logging
}
return isValid;
}
This is just an attempt to try and (hopefully) guide you further in the right direction. I am not sure that there is a built-in feature that holds this information, so we may need to store the data manually. Maybe it could be something like this:
public ActionResult Login(LoginViewModel login)
{
if (ModelState.IsValid)
{
SaveLoginTimeToDatabase(); //here, we call a method that we define ourselves
... //rest of your original code
}
return View(login);
}
public void SaveLoginTimeToDatabase()
{
DateTime loginTime = new DateTime().Now;
sqlConnection = new SqlConnection(ConnectionString);
string query = #"Insert* into UserLoginTimeTable
VALUES (User.Email, loginTime)";
//So, we need to create a new database table, UserLoginTimeTable, for this info
//... Rest of code: open SQL connection, execute etc.
}
However, we also need to display the login time when user logs in, so we need a method for that. To do that, we probably a field on your Razor login-page, where that information can be displayed.
Then, in the login method, we call a new method to fetch that data
public ActionResult Login(LoginViewModel login)
{
if (ModelState.IsValid)
{
var lastLogin = FetchLastLoginTime(login.EmailId); //new method for retrieving the data
// you need to call it before SaveLoginTime...(), so that you dont get the current login, that will be saved in the next line
SaveLoginTimeToDatabase();
//you may need to include lastLogin in your loginViewModel:
login.LastLogin = lastLogin;
... //rest of your original code
}
return View(login);
}
public DateTime FetchLastLoginTime(string emailId)
{
sqlConnection = new SqlConnection(ConnectionString);
string query = #"Select TOP 1 from UserLoginTimeTable
Where EmailID = ' emailId"
//Open sql connection, execute etc
//Now, you should have access to the last time that user logged in. Return it to the original method and display it
var lastLogin = //get the logintime from the query
return lastLogin;
}
This is not a definitive answer and may have incorrect syntax, but just an overall attempt to show how you maybe can go about it. You don't need to accept it as answer, it's just a suggestion that you hopefully can make work. Since you would need multiple queries to the database like this, you may need to implement some asynchronous behaviour with await/async, unit of work/transactions or similar, but hopefully it just works.
So to sum up, with this approach you need a new database table, queries and additional logic. You are always welcome to tag me/write if you have more questions, you think I can help with (hopefully you can use some of this), best of luck
Related
I want to save the story without ajax request,just with mvc logic.It keeps giving me error that the page Save/storyId is not found.Any help wiil be good.
I dont want to use api controllers,i want to take the stories id,take the data of that story and create a favstory object,inside the sql database.
Thats my Service Save method logic:
public int Save(int id,string title,string topic,string genredid,string psedonym,string favcon, string userId)
{
var story = this.data.Stories.Where(x => x.Id == id).FirstOrDefault();
var favbook = new FavouriteBook
{
FavTitle = story.Title,
FavTopic = story.Topic,
FavGenreId = story.GenreId,
FavUserAuthor = story.Pseudonym,
FavCon = story.StoryText
};
this.data.FavouriteBooks.Add(favbook);
this.data.SaveChanges();
return favbook.Id;
}
Thats the Controller Save method logic:
[HttpPost]
public IActionResult Send(int id,AddFavouriteModel postm)
{
var userId = this.User.FindFirst(ClaimTypes.NameIdentifier).Value;
this.favouris.Save(
id,
postm.FavTitle,
postm.FavTopic,
postm.FavGenre.Name,
postm.FavUserAuthor,
postm.FavCon,
userId
);
return RedirectToAction(nameof(Index));
}
Thats the link to the Save method,from which i try to get the stories id,
<a smooth="true" asp-controller="Favourites" asp-action="Save" asp-route-id="#sto.Id" class="btnfav"></a>
I don't know if its right,but i have never implented favourites logic with c#.
after looking through many articles and not finding a clear answer, I would like to start one more time a topic about adding Health Checks to the swagger in ASP .Net Core.
Firstly, I would like to ask you if it is good idea to do that and how to do it in the easiest way.
Thanks in advance for all answers.
First question, Why do we need Health Check?
When we create Health Checks, we can create very granular, specific checks for certain services, which helps us greatly when diagnosing issues with our application infrastructure, as we can easily see which service/dependency is performing poorly. Our application may still be up and running, but in a degraded state that we can’t easily see by simply using the application, so having Health Checks in place give us a better understanding of what a healthy state of our application looks like.
Instead of relying on our users reporting an issue with the application, we can monitor our application health constantly and be proactive in understanding where our application isn’t functioning correctly and make adjustments as needed.
Here is simple demo about database Health check
First, Write a controller and Inject HealthCheckService in it.
[Route("[controller]")]
[ApiController]
[AllowAnonymous]
public class HealthController : ControllerBase
{
private readonly HealthCheckService healthCheckService;
public HealthController(HealthCheckService healthCheckService)
{
this.healthCheckService = healthCheckService;
}
[HttpGet]
public async Task<ActionResult> Get()
{
HealthReport report = await this.healthCheckService.CheckHealthAsync();
var result = new
{
status = report.Status.ToString(),
errors = report.Entries.Select(e => new { name = e.Key, status = e.Value.Status.ToString(), description = e.Value.Description.ToString() })
};
return report.Status == HealthStatus.Healthy ? this.Ok(result) : this.StatusCode((int)HttpStatusCode.ServiceUnavailable, result);
}
}
Then, In Program.cs(.Net 6), Configure the health check to test whether the query function of the database is normal
//.....
string connectionString = builder.Configuration.GetConnectionString("default");
builder.Services.AddHealthChecks().AddCheck("sql", () =>
{
string sqlHealthCheckDescription = "Tests that we can connect and select from the database.";
string sqlHealthCheckUnHealthDescription = "There is something wrong in database.";
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
//You can specify the table to test or test other function in database
SqlCommand command = new SqlCommand("SELECT TOP(1) id from dbo.students", connection);
command.ExecuteNonQuery();
}
catch (Exception ex)
{
//Log.Error(ex, "Exception in sql health check");
return HealthCheckResult.Unhealthy(sqlHealthCheckUnHealthDescription );
}
}
return HealthCheckResult.Healthy(sqlHealthCheckDescription);
});
//......
Result:
Swagger will expose this health check endpoint
When the query function works fine in database,It will return 200
When there is something wrong in database, It will return 503
I am working on a side project(student, not homework, just holiday curiosity), which would be my simple personal password manager/vault. It will be a windows app. I want it to support more than just one user. Now that i have my login screen and other functionalities, i struggle to find a simple and effective way to check if login and password of the user are correct. I store the information in a simple SQL table called Users(picture below). Now, i want to get the bool result, whether are these two strings (username,password) in database. i will include some code and screenshots below. Any help appreciated!
P.S.: I am pretty familiar with mySQL(Oracle), i just can´t fin a good way to do this without being ridiculous. :)
namespace KeyLocker.Database {
[Serializable]
public class UserDatabase {
public void AddUser(string username,string password,string question,string answer) {
using(var db = new KeyLockerContext()) {
db.Add(new User { Username = username,Password = password,SecurityQuestion = question,SecurityAnswer = answer });
db.SaveChanges();
}
}
public bool CheckUser(string username,string password) {
using(var db = new KeyLockerContext()) {
/*here i need to find out if username is present in database
and if it is, i need to find out if the password is correct*/
}
}
}
}
Table Users ScreenShot
Table SQL detail
At first glance, it seems like the easiest code to execute your idea would be:
public bool CheckUser(string username,string password) {
using(var db = new KeyLockerContext()) {
// Check if that combination already exists in DB.
var result = db.Users.Where(x => x.Username == username && x.Password == password).SingleOrDefault();
// See if result has a value, SingleOrDefault() returns null if no match
return (result == null);
}
}
EDIT/Disclaimer: Since there seems to be some confusion, this is an idea for how to quickly check if an object w/ certain values already exists in the DB - not a complete authentication library. You should never store cleartext passwords.
I created a view to display data from the database
public ActionResult UpdateDetail()
{
using (UsersDatabaseEntities ude = new UsersDatabaseEntities())
{
ude.Configuration.ValidateOnSaveEnabled = false;
return View(ude.Users.Where(a => a.Email == User.Identity.Name).FirstOrDefault());
}
}
Then, I tried to edit and save to database
[HttpPost]
public ActionResult UpdateDetail([Bind(Exclude = "IsEmailVerified,ActivationCode")] User user)
{
if (ModelState.IsValid)
{
using (UsersDatabaseEntities ude = new UsersDatabaseEntities())
{
ude.Entry(user).State = EntityState.Modified;
ude.SaveChanges();
}
}
return View(user);
}
The problem is, it seems to not be saved to the database. i tried to call UpdateDetail again, and it shows the data do not saved.
I do not find syntax error.
does the data truly saved?
Add the debugger inside your UpdateDetail action and also write the if(ModelState.IsValid){ //..logic goes there } else{ return View();} check the modelstate don't have any error then try to update User and seem like it's happen when we have some non-nullable field and passing to the null values into them.
im stuck with this and im really going to bang my head against a wall in a minutes
I have a logging page where the user enters there username and password and clicks login when they have pressed this a function is called to get all the user details i.e firstname surname Email AccountType Examtaken etc within the function im trying to set "Get; Set;" Properties so i can use them on the home page, but for some stupid reason un-known to me its not working! below you will see the method that is called when the user clicks login
public class ExamMethods
{
public int UserID { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public int AccountType { get; set; }
public bool ExamTaken { get; set; }
private enum Datafield
{
UserID,
FirstName,
Surname,
Email,
AccountType,
ExamTaken,
}
public Hashtable CheckLogin(Hashtable Usercredentials)
{
try
{
SqlConnection Connection = new SQLAccess().CreateConnection();
SqlCommand Command = new SqlCommand("GetUserDetails", Connection);
Command.CommandType = System.Data.CommandType.StoredProcedure;
foreach (DictionaryEntry SpParameter in Usercredentials)
{
Command.Parameters.Add(new SqlParameter(SpParameter.Key.ToString(), SpParameter.Value.ToString()));
}
SqlDataReader da = Command.ExecuteReader();
while (da.Read())
{
Details.Add("UserID", da["UserID"]);
UserID = (da.IsDBNull((int)Datafield.UserID)) ? 0 : da.GetInt32((int)Datafield.UserID);
Details.Add("FirstName", da["FirstName"]);
FirstName = (da.IsDBNull((int)Datafield.FirstName)) ? "" : da.GetString((int)Datafield.FirstName);
Details.Add("Surname", da["Surname"]);
Surname = (da.IsDBNull((int)Datafield.Surname)) ? "" : da.GetString((int)Datafield.Surname);
//Details.Add("AccountType", da["AccountType"]);
//AccountType = (da.IsDBNull((int)Datafield.AccountType)) ? 0 : da.GetInt32((int)Datafield.AccountType);
//Details.Add("ExamTaken", da["ExamTaken"]);
//ExamTaken = (da.IsDBNull((int)Datafield.ExamTaken)) ? false : da.GetBoolean((int)Datafield.ExamTaken);
}
Connection.Close();
da.Close();
return Details;
}
catch
{
Console.WriteLine("Error Checking Login Details");
return Details;
}
}
}
as you can see from the above in the while(da.read) im assigning the values to a hashtable and the get set methods when debuggin i can see values going in! and im 100% this values arent null or empty
the code then reverts back to the login page with it results if all is fine then response.redirect to the home page where the user can take the exam, but in the page load of the home.aspx i have a label which i want to popualte with the users name so i reference the get propertie on the ExamMethods class but its null? how can this be possible? what am i missing?
This is the code for the behind home.aspx page
public partial class Home : System.Web.UI.Page
{
Hashtable UpdateUser = new Hashtable();
protected void Page_Load(object sender, EventArgs e)
{
Methods.ExamMethods obj_UserDetails = new Methods.ExamMethods();
if (Request.QueryString["uid"] == null)
{
Response.Redirect("Login.aspx");
}
else
lblUserName.Text = obj_UserDetails.FirstName;
}
Is it because I have used reponse.redirect from the login page to the home page that the get set methods are nothing?
Variables aren't shared among web pages when you are working with web pages. As you might know HTTP is a stateless protocol.
So how do I do this?
You need state management. You need a way to pass the information around. From what I see, Sessions seems to be best place to store this data that you require to use in multiple pages.
But sessions are not the only state management option you have. You have many more depending on what you want to store, how much you want to store and where/when you want to access them.
I suggest you read up on ASP .NET State Management also read up on recommendations to understand which state management feature to use in which scenario.
In Page_Load method you're creating a new instance of Methods.ExamMethods() each time so all of its properites are not initialized. After you are redirected to login page, perform login and are redirected back, Page_Load is executed again and a new instance of the class is created.
The preffered way of doing it would be just reading user's data from database based on uid when you have it defined in theQueryString.
protected void Page_Load(object sender, EventArgs e)
{
Methods.ExamMethods obj_UserDetails = new Methods.ExamMethods();
if (Request.QueryString["uid"] == null)
{
Response.Redirect("Login.aspx");
}
else
{
if (!Page.IsPostback)
{
//read value of uid parameter
int uid = Request.QueryString["uid"];
//access database to retrieve user's details
obj_UserDetails = GetUserDetails(uid);
lblUserName.Text = obj_UserDetails.FirstName;
}
}
}
It's also worth monetioning that you can use Page.IsPostback attribute to fill controls with user's data. On postbacks ViewState mechanism should preserve controls' contents.
There are also some other mechanisms that allow you to pass data between pages, like Session state. This can be used if you need user details on more pages than just those two. This way you don't have to access the database to often.
Using Server.Transer() method to redirect user to another page and using PreviousPage object can give you access to other page as well, but I suppose using QueryString and reading data directly on Home page would be the most appropriate in your case.
Links that can be helpful:
ASP.NET Session State Overview
Understanding ASP.NET View State
HttpServerUtility.Transfer method
Instances don't stay alive when you browse through pages on the web, you can store things you need in a session and get it when the new page loads
you can do this when you need to store the data
Session["data"] = new Data("SomeData");
and you can do this when you need the data again
var data = Session["data"] as Data;
if(data != null)
//do something with the data