I'm developing a web app based on Orchard.
I'm coding a module that manages Staff Users, this users are ContentTypes(Staff_User) composed of UserPart and StaffUserPart (Custom part, defined in a migration) -> this part has a MediaPickerField.
This is the code in my controller to show the creation template of a staff users
public ActionResult CreateStaff() {
IContent staffUser = _contentManager.New("Staff_User");
var model = _contentManager.BuildEditor(staffUser);
return View((object)model);
}
Ok, I have a template in EditorTemplates/Staff.cshtml . The MediaPicker field is attached by the the BuildEditor function (as a shape).
This is the Post controller:
public ActionResult CreateStaffPost(FormCollection input) {
IContent staffUser = _contentManager.New("Staff_User");
//UserPart validation
if (String.IsNullOrEmpty(input["user.Email"]))
ModelState.AddModelError("Email", "The Email field is required.");
//Check if user already exits
var oldUser = _contentManager.Query("User").Where<UserPartRecord>(x => x.Email == input["user.Email"])
.List()
.FirstOrDefault();
if (oldUser != null)
ModelState.AddModelError("Email", "That email adress is already registered.");
if (!ModelState.IsValid) {
var model = _contentManager.UpdateEditor(staffUser, this);
return View(model);
}
StaffUserPart staff = staffUser.As<StaffUserPart>();
staff.FirstName = input["FirstName"];
staff.LastName = input["LastName"];
staff.Location = input["Location"];
staff.JobTitle = input["JobTitle"];
staff.Summary = input["Summary"];
staff.AreaOfExpertise = input["AreaOfExperience"];
staff.Category = input["Category"];
staff.Experience = input["Experience"];
//Media picker field values
var staffImageField = (MediaPickerField)staff.Fields.Single(x => x.Name == "Photo");
//TODO Fix image save during creation
staffImageField.Url = input["StaffUserPart.Photo.Url"];
staffImageField.AlternateText = input["StaffUserPart.Photo.AlternateText"];
staffImageField.Class = input["StaffUserPart.Photo.Class"];
staffImageField.Style = input["StaffUserPart.Photo.Style"];
staffImageField.Alignment = input["StaffUserPart.Photo.Alignment"];
staffImageField.Width = String.IsNullOrEmpty(input["StaffUserPart.Photo.Width"]) ? 0 : Convert.ToInt32(input["StaffUserPart.Photo.Width"]);
staffImageField.Height = String.IsNullOrEmpty(input["StaffUserPart.Photo.Height"]) ? 0 : Convert.ToInt32(input["StaffUserPart.Photo.Height"]);
UserPart userPart = staffUser.As<UserPart>();
userPart.UserName = input["user.Email"];
userPart.Email = input["user.Email"];
userPart.NormalizedUserName = input["user.Email"].ToLowerInvariant();
userPart.Record.HashAlgorithm = "SHA1";
userPart.RegistrationStatus = UserStatus.Approved;
userPart.EmailStatus = UserStatus.Approved;
//Set Password
_membershipService.SetPassword(userPart.As<UserPart>(), input["password"]);
//Create the StaffUser
_contentManager.Create(staffUser);
return RedirectToAction("Index");
}
Question
This works but the MediaPickerField doesn;t save the data. I use the debugger to see if the values from input["StaffUserPart.Photo"] and the values are there.
Any ideas?
It looks like you're doing more work than you need to. If you move your call to UpdateEditor, this method will do the work of putting posted values into your content. You'll need to make sure you're implementing IUpdater. Also, I added a dependency on ITransactionManager. I'm hoping this will help catch something not getting put in the right spot.
public ActionResult CreateStaffPost(FormCollection input) {
IContent staffUser = _contentManager.New("Staff_User");
//Create the StaffUser
_contentManager.Create(staffUser);
//UserPart validation
if (String.IsNullOrEmpty(input["user.Email"]))
ModelState.AddModelError("Email", "The Email field is required.");
//Check if user already exits
var oldUser = _contentManager.Query("User").Where<UserPartRecord>(x => x.Email == input["user.Email"])
.List()
.FirstOrDefault();
if (oldUser != null)
ModelState.AddModelError("Email", "That email adress is already registered.");
//This does all the work of hydrating your model
var model = _contentManager.UpdateEditor(staffUser, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
return View(model);
}
//Set Password
_membershipService.SetPassword(userPart.As<UserPart>(), input["password"]);
return RedirectToAction("Index");
}
Related
I've got a project I've inherited and I've recently just started working with RavenDb. I'm needing to save a document to one database that already has a connection with, but I need to save that document to a second RavenDb. Just wondering how I would go about that? Below is the method I would need to alter.
[HttpPost]
public ActionResult SaveContact(ContactInput input)
{
var id = getId();
var profile = RavenSession.Load<TechProfile>(id) ?? new TechProfile();
input.MapPropertiesToInstance(profile);
// check for existing user
if (RavenSession.Query<TechProfile>().Any(x => x.Email == profile.Email && x.Id != profile.Id))
{
return Json(new {error = "Profile already exists with that email address.", msg = "Error"});
}
RavenSession.Store(profile);
return Json(new {error = "", msg = "Success", id = profile.Id.Substring(profile.Id.LastIndexOf("/") + 1)});
}
You need to create a second session and point it toward the second database.
Entities aren't tied to a particular session in RavenDB, so you can do that.
I am trying to delete an already existing user from a database, which was created automatically when creating MVC application.
The database consists of tables:
AspNetUsers
AspNetUserRoles
AspNetUserLogins
AspNetUserClaims
AspNetRoles
In my code it looks like this:
var user = new ApplicationUser { UserName = model.email, Email = model.email };
var context = new ApplicationDbContext();
context.Users.Attach(user);
context.Users.Remove(user);
context.SaveChangesAsync();
return RedirectToAction("OperationSuccess", "Account");
I have also tried this:
var user = new ApplicationUser { UserName = model.email, Email = model.email };
var context = new ApplicationDbContext();
UserManager.DeleteAsync(user);
But it doesn't help at all. The application itselt does not break and does not show any errors, but the user is still in the database. How do I delete it?
Try this code:
public async Task<IdentityResult> DeleteUser(string email)
{
var user = UserManager.Users.FirstOrDefault(x => x.Email == email);
if(user == null) return null;
var result = await UserManager.DeleteAsync(user); //here result has two properties Errors and Succeeded.
return result;
}
Also, your code is not working because you are creating the object yourself and assigning only two properties yourself in spite of fetching the data from database.
Hi I think you have some versioning problem and its seems that you need to give one extra paramater to the DeleteAsync method.
Kindly refer the below link, since they had same kind of issue and resolved it.
https://stackoverflow.com/a/24594440/3397630
Hope it may give you some idea for your solution too.
Thanks
Karthik
Hope below code will help you to fix your problem
[HttpPost]
public async Task<ActionResult> Delete(string userId)
{
// Check for for both ID and exit if not found
if (String.IsNullEmpty(userId))
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var user = UserManager.Users.SingleOrDefault(u => u.Id == Userid);
// Look for user in the UserStore
// If not found, exit
if (user == null)
{
return HttpNotFound();
}
var results = await UserManager.DeleteAsync(user); // Remove user from UserStore
// If the statement is a success
if (results.Succeeded)
{
// Redirect to Users page
return RedirectToAction("Index", "Users");
}
else
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
}
So, I have a problem I am curious about. I have a UserAccountViewModel that I am reusing for create account view and Edit Account view. So that I can use one view and one viewmodel for my code but different controller actions.
On Create Account, UserName, Password and Confirm Password are all required fields. However, on Edit Account, those fields are not required fields (I hide those fields in my view on Edit Account).
The problem is when I do this:
[HttpPost]
public ActionResult EditUserAccount_Save(UserAccountViewModel editUserAccountViewModel)
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid)
{
editUserAccountViewModel.UserName = UserSession.GetValue(StateNameEnum.UserName, StateNameEnum.UserName.ToString()) as string;
db_user user = new db_user();
user.Title = editUserAccountViewModel.Title;
user.FirstName = editUserAccountViewModel.FirstName;
user.LastName = editUserAccountViewModel.LastName;
user.PhoneNumber = editUserAccountViewModel.PhoneNumber;
user.AltPhoneNumber = editUserAccountViewModel.AltPhoneNumber;
user.EmailAddress = editUserAccountViewModel.EmailAddress;
user.LanguageId = context.languages.Where(t => t.Code == editUserAccountViewModel.Language).Select(t => t.Id).FirstOrDefault();
user.CreatedDate = DateTime.Now;
user.UserId = WebSecurity.GetUserId(editUserAccountViewModel.UserName);
context.Entry(user).State = EntityState.Modified;
context.SaveChanges();
JsonResult res = Json(new { Success = true, data = "", Message = "" });
return res;
}
JsonResult res2 = Json(new { Success = false, data = "", Message = "" });
return res2;
}
My ModelState.IsValid returns false and I added the errors statement above and it says:
It's because UserName, Password and Confirm Password fields are required. How can I reuse my viewmodel so that I can those fields required when I'm creating an account but not required on editing an account? That is, I want to keep those fields are the same (not editable in edit account?)
You could output some dummy values into hidden fields in the view so they won't be null when they come back in, however, that is more data being pushed back and forth.
Secondly, you can remove the keys from the modelstate and thus remove their errors.
ModelState.Remove("UserName");
ModelState.Remove("Password");
ModelState.Remove("ConfirmPassword");
After doing that, when you call ModelState.IsValid, it will give the answer based only on the fields you are interested in
HTH
I have a controller action which i am performing some work on (example below)
public ActionResult Dashboard()
{
// Redirect back to login page if not authenticated
if (!this.HttpContext.User.Identity.IsAuthenticated)
{
return this.RedirectToAction(string.Empty, "Account");
}
this.ApplicationDbContext = new ApplicationDbContext();
this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));
var user = this.UserManager.FindById(this.User.Identity.GetUserId());
MyRitualDashboardData model = new MyRitualDashboardData();
Member member = db.Members.Single(m => m.AspNetUserId == user.Id);
model.Gravatar = string.Format("<img src='{0}' class='gravatar img-circle'/>", user.PhotoUrl);
model.UserMember = member;
model.UserHomeLocation = member.getUserHomeLocation();
model.UserActiveMembership = member.getActiveMembership();
model.UserPastMemberships = member.getExpiredMemberships();
model.UserPayments = member.getUserPayments();
model.UserStatistics = member.GetMembershipStatistics();
if (model.UserActiveMembership != null)
{
model.DaysTillMembershipExpiry = member.getActiveMembership().daysTillExpiry();
}
return this.View(model);
}
If i run this code and perform some changes to the database with some other actions then when i refresh my dashboard the various updates that i am making to the member profile is fine.
If however i try to re-factor my code and place the above code into a seperate class and use a static method to do the call like so:
public ActionResult Dashboard()
{
// Redirect back to login page if not authenticated
if (!this.HttpContext.User.Identity.IsAuthenticated)
{
return this.RedirectToAction(string.Empty, "Account");
}
this.ApplicationDbContext = new ApplicationDbContext();
this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));
var user = this.UserManager.FindById(this.User.Identity.GetUserId());
MyRitualDashboardData model = new MyRitualDashboardData();
model = MyRitualService.GetModelForMyRitual(user);
return this.View(model);
}
and have a method in a seperate class like so:
public static MyRitualDashboardData GetModelForMyRitual(ApplicationUser user)
{
MyRitualDashboardData model = new MyRitualDashboardData();
Member member = db.Members.Single(m => m.AspNetUserId == user.Id);
model.Gravatar = string.Format("<img src='{0}' class='gravatar img-circle'/>", user.PhotoUrl);
model.UserMember = member;
model.UserHomeLocation = member.getUserHomeLocation();
model.UserActiveMembership = member.getActiveMembership();
model.UserPastMemberships = member.getExpiredMemberships();
model.UserPayments = member.getUserPayments();
model.UserStatistics = member.GetMembershipStatistics();
if (model.UserActiveMembership != null)
{
model.DaysTillMembershipExpiry = member.getActiveMembership().daysTillExpiry();
}
return model;
}
Then it is using cached data from the database and i do not know why? Why would the same code called inline in the action be fine but when called from a seperate static function that it caches the data.
Any clues would be great.
Thanks
Both versions have the line
Member member = db.Members.Single(m => m.AspNetUserId == user.Id);
but since this is now in 2 different classes it must also be 2 different dbs.
The second one is static and will live longer (ie never refresh).
Avoid static. The separation in 2 classes is a good idea but just make instances.
Follow naming standards so that properties are easier to recognize.
I am struggling a bit with Asp.net Identity and updating a user. When I run the code below succeed is false and the error message is that the user with username exists. Which is - of course - obvious because you are updating a user, not creating a new one.
I have tried to remove the username without much success, I was then told that the Name (I believe it meant Username) could not be empty.
Snip of code below.
public async Task<ActionResult> Edit(RegisterViewModel model)
{
var user = new User()
{
UserName = model.UserName, FirstName = model.FirstName, LastName = model.LastName, Email = model.EmailAddress,
ApplicationId = Utilities.ApplicationUtilities.GetApplicationId()
};
var userContext = new ApplicationDbContext();
var userStore = new UserStore<User>(userContext);
var userManager = new UserManager<User>(userStore);
var result = await userManager.UpdateAsync(user);
if (result.Succeeded)
{
var selectedRole = model.SelectedRole;
if (!userManager.IsInRole(user.Id, selectedRole.Id))
{
// We are removing the user from the old role. He / she cannot have two or more roles
userManager.RemoveFromRole(user.Id, model.OldRole);
// Now we are adding the user to the new role
userManager.AddToRole(user.Id, selectedRole.Id);
userManager.Update(user);
}
userContext.SaveChanges();
// await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "UserManager");
}
The solution based on the input from Jonesy became something like this:
/*
* Some more information /Just in case someone else does the same
* mistakes I did...
*/
model.OldRole = "User"; // Name of old role - not ID of old role
model.SelectedRoleId = "Administrator"; // Name of new role, not ID of new role
// This test is here just to check if the model is valid or not
// By adding this part, you can check what is possibly wrong with your model
if (!ModelState.IsValid)
{
var errors = ModelState
.Where(x => x.Value.Errors.Count > 0)
.Select(x => new {x.Key, x.Value.Errors})
.ToArray();
}
// Creating the ApplicationDbContext object
var userContext = new ApplicationDbContext();
// Getting the list of users (I tried using Find here, but got errors)
var userList = userContext.Users.ToList();
// Decided to use First or Default. You also have to use double
// equal-characters(=) otherwise you will get errors
var user = userList.FirstOrDefault(u => u.UserName == model.UserName);
// Checking that we really found the user to update
if (user != null)
{
// populate the user object
user.UserId = model.UserId;
user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Email = model.EmailAddress;
}
// creating the UserStore object
var userStore = new UserStore<User>(userContext);
// ... and the userManager object
var userManager = new UserManager<User>(userStore);
// Do the update - I believe this is on the userManager-object
// and not in the database
var result = await userManager.UpdateAsync(user);
// If we get an error, we return to list of Users
// (You should log the error and also return the user to the form)
if (!result.Succeeded) return RedirectToAction("Index", "UserManager");
// Do the actual update in the database
userContext.SaveChanges();
// If the old role and the selected role is the same, we don't
// have to update
if (model.OldRole == model.SelectedRoleId) return RedirectToAction("Index", "UserManager");
// Get the selected role (sort of not needed, but here for clarity)
string selectedRole = model.SelectedRoleId;
// We are removing the user from the old role.
// In our application a user cannot have two or more roles
userManager.RemoveFromRole<User, string>(user.UserId, model.OldRole);
// Now we are adding the user to the new role
userManager.AddToRole<User, string>(user.UserId, selectedRole);
// We are updating the userManager-object
userManager.Update(user);
// And storing the information in the database
userContext.SaveChanges();
// Returning the user to the list of users
return RedirectToAction("Index", "UserManager");
use your dbContext to pull the user to update, instead of creating a new one:
var user = userContext.Find(model.UserName);
or you may need
var user = userContext.FirstOrDefault(u => u.UserName = model.UserName && u.Email = model.EmailAddress);
if(user != null)
{
//update user
}
this is an old one but just wanted to post my solution to the same update issue
var user = UserManager.FindByEmail(model.Email);
user.Address = model.Address;
user.City = model.City;
user.State = model.State;
var result = await UserManager.UpdateAsync(user);
you can also manage roles
user.Roles.Add(Role);
user.Roles.Remove(Role);