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
Related
When I check the box, it shows it has a false value in the server side model but in the ajax call getting values it shows null values.
In the model class:
[Display(Name = "Is Buyer")]
public bool IsBuyer { get; set; }
In the Razor Page:
<div class="row g-my-4">
<div class="col-md-10 g-pl-0">
<div class="row">
<div class="col-md-1"> </div>
<div class="col-md-7 g-pl-0 g-pr-0" id="IsBuyer">
<label>
#Html.CheckBoxFor(m=>m.IsBuyer)
#*#Html.CheckBoxFor(model => model.IsBuyer, new { id = "CheckBuyer" })*#
#*#Html.CheckBox("IsBuyer")*#
Buyer
</label>
</div>
</div>
</div>
</div>
I tried to use everything but nothing is working.
Getting data values to use ajax call
Here you can see the IsBuyer attribute is null = empty, and here on the server side it's getting false value however I have checked every check box but that's what I am getting back
Try to use usual BeginForm() block and post data like below:
#model Models.ViewModel
#using (Html.BeginForm())
{
<div class="form-group row">
<p>#Html.LabelFor(l => Model.IsBuyer) </p>
#Html.CheckBoxFor(r => Model.IsBuyer)
</div>
<input id="Button" type="submit" value="Save" />
}
In the controller code:
public IActionResult IndexTest()
{
var model = new ViewModel() { IsBuyer = true };
return View(model);
}
[HttpPost]
public IActionResult IndexTest(ViewModel data)
{
if (ModelState.IsValid)
{
// your code here...
}
return RedirectToAction("IndexTest", data);
}
// View data model class
public class ViewModel
{
[Display(Name = "Is Buyer")]
public bool IsBuyer { get; set; }
// Additional propereties is defined here...
}
Index.cshtml code for text box
#Html.LabelFor(m => m.ValidFromDate, "ValidFromDate")
#Html.TextBoxFor(m => m.ValidFromDate)
I don't get idea how to insert this text box value to database
Let's assume you have a table names Users in the db. First we will create a POCO which will represent this table as follows:
public class User
{
public string Username { get; set; }
public DateTime ValidFromDate { get; set; }
//more propteries
}
Now let's assume we have a view named Create. In this view you will pass the User class we've created as your model. So your view should look something like this.
#model Models.User
#{
ViewBag.Title = "User";
}
<div>
#using (Html.BeginForm("Create", "User"))
{
#Html.AntiForgeryToken()
#Html.LabelFor(m => m.Username)
#Html.TextBoxFor(m => m.Username)
#Html.LabelFor(m => m.ValidFromDate)
#Html.TextBoxFor(m => m.ValidFromDate)
<button type="submit">Submit</button>
}
</div>
Now you want to get all the values from this view inside your controller action. We will go ahead and create a controller named UserController and inside this controller we will provide GET and POST methods our Create
//This is our GET action for the view
public ActionResult Create()
{
User user = new User();
return View(user); //we pass in the user object to the view
}
[HttpPost]
[ValidateAntiForgeryToken]
//when you click submit this is the action that will get hit
public ActionResult Create(User model)
{
if (!ModelState.IsValid)
return View(model);
string userName = model.Username;
DateTime validFrom = model.ValidFromDate;
//save to db here. I'm not sure if you're making direct calls or using entity framework or similar framework
return RedirectToAction("Index", "Home"); //this will redirect the user to home. You can return a view or redirect user somewhere else.
}
Here we go . I tested this and it returned me the model properties along with files posted .
//-- this is the controller
public class FileUploadDemoController : Controller
{
//
// GET: /FileUploadDemo/
public ActionResult Index()
{
return View();
}
-- here you can name the method as you like to I justuse postform
[HttpPost]
public ActionResult PostForm(FileUploadModel model)
{
Request.Files is the object which contrins all files which you posted from the form when you hit submit buuton after selecting excel file.
if (Request.Files != null && Request.Files.Count > 0)
{
// here you have files attached and model propertied now you can go to db and perform operation which you need to do
}
return View("Index", model);
}
}
-- This is the model which I use to bind the form
namespace WebApplication1.Models
{
public class FileUploadModel
{
public string Name { get; set; }
public string ValidFromDate { get; set; }
}
}
-- Finaly the cshml file . The import point is to use new { enctype = "multipart/form-data" } inside BeginForm .
// the page from where you will post the data . Please change you model class in place of FileUploadModel I created ot for me .
// Please not I didnt not use any datepicket to keep it simple if you enter date like 01-01-2015 this to test .
#model WebApplication1.Models.FileUploadModel
#using (Html.BeginForm("PostForm", "FileUploadDemo", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="panel">
<div class="panel-body">
<div class="form-group row">
<div class="col-md-2 form-label">
<label>Name:</label>
</div>
<div class="col-md-6">
#Html.TextAreaFor(x => x.Name, new { #class = "form-control" })
</div>
</div>
<div class="form-group row">
<div class="col-md-2 form-label">
<label>Date</label>
</div>
<div class="col-md-6">
#Html.TextAreaFor(x => x.ValidFromDate, new { #class = "form-control" })
</div>
</div>
<div class="col-md-10">
<div class="form-group row">
<div class="col-md-2 form-label">
<label>Select File<i class="required-field">*</i>:</label>
</div>
<div class="col-md-8">
<input type="file" class="file-upload" style="margin: 0px;" hidden="hidden" accept=".xlsx" name="file" id="file" />
</div>
</div>
</div>
<div class="form-group row">
<div class="col-md-3 pull-right text-right">
<button class="btn btn-primary" id="process-submission" type="submit"
>Submit</button>
</div>
</div>
</div>
</div>
}
I have a jQueryUI tabbed html page, and in its content area for one of the tabs, I have put as follows:
<div id="tabs-1ua">
#RenderPage("~/Views/Admin/Create.cshtml")
</div>
The Create.cshtml page does correctly appear within my tab, however when I create the user (this view is a basic user creation page) and click the button, nothing happens. No user is created and no error is presented. The "this" html with the tabs is in a different controller which does not have any model associations. The user creation is inside the AdminController, pertinent methods shown below:
public ActionResult Create()
{
return View();
}
[HttpPost]
public async Task<ActionResult> Create(CreateModel model)
{
if (ModelState.IsValid)
{
AppUser user = new AppUser { UserName = model.Name, Email = model.Email};
IdentityResult result = await UserManager.CreateAsync(user,
model.Password);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
AddErrorsFromResult(result);
}
}
return View(model);
}
I put a breakpoint at the beginning of the Post method, but it was never hit when I accessed the create page from within my other page.
When I access this page directly and create a user, I get the expected behavior for new creation and validation. The model is as follows:
public class CreateModel
{
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
And the Create.cshtml view is as follows:
#model IdentityDevelopment.Models.CreateModel
#{ ViewBag.Title = "Create User";}
<h2>Create User</h2>
#Html.ValidationSummary(false)
#using (Html.BeginForm())
{
<div class="form-group">
<label>Name</label>
#Html.TextBoxFor(x => x.Name, new { #class = "form-control" })
</div>
<div class="form-group">
<label>Email</label>
#Html.TextBoxFor(x => x.Email, new { #class = "form-control" })
</div>
<div class="form-group">
<label>Password</label>
#Html.PasswordFor(x => x.Password, new { #class = "form-control" })
</div>
<button type="submit" class="btn btn-primary">Create</button>
#Html.ActionLink("Cancel", "Index", null, new { #class = "btn btn-default" })
}
My questions are, is it possible to do what I am trying to do? If so what changes do I need to make in order to reuse the existing available code?
Thank you.
You may explcitly specify which action method the form should post to when submit button is clicked.
You can use this overload of Html.BeginForm method to do so.
public static MvcForm BeginForm(
this HtmlHelper htmlHelper,
string actionName,
string controllerName
)
So update your Create view.
#model IdentityDevelopment.Models.CreateModel
#using (Html.BeginForm("Create","Admin"))
{
#Html.TextBoxFor(x => x.Name, new { #class = "form-control" })
<button type="submit" class="btn btn-primary">Create</button>
}
Now nomatter where you include this view, it will always post to Admin/Create
You should move your create form into a partial view which you can then render with RenderPartial. Then in your parent html page form do an ajax post to the partial views controller that defines the create method. Then you can use your partial anywhere you like with the logic centralized into the partial views controller.
I am developing an ASP.NET MVC web application. I am doing remote validation to one of my view model in controller. But it is not working. Remote validation method in controller is not even executed. I searched solutions online and that could not solve my problem. I found these (Remote Attribue Validation not firing in Asp.Net MVC and ASP.NET MVC RemoteAttribute validation not working - Action not being executed) and I tried on it.
This is my model class remote validation applied on Name property
public class CreateCategoryVM
{
public int Id { get; set; }
[Required]
[MaxLength(50)]
[Remote("IsNameUnique","Category",ErrorMessage= "Name must be unique")]
public string Name { get; set; }
[MaxLength(55)]
public string MmName { get; set; }
public IEnumerable<SelectListItem> CategorySelectItems { get; set; }
public int SelectedCategoryId { get; set; }
}
My remote validation method and action method are in the same controller.
This is my create action method and validation method in my controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateCategoryVM model)
{
if(ModelState.IsValid)
{
try
{
Category category = new Category
{
Name = model.Name,
MmName = model.MmName
};
categoryRepo.Create(category);
return RedirectToAction("Create");
}
catch
{
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}
}
model.CategorySelectItems = categoryRepo.CategorySelectItems(model.SelectedCategoryId, "Select category", Thread.CurrentThread.CurrentCulture.Name);
return View(model);
}
public JsonResult IsNameUnique(string Name,int Id)
{
if(string.IsNullOrEmpty(Name))
{
return Json(true,JsonRequestBehavior.AllowGet);
}
else
{
var category = categoryRepo.GetCategoryByName(Name);
if(category)
{
return Json(false, JsonRequestBehavior.AllowGet);
}
else
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
}
Required JavaScript settings are enabled in web.config as well
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
But when I submit the form, IsNameUnique action is not executed for remote validation. Everything is working well except from it. New category is also created if validation is passed. Required validation is working also. Only remote validation method is not executed. I tested using break point. How can I fix this?
Update
I added jquery.validate.js and jquery.validate.unobtrusive.js. Then I run and submit the form. Now it is not even submitted. I check JavaScript code and I have no idea how to fix it. I set break point. Not get run when I click submit button.
This is the JavaScript console of browser
This is debugger of browser
This is my view
#using(Html.BeginForm())
{
#Html.AntiForgeryToken();
#Html.ValidationSummary()
#Html.HiddenFor(m=>m.Id)
<div class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label col-md-3">Name</label>
<div class="col-md-9">
#Html.TextBoxFor(m => m.Name, new { #class="form-control" })
#Html.ValidationMessageFor(m=>m.Name)
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">MM Name</label>
<div class="col-md-9">
#Html.TextBoxFor(m => m.MmName, new { #class="form-control" })
#Html.ValidationMessageFor(m=>m.MmName)
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">Parent</label>
<div class="col-md-9">
#Html.DropDownListFor(m => m.SelectedCategoryId, Model.CategorySelectItems, new { #class = "form-control" })
#Html.ValidationMessageFor(m=>m.SelectedCategoryId)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-3 col-md-9">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</div>
}
How can I get it work?
I'm have problem when practice send email in ASP MVC in tutorials:
How To Send Email In ASP.NET MVC.
I think problem in class:
public async Task<<ActionResult>ActionResult> Index(EmailFormModel model)
{
todosomething
return RedirectToAction("Sent");
}
When run website it show the below error:
Solve:
Thanks to #Simon C.
So, based on your comments, you have a POST contact method, but no way to navigate to the page yet ( just navigating to home/contact in your browser will send a GET request and since you have a [HttpPost] attribute, the route won't match). I think you need to add a GET method to your home controller to get you there:
[HttpGet]
public ActionResult Contact()
{
return View(new EmailFormModel());
}
This means when you first navigate to /home/contact, you will hit the above method. When you post your form back to your site, you will hit the Contact Method marked with [HttpPost].
Edit: As an aside, you will also need to add a method called Sent on your controller for when the email is sent successfully. The line return RedirectToAction("Sent"); will be looking for a method called Sent.
So, based on your comments, you have a POST contact method, but no way to navigate to the page yet ( just navigating to home/contact in your browser will send a GET request and since you have a [HttpPost] attribute, the route won't match). I think you need to add a GET method to your home controller to get you there:
[HttpGet]
public ActionResult Contact()
{
return View(new EmailFormModel());
}
This means when you first navigate to /home/contact, you will hit the above method. When you post your form back to your site, you will hit the Contact Method marked with [HttpPost].
Edit: As an aside, you will also need to add a method called Sent on your controller for when the email is sent successfully. The line return RedirectToAction("Sent"); will be looking for a method called Sent.
In EmailFormModel.cs model:
using System.ComponentModel.DataAnnotations;
using System.Web;
namespace MVCEmail.Models
{
public class EmailFormModel
{
[Required, Display(Name="Your name")]
public string FromName { get; set; }
[Required, Display(Name = "Your email"), EmailAddress]
public string FromEmail { get; set; }
[Required]
public string Message { get; set; }
public HttpPostedFileBase Upload { get; set; }
}
}
Change class Contact in HomeController.cs to:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Contact(EmailFormModel model)
{
if (ModelState.IsValid)
{
var body = "<p>Email From: {0} ({1})</p><p>Message:</p><p>{2}</p>";
var message = new MailMessage();
message.To.Add(new MailAddress("name#gmail.com")); //replace with valid value
message.Subject = "Your email subject";
message.Body = string.Format(body, model.FromName, model.FromEmail, model.Message);
message.IsBodyHtml = true;
if (model.Upload != null && model.Upload.ContentLength > 0)
{
message.Attachments.Add(new Attachment(model.Upload.InputStream, Path.GetFileName(model.Upload.FileName)));
}
using (var smtp = new SmtpClient())
{
await smtp.SendMailAsync(message);
return RedirectToAction("Sent");
}
}
return View(model);
}
And alter the Contact view (Views\Home\Contact.cshtml):
#model MVCEmail.Models.EmailFormModel
#{
ViewBag.Title = "Contact";
}
<h2>#ViewBag.Title.</h2>
#using (Html.BeginForm("Contact", "Home", null, FormMethod.Post, new {enctype = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
<h4>Send your comments.</h4>
<hr />
<div class="form-group">
#Html.LabelFor(m => m.FromName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.FromName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.FromName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.FromEmail, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.FromEmail, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.FromEmail)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Message, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextAreaFor(m => m.Message, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Message)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Upload, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
<input type="file" name="upload" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Send" />
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
And Webconfig.cs is:
<system.net>
<mailSettings>
<smtp from="you#outlook.com">
<network host="smtp-mail.outlook.com"
port="587"
userName="you#outlook.com"
password="password"
enableSsl="true" />
</smtp>
</mailSettings>
</system.net>
Thank #Dijkgraaf