Contour 3.0 Code First, Member registration, profile, login, change password
The upcoming Contour 3.0 release features a new code first framework that is outlined in this post on umbraco.com
To add some more examples I’ve updated the example with some additional member forms:
Profile form
using System;
using System.Collections.Generic;
using Umbraco.Forms.CodeFirst;
using Umbraco.Forms.Core.Providers.FieldTypes;
using umbraco.cms.businesslogic.member;
namespace Contour.CodeFirstExample
{
[Form("Member/Profile", ShowValidationSummary = true, MessageOnSubmit = "Profile updated!")]
public class Profile: FormBase
{
[Field("Profile", FormFieldsets.Details,
Mandatory = true,
DefaultValue = "{member.name}")]
public string Name { get; set; }
[Field("Profile", FormFieldsets.Details,
Mandatory = true,
Regex = @"(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})",
DefaultValue = "{member.email}")]
public string Email { get; set; }
[Field("Profile", FormFieldsets.Details,
Type = typeof(FileUpload),
DefaultValue = "{member.avatar}")]
public string Avatar { get; set; }
public override IEnumerable<Exception> Validate()
{
var e = new List<Exception>();
var m = Member.GetCurrentMember();
if (m != null)
{
if (m.Email != Email)
{
if (Member.GetMemberFromLoginName(Email) != null)
e.Add(new Exception("Email already in use"));
}
}
return e;
}
public override void Submit()
{
var m = Member.GetCurrentMember();
if (m != null)
{
m.Email = Email;
m.LoginName = Email;
m.Text = Name;
//asign custom properties
if (!string.IsNullOrEmpty(Avatar))
m.getProperty("avatar").Value = Avatar;
}
}
}
}
Change password form
using System;
using System.Collections.Generic;
using Umbraco.Forms.CodeFirst;
using Umbraco.Forms.Core.Providers.FieldTypes;
using umbraco.cms.businesslogic.member;
namespace Contour.CodeFirstExample
{
[Form("Member/Change password", ShowValidationSummary = true, MessageOnSubmit = "Password updated!")]
public class ChangePassword: FormBase
{
[Field("Change password", "",
Type = typeof(Password),
Mandatory = true)]
public string Password { get; set; }
[Field("Change password", "",
Type = typeof(Password),
Mandatory = true)]
public string RepeatPassword { get; set; }
public override IEnumerable<Exception> Validate()
{
var e = new List<Exception>();
//makes sure the passwords are identical
if (Password != RepeatPassword)
e.Add(new Exception("Passwords must match"));
return e;
}
public override void Submit()
{
var m = Member.GetCurrentMember();
if(m != null)
m.Password = Password;
}
}
}
Login form
using System;
using System.Collections.Generic;
using Umbraco.Forms.CodeFirst;
using Umbraco.Forms.Core.Providers.FieldTypes;
using umbraco.cms.businesslogic.member;
namespace Contour.CodeFirstExample
{
[Form("Member/Login", ShowValidationSummary = true, MessageOnSubmit ="You are now logged in")]
public class Login: FormBase
{
[Field("Login", "",
Mandatory = true,
Regex = @"(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})")]
public string Email { get; set; }
[Field("Login", "",
Type = typeof(Password),
Mandatory = true)]
public string Password { get; set; }
public override IEnumerable<Exception> Validate()
{
var e = new List<Exception>();
if(Member.GetMemberFromLoginName(Email) == null)
e.Add(new Exception("No member found with that email address"));
else if (Member.GetMemberFromLoginNameAndPassword(Email, Password) == null)
e.Add(new Exception("Incorrect password"));
return e;
}
public override void Submit()
{
var m = Member.GetMemberFromLoginNameAndPassword(Email, Password);
if (m != null)
Member.AddMemberToCache(m);
}
}
}
Registration form
using System;
using System.Collections.Generic;
using Umbraco.Forms.CodeFirst;
using umbraco.cms.businesslogic.member;
using umbraco.BusinessLogic;
using Umbraco.Forms.Core.Providers.FieldTypes;
namespace Contour.CodeFirstExample
{
public enum FormPages
{
Registration
}
public enum FormFieldsets
{
Details
}
[Form("Member/Registration", ShowValidationSummary = true, MessageOnSubmit="You are now registered!")]
public class Registration: FormBase
{
public const string MemberTypeAlias = "Member";
public const string MemberGroupName = "Authenticated";
[Field(FormPages.Registration,FormFieldsets.Details,
Mandatory= true)]
public string Name { get; set; }
[Field(FormPages.Registration, FormFieldsets.Details,
Mandatory = true,
Regex = @"(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})")]
public string Email { get; set; }
[Field(FormPages.Registration, FormFieldsets.Details,
Type = typeof(Password),
Mandatory = true)]
public string Password { get; set; }
[Field(FormPages.Registration, FormFieldsets.Details,
Type = typeof(Password),
Mandatory = true)]
public string RepeatPassword { get; set; }
[Field(FormPages.Registration, FormFieldsets.Details,
Type = typeof(FileUpload))]
public string Avatar { get; set; }
public override IEnumerable<Exception> Validate()
{
var e = new List<Exception>();
//checks if email isn’t in use
if(Member.GetMemberFromLoginName(Email) != null)
e.Add(new Exception("Email already in use"));
//makes sure the passwords are identical
if (Password != RepeatPassword)
e.Add(new Exception("Passwords must match"));
return e;
}
public override void Submit()
{
//get a membertype by its alias
var mt = MemberType.GetByAlias(MemberTypeAlias); //needs to be an existing membertype
//get the user(0)
var user = new User(0);
//create a new member with Member.MakeNew
var member = Member.MakeNew(Name, mt, user);
//assign email, password and loginname
member.Email = Email;
member.Password = Password;
member.LoginName = Email;
//asign custom properties
if(!string.IsNullOrEmpty(Avatar))
member.getProperty("avatar").Value = Avatar;
//asssign a group, get the group by name, and assign its Id
var group = MemberGroup.GetByName(MemberGroupName); //needs to be an existing MemberGroup
member.AddGroup(group.Id);
//generate the member xml with .XmlGenerate
member.XmlGenerate(new System.Xml.XmlDocument());
//add the member to the website cache to log the member in
Member.AddMemberToCache(member);
}
}
}
The code assumes there is a membertype called Member with a additional property with the alias avatar and a membergroup called Authenticated
For more member properties the code needs to be updated…
After deploying you should end up with the following forms
With this solution would you not then be storing all you users password in plain text?
@Shannon nope
Is it possible to use this pattern with custom fieldtypes like the re-captcha in contour contrib? Or is it limited only to core fieldtypes?
@martin yup custom fieldtypes is also possible, add reference and then set the type on the field attribute
Is it possible to enable conditions or the additional settings on the fields?
If yes how would we do it?
@Ash check http://www.nibble.be/?p=221
How can we add more fields? I try to apply for iwin and have to copy code
hey,
Is it possible to create form steps using the code first approach?
Thanks, will
@Will yeah if you have different page names in the field attributes
Hey Tim,
We’ve had a nasty time getting this working on a recent project trying to get login, signup etc working. Feels like we are going against the grain. Where best to send feedback, quirks and issues for this sort of stuff so others don’t get as stuck?
Cheers
Pete
I’m using Umbraco 6.0.5 and Contour 3.0.12 and the reg form works fine except no custom properties are being saved. Help!
For the Login the Password and UserName is being stored in clear text in the UFRecordDataString table. Is there anyway to prevent this ?
I’ve tried the option StoreRecordsLocally=false but that does seem to effect it.
Thanks,
Gavin
Hi Tim
These forms are great, however all users login info (passwords in particular) are saved in Contour in plain text. Is there an easy way to stop Contour saving this information as it’s a bit of a security risk.
Thanks
Dan
@Dan, yeah you can specify to not store locally on the form attribute
For some reason only one of my contour forms renders correctly at a time. If I restart the app pool they alternate consistently, even the count of field sets changes in the database. They are two different classes in the same namespace and compiled into one dll. Is that okay or should I be breaking up each form into a separate dll?
Hi Tim,
Does the above code examples work in Umbraco 7? Thank you.
Chen
Precisely what I was looking for, thank you for putting up.
It’s fantastic that you are getting ideas
from this article as well as from our argument made here.
If some one wants expert view concerning running a blog after that i advise him/her
to pay a visit this weblog, Keep up the good work.
What’s up mates, pleasant post and fastidious arguments commented here, I am in fact enjoying by
these.
This is very interesting, You are a very skilled blogger.
I’ve joined your feed and look forward to seeking
more of your fantastic post. Also, I’ve shared your web
site in my social networks!
Hmm it looks like your website ate my first comment (it
was extremely long) so I guess I’ll just sum it up what I wrote and say, I’m thoroughly enjoying your blog.
I as well am an aspiring blog blogger but I’m still
new to the whole thing. Do you have any helpful hints for rookie blog writers?
I’d definitely appreciate it.
maximized
RAM
firewall
Mississippi
Credit Card Account
hello!,I love your writing very much! share we keep in touch more approximately your article on AOL?
I need a specialist on this area to resolve my problem. Maybe that’s you!
Taking a look forward to see you.
unleash
As I website owner I conceive the content here
is very excellent, appreciate it for your efforts.
back-end
I believe this is one of the most significant information for me.
And i am satisfied studying your article. But wanna observation on few general issues, The web site
taste is perfect, the articles is in point of fact nice : D.
Good task, cheers
payment
XML
Borders
neural
indigo
Mountains
grey
De-engineered
It’s remarkable to visit this website and reading the views of all
colleagues about this piece of writing, while I am
also zealous of getting know-how.
primary
Director
RAM
help-desk
integrated
Home
array
efficient
Car
Industrial
vortals
incentivize
Small
Rustic
you’re actually a just right webmaster. The web site loading velocity is
amazing. It sort of feels that you’re doing any distinctive trick.
Moreover, The contents are masterwork. you’ve performed a excellent process
on this subject!
is this for real??
invoice
target
What i ddo not understood is iff truth be tolpd how
you are not really much more smartly-preferred than you may bee right now.
You are very intelligent. You realize therefore significantly with regards to this topic,
produced me inn my view consider it from numerous varied angles.
Its like men and women don’t seem to be involved until it is something to do with Woman gaga!
Yoour individual stuffs great. All the time care for it up!
data-warehouse
Health
Licensed
I have learn some good stuff here. Definitely price bookmarking
for revisiting. I wonder how much attempt you place to
create this kind of excellent informative web site.
Azerbaijan
protocol
Amazing! Its actually awesome post, I have got much clear idea concerning from this paragraph.
Aruba
Fundamental
This is my first time go to see at here and i am truly impressed to read everthing at single place.
Intranet
indexing
primary
platforms
Handmade Soft Salad
brand
Multi-layered
Rustic