Entity framework: string property is empty after calling SaveChanges - entity-framework

I got a mapped entity named User - with username and pass, the pk is the username.
When saving a new user, the username for some reason becomes an empty string.
Here is a code sample:
var newUser = new User() {Username = model.UserName, Password = hashedPassword};
_db.Users.AddObject(newUser);
_db.SaveChanges();
In debug view I see user name is not empty before save and after save it's empty. Whats wrong with me?

The dev server decided to ignore my reset, so I needed to reset it again and it's fine.

Related

CakePHP 3 how to edit user without changing password (hashed)

I have my UsersController with my edit.ctp view. When I browse /users/edit/1, I see password field filled with ***** (filled with hash in entity User.php, using DefaultPasswordHasher). My UsersTable.php has password has required.
So, I can try:
unset($user->password); // in edit() from UsersController.php
and setting [require => false] in edit.ctp
When I save, I get
The user could not be saved. Please, try again.
Because in my UsersTable.php I have:
$validator
->requirePresence('password', 'create')
->notEmpty('password');
If I try to leave blank from controller I get error, if I try to fill with actual password, it hashes again.
How could I edit any user without change his password? Can I set this from model or I need to make password as not required?
I don't need show the real password to admins
I validate from controller for password_confirm (already works)
In add.ctp there is no problem because default value is always blank
I want to change password only if password field is filled
I suppose password needs to be required in Model because all users need their passwords, that's why I'm trying to keep it far from validation in controller
Validation says "on create" but even in update is needed, bug possible?
My cake version is 3.4.4
Thanks in advance
Couple of things:
Firstly, if you haven't already, you may want to mark the password field as hidden to prevent it from exposing the hash in toArray calls or JSON views.
Secondly, any data field provided to patchEntity will be validated and saved (as you've discovered), even if the value for the field is blank.
If you look at the entity with debug($user) you'll notice it tracks which fields are "dirty", and since patchEntity saw you submitted a password field (even if it was blank), it set the User entity's password to blank and marked it as "dirty". Even if you later call unset($user->password) it's still got a record of it being dirty, and so it'll attempt to validate a value for it.
You could potentially mark the field clean with $export->setDirty('password', false); but then when a new password was submitted in the form it wouldn't be saved.
A better option would be to check if the password field was blank before calling patchEntity, and unset it then:
if ($this->request->is(['patch', 'post', 'put'])) {
$data = $this->request->getData();
if(empty($data['password'])){
unset($data['password']);
}
$user = $this->Users->patchEntity($user, $data);

Entity framework - Avoid circular Relationship in serialization

I have two tables : Users & Profiles. A user has one profile (1:1), a profile can be affected to many users, each profile has many modules, each module has many actions.
I'm sending this object from an asmx to a aspx page using a direct service call.
I got an error because of lazy loading ... so I disabled the lazy loading.
this.Configuration.LazyLoadingEnabled = false;
this works fine, I got my user, with the profile null.
To build the menu tree I have to retrieve the profile. I included It :
User user = new User();
using (cduContext db = new cduContext())
{
// get the user
string encryptedPassword = Encryption.Encrypt(password);
user = (from u in db.Users
where u.UserName.Equals(login) &&
u.Password.Equals(encryptedPassword)
select u).FirstOrDefault();
// Include the users profile
user = db.Users.Include("Profile").FirstOrDefault();
}
return user;
I got this error in the javascript call function :
A circular reference was detected while serializing an object of type 'CDU.Entities.Models.User'.
When I made a quick watch on the user object, in asmx ( before sending it ) , I found, that the profile has included the list of the users who had this pofile, each user has his profile loaded ... etc
Any idea please ?
Note, your code should look like this:
using (cduContext db = new cduContext())
{
// get the user
string encryptedPassword = Encryption.Encrypt(password);
var user = from u in db.Users
where u.UserName.Equals(login) &&
u.Password.Equals(encryptedPassword)
select u;
// Include the users profile
return user.Include("Profile").FirstOrDefault();
}
In your code, you were throwing away the first query by overwriting it with the second. And there was no valid reason to create a blank user.
To address your problem, you're going to have make a decision on what you don't want to serialize. In your case, you probably don't want to serialize Profile.Users
You don't mention what serializer you're using. I'm assuming you're using the DataContract serializer?
EDIT:
You would mark your Profile.Users object with the [IgnoreDataMember] Attribute.

How to dynamically change the title of only one node

In a node, the title should be the name of the user logged into the system.
In addition I would like the result to be cached, because to retrieve the username I have to go to the database since the username is the email.
How to modify the title with the name of the logged in user and cache the result, but so that if another user logs in it will not load a cached page but a new page will be rendered to him.
In v4 you can simply set the title in either your view or controller and it will be request cached for that user (no other user will see it).
#MvcSiteMapProvider.SiteMaps.Current.CurrentNode.Title = "My Username"
Of course, I am using CurrentNode as an example, you can do this with any node by walking the tree.
However, you will need to handle the caching of the username to prevent a database hit per request outside of MvcSiteMapProvider. You can do this by creating a cache item for each user, incorporating the username (as long as it is unique) into the key.
var key = "My Username";
var userName = HttpContext.Current.Cache.Item[key];
if (userName == null)
{
userName = GetUserNameFromDB();
HttpContext.Current.Cache.Item[key] = userName;
}

How to have different connection string for different users in Entity Framework

I have a requirement in which I need to have different connection strings for different users. The idea is to have the username and password supplied at the login screen to be used as the username and password of the connection string. Thus making application to use different connection string for different user, and to use this connection string throughout the application.
How to get this setup in EF 4.1
PS: I am using DbContext
Thanks to Kevin Junghans
This is how I have done it.
in the model context class
public class MyEntities : DbContext
{
public MyEntities (string connectionString)
: base(connectionString)
{
}
then in the login controller
var dataConnection = WebConfigurationManager.OpenWebConfiguration("/").ConnectionStrings.ConnectionStrings["MyConnectionString"].ConnectionString;
dataConnection = dataConnection.Substring(0, dataConnection.LastIndexOf("\"")) + ";USER ID=" + userName +";Password=" + password + "\"";
Session["connectionString"] = dataConnection;
and the from else where
var _db = new MyEntities (Session["connectionString"].ToString());
You could use the following DbContext constructor which accepts the connections string or name as an argument.
public DbContext(
string nameOrConnectionString,
DbCompiledModel model
)
I dont know which is specifically your question, its not about MVC its only for EF.
If I understand correctly what you want to do, you probably have separeted databases for each user, but you have only ONE database for the users account information for login
You can add one more field to that database, the users login databse, with the specific connectionString for that user. Then when you login the user use the DbContext for that databse and login, then get the value for the connectionString and generate the new DbContext for the specific database for the user loged in.
If you need more help please comment.

Get username from SecurityIdentifier

I am using Windows Authentication on a website where users create reports that are stored in a database. When I save a report, I want to know which user filled it out, so I have been storing the SecurityIdentifier of their WindowsIdentity in the database to identify which user filled out the report. Here is the code I use to get the SecurityIdentifier value for the current Windows user:
public static string GetCurrentUserSID()
{
IPrincipal princ = HttpContext.Current.User;
WindowsIdentity winId = princ.Identity as WindowsIdentity;
SecurityIdentifier si = winId.User;
string securityIdentifierValue = winId.User.Value;
return securityIdentifierValue;
}
Questions
Am I doing the right thing by storing the SecurityIdentifier in the database instead of username or some other value? What is the best practice to follow in this sort of situation?
How can I get the user’s username from the SecurityIdentifier value I have stored?
Should contain the username:
HttpContext.Current.User.Identity.Name