ASP.NET MVC 3 login page by using partial - asp.net

I want to use Logon page in on home page partially (which is index page).
Then my homepage has UserName textbox, Password textbox , RememberMe checkbox and button for login and register which means Logon page is partial view.
When I run the homepage and if I click Login button, it does not work validation error even
I linked JavaScript and I put [Required] on model class.
I don't know how can I enable the validation error with JavaScript?
And how can I use the HomeController? (Homepage is default page)
Could you help me?
I am beginner, and I am just started to develop MVC application.
Index.cshtml on Home folder
<div id="border_frame">
#Html.Partial("_LogOnPartial")
</div>
LogonPartial.cshtml on Shared folder
#model MvcApplication2.Models.LogOnModel
#if (Request.IsAuthenticated)
{
<text>Welcome <strong>#User.Identity.Name</strong>!
[ #Html.ActionLink("Log Off", "LogOff", "Account") ]</text>
}
else
{
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
using (Html.BeginForm())
{
<div>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName, new { style = "width:150px;" })
#Html.ValidationMessageFor(m => m.UserName)
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password, new { style = "width:150px;" })
#Html.ValidationMessageFor(m => m.Password)
<div>
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe)
</div>
<button name="button" class="login_button" value="logIn">Log In</button>
<button name="button" class="register_button" value="register">Register now</button>
</div>
#Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
}
}
AccountModel.cs
public class LogOnModel
{
[Required]
[Display(Name = "User ID")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
HomeController.cs
public ActionResult Index()
{
return View();
}

You have to have a post action method to handle your postback.
[HttpPost]
public ActionResult Index(LogonModel model)
{
if (ModelState.IsValid) {
// do your validation stuff
}
// If you don't return the model, validation won't work.
return View(model);
}

Related

How to use MVC ValidationMessageFor into bootstrap-modal dialog

Hi everybody i've a little trouble to ask... I'm trying to get error message into a login bootstrap modal dilog using ValidationMessageFor, but actually isn't working and i don't know why.
This is my login dilog with Html.BeginForm
<div class="col-xs-2 login-btn">
<a class="btn pfologin" data-toggle="modal" data-target=".bootstrapmodal">
<span> LOGIN</span>
</a>
<!-- Modal dialog -->
<div class="modal fade bootstrapmodal">
<div class="modal-dialog">
#using (Html.BeginForm("Login", "Account"))
{
<div class="modal-content modal-pfo">
<div class="modal-body">
<p>
User:<br />
#Html.TextBoxFor(s => s.Name, new { #class = "form-control" })
#Html.ValidationMessageFor(s => s.Password, "", new { #class = "text-danger" })
</p>
<p>
Password:<br />
#Html.TextBoxFor(s => s.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(s => s.Password, "", new { #class = "text-danger" })
</p>
<p style="display: flex;">
#Html.CheckBoxFor(s => s.Privacy, new { #class = "checkbox" }) Remember me
</p>
</div>
<div class="modal-footer">
<button data-dismiss="modal" class="btn btn-pfo">Cancel</button>
<input type="submit" value="Login" class="btn btn-pfo" />
</div>
</div>
}
</div>
</div>...
this is the model
public class LoginModel
{
[Required(ErrorMessage = "Username requested")]
public string Name { get; set; }
[Required(ErrorMessage = "Password requested")]
[DataType(DataType.Password)]
public string Password { get; set; }
public bool Privacy { get; set; }
}
and this is the controller
[HttpPost]
public async Task<ActionResult> Login(LoginModel loginModel)
{
if (String.IsNullOrEmpty(loginModel.Name))
{
return ModelState.AddModelError("Name", loginModel.Name);
}
if (String.IsNullOrEmpty(loginModel.Password))
{
ModelState.AddModelError("Password", loginModel.Password);
}
if (ModelState.IsValid)
{
}
return RedirectToAction("Index", "Home");
}
yes I redirect from Login/Post to Index but i don't think this is the problem... thank you!
When you return RedirectToAction, you lose all your form data (and, therefore, all validation information). Instead of redirecting to Index, return the View with the model that was passed in.
Second, because both properties are marked as Required, you do not need to explicitly check if they are null or empty. The model is already validated before it hits your [HttpPost] method, based on the attributes you set on the model. If you return the View with this model, your validation messages will appear. This is the most basic implementation, but you can probably get away with:
[HttpPost]
public async Task<ActionResult> Login(LoginModel loginModel)
{
if (ModelState.IsValid)
{
// Do work
return RedirectToAction("Index", "Home");
}
// Else, if not valid, re-render the view with the updated information and display it to the user
return View(loginModel);
}
More info on validation here

ModelState.IsValid is always true

As is typical in MVC, I have a View, a Model, and a Controller.
The View contains a form:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Id)
<ul class="fieldlist">
<li>
#Html.LabelFor(m =>m.Email)
#Html.TextBoxFor(m => m.Email)
#Html.ValidationMessageFor(m => m.Email)
</li>
<li>
<div class="row">
<div class="col-md-6">
#Html.LabelFor(m => m.FirstName)
#Html.TextBoxFor(m => m.FirstName)
#Html.ValidationMessageFor(m => m.FirstName)
</div>
<div class="col-md-6">
#Html.LabelFor(m => m.LastName)
#Html.TextBoxFor(m => m.LastName)
#Html.ValidationMessageFor(m => m.LastName)
</div>
</div>
</li>
<li>
#Html.LabelFor(m => m.PhoneNumber)
#Html.TextBoxFor(m => m.PhoneNumber)
#Html.ValidationMessageFor(m => m.PhoneNumber)
</li>
<li>
<div Class="row">
<div Class="col-md-2">
<input type="submit" value="Save" />
</div>
</div>
</li>
</ul>
}
The model looks like this:
public class UserAdminUserViewModel
{
[Display(Name = "User Database ID"), DataType(DataType.Text)]
public string Id { get; set; }
[Display(Name = "Full Name")]
public string Name { get { return FirstName + " " + LastName; } }
[Required()]
[Display(Name = "First Name"), DataType(DataType.Text)]
public string FirstName { get; set; }
[Required()]
[Display(Name = "Last Name"), DataType(DataType.Text)]
public string LastName { get; set; }
[Required()]
[Display(Name = "Email Address"), DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Display(Name = "Telephone Number"), DataType(DataType.Text)]
public string PhoneNumber { get; set; }
}
And the controller to receive the updates:
[HttpPost,ValidateAntiForgeryToken]
public ActionResult User(UserAdminUserViewModel model)
{
if (ModelState.IsValid)
{
// do something, apply the updates to the database, presumably
}
return View(model);
}
...but ModelState.IsValid is always true. The controller is receiving the entered information, but it appears that no validation is taking place. I have tried:
TryUpdateModel<UserAdminUserViewModel>(model);
and
UpdateModel<UserAdminUserViewModel>(model);
I'm not sure I see how these would work, but they were the first suggestions I came across. No dice. Still valid regardless of the data in 'model'. I also tried:
System.ComponentModel.DataAnnotations.Validator.ValidateObject(model, new System.ComponentModel.DataAnnotations.ValidationContext(model));
More promising, but still doesn't work. I also tried the more verbose approach:
System.ComponentModel.DataAnnotations.ValidationContext valContext = new System.ComponentModel.DataAnnotations.ValidationContext(model, null, null);
List<System.ComponentModel.DataAnnotations.ValidationResult> valResults = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
System.ComponentModel.DataAnnotations.Validator.TryValidateObject(model, valContext, valResults, true);
foreach(System.ComponentModel.DataAnnotations.ValidationResult result in valResults)
{
this.ModelState.AddModelError(result.MemberNames.FirstOrDefault() ?? string.Empty, result.ErrorMessage);
}
...which also didn't work. 'valResults', which should contain any errors in the state of the model, is never filled; no validation is happening.
I would use this for email validation:
#using using System.ComponentModel.DataAnnotations;
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
Please see this StackOverflow post
However, EmailAddressAttribute adds server-side validation on top of
that. I.e. there is no server-side validation if you only use
DataTypeAttribute!
If the problem with incorrect email address, here's the solution:
[Email(ErrorMessage = "Invalid Email Address")]
[Required()]
[Display(Name = "Email Address"), DataType(DataType.EmailAddress)]
public string Email { get; set; }
DataType(DataType.EmailAddress) means only how to show textbox on client-side, while Email attribute does actual validation.

Validate function of IValidatableObject not working

I have a "Review" Class:
public class Review : IValidatableObject
{
public int ReviewId { get; set; }
[DisplayName("Digning Date")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
public DateTime Created { get; set; }
[Range(1, 10)]
public int Rating { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string Body { get; set; }
public int RestaurantId { get; set; }
public virtual Restaurant Resturant { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var fields = new[]{ "Created"};
if(Created > DateTime.Now)
{
yield return new ValidationResult("Created date cannot be in the future.", fields);
}
if (Created < DateTime.Now.AddYears(-1))
{
yield return new ValidationResult("Created date cannot be to far in the past.", fields);
}
}
}
which uses Validate method of IValidatableObject to validate Create property. also this is my cshtml code:
#model OdeToFood.Models.Review
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#section scripts
{
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Review</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Created)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Created)
#Html.ValidationMessageFor(model => model.Created)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Rating)
#Html.ValidationMessageFor(model => model.Rating)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Body)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Body)
#Html.ValidationMessageFor(model => model.Body)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
The Validate method simply check wether the year of date of Create is in present year(2012) or last year(2011). So if user enter 2000 as year he should get error: "Created date cannot be in the future.". But i does not work!
also this is my configuration in web.config:
<appSettings>
<add key="webpages:Version" value="1.0.0.0" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
also this my controller code:
public ActionResult Create()
{
return View(new Review());
}
//
// POST: /Reviews/Create
[HttpPost]
public ActionResult Create(int restaurantId, Review newReview)
{
try
{
//_db is my DBContext
var restaurant = _db.Restaurants.Single(r => r.RestaurantId == restaurantId);
newReview.Created = DateTime.Now;
restaurant.Reviews.Add(newReview);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch(System.Data.Entity.Validation.DbEntityValidationException ex)
{
return View();
}
}
What i must to do?
Thanks
It's getting called twice because once when you post and the model binder binds to newReview, and once when you call SaveChanges.
What you should do is when you post check if ModelState.IsValid= false, if so return View(newReview);
in addition your DbEntityValidationException should return View(newReview);
and lastly check out the action filter I wrote here - you don't need to have a try catch - simply use the attribute on your controller's method or register it on application startup like is done with HandleError
MapEntityExceptionsToModelErrorsAttribute

Remote Validate for DropDownList, MVC3, not firing in my case

I am using ASP.NET MVC3 and EF 4.1
I have two DropDownList in my Model, It is required and not duplicated too.
And I want the Remote validate function: ValidateDuplicateInsert get firing when user submit data. But I can NOT get the ValidateDuplicateInsert function firing.
Where am I wrong?
My Model
[Key]
public int CMAndOrgID { get; set; }
[Display(Name = "CM")]
[Required(ErrorMessage = "CM is required.")]
[Remote("ValidateDuplicateInsert", "CMAndOrg", HttpMethod = "Post", AdditionalFields = "CMID, OrganizationID", ErrorMessage = "CM is assigned to this Organization.")]
public int? CMID { get; set; }
[Display(Name = "Organization")]
[Required(ErrorMessage = "Organization is required.")]
public int? OrganizationID { get; set; }
public virtual CM CM { get; set; }
public virtual Organization Organization { get; set; }
The ValidateDuplicateInsert function in my CMAndOrg controller
[HttpPost]
public ActionResult ValidateDuplicateInsert(string cmID, string orgID)
{
bool flagResult = true;
foreach (CMAndOrg item in db.CMAndOrgs)
{
if (item.CMID.ToString() == cmID && item.OrganizationID.ToString() == orgID)
{
flagResult = false;
break;
}
}
return Json(flagResult);
}
And my View
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>CMAndOrg</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CMID, "CM")
</div>
<div class="editor-field">
#Html.DropDownList("CMID", String.Empty)
#Html.ValidationMessageFor(model => model.CMID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.OrganizationID, "Organization")
</div>
<div class="editor-field">
#Html.DropDownList("OrganizationID", String.Empty)
#Html.ValidationMessageFor(model => model.OrganizationID)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
There is a bug in MVC3 related to unobtrusive validation on dropdownlist. Please reference to this http://aspnet.codeplex.com/workitem/7629[^] link for more detail explaination.
Briefly, you can't use the same name for category collection and category field, so just change your collection name and update following line in your view
#Html.DropDownList("CategoryID", String.Empty)
with this
#Html.DropDownListFor(model => model.CategoryID, new SelectList((System.Collections.IEnumerable)ViewData["Categories"], "Value", "Text"))
Thanks again Henry He
Original link
http://www.codeproject.com/Articles/249452/ASP-NET-MVC3-Validation-Basic?msg=4330725#xx4330725xx

How do I access my post data in a asp.net mvc editor view?

I have gotten this semi autogenerated code, but I am uncertain where the Post data is saved and how I access the variables in my controller so I can validate and upload it to my database.
#model FirstWeb.Models.Picture
#{
ViewBag.Title = "Upload et billede";
}
<h2>Upload et billede</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<input type="file" name="file" id="file" />
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ConcertYear)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ConcertYear)
#Html.ValidationMessageFor(model => model.ConcertYear)
</div>
<p>
<input type="submit" value="Upload" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Tilbage til billeder", "Index")
</div>
It seems that you are trying to upload files here. Checkout the following blog post. You will need to use a multipart/form-data enctype for your form in order to be able to upload files. So the first step is to fix your form definition:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
}
then update your view model so that it takes the uploaded file as property:
public class Picture
{
public HttpPostedFileBase File { get; set; }
public string Title { get; set; }
public int ConcertYear { get; set; }
... some other properties used in the view
}
and and finally have your controller POST action take this view model as parameter:
[HttpPost]
public ActionResult Foo(Picture model)
{
if (!ModelState.IsValid)
{
// there were validation errors => re-display the view
return View(model);
}
// the model is valid at this stage => check if the user uploaded a file
if (model.File != null && model.File.ContentLength > 0)
{
// the user uploaded a file => process it ...
}
...
}
The Edit action should take your model as a parameter.
Its proeprties will have the edited values.

Resources