How can I add user's name in WPF? - c#

I'm creating a UI App on C# using .NET Core .
I have to register users and let them login. So, the question is: how may I welcome logged user? I want the following: "Welcome back, {UserName}".
I create new window with input of class User object, so I know where to get his/her name, but I'm not sure how to program adding the name in .xaml.
Would be grateful for any possible help!

From your description, you may created a wpf Application(net core 3.0)?
When you logged from the log form. You can show the "Welcome back, {UserName}" in the main form. Like the following simple code.
We can define a User object property in App class.
public partial class App : Application
{
public static Users usersd { get; set; }
}
And assign the User object when logging. Then, in the Main Windows/others form, you can show the user information:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (App.usersd != null)
{
label.Content = "Welcome back, {" + App.usersd.Name + "}";
}
}

In order to welcome users back, you need to store the user data in a database or in a file(.txt,.json,..). One way to do this is storing the user data as JSON when they first open the program. link
Then, you can check if the user has already logged in before. (perhaps use a userID property in User class)
Don't forget you need to add a NuGet package called Newtonsoft.Json in order to serialize and deserialize the data. Install NuGet package

Related

How to define implementation of event to viewmodel?

I want to centralized all bussiness logic into viewmodel. but i have problem with implemetation event. so i think i create delegate in code behind for reference. and the implementation in view model by pass view object to view model. how to do this?
<UserControl x:Class="Project.Views.IndexView">
<PasswordBox PasswordChanged="PasswordChangedHandler"/>
</UserControl>
C#
public partial class IndexView
{
public IndexView()
{
InitializeComponent();
DataContext = new IndexViewModel(this);
}
private delegate void PasswordChangedHandler(object sender, RoutedEventArgs args);
}
public class IndexViewModel
{
public IndexViewModel(UserControl view)
{
view.PasswordChangedHandler = this.PasswordChangedHandler;
}
public string Password { get; set; }
private void PasswordChangedHandler(object sender, RoutedEventArgs args)
{
var passwordBox = (PasswordBox)sender;
Password = passwordBox.Password;
}
}
If you want to stay out of code behind you are going to have to look into implementing EventToCommand: Support in Framework, and Core as long as you reference Windows.Interactivity.WPF Nuget
Bind command to Loaded event of view
MVVM Light: Adding EventToCommand in XAML without Blend, easier way or snippet?
https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/may/mvvm-commands-relaycommands-and-eventtocommand
"I want to centralized all bussiness logic into viewmodel." - Business logic belongs to the Model (but I guess you know this).
"by pass view object to view model. how to do this?" - You should never pass an object of the View to the View Model.
If your real problem is "How to pass the password to the view model", then you should know that you need to pass it explicitly. This is how the control is designed to be used.
The reason for this is, that the password is a very critical information. Passing the password around the application always introduces a privacy or security issue. Strings are stored in the memory as their simple byte representation/plaintext. The memory is public. This means, everybody can read a string from the memory. That's why the PasswordBox exposes the password as SecureString.
The general recommendation is to avoid this classic authentication system where the user enters a plaintext password.
The recommendation is to use existing authentication flows.
For example, you can use Windows authentication. By storing application data in the user domain, you can be sure that only the user that is currently logged in is using your application: Windows authentication ensures that a user of a instance-per-user desktop application is properly authenticated.
Alternatively, use OAuth authentication.
Modern web applications ask the user to login with their Google or Facebook account etc. Those authentication flows are very secure. The password handling is completely external as it is delegated to a 3rd party service (on behalf of the user that must have a related account). This service will maintain the implemented authentication procedure to keep it secure up to the latest security standards.
Although I highly recommend against implementing a custom authentication flow, the following example is meant to show you how PasswordBox is intended to be used:
MainWindow.xaml
<Window>
<PasswordBox PasswordChanged="OnPasswordChanged" />
<Window>
MainWindow.xaml.cs
partial class MainWindow : Window
{
private ViewModel { get; set; }
public MainWindow()
{
InitializeComponent();
this.ViewModel = new ViewModel();
this.DataContext = this.ViewModel;
}
private void OnPasswordChanged(object sender, RoutedEventArgs args)
{
var passwordBox = sender as PasswordBox;
this.ViewModel.HandlePassword(passwordBoc.SecurePassword);
}
}
The general practice is to ensure that the desktop application is installed as instance-per-user (so that we can rely on the OS authentication system) or to use a OAuth service. OAuth is very popular for web applications where an URL can be visited from any system (which declares local OS level authentication as meaningless).

Proper way to use a database class

I've been searching for this for a little while now and cannot seem to find a way to accomplish my goal.
First, what I'm currently trying to code is a ticketing app for our IT department to use, mostly to help us keep track of what has and hasn't been done to different machines and some people that may need further training in the software that is used on site. I have a few tables created to keep tracking of work performed, issues, and any relevant notes. The final product will be more than a ticketing system, but a somewhat comprehensive IT support app.
My goal in the use is to have the tech "sign in" to the app by providing his/her username and password to our database system. From there the tech's permissions will be loaded as to what a tech can and can't do with tickets. When the tech would like to view tickets or edit tickets I want the app to load any relevant tickets (i.e. open tickets, closed tickets, PC tickets, printer tickets,...etc.).
I have a ticket class that contains all of the properties that are stored within the database, but my question is how to properly link the first sign on information to the ticket class.
For example in my class I have something like:
public class ticket
{
public int TicketNumber {get;set;}
public string Tech {get;set;}
public string Category {get;set;}
public string ReportedBy {get;set;}
public void Save()
{
//Code to update record in DB
}
public void Create()
{
//Code to add a new record to DB
}
}
So, how do I properly get the class to where I can add the proper user name and password to this to include the tech's user name and password? I've had similar projects working before, but I have pretty much always used another person's user name and password hard coded. For this I would not want someone else using the application to be changing any of the ticket information if their user name and password was not valid for these tables.
Sorry for being wordy, but wanted to provide a basic look at what the app is in case someone has a better idea. I am open to suggestions especially on proper ways to pass the sign on information from app to class then data back to app.
The database is an iSeries. We use the IBM iSeries 32-bit ODBC driver to connect from Windows, if this helps. Most of the coding will be done in C# using Visual Studio 2013.
Thank you for any help.
Create a separate class to hold to user:
public class TechUser
{
public string UserName {get; private set;}
public string Password{get; private set;}
public TechUser(string userName, string password)
{
UserName = userName;
Password = password;
}
}
Then pass it in to the create function:
TechUser user = new TechUser("name", "pw");
ticket t = new ticket();
t.Create(user)

Asp.net HttpContext.Current.Items returning null

I am testing to build a asp.net web application.
What I have is 3 web pages:
Default.aspx;
Home.aspx;
ThirdPage.aspx;
When user submits login data to Default.aspx, I retrieve user information from db, put it in a class and add it to Context like this
HttpContext.Current.Items.Add("UserData", userData);
Then I use Server.Transfer to send the request to Home.aspx.
On Home.aspx, I have a link which points to ThirdPage.aspx. I click on this link and hoped that user information would be available here as well but it is not. Where as I was hoping to retain the userdata class across the user session across all pages in my web application until users session is expired .
Can some one please guide?
It is possibly a beginner question so please be kind.
Thanks
Check ASP.NET Session State Overview
Usage:
Session["UserData"] = userData;
I am unsure what the exact problem may be but I have some solutions that might work. If I am not mistaken you are trying to get user information over a couple of pages?
Here are some ways to get that done:
Repeat the code you did on the first page that transfers the data to
the second page and adapt it so it will work from the second to the
third. This might work but I won't recommend because having to reuse
and adapt the code each time you create a new page.
The better one I think is to write your information to an XML file and deleting the file when the session expires.
You can find how to write it here and reading it here.
But my personal favorite is to have a static Class. Static classes can be acces from anywhere. As shown on the page here.
public static class Globals
{
public static String name;
public static int age;
public void SetName(){...}
public void SetAge(){...}
public String GetName(){...}
public int GetName(){...}
}
Just make it a mutable class (You can change the variables using functions) and it should be easy to get the user information across pages.
Using JSON to save and load here are c# functions:
public void SaveInfo(User user){
//Convert to Json
string json = JsonConvert.SerializeObject(user, Formatting.Indented);
//Write to file, you will have to create a file serverside if you want
//if you have a
File.WriteAllText(#"location.json", json);
}
public void LoadUser(){
using (StreamReader r = new StreamReader("Location.json"))
{
string json = r.ReadToEnd();
List items = JsonConvert.DeserializeObject>(json);
}

Access to session variables from IHttpModule's OnBeginRequest method

I have a website that, in order to work properly, needs to have a XML file appended to all its URLs, let's say the file is called module-1.xml.
In order to keep those URls clean, I wrote a IHttpModule's that uses the HttpContext.Current.RewritePath to do the appending job inside the OnBeginRequest event.
The IHttpModule looks pretty simple and works:
public void OnBeginRequest(Object s, EventArgs e)
{
string url = HttpContext.Current.Request.Url.AbsolutePath;
if (url.EndsWith(".aspx"))
HttpContext.Current.RewritePath(url + "?module-1.xml");
}
Now, I wanted to use the session variable to detect when a user decides to switch the website from model-1.xml to model-2.xml and have my code changed as follow:
public void OnBeginRequest(Object s, EventArgs e)
{
string url = HttpContext.Current.Request.Url.AbsolutePath;
if (url.EndsWith(".aspx"))
{
if (HttpContext.Current.Session["CurrentMode"] == "1")
HttpContext.Current.RewritePath(url + "?module-1.xml");
else if(HttpContext.Current.Session["CurrentMode"] == "2")
HttpContext.Current.RewritePath(url + "?module-2.xml");
}
}
From what I have found, the session can be accessed inside a module but
not from inside the OnBeginRequest event which is the only event where HttpContext.Current.RewritePath can be made functional (at least from all the testing I have been doing).
Is my assumption correct? And if it is, what alternative could I use? Create a custom Session variable? Should I read from a txt file or from a DB in order to know what module the user is looking at? How could I keep track of a user from within the module?
It depends on the security required by your application. If you don't care about a malicious user being able to change the value, just store the module name in a cookie. If you do, you could store a securely generated identifier in a cookie, and look that up in a database to get the value you need to use.
Get rid of the module completely. You are only attaching it to aspx pages, so there is no need for that to be in the URL. Instead just create a base page for your project pages to inherit from:
public class Solution.Web.UI.Page : System.Web.UI.Page
{
public string CurrentMode
{
get { return String.Compare(Session["CurrentMod"].ToString(), "1") == 0) ? "module-1.xml" : "module-2.xml"; }
}
}
That way you can simply access it on your pages without the overhead of that module or the risk of putting that info in a cookie.

Simple question regarding reference variables and passing of variables in C#

I am creating a WindowForm application and right now i have a small problem. I have a register form which will ask user for username, mobile number and password. Upon registering the the information will be written to a text file. And the user will be shown a login form once the user login successfully i will create a user object from a user entity class and pass it to my main form and display the main form hiding the login form. After certain period of inactivity the main form will be hidden and the login form will be shown to the user.
public class User
{
private string userName;
private string mobileNumber;
public User(string uName, string mnumber)
{
userName = uName;
mobileNumber = mnumber;
}
public string MobileNumber
{
get
{
return mobileNumber;
}
set
{
mobileNumber = value;
}
}
public string UserName
{
get
{
return userName;
}
set
{
userName = value;
}
}
}
public partial class Login : Form
{
//Other codes
//Upon successful login
User user = new user(username,mobilenumber);
//Hide the Login Form
this.Hide();
//Display the main Form
MainForm main = new MainForm(ref user, this);
main.Show();
}
public partial class MainForm : Form
{
private User user;
private Login login;
Public MainForm(ref User user, Login login)
{
this.user = user;
this.login = login;
}
}
The form will toggle often login -> MainForm -> login. Here is my question. , when i pass over the user object as reference variable to MainForm as shown above any change made to the user object in the MainForm class will be reflected as well in the login class but the user object in the MainForm will not have the latest value and it will be the value when the mainForm object is first created. Why is that so why is the changes made in MainForm being reflected in the login form but not in the MainForm class ? Thanks in advance for any help provided. Cheers.
You can't do this. There is no such thing as a reference field or reference variable. Just have an event that fires when the user changes, or let calling code poll for a change in the form's user variable. There's no other way to do it.
Using the ref keyword makes no difference here. If it is the same object any changes to it will be reflected everywhere.
First of all, you're User object is not a ValueType therefore the ref modifier is not necessary in this particular case. You would only need to do this when you are using Pass By Value semantics, were User defined as a struct.
Second, I'm not sure you are handling you'r problem the right way. You should think about refactoring your code to work similar to:
Application starts with MainForm:
Uppon Form Load (this happens the first time the Main Form is about to render) create User Login and show it as a dialog (you will want to do this in a seperate method so that you can reuse it in step 4). Make an option available on this Login Form to Register a new user.
Upon succesful login, store the User only in Main Form and close the Log In form (do not hide it, Close and Dispose and just create a new one when you need it). Any subsequent edits to the User should map to this variable.
If inactivity period expires (via an event handler), cancel the current user and show the User login again and redo step 2.
Hope this helps and you get the general idea.

Categories