简体   繁体   中英

Windows Azure Database Entity Framework DbContext and MergeOptions

I have a web role hosting a Unity3D application. In the application I have a connection screen. Like any other connection screen you can fill your login and password to access the core of the application (a game for example).

All of those information are stored in a Windows Azure Database and I can create user using an admin panel. This panel is hosted in another Web Role and can access the database.

If I create a new user, I can connect with those information in my application. There is no problem. But now if I want to change the user password using the admin panel the value is well changed in the database but in my application I can't connect with the new password, the old one is always used.

The user creation and password change are done with the Razor Entity Framework .

I don't understand because in my Unity3D application I do a request to the web role and the user controller and the role returns the old password and not the new one. But in my db and my admin panel there is the new one... How can this be ? How can I solve this ?

Is it a Response caching problem ?

How I find and return User:

DatabaseContext db = DatabaseContextProvider.WebDatabase;
string login = Request.Form["login"]; //The login typed by user
var users = from u in db.Users where u.Login == login select u;
User[] userArray = users.ToArray<User>();

Then I fill the Response to Unity3D with some Header like
Response.AddHeader("data", userArray[0].data.ToString());

If you need any information that can help you solving my problem, just ask.

Thanks a lot for your help !

Found the problem, this was caused by Entity Framework :
Entity Framework and DbContext - Object Tracking
http://msmvps.com/blogs/kevinmcneish/archive/2010/02/16/setting-entity-framework-mergeoptions-what-works-what-doesn-t.aspx

Before

DatabaseContext db = DatabaseContextProvider.WebDatabase;
string login = Request.Form["login"];
var users = from u in db.Users where u.Login == login select u;
User[] userArray = users.ToArray<User>();

Now

DatabaseContext db = DatabaseContextProvider.WebDatabase;
string login = Request.Form["login"];
ObjectContext objectContext = ((IObjectContextAdapter)db).ObjectContext;
ObjectSet<User> set = objectContext.CreateObjectSet<User>();
set.MergeOption = MergeOption.OverwriteChanges;
var users = from u in set where u.Login == login select u;
User[] userArray = users.ToArray<User>();

@Sandrino Di Mattia : Thanks for helping me finding the answer !

If you can see the new password in the database but the controller returns the old password try to disable caching by creating the following ActionFilter and adding it to your Action returning the password ( as described here ):

public class NoCacheAttribute : ActionFilterAttribute
{  
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
    }
}

And just on the side, why are you returning the password? The username/password validation should happen server side and should simply return true/false or a token after authentication succeeds. Returning passwords (even if hashed) is not a good idea from a security point of view.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM