asp.net-mvc


asp.net MVC 5 - split registration over several pages. How can I still use [Required] annotations?


I have a user object:
namespace MySolution.Models
{
public class MyUser
{
public Int32 Id { get; set; }
[Required]
public string CompanyName { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
}
}
Id is auto generated by SQL Server. I am using Dapper.
All these properties are required. However I want to split this into two parts - so the user is asked first for Email - then on the next 'page' for Company name, first name & last name.
The [HttpPost] controllers looks like this:
[HttpPost]
public ActionResult SignUp(MyUser myuser)
{
if (ModelState.IsValid)
{
// Insert returns success
if (MyUserRepo.InsertEmailPass(myuser))
{
// Successfully added user, go to next user section
return RedirectToAction("SignUp2", myuser);
}
else
{
// Adding prospect failed
ViewBag.Error = "Email already registered";
}
}
return View(myuser);
}
[HttpPost]
public ActionResult SignUp2(MyUser myuser)
{
if (ModelState.IsValid)
{
// Insert returns success
if (MyUserRepo.UpdateNameCopany(myuser))
{
// Successfully added myuser, go to thank you page
return RedirectToAction("SignUpEnd");
}
else
{
// Adding prospect failed
ViewBag.Error = "Something went wrong";
}
}
}
I want unobtrusive validation and all the built in MVC capabilities - such as if (ModelState.IsValid) - however, as I'm splitting this over 2 pages the model will never be valid on the first page - and unless I manually add email to the model on the second page there too (whereas all I need to do is a SQL update on first name, last name & company name (not email)- so adding email to the SQL un-necessarily).
This all feels rather 'hacky'. How can I do this and still use built in validation and ModelState etc?
I can find nothing about this on Google.
My aim is to do this 'correctly', with minimal code, in a clear way (& best practice?).
EDIT:
I now have these 2 view models:
namespace MyNamespace.ViewModels
{
public class SignUpViewModelPage1
{
public int Id { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[StringLength(50, MinimumLength = 8, ErrorMessage = "{0} must be at least {2} characters long")]
[DataType(DataType.Password)]
public string Password { get; set; }
}
public class SignUpViewModelPage2
{
public int Id { get; set; }
[Required]
public string CompanyName { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
}
}
The controllers:
[HttpPost]
public ActionResult SignUp(SignUpViewModelPage1 svmp1)
{
if (ModelState.IsValid)
{
int Id = senderRepo.InsertEmailPass(svmp1);
// Insert failure returns -1
if (Id != -1)
{
// Successfully added user - go to page 2, pass Id
return RedirectToAction("SignUp2", new { Id = Id });
}
else
{
// Adding user failed - probably duplicate email - tell user & pass invalid model back
ViewBag.Error = "Email already registered";
}
}
return View(svmp1);
}
public ActionResult SignUp2(int Id)
{
return View();
}
[HttpPost]
public ActionResult SignUp2(SignUpViewModelPage2 svmp2)
{
if (ModelState.IsValid)
{
// Insert success returns true
if (senderRepo.UpdateNameCopany(svmp2))
{
// Successfully added user - go to success page
return RedirectToAction("SignUpEnd");
}
else
{
// Adding user failed - tell user
ViewBag.Error = "Email already registered";
}
}
return View();
}
Does this all look OK? Any obvious errors or bad ways of doing things?
thx
As others have mentioned, you should look at creating a ViewModel that represents your page inputs not your domain model.
From there, you have a few options:
1) Use something like bootstrap wizard that essentially hides/shows parts of your page until you submit. All of the properties of your single viewmodel are on your page, but just hidden by the wizard. This handles validation as well, pretty good stuff. Here is an example of it: Bootstrap Form Wizard Example. You can find more examples and download here.
2) Break up into several smaller ViewModels for each step of your forms.
I have recently used option 1 and it worked well for my project.
Your model should reflect what is on your page. I would create 2 models one for each page and do the normal validation.I would then merge the result into one model if need be.
There are different approaches to this. If you want/need to do this through full page updates (as opposed to partial ones) you need to split your model on n parts, where n equals the steps of the wizard you like to present you users with. Then you need to come up with a way to store the data before actually register the user. In WebForms era I did this a lot by saving session relative data, which is not ready for the DB yet in hidden field(s) between round trips.
However I wouldn't recommend this approach as it somewhat clumsy and obsolete. Better approach is to design the wizard steps as partial views. Then on your login page designate a popup window and a button that reads Signup. There are plenty of JS libs offering popups. I use notorious Twitter Bootstrap or jQuery UI, but there are others if you like. So when the user click on Signup, you fed the designated popup with the first partial view and show it. You do this by making AJAX call back to the server. Of course the UI for the current step needs to provide button which loads the next step. You can even design one partial view for your model, load it at once, but show different parts of it, depending on the step we're currently in.
All this requires javascript. You can - correction - you should employ jQuery and request the partial views through AJAX. You can store each step's data in a local javascript variable. At the end of the wizard inspect the collected data and make another AJAX call to the sign-up method. On the server side, you don't have to change your model and leave the annotations in place.
You can google on AJAX, jQuery, partial views and so on. The internet is full of information on the subject.

Related Links

Edit view from HttpPost method
Best practive for logging errors (handled and unhandled) in MVC
ServiceStack request giving 500 for large request
Cross domain session asp mvc in IE and old browsers
Adding MVC Controller scaffolding error
Unable to debug plugin in NopCommerce
Displaying HTML and Images in MultiSelectList ASP.NET MVC Razor
#Html.DisplayFor() value not change after the postback
Location of Validation Message
ASP.NET Identity update column type for primary key Id in AspNetUsers table from a string to and int or a guid, yes or no?
Deploying ASP MVC 5 App with IIS 7.5
validation for dropdown in MVC3
MVC getting a list of music and image into a table
How to allow users to only edit their details in a catalog
Defining Repository for MVC best practice
MVC ASP.NET search filter by int

Categories

HOME
svg
bootstrap-4
compliance
spring-roo
python-3.5
swashbuckle
turing
gluu
stripe-payments
vsix
encog
openvpn
spacemacs
prestashop-1.7
windows-10-desktop
gcov
obiee
command-line-interface
nservicebus
scale
syswow64
lookup-tables
snort
lexikjwtauthbundle
realm-java
code-analysis
rgdal
burp
vnc
fat-free-framework
iar
android-security
phonegap-desktop-app
editorconfig
python-behave
whatsapi
bluebird
apache-commons-httpclient
dokuwiki
vrtk
tensor
nav
zipline
ecmascript-4
jsonstore
mindstorms
plasticscm
essbase
subscription
stateful
formatdatetime
qmenubar
php-deployer
gulp-babel
rating-system
azure-cdn
spring-form
asyncsocket
sharpziplib
qtcpserver
zenity
email-notifications
ipmi
xnamespace
webpagetest
ng-annotate
python-3.1
winobjc
mongolab
blpapi
jca
egl
dual-table
pypdf
ospf
text-alignment
many-to-one
polygons
spinach
mailx
sigkill
nolio
express-jwt
dojo.gridx
dirpagination
ramdisk
location-client
mod-python
datapump
memoization
ccombobox
kmz
google-authorship
uptime
ariatemplates
undeclared-identifier
quilt
cellphone
data-oriented-design
bubble-popup
.net-1.1
apache-config
anemic-domain-model
stsadm
variable-names

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App