2016-04-14 2 views
12

Моя установка:SQL запись в таблице пользователей ASP.NET не сохраняет

  • ASP.NET 4.5 Web API (на Azure) Сохранение данных SQL дб (также на Azure)
  • AngularJS веб фронт end (другой веб-сайт Azure)

Когда пользователь сначала регистрируется, я показываю им «вводное начало». Вступление должно запускаться только один раз - я регистрирую временную метку даты запуска ввода в качестве настраиваемого поля в пользовательской таблице ASP.NET.

Представьте мое удивление, когда я вхожу в систему (как пользователь) и увижу вступительное ДВУХ.

Передняя часть AngularJS правильно отправляет сообщение «intro view» на ASP.NET api, и api отвечает сообщением об успешном завершении. Однако, когда я смотрю на необработанные данные в db, метка времени определенно НЕ обновляется. Следовательно, пользователь увидит ввод второй раз (в какой момент метка времени записывается в db должным образом).

У меня дерьмовое обходное решение. После того как клиент запрашивает токен маркера OAuth с моего сервера, клиент затем запрашивает информацию пользователя (чтобы решить, показывать или не показывать тур). Ожидание 100 мс, а затем отправка сообщения «Просмотр тура» обратно на сервер маскирует проблему.

Я не видел ЛЮБЫХ других проблем хранения данных в любой точке. Поскольку наш db находится на Azure, я не могу подключить Profiler, и built in auditing не дает мне никаких подсказок.

Есть ли что-то о запросе маркера, который оставляет личность ASP.NET в смешном состоянии? И требуется короткое ожидание, прежде чем вы сможете написать в таблицу? Являются ли настраиваемые поля, которые расширяют базовую настройку Identity, подверженной таким проблемам? Возможно, UserManager делает что-то странное в своем черном ящике?

У кого-нибудь есть предложения по продолжению отладки этой проблемы? Или когда-либо слышал о чем-нибудь подобном?

Вот соответствующий код, который должен быть обновление «тур просматривалась» метку времени в БД:

[HttpPost, Route("UserInfo")] 
    public async Task<IHttpActionResult> UpdateUserInfo(UpdateBindingModel model) 
    { 
     var currentUser = UserManager.FindById(User.Identity.GetUserId()); 

     if (model.FirstName != null) 
     { 
      currentUser.FirstName = model.FirstName; 
     } 
     if (model.LastName != null) 
     { 
      currentUser.LastName = model.LastName; 
     } 
     if (model.SetIntroViewCompleteDate) 
     { 
      currentUser.IntroViewCompleteDate = DateTime.UtcNow; 
     } 
     if (model.SetIntroViewLaunchDate) 
     { 
      currentUser.IntroViewLaunchDate = DateTime.UtcNow; 
     } 
     if (model.SetTipTourCompleteDate) 
     { 
      currentUser.TipTourCompleteDate = DateTime.UtcNow; 
     } 
     if (model.SetTipTourLaunchDate) 
     { 
      currentUser.TipTourLaunchDate = DateTime.UtcNow; 
     } 

     IdentityResult result = await UserManager.UpdateAsync(currentUser); 
     if (result.Succeeded) 
     { 
      var data = new UserInfoViewModel 
      { 
       FirstName = currentUser.FirstName, 
       LastName = currentUser.LastName, 
       IntroViewLaunchDate = currentUser.IntroViewLaunchDate 
      }; 

      return Ok(data); 
     } 

     return InternalServerError(); 
    } 

UPDATE ********* 4/18

Я также пытался полностью отойти от материалов UserManager. Я пробовал следующие изменения (вытаскивание пользовательских данных из таблицы, как я хотел бы получить доступ к любым другим данным), но он по-прежнему ведет себя одинаково. Я начинаю думать, что ввод пользовательских полей на объекте ApplicationUser это плохая идея ...

Новый дб получить и сохранить выглядит следующим образом:

ApplicationDbContext newContext = new ApplicationDbContext(); 
var currentUser = await (from c in newContext.Users 
          where c.Email == User.Identity.Name 
          select c).SingleOrDefaultAsync(); 

//update some values 

await newContext.SaveChangesAsync(); 
+1

Вы говорите, что API отвечает «сообщение успеха». FROM, что я вижу в вашем коде, вы получите ответ 200, а также 'UserInfoViewModel'. Это так? Вы также уверены в первом вызове, что маркер отправляется с запросом (т. Е. Дает ли пользователь User.Identity.GetUserId() 'правильный пользователь)? Наконец, возможно, стоит добавить логику, которую вы прокомментировали, - она ​​выполняется до того, как вы обновите пользователя, так что, возможно, что-то происходит там –

+1

Correct - 200 плюс модель представления. Токен отправляется, и клиентский вызов правильно аутентифицирован. Хороший вопрос. Я обновляю исходный вопрос с помощью сокращенного кода ... это довольно обыденно. – waffles

ответ

3

Ну, вот что я сделал для решения проблемы. Я полностью отключил свои пользовательские данные от встроенных компонентов идентификации ASP.NET. Теперь у меня есть отдельный объект (и, следовательно, отдельная таблица SQL), в котором хранятся такие вещи, как FirstName, LastName, LastActiveDate и т. Д.

Это полностью разрешило мою проблему, хотя она представила еще один вызов базы данных в определенных ситуациях. Я считал, что это не большая проблема с производительностью, о которой нужно беспокоиться. Мне осталось думать, что это было какое-то странное состояние гонки, связанное с генерацией токена для пользователя с идентификатором ASP.NET, а затем быстро записывая базу данных Azure SQL - лорд знает, что именно в моем коде вызвало эту проблему.

Если у вас есть проблема, которую трудно решить, часто лучшим вариантом является изменение проблемы.

Теперь мне нужно найти мету нити обсуждала, что делать с наемными очками, когда вы взорвали эту проблему ...

5

В основном проблема может быть с инициализацией `UserManager 'и тот факт, что этот класс работает в контексте db, поэтому вам нужно сохранить изменения в этом контексте. Вот пример:

var userStore = new UserStore<ApplicationUser>(new MyDbContext()); 
var userManager = new UserManager(userStore); 

Таким образом, вы помните как менеджера, так и контекста.Тогда в вашем методе вы обычно называют:

IdentityResult result = await userManager.UpdateAsync(currentUser); 

с последующим сохраняющиеся это изменение в контексте дб:

var dbContext = userStore.context; 
dbContext.saveChanges(); 
+0

Ну, это похоже на довольно хороший ответ, поэтому я дал вам +1. Я не могу заставить проблему воспроизводить прямо сейчас, поэтому мне нужно больше тестирования, чтобы понять это. Я ничего не изменил. Я оставил думать, что это либо какое-то странное состояние гонки (и все работает быстро прямо сейчас), либо я представил все это ... – waffles

+0

Больше тестов показало, что это не устранило проблему - и моя попытка избежать UserManager. Обновлено исходное сообщение с подробностями. Тот факт, что я не мог воспроизвести проблему ранее этим утром, чувствует состояние гонки-у ... Может быть, есть что-то с тем, как загружен мой сервер/db ... – waffles

+1

@ waffles Можете ли вы попробовать запустить приложение на локальном db ? Просто для устранения лазурных проблем? – Lesmian

4

Основываясь на ваш комментарий, что ждет 100 мс маскирует проблему, я думаю, что вы можете иметь проблемы с многочисленными асинхронными ожиданиями. Попробуйте синхронно запускать вызовы и посмотрите, есть ли у вас такая же проблема. Я предполагаю, что проблема может исчезнуть. Мой опыт заключается в том, что использование async-ожидания может быть сложным, если вы вызываете асинхронные методы, которые вызывают другие асинхронные методы. У вас может быть код, который выполняется без правильных результатов.

+0

Еще одно хорошее предложение, но я уже пробовал это. Нет изменений в поведении данных. Спасибо хоть... – waffles

Смежные вопросы