public class RegisterModel
{
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Name", Prompt = "NamePrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.TextBox)]
public string Name { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Email", Prompt = "EmailPrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.Email)]
public string Email { get; set; }
[Display(Name = "PersonalWebsite", Prompt = "SitePrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.Url)]
public string Website { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Password", ResourceType = typeof(Resource))]
[BsControl(BsControlType.Password)]
public string Password { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "RetypePassword", ResourceType = typeof(Resource))]
[Compare("Password")]
[BsControl(BsControlType.Password)]
public string PasswordRetyped { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Birthday", ResourceType = typeof(Resource))]
[BsControl(BsControlType.DatePicker)]
public BsDateTime Birthday { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "AnnualIncome", ResourceType = typeof(Resource))]
[BsControl(BsControlType.Number)]
public decimal? AnnualIncome { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Location", Prompt = "PromptLocation", ResourceType = typeof(Resource))]
[BsControl(BsControlType.DropDownList)]
public BsSelectList<string> CountriesList { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "EmailNotifications", Description = "EmailNotificationsPrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.RadioButtonList)]
public BsSelectList<NotificationType?> NotificationList { get; set; }
[Display(Name = "ReceiveEmailsAtSpecifiedTime", ResourceType = typeof(Resource))]
[BsControl(BsControlType.TimePicker)]
public BsDateTime NotificationTime { get; set; }
[Display(Name = "AspTechnologiesQuestion", ResourceType = typeof(Resource))]
[BsControl(BsControlType.CheckBoxList)]
public BsSelectList<List<int>> TechnologiesCheckboxList { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Technologies", Prompt = "TechnologiesPrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.ListBox)]
public BsSelectList<List<int>> TechnologiesList { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "ProgrammingLanguages", Prompt = "ProgrammingLanguagesPrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.TagList)]
public BsSelectList<List<string>> LanguagesList { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "ProgrammingIDE", Prompt = "ProgrammingIDEPrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.Autocomplete)]
public BsSelectList<string> IdeList { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Gender", Prompt = "GenderPrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.DropDownList)]
public int? Gender { get; set; }
public List<System.Web.Mvc.SelectListItem> GenderList { get; set; }
[BsMandatory(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "ConsentAgreement", ResourceType = typeof(Resource))]
[BsControl(BsControlType.CheckBox)]
public bool ConsentAgreement { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Interval", Prompt = "IntervalPrompt", ResourceType = typeof(Resource))]
[BsControl(BsControlType.DateTimePickerRange, IsReadonly = true)]
public BsRange<DateTime?> Interval { get; set; }
[Required(ErrorMessageResourceName = "RequiredField", ErrorMessageResourceType = typeof(Resource))]
[Display(Name = "Avatar", Prompt = "Choose avatar")]
[BsControl(BsControlType.Upload)]
public HttpPostedFileBase Avatar { get; set; }
}
@using (Html.BsBeginForm("Register", "Login", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "bs-form js-registerForm" }, Html.GetTheme()))
{
<div class="col-lg-12 bs-validation_summary">
@Html.BsValidationSummary()
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Name)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.User)
@Html.BsInputFor(m => m.Name)
@Html.BsValidationFor(m => m.Name)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Email)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.Envelope)
@Html.BsInputFor(m => m.Email)
@Html.BsValidationFor(m => m.Email)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Website)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.Link)
@Html.BsInputFor(m => m.Website)
@Html.BsValidationFor(m => m.Website)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Password)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.Lock)
@Html.BsInputFor(m => m.Password)
@Html.BsValidationFor(m => m.Password)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.PasswordRetyped)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.Lock)
@Html.BsInputFor(m => m.PasswordRetyped)
@Html.BsValidationFor(m => m.PasswordRetyped)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Interval)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.Calendar)
@Html.BsRangeFor(m => m.Interval, new { }, new { usePresetRanges = true})
@Html.BsValidationFor(m => m.Interval)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Birthday)
<div class="input-group">
@Html.BsInputFor(m => m.Birthday)
@Html.BsValidationFor(m => m.Birthday)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.NotificationList)
<div class="input-group">
@Html.BsSelectFor(m => m.NotificationList)
@Html.BsValidationFor(m => m.NotificationList)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.NotificationTime)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.Time)
@Html.BsInputFor(m => m.NotificationTime)
@Html.BsValidationFor(m => m.NotificationTime)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.CountriesList)
<div class="input-group">
@Html.BsSelectFor(m => m.CountriesList)
@Html.BsValidationFor(m => m.CountriesList)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.TechnologiesCheckboxList)
<div class="input-group">
@Html.BsSelectFor(m => m.TechnologiesCheckboxList)
@Html.BsValidationFor(m => m.TechnologiesCheckboxList)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.TechnologiesList)
<div class="input-group">
@Html.BsSelectFor(m => m.TechnologiesList)
@Html.BsValidationFor(m => m.TechnologiesList)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.LanguagesList)
<div class="input-group">
@Html.BsSelectFor(m => m.LanguagesList)
@Html.BsValidationFor(m => m.LanguagesList)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.IdeList)
<div class="input-group">
@Html.BsSelectFor(m => m.IdeList)
@Html.BsValidationFor(m => m.IdeList)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Gender)
<div class="input-group">
@Html.BsDropDownListFor(m => m.Gender, Model.GenderList)
@Html.BsValidationFor(m => m.Gender)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.AnnualIncome)
<div class="input-group">
@Html.BsGlyphiconAddon(Glyphicon.Euro)
@Html.BsInputFor(m => m.AnnualIncome)
@Html.BsValidationFor(m => m.AnnualIncome)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.JavascriptMvcFramework)
<div class="input-group">
@Html.BsSelectFor(m => m.JavascriptMvcFramework)
@Html.BsValidationFor(m => m.JavascriptMvcFramework)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.WebBrowsers)
<div class="input-group">
@Html.BsSelectFor(m => m.WebBrowsers)
@Html.BsValidationFor(m => m.WebBrowsers)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group">
@Html.BsLabelFor(m => m.Avatar)
<div class="input-group">
@Html.BsInputFor(m => m.Avatar)
@Html.BsValidationFor(m => m.Avatar)
</div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6 form-group checkbox">
@Html.BsInputFor(m => m.ConsentAgreement)
@Html.BsValidationFor(m => m.ConsentAgreement)
</div>
<div class="col-sm-12 col-md-12 col-lg-12">
<hr />
<button class="btn btn-theme js-registerBtn" type="submit">Register</button>
<a class="btn btn-primary pull-right" href="@Url.Action("Index", new { mode="login"})">Login</a>
</div>
<div class="clearfix"></div>
}
public class LoginController : BaseController
{
[HttpGet]
public ActionResult Index(string mode)
{
var model = new AuthenticationModel()
{
LoginModel = new LoginModel(),
RegisterModel = InitRegisterModel()
};
RequireJsOptions.Add("registerUrl", Url.Action("Register"));
return View(model);
}
public BsJsonResult Register(AuthenticationModel model)
{
//add validation error to BsRange field
if (model.RegisterModel != null &&
model.RegisterModel.Interval != null &&
model.RegisterModel.Interval.To.HasValue &&
model.RegisterModel.Interval.From.HasValue &&
model.RegisterModel.Interval.From.Value > model.RegisterModel.Interval.To.Value)
{
ModelState.AddFieldError("RegisterModel.Interval",
model.RegisterModel.Interval.GetType(),
"Invalid interval");
}
//add validation error to BsSelectList field
ModelState.AddFieldError("RegisterModel.CountriesList",
model.RegisterModel.CountriesList.GetType(),
"Selected location doesn't match your GPS location");
//add global validation error
ModelState.AddFormError("RegisterModel",
"This email address is in use.");
if (ModelState.IsValid)
{
//save new user to db
}
else
{
//JSON serialize ModelState errors
return new BsJsonResult(
new Dictionary<string, object> { { "Errors", ModelState.GetErrors() } },
BsResponseStatus.ValidationError);
}
return new BsJsonResult();
}
}
require([
'jquery',
'bootstrap',
'bforms-validate-unobtrusive',
'bforms-initUI',
'bforms-ajax',
'bforms-resetInput',
'bforms-extensions',
'main-script'
], function () {
var LoginIndex = function (options) {
this.options = $.extend(true, {}, options);
};
LoginIndex.prototype.init = function () {
this.$loginForm = $('.js-loginForm');
this.$registerForm = $('.js-registerForm');
this.$loginForm.bsInitUI(this.options.styleInputs);
this.$registerForm.bsInitUI(this.options.styleInputs);
this.addHandlers();
};
LoginIndex.prototype.addHandlers = function () {
this.$registerForm.on('click', '.js-registerBtn', $.proxy(this.onRegisterSubmit, this));
};
LoginIndex.prototype.onRegisterSubmit = function (e) {
e.stopPropagation();
e.preventDefault();
var $target = $(e.currentTarget);
$.validator.unobtrusive.parse(this.$registerForm);
var validatedForm = this.$registerForm.validate();
if (this.$registerForm.valid()) {
var registerData = this.$registerForm.parseForm();
$target.prop('disabled', "disabled");
$.bforms.ajax({
url: this.options.registerUrl,
data: registerData,
}).then($.proxy(function (response, status, jqXHR) {
if (response.Status == 2) {//validation error
validatedForm.showErrors(response.Data.Errors, true);
} else {
}
$target.removeProp('disabled');
}, this), function () {
$target.removeProp('disabled');
});
}
};
$(document).ready(function () {
var ctrl = new LoginIndex(requireConfig.pageOptions);
ctrl.init();
});
});