Orchard User Account Edit

Topics: Administration, Core, Customizing Orchard, General
Mar 9, 2013 at 8:40 PM
Edited Mar 9, 2013 at 8:40 PM
I need to add a link to allow users to edit their account emails/usernames.

Basically, the Registration page at

https://orchard/Users/Account/Register But in edit mode.

How can I do this? It seems like it should be really simple, but I can't find any info on google.

Thanks
Developer
Mar 13, 2013 at 2:18 AM
Edited Mar 13, 2013 at 2:18 AM
It is simple, but you will have to create your own controller for that, which returns a view with the form, and handles the postback.
Mar 14, 2013 at 4:52 PM
Edited Mar 14, 2013 at 4:53 PM
Isn't their a profile module on the gallery? May suit your needs, or at least explain how you could go about doing it yourself :)

EDIT: because I'm nice, here is a link: http://gallery.orchardproject.net/List/Modules/Orchard.Module.Contrib.Profile
Mar 21, 2013 at 7:54 PM
Edited Mar 21, 2013 at 8:03 PM
using @Hazza's idea, you could make a couple of minor changes to the contrib module to allow a user to edit their own profile..
For example:-
In the Contrib module, inside the Views Folder create EditorTemplates folder, then create a Parts folder inside that. Add a User.Edit.cshtml to the parts folder with the following markup.
@model Orchard.Users.ViewModels.UserEditViewModel
<fieldset>
    @Html.LabelFor(m => m.UserName, T("User Name"))
    @Html.TextBoxFor(m=>m.UserName, new { @class = "textMedium" })
    @Html.ValidationMessageFor(m=>m.UserName, "*")
</fieldset>
<fieldset>
    @Html.LabelFor(m => m.Email, T("Email"))
    @Html.TextBoxFor(m=>m.Email, new { @class = "textMedium" })
    @Html.ValidationMessageFor(m=>m.Email, "*")
</fieldset>
inside the HomeController.cs class modify the Edit and EditPost methods with the following
public ActionResult Edit() {
            if(Services.WorkContext.CurrentUser == null) {
                return HttpNotFound();
            }

            //IUser user = Services.WorkContext.CurrentUser;

            //dynamic shape = Services.ContentManager.BuildEditor(user.ContentItem);

            //return View((object)shape);
            var user = Services.ContentManager.Get<UserPart>(Services.WorkContext.CurrentUser.Id);
            var editor = Shape.EditorTemplate(TemplateName: "Parts/User.Edit", Model: new UserEditViewModel { User = user }, Prefix: null);
            editor.Metadata.Position = "2";
            dynamic model = Services.ContentManager.BuildEditor(user);
            model.Content.Add(editor);

            // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            return View((object)model);
        }

        [HttpPost, ActionName("Edit")]
        public ActionResult EditPost() {
            if (Services.WorkContext.CurrentUser == null) {
                return HttpNotFound();
            }

            int id = Services.WorkContext.CurrentUser.Id;
            var user = Services.ContentManager.Get<UserPart>(id, VersionOptions.DraftRequired);
            string previousName = user.UserName;

            dynamic model = Services.ContentManager.UpdateEditor(user, this);

            var editModel = new UserEditViewModel { User = user };
            if (TryUpdateModel(editModel))
            {
                if (!_userService.VerifyUserUnicity(id, editModel.UserName, editModel.Email))
                {
                    ModelState.AddModelError("NotUniqueUserName", T("User with that username and/or email already exists."));
                }
                else if (!Regex.IsMatch(editModel.Email ?? "", UserPart.EmailPattern, RegexOptions.IgnoreCase))
                {
                    // http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx    
                    ModelState.AddModelError("Email", T("You must specify a valid email address."));
                }
                else {
                    // also update the Super user if this is the renamed account
                    if (String.Equals(Services.WorkContext.CurrentSite.SuperUser, previousName, StringComparison.Ordinal)) {
                        _siteService.GetSiteSettings().As<SiteSettingsPart>().SuperUser = editModel.UserName;
                    }

                    user.NormalizedUserName = editModel.UserName.ToLowerInvariant();
                }
            }

            if (!ModelState.IsValid)
            {
                Services.TransactionManager.Cancel();

                var editor = Shape.EditorTemplate(TemplateName: "Parts/User.Edit", Model: editModel, Prefix: null);
                editor.Metadata.Position = "2";
                model.Content.Add(editor);

                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            
            Services.ContentManager.Publish(user.ContentItem);

            Services.Notifier.Information(T("User information updated"));

            return RedirectToAction("Edit");
        }
You will need to add a reference to the Orchard.Users module, and inject a couple of extra services to make this work.. But a variation of this was used by our company to get users edit access to their profiles..
Disclaimer:- The User.Edit.cshtml and the code for the Edit and EditPost are just copied from the Orchard.User module from it's Admin controller..
Developer
May 18 at 2:14 AM
Kudos to Excommunicated...

I wanted the same functionality just a bit neater.
I implemented a part that "adds-on" to the ProfilePart.

https://orchardprofile.codeplex.com/SourceControl/network/forks/StanleyGoldman/UserEditorPart/changeset/a29185332894