I am trying to hook up Foundation 5 abide validation to my MVC 5 view.When I leave the required fields and try to submit the form,I see all the required fields highlighted in red,but I want to see the error message I added to the C# view model in the Required(ErrorMessage="username is required"]
These are the things I already added
Added these keys to my root level web.config
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
Added the data_abide attribute to the form element
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { id = "form-user-register", data_abide = "" }))
{
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.LoginName)<br />
#Html.TextBoxFor(m => m.LoginName, new { id = "register-loginname"})
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.UserPassword)<br />
#Html.TextBoxFor(m => m.UserPassword, new { id = "register-loginpassword" })
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.Email)<br />
#Html.TextBoxFor(m => m.Email, new { id = "register-loginpassword" })
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.FirstName)<br />
#Html.TextBoxFor(m => m.FirstName, new { id = "register-login-firstname" })
</div>
</div>
<div class="row">
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.LastName)<br />
#Html.TextBoxFor(m => m.FirstName, new { id = "register-login-firstname" })
</div>
</div>
<div class="row">
<div class="small-12 columns">
<div class="left">
<input type="submit" class="button radius small right" value="Register" />
</div>
</div>
</div>
}
I made sure that the jquery.validate.unobtrusive.js and jquery.validate.js is added to the _LayoutView.cshtml
This is the C# Viewmodel
public class RegisterViewModel
{
public int AppUserId { get; set; }
[Display(Name="Username")]
[Required(ErrorMessage="Username is required")]
public string LoginName { get; set; }
[Display(Name = "Email")]
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Display(Name = "FirstName")]
[Required(ErrorMessage = "FirstName is required")]
public string FirstName { get; set; }
[Display(Name = "LastName")]
[Required(ErrorMessage = "LastName is required")]
public string LastName { get; set; }
[Display(Name = "Password")]
[Required(ErrorMessage = "Password is required")]
public string UserPassword { get; set; }
public AddressViewModel Address { get; set; }
}
Still I only the the above screenshot
I figured out what the issue was.This might help someone like me in the future
I was missing couple of things in my _Layout.cshtml and the Register view
1.Missed thi sfrom _Layout view
<script>
$(document).foundation()
</script>
2.Forgot to add the required HTML5 attribute and the html tag that abide validation uses to display the model error
<div class="small-3 columns">
#Html.DisplayNameFor(m => m.LoginName)<br />
#Html.TextBoxFor(m => m.LoginName, new { id = "register-loginname" ,required=""})
<small class="error">Username is required</small>
</div>
And validation worked like a charm
Related
I am trying to get some more information about Razor Pages with core 2.0 and I am having some issues with the post. Please note, this is not production worthy, its just code to try and getting a better understanding of what you can do in razor pages.
The issue is, if my button is in the form, it does not send any data back to the view. So, computedURL in OnPostConcatURL() is never getting to the view.
If the button is outside the form, the form data does not get to the post controller OnPostEdit23 but I can send back ComputedURL to the view. Clearly I am missing something or a lot. And I cannot find an example to fix this.
#page
#model VisibilityTest
#{ ViewData["Title"] = "Visibility Test Site"; }
<form id="frmVisibility" method="post">
<div class="container">
<div class="row form-group">
<div class="col-md-1"> Select Portal: </div>
<div class="col-md-1"><select id="ddlEnvironment" asp-for="selectedEnvironment" asp-items="Model.Environments"></select></div>
<div class="col-md-2"><select id="ddlPortalName" asp-for="selectedPortalName" asp-items="Model.portalNames"></select></div>
<div class="col-md-3"><input asp-for="#Model.ComputedURL" /></div>
</div>
<div class="row form-group">
<div class="col-md-1"><button id="btnConcatURL" asp-page-handler="ConcatURL" type="submit" class="btn btn-primary">Submit23</button></div>
</div>
</div>
</form>
<form method="post">
<button asp-page-handler="edit23" class="btn btn-default">Edit2</button>
</form>
[BindProperty]
public string ComputedURL { get; set; }
public void OnGet()
{
config = GetConfigFile();
PopulatedEnvironmentSelectList();
PopulatePortalNameSelectList(config);
}
public IActionResult OnPost()
{
ComputedURL = selectedEnvironment + selectedPortalName;
return RedirectToPage("./VisibilityTest");
}
public void OnPostConcatURL()
{
ComputedURL = "this is a test";
}
public void OnPostEdit23()
{
ComputedURL = "this is a test";
}
I'm still figuring out Razorpages as well but I noticed a couple of points about your example:
The Model should be the code behind page class not some other object.
The BindProperty should probably be to an object and not just a string (or you can bind to multiple properties on the code-behind object)
If you want to pass back just a message (string) you can use temp data.'
You definitely want the button inside the form as it will populate the model properties with form values (but as with #2 the binding property should be more than a simple string).
So your example modified example below seems to do what you are looking for (I simplified the dropdowns to text fields for easy testing).
.cshtml page
#page
#model VisibilityTestModel
#{
ViewData["Title"] = "Visibility Test Site";
}
<hr />
<form id="frmVisibility" method="post">
<div class="container">
<div class="row form-group">
<div class="col-md-1"> Select Portal: </div>
<div class="col-md-3"><input asp-for="#Model.Portal.Environment" /></div>
<div class="col-md-3"><input asp-for="#Model.Portal.Name" /></div>
<div class="col-md-3">#Model.Portal.ComputedURL</div>
</div>
<div class="row form-group">
<div class="col-md-1"><button id="btnConcatURL" asp-page-handler="ConcatURL" type="submit" class="btn btn-primary">Submit23</button></div>
</div>
</div>
</form>
<h3>Msg: #Model.Message</h3>
.cshtml.cs page:
public class VisibilityTestModel : PageModel {
[BindProperty]
public PortalInfo Portal { get; set; }
[TempData]
public string Message { get; set; }
public void OnGet() {
Portal = new PortalInfo {
Environment = "www.example.com",
Name = "test"
};
}
public void OnPostConcatURL() {
Portal.ComputedURL = Portal.Environment + " " + Portal.Name;
Message = "URL concat";
}
}
public class PortalInfo {
public string Environment { get; set; }
public string Name { get; set; }
public string ComputedURL { get; set; }
}
I have a form where the user enter his/her details.
#using (Html.BeginForm("Create","Coupons"))
{
<div class="row">
<div class="col-sm-8">
<div class="page-header">Generer Coupon</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(m => m.Student)
#Html.DropDownListFor(m => m.Student, new SelectList(Model.Students, "Id", "Name"), "", new { #class = "form-control input-lg" })
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(m => m.Price)
#Html.TextBoxFor(m => m.Price, new { #class = "form-control input-lg" })
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(m => m.NumberOfCoupons)
#Html.TextBoxFor(m => m.NumberOfCoupons, new {#class = "form-control input-lg"})
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4">
<button class="btn btn-success btn-lg">Generer</button>
</div>
</div>
}
I redirect the view to the Create Method on CouponsController
[HttpPost]
public ActionResult Create(CouponViewModel viewModel)
{
if (!ModelState.IsValid)
{
var model = new CouponViewModel
{
Students = _context.Students.ToList()
};
return View("Index", model);
}
for (int i = 1; i <= viewModel.NumberOfCoupons; i++)
{
var coupon = new Coupon
{
CouponNumber = viewModel.CouponNumber,
ValidationCode = viewModel.ValidationCode(6),
Price = viewModel.Price,
StudentId = viewModel.Student,
DateTime = Convert.ToDateTime(DateTime.Now.ToString("yy-MMM-dd ddd"))
};
_context.Coupons.Add(coupon);
_context.SaveChanges();
}
var coupons = _context.Coupons
.Where(c => c.StudentId == viewModel.Student)
.Include(s => s.Student)
.ToList();
TempData["viewModel"] = coupons;
return RedirectToAction("GetCoupons");
}
here is the view i receive the tempdata to display on the view
[HttpPost]
public ActionResult GetCoupons()
{
Coupon coupon = TempData["viewModel"] as Coupon;
return View("Print", (IEnumerable<Coupon>)coupon);
}
I have been stucked for like 3 days. I don't know where im wrong
There are a couple of problems with your example. But you can eliminate them if you do some things differently.
[HttpPost]
public ActionResult Create(CouponViewModel viewModel)
{
return RedirectToAction("GetCoupons", new { studentId = viewModel.Student });
}
First, your redirected action needs to be marked [HttpGet]. You can also avoid TempData if you pass the id on the query string, then perform the lookup in the redirected action.
[HttpGet]
public ActionResult GetCoupons(int studentId)
{
var coupons = _context.Coupons
.Where(c => c.StudentId == studentId)
.Include(s => s.Student)
.ToList();
return View("Print", coupons);
}
TempData isn't wrong but it won't persist on a refresh. Sometimes you will pass sensitive data which makes it useful then. Your cast to a single Coupon isn't quite what you want -- Cast to a collection instead.
[HttpGet]
public ActionResult GetCoupons()
{
var coupons = TempData["viewModel"] as IEnumerable<Coupon>;
return View("Print", coupons);
}
I'm developing a website in MVC 5 using code first migration. I want to add the custom attributes in default identity to update the users data but I failed to update the AspNetUsers table although I have added migration and update database too but the result is the same. my code is
in applicationUser I have add three more properties.
public class ApplicationUser : IdentityUser
{
public string Name { get; set; }
public string MobileNo { get; set; }
public string Address { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
then I updated RegisterViewModel
[Required]
[Display(Name ="Name")]
public string Name { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
[Display(Name = "Mobile Number")]
public string MobileNo { get; set; }
[Required]
[Display(Name = "Address")]
public string Address { get; set; }
and Register View is
<h4>Create a new account.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Name, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.MobileNo, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.MobileNo, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Address, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Address, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register" />
</div>
</div>
after adding the migration and update database in console manager I am unable to create the columns in AspNetUsers table and when I use the -Verbose flag then the error message was
"Cannot find the object "AspNetUsers" because it does not exist or you do not have permissions."
I'm unable to understand that how to fix the problem. Please tell me how to deal with that problem. Thanks
Check whether you can actually connect to your database as fail connection might prevent you from updating the database table. I am using this connection string in my code :
<connectionStrings>
<add name="CONNECTIONSTRING_NAME" connectionString="Data Source(local);
Initial Catalog=YOUR_DATABASE_NAME;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
I'm using the Postal library to send emails from the contact page. I have the following code:
ContactEmail
using AccessorizeForLess.ViewModels;
using Postal;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace AccessorizeForLess.Models
{
public class ContactEmail : Email
{
public string To { get; set; }
[DataType(DataType.EmailAddress)]
[DisplayName("Email Address")]
[RegularExpression(#"^([\w\.\-]+)#([\w\-]+)((\.(\w){2,3})+)$", ErrorMessage = "The Email field is not valid, Please enter a valid email address!")]
[Required(ErrorMessage="Email address is required.")]
public string From { get; set; }
[DisplayName("First Name")]
[Required(ErrorMessage="Please provide your first name")]
public string FirstName { get; set; }
[DisplayName("Last Name")]
[Required(ErrorMessage="Please provide your last name")]
public string LastName { get; set; }
[DisplayName("Subject")]
[Required(ErrorMessage="Please select a topic")]
public SelectList Subject { get; set; }
public string SelectedSubject { get; set; }
[DisplayName("Message")]
[DataType(DataType.MultilineText)]
[Required(ErrorMessage="PLease provide a message for the email")]
public string Message { get; set; }
public List<EmailSubjectViewModel> Subjects { get; set; }
}
}
EmailSubjectViewModel
namespace AccessorizeForLess.ViewModels
{
public class EmailSubjectViewModel
{
public int Id { get; set; }
public string Subject { get; set; }
}
}
ContactController
public ActionResult Index()
{
List<EmailSubjectViewModel> Subjects = new List<EmailSubjectViewModel>()
{
new EmailSubjectViewModel(){Id=1, Subject="Website Issues"},
new EmailSubjectViewModel(){Id=2, Subject="Order Issue"},
new EmailSubjectViewModel(){Id=3, Subject="Product Question"},
new EmailSubjectViewModel(){Id=4, Subject="Returns Questions"},
new EmailSubjectViewModel(){Id=5, Subject="Other"}
};
ContactEmail email = new ContactEmail()
{
Subjects = Subjects
};
return View(email);
}
public ActionResult Send(ContactEmail email)
{
ContactEmail e = new ContactEmail();
e.From = email.From;
e.FirstName = email.FirstName;
e.LastName = email.LastName;
e.SelectedSubject = email.SelectedSubject;
e.Message = email.Message;
e.Send();
return View();
}
And last but not least my view:
#model AccessorizeForLess.Models.ContactEmail
#{
ViewBag.Title = "Contact";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Contact</h2>
#using (Html.BeginForm("Send", "Contact", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>AccessorizeForLess.net
<img src="~/Content/icon-facebook.png" /></h4>
<div style="color:red;font-weight:bold;">#ViewBag.Message</div>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.FirstName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.From, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.From)
#Html.ValidationMessageFor(model => model.From)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedSubject, "Category", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedSubject, new SelectList(Model.Subjects, "Id", "Subject"), "- Please Select -")
#Html.ValidationMessageFor(model => model.SelectedSubject)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Message, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Message, new { #cols = "25", #rows = "55" })
#Html.ValidationMessageFor(model => model.Message)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Send" class="btn btn-default" />
</div>
</div>
</div>
}
Oops almost forgot the section in my web.config
<system.net>
<mailSettings>
<smtp deliveryMethod="Network" from="admin#accessorizeforless.net">
<network host="smtp.gmail.com" port="587" enableSsl="true" defaultCredentials="true" userName="***********#gmail.com" password="**********" />
</smtp>
</mailSettings>
</system.net>
Now when I fill out the form and click send I get the following error:
System.Net.Mail.SmtpException: The SMTP server requires a secure
connection or the client was not authenticated. The server response
was: 5.5.1 Authentication Required.
I thought I was setting the authenticatioon credentials in the web.config?
I had to change defaultCredentials to false in the web.config and all seems to be working right now.
The following is my class. I am trying to make a small login form. I have a class LoginApp which has username and password. Both I have made required.
[Required(ErrorMessage="This Is a required field")]
[Display(Name="User Name")]
public string userName { get; set; }
[Required]
[Display(Name = "PassWord")]
public string passWord { get; set; }
Following is my controller where i have used tryUpdateModel for checking.
public ActionResult Login(Models.LoginApp LA)
{
LoginApp LAPP = new LoginApp();
bool g = TryUpdateModel(LAPP);
if (ModelState.IsValid)
{
if (LA.userName == "admin" && LA.passWord == "admin")
return RedirectToAction("LoginSuccessful", new { userName = LA.userName});
else
return RedirectToAction("Index");
}
else
return RedirectToAction("Index");
}
Here is the view.
<div class="container">
#using (Html.BeginForm("Login", "Login"))
{
#Html.ValidationSummary(true)
<div class="row">
<div class="form-group ">
#Html.Label("User Name", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(Model => Model.userName, "", new { #class = "form-control" })
#Html.ValidationMessageFor(Model => Model.userName)
</div>
</div>
<br />
<br />
<div class="form-group ">
#Html.Label("PassWord", new { #class = "col-md-2 control-label" })
<div class="col-md-10 ">
#Html.PasswordFor(u => u.passWord, new { #class = "form-control" })
#Html.ValidationMessageFor(Model => Model.passWord)
</div>
</div>
<br />
<br />
<div class="form-group ">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
<input type="button" id="btn" value="Reset" onclick="" class="btn btn-default" />
</div>
</div>
</div>
}
</div>
When I click the log in button without supplying the username or password it doesn't give me validation messages. Where I am going wrong.
You didn't include the validate.js and unobtrusiveon the page.
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
You should check if the ModelState.IsValid in the controller in order to ake the validation in back-end too (so in both side)