Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • TomD 11 posts 103 karma points
    Oct 27, 2015 @ 14:20
    TomD
    0

    How to save a value from DropdownList in frontend

    Hi all,

    I’m new to Umbraco und MVC and my problem is as follows:

    I created a new data type named “Gender List” and added three prevalues:

    enter image description here

    Subsequent I created a new member property of the type „Gender-List“:

    enter image description here

    Now the users should have the opportunity to edit their profile in frontend and change the value of the DropDownList.

    My problem is how to store the new value back in the member property.

    This is my code. I hope somebody can help me.

    My Model:

    public class ProfileViewModel
    {
        [Required]
        [Display(Name = "Sex")]
        public string Sex { get; set; }
    
        public IEnumerable<SelectListItem> GenderList { get; set; }
    }
    

    My Controller:

        public class ProfileSurfaceController : SurfaceController
    {
    
        [Authorize]
        [ActionName("RenderEditProfile")]
        public ActionResult RenderEditProfile()
        {
            ProfileViewModel profileModel = new ProfileViewModel();
    
            if (@Members.IsLoggedIn())
            {
                var membershipHelper = new MembershipHelper(UmbracoContext);
                var memberId = membershipHelper.GetCurrentMemberId();
                var member = ApplicationContext.Current.Services.MemberService.GetById(memberId);
    
                profileModel.Sex = member.Properties["sex"].Value.ToString();
    
                XPathNodeIterator genderIterator = umbraco.library.GetPreValues(1053);
    
                genderIterator.MoveNext();
                XPathNodeIterator genderPreValues = genderIterator.Current.SelectChildren("preValue", "");
    
                List<SelectListItem> genderItems = new List<SelectListItem>();
    
                while (genderPreValues.MoveNext())
                {
                    string preValue = genderPreValues.Current.Value;
                    int preValueId = genderPreValues.CurrentPosition;
    
                    genderItems.Add(new SelectListItem
                    {
                        Text = preValue,
                        Value = preValue,
    
                    });
    
                    profileModel.GenderList = genderItems;
                }
            }
            else
            {
                //They are not logged in, redirect to home
                return Redirect("/");
            }
    
            //Pass the model to the view
            return PartialView("EditProfile", profileModel);
        }
    
        [Authorize]
        [ActionName("HandleEditProfile")]
        public ActionResult HandleEditProfile(ProfileViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return PartialView("EditProfile", model);
            }
    
            var member = System.Web.Security.Membership.GetUser();
            var membershipService = ApplicationContext.Current.Services.MemberService;
            var updateMember = ApplicationContext.Current.Services.MemberService.GetById(model.MemberID);
    
            updateMember.Properties["sex"].Value = model.Sex;
    
            //Save the member
            membershipService.Save(updateMember);
            TempData["Status"] = "Ihr Profil wurde aktualisiert";
    
            //Return the view
            return PartialView("EditProfile", model);
        }
    
    }
    

    My View:

    <div class="editor-field">
    
            @Html.DropDownListFor(model => model.Sex, ViewData["MyGenderList"] as IEnumerable<SelectListItem>)
    
            @Html.ValidationMessageFor(model => model.Sex)
    
    </div>
    

    My question: How to store the new value from the “Genderlist” in my member property “Sex”?

    Thanks in advance!

    Tom

  • Steve Morgan 1348 posts 4457 karma points c-trib
    Oct 28, 2015 @ 13:05
    Steve Morgan
    0

    What you're doing looks right.

    Two things to check - are the values that are being output for the html select option the textual values of "sex" or the ids - I think from my memory you want them to be the text?

    Stick a breakpoint on the HandleEditProfile line where you're setting the property and see what value is being passed in model.Sex - try a hardcoded value there to rule out any issues?

    HTH Steve

  • TomD 11 posts 103 karma points
    Oct 28, 2015 @ 14:02
    TomD
    0

    Hi Steve,

    1. Although the values are displayed as text, but the currently selected value from the member property is not selected.

    2. When I try to update the profile, an error message will be appear: The ViewData item that has the key 'Sex' is of type 'System.String' but must be of type 'IEnumerable -SelectListItem-

    So, do I have to cast the SelectListItem? And, if so, how can I do that?

    thanks

  • Steve Morgan 1348 posts 4457 karma points c-trib
    Oct 28, 2015 @ 20:27
    Steve Morgan
    100

    Hi Tom,

    This got me in a bit of a mess, in the end I started merging some code I have from an old project to see what was happening so I may have changed a few bits!

    The error you're getting is a little misleading - it's because the value for Sex can't be found in the GenderList not due to a type issue. As I said I've changed a few bits of your code to get this working (in particular using the IDataTypeService to look up the values, I'm not sure but I think this is the current recommended way of doing it). I've posted the lot here rather than showing what I've changed as there were a couple of other issues I think (or stuff I perhaps introduced!!?).

    I've got it working where it will update the member value and post back but it renders just the PartialView and not the view surrounding it! Hopefully this will at least get you back on track though!

    As I say this works but is hacky - I think you should change the key - value of the drop down to be both the text and look up the internal ID to set the member property (especially as it results in the hack I've marked and get the GenderList in a Constructor)??

    Controller

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Umbraco.Core;
    using Umbraco.Core.Models;
    using Umbraco.Core.Services;
    using Umbraco.Web;
    using Umbraco.Web.Mvc;
    using Umbraco.Web.Security;
    using UmbracoV7_3.Model;
    
    
    namespace UmbracoV7_3.Controllers
    {
        public class ProfileSurfaceController : SurfaceController
        {
    
            [Authorize]
            [ActionName("RenderEditProfile")]
            public ActionResult RenderEditProfile()
            {
                ProfileViewModel profileModel = new ProfileViewModel();
    
                if (@Members.IsLoggedIn())
                {
                    var membershipHelper = new MembershipHelper(UmbracoContext);
                    var memberId = membershipHelper.GetCurrentMemberId();
                    var member = ApplicationContext.Current.Services.MemberService.GetById(memberId);
    
                    profileModel.Sex = member.Properties["sex"].Value.ToString();
    
                    IDataTypeService ds = ApplicationContext.Services.DataTypeService;
                    IDataTypeDefinition SizeType = ds.GetAllDataTypeDefinitions().First(d => d.Name == "Sex List");
                    profileModel.GenderList = ds.GetPreValuesCollectionByDataTypeId(SizeType.Id).PreValuesAsDictionary.Select(size => new SelectListItem { Text = size.Value.Value, Value = size.Value.Id.ToString(), Selected = false }).ToList();
    
                }
                else
                {
                    //They are not logged in, redirect to home
                    return Redirect("/");
                }
    
                //Pass the model to the view
                return PartialView("EditProfile", profileModel);
            }
    
            [Authorize]
            [ActionName("HandleEditProfile")]
            public ActionResult HandleEditProfile(ProfileViewModel model)
            {
                if (!ModelState.IsValid)
                {
                    return PartialView("EditProfile", model);
                }
    
               // var member = System.Web.Security.Membership.GetUser();
    
               // var membershipService = ApplicationContext.Current.Services.MemberService;
                //var updateMember = ApplicationContext.Current.Services.MemberService.GetById(member.IMemberID);
    
                // bit hacky must be a better way
                MembershipHelper mh = new MembershipHelper(UmbracoContext.Current);
                var membershipService = ApplicationContext.Current.Services.MemberService;
                var updateMember = membershipService.GetById(mh.GetCurrentMember().Id);
    
                updateMember.Properties["sex"].Value = model.Sex;
    
                //Save the member
                membershipService.Save(updateMember);
                TempData["Status"] = "Ihr Profil wurde aktualisiert";
    
                // model contains the ID of the prevalue not the string so let's replace that.
                model.Sex = updateMember.Properties["sex"].Value.ToString();
                // need the gender list - I'd move this to a constructor - but you probably won't return the Partial?
                IDataTypeService ds = ApplicationContext.Services.DataTypeService;
                IDataTypeDefinition SizeType = ds.GetAllDataTypeDefinitions().First(d => d.Name == "Sex List");
                model.GenderList = ds.GetPreValuesCollectionByDataTypeId(SizeType.Id).PreValuesAsDictionary.Select(size => new SelectListItem { Text = size.Value.Value, Value = size.Value.Id.ToString(), Selected = false }).ToList();
    
                //Return the view
                return PartialView("EditProfile", model);
            }
    
        }
    }
    

    Partial View

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<UmbracoV7_3.Model.ProfileViewModel>
    
    @using (Html.BeginUmbracoForm<UmbracoV7_3.Controllers.ProfileSurfaceController>("HandleEditProfile", null, new { @id = "profile-edit-form" }))
    {
        @Html.LabelFor(m => m.Sex)
        @Html.DropDownListFor(x => x.Sex, Model.GenderList, "Select...")
        @Html.ValidationMessageFor(x => x.Sex)
    
        <button id="callback-submit" type="submit" value="Register">Register</button>
    }
    
  • Steve Morgan 1348 posts 4457 karma points c-trib
    Oct 28, 2015 @ 20:29
    Steve Morgan
    1

    Oh and the...

    Model - note the GenderList is of type List

    namespace UmbracoV7_3.Model
    {
        public class ProfileViewModel
        {
            public int MemberID;
            [Required]
            [Display(Name = "Sex")]
            public string Sex { get; set; }
    
            public List<SelectListItem> GenderList { get; set; }
        }
    }
    
  • TomD 11 posts 103 karma points
    Oct 29, 2015 @ 11:03
    TomD
    0

    Hi Steve,

    Thank you very much for all your efforts! That works fine for me.

    Tom

Please Sign in or register to post replies

Write your reply to:

Draft