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.
Related
I'm new to web application in asp.net mvc 5. I'm curious about how static classes behaves in web application. I'd like to know how my program will behave.
Let's say I have CurrentUser static class which stores logged user id.
public static class CurrentUser{
public static int UserId {get; set;}
}
Which is set whenerever user is logging in.
My app is in external server.
So what will happen if:
User A log in -> userId is set to 1, then User B log in (they access to from differentlcoations) so user Id is set to 2. When User A would like to perform action which need to check his Id, will it be 1 or 2?
I checked one scenario where 2 differentpersons log in from one pc at the same time (different tabs) and I know that User Id will be 2 for both of them (when User B logged in as second to the app). How to resolve this?
I've already read: Static classes in web applications.
I know that my solution may be error prone because every one has access to that class but I don't know if static classes in web app aren't store per user (thread?)?
If you store current user in session storage it will be better than static class. Because there is one copy of static class and fields and for every user login the last login is kept.
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
what is the best way to save data in a state-machine-like application?
How the application works:
There are multiple states, like Loging, MainMenu, Registration, etc. There is a loop that working until the state reaches Exit.
while(currentState != States.Exit)
{
switch (currentState)
{
case Login:
// Do everything needed for the login, including showing the Login-Window.
LoginProcess();
break;
case MainMenu:
MainMenuProcess();
break;
// Etc...
}
}
The problem:
I want to save data in between these processes. For example I want to have a User Object after the login containing everything that has to do with the user. There are many variables I could have to save and they are not always initialized (i.e. the User can only exist after login).
How it's done until now:
Right now there are just "public" members that can be null if the respective process has not started. They are defined in the class of the State-Machine loop. This can get messy easily.
Expectations:
I would like to have a way to do this data-saving in a clean way. Maybe even extract it from the state-machine or something similar. Maybe there is a way to restrict processes to access members they should not change?
Thanks in advance.
You could persist it to a database, or serialize your model into a JSON object, this object could be saved, then loaded up later and deserialized into your domain model.
You can also consider sagas, there are frameworks that support the notion of this and might help solve the problem.
http://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
Instead having every possible field for each process in the state machine, I would create small POCO objects which are in charge of passing information to each step of the state machine.
For example:
public class LoginProcessInfo
{
private readonly string username;
private readonly string password;
public LoginProcessInfo(string username, string password)
{
this.username = username;
this.password = password;
}
}
Now, with each iteration of the state, pass the relevant arguments to the method. You could either create a new one each time, or pool the created object if you're simply re-using them:
while(currentState != States.Exit)
{
switch (currentState)
{
case Login:
LoginProcess(new LoginProcessInfo(username, password));
break;
case MainMenu:
MainMenuProcess();
break;
}
}
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.
Once authenticatated I use HttpContext.Current.User.Identity.Name; to ensure user is authorized to view a part of my site.
When I access certain parts of my site I need to get the User and get which context (organization they are logged into), url would be something like settings/supercompany/profile. where supercompany is the current context.
For each user I would need to check if they are admin in that company or a general user, if a general user then they cannot see certain things.
public class SettingsApi
{
private readonly string _userId;
private readonly string _contextId;
public SettingsApi(string userId, string contextId)
{
_userId = userId;
_contextId = contextId;
}
}
If I instantiate the class above from a controller (post or get), would caching somehow mess things up? Users role changed and I don't pick it up? Would something like the below work well?
var settings = new SettingsApi(HttpContext.Current.User.Identity.Name, currentContextId);
settings.IsAdmin();
Note: I would have used attributes to authorize but my requirements are I need to pick out the currentContext from the URL plus I need to use the class above elsewhere in my code.
Update
AuthorizeAttribute works well with caching, but the method used to authorize i.e.
protected override bool AuthorizeCore(HttpContextBase httpContext)
Will not hand me back an instance of the class I need...
Update 2 I don't want this class or an instance of this class to be cached in anyway, everytime I ask for a new instance I don't mind fetching one from the DB...
My Question - is the way I am coding ok? Will my user and his permissions NOT be cached?
It is possible, if you're not careful, to let MVC cache the output of the first request by an authenticated user. I use VaryByCustom and the current identity's name.
[OutputCache(VaryByCustom="user")]
public class SomeController : Controller
{
// etc.
}
In my Global.asax.cs I define:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (custom.Equals("user", StringComparison.OrdinalIgnoreCase))
{
return context.User.Identity.IsAuthenticated ? context.User.Identity.Name : string.Empty;
}
return base.GetVaryByCustomString(context, custom);
}
If you are proposing to add instances of the SettingsApi to the cache then it definitely will not work as caching is app wide and so all users will end up sharing the same SettingsApi. Using the OutputCache should be fine (as long as you dont do something like put userid in a hidden field and use [OutputCache(VaryByCustom="user")] or similar).
If you are looking to cache the SettingsApi you should do so through SessionState which is per user/session and wont affect the authentication.