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:
Subsequent I created a new member property of the type „Gender-List“:
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);
}
}
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?
Although the values are displayed as text, but the currently selected value from the member property is not selected.
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?
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);
}
}
}
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; }
}
}
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:
Subsequent I created a new member property of the type „Gender-List“:
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:
My Controller:
My View:
My question: How to store the new value from the “Genderlist” in my member property “Sex”?
Thanks in advance!
Tom
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
Hi Steve,
Although the values are displayed as text, but the currently selected value from the member property is not selected.
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
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
Partial View
Oh and the...
Model - note the GenderList is of type List
Hi Steve,
Thank you very much for all your efforts! That works fine for me.
Tom
is working on a reply...