I am using entity framework with database first approach.
I have created separate class for validations.
[MetadataType(typeof(RoleMetaData))]
public partial class Role
{
}
class RoleMetaData
{
[Required(ErrorMessage = "Please enter role name")]
public string Name { get; set; }
}
and my html form:
#using (Html.BeginForm("Create", "Role", FormMethod.Post, new { #class = "submitform" }))
{
#Html.TextBoxFor(x => x.Name, new { #class="form-control" })
<input type="submit" class="btn btn-success width-150" value="Save" />
}
but html rendering to browser without any data-* attributes like:
<input class="form-control" id="Name" name="Name" type="text" value="">
I am wondering why it is not rendering data-* attributes.
Please guide me what I am doing wrong.
Thanx.
You need to use ValidationMessageFor to render data-* attributes for unobstrusive-validation. Use ValidationMessageFor like below:
#using (Html.BeginForm("Create", "Role", FormMethod.Post, new { #class = "submitform" }))
{
#Html.TextBoxFor(x => x.Name, new { #class="form-control" })
#Html.ValidationMessageFor(x => x.Name, "", new { #class = "text-danger" })
<input type="submit" class="btn btn-success width-150" value="Save" />
}
And make sure client side validation is enabled in web.config like below:
<configuration>
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
</configuration>
I found out where the problem was, the namespace of my validation class is different from namespace where data entity exist.
Related
I have an ASP.Net MVC 5 project that has a page with 2 bootstrap tabs. Each tab has two forms for a total of 4 forms on the page. My viewmodel has a superset of all the fields in the 4 forms.
When I post a form, I want the response view to display the same tab that was showing when the form was posted. This SO answer Remain bootstrap tab after postback c# indicates that I should set the active tab in a hidden field, return it in the view model, then restore it on postback.
This SO answer asp.net MVC 4 multiple post via different forms indicates that returned fields must be within the form I'm returning. This presents a problem since the hidden field needs to be in the scope of all the forms.
On postback, how do I display the same tab that was showing when the form was posted when I have multiple forms on the page?
I solved this problem by removing the 4 forms and replacing it with a single form that spanned the previous 4. To get the form to post-back to the proper controller/action, I wrote some javascript that is invoked when one of the 4 submit buttons is activated.
It sets the new form's action to the appropriate controller/action and then submits the form. This way, there is only 1 form and 1 hidden field to hold the active tab and the correct action still gets invoked on post-back. A test program with 2 tabs and (for simplicity) only 2 actions is here:
View:
#model MultiPostDestinations.Models.HomeVM
#{
ViewBag.Title = "Home Page";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br/><br /><br /><br />
<div class="row">
<div class="col-md-4">
#using (Html.BeginForm("SubmitForm", "Home", FormMethod.Post, new { id = "submitForm", enctype = "multipart/form-data" })) {
#Html.HiddenFor(m => m.ActiveTab)
<div id="Tabs" role="tabpanel" class="container" style="width: 1000px">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li class="active">Details</li>
<li>Historic Model Analysis</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div id="details" role="tabpanel" class="tab-pane fade in active">
<h2>Details Tab</h2>
<h4>label: #Model.F1</h4><br /><br />
#Html.DisplayFor(m => m.F1)<br /><br />
#Html.EditorFor(m => m.F1)<br /><br />
#Html.ActionLink("ActionLink Submit form", "SubmitGet", "Home", new { #class = "btn btn-default" })<br /><br />
<input type="submit" value="input SubmitForm" class="btn btn-default" /><br /><br />
<input id="submitButton1" type="button" value="javascript input to /Home/Submit1" class="btn btn-default" /><br /><br />
</div>
<div id="history" role="tabpanel" class="tab-pane fade">
<h2>Historic Model Analysis tab</h2>
<h4>label: #Model.F2</h4><br /><br />
#Html.DisplayFor(m => m.F2)<br /><br />
#Html.EditorFor(m => m.F2)<br /><br />
<input type="submit" value="input SubmitForm" class="btn btn-default" /><br /><br />
<input id="submitButton2" type="button" value="javascript input to /Home/Submit2" class="btn btn-default" /><br /><br />
</div>
</div>
</div>
}
</div>
</div>
#section scripts {
<script type="text/javascript">
$(document).ready(function () {
$('#submitButton1').click(function (e) {
e.preventDefault(); // recommended in SO, does not appear to be required
$('#submitForm').attr('action', '/Home/Submit1');
$('#submitForm').submit();
});
$('#submitButton2').click(function (e) {
e.preventDefault(); // recommended in SO, does not appear to be required
$('#submitForm').attr('action', '/Home/Submit2');
$('#submitForm').submit(); // previous doesn't work - why?
});
var lastActiveTab = ($('#ActiveTab').val() !== '') ? $('#ActiveTab').val() : 'details';
$('#Tabs a[href="#' + lastActiveTab + '"]').tab('show');
$("#Tabs a").click(function () {
$('#ActiveTab').val($(this).attr("href").replace("#", ""));
});
});
</script>
}
Here is the Controller with 2 actions:
using MultiPostDestinations.Models;
using System.Web.Mvc;
namespace MultiPostDestinations.Controllers {
public class HomeController : Controller {
public ActionResult Index() {
var vm = new HomeVM() { F1 = "Index-F1", F2 = "Index-F2", ActiveTab = "" };
return View("Index", vm);
}
[HttpPost]
public ActionResult Submit1(HomeVM vm) {
System.Diagnostics.Debug.WriteLine("HomeVM.Submit1: F1={0}, F2={1}", vm.F1 ?? string.Empty, vm.F2 ?? string.Empty);
// ModelState.Clear(); // uncomment if you want Html.EditorFor() fields to update on postback
return View("Index", vm);
}
[HttpPost]
public ActionResult Submit2(HomeVM vm) {
System.Diagnostics.Debug.WriteLine("HomeVM.Submit2: F1={0}, F2={1}", vm.F1 ?? string.Empty, vm.F2 ?? string.Empty);
//ModelState.Clear(); // uncomment if you want Html.EditorFor() fields to update on postback
return View("Index", vm);
}
}
}
And finally the view-model:
namespace MultiPostDestinations.Models {
public class HomeVM {
public string ActiveTab { get; set; }
public string F1 { get; set; }
public string F2 { get; set; }
}
}
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
I Can't get the Display -> Order attribute to work.
I'm using VS2013 update 4 and the System.ComponentModel.DataAnnotations appears to be up to date with runtime version 4.0.30319.
I built a tiny MVC app with a small model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace TestDataAnnotation.Models
{
[MetadataType(typeof(TestDB))]
public class TestDB
{
public int TestDBID { get; set; }
[Display(Order=2)]
public int MyProperty1 { get; set; }
[Display(Order=1)]
public int MyProperty2 { get; set; }
}
}
I created a controller and view using scaffolding. The GET for the Create is standard MVC
// GET: TestDBs/Create
public ActionResult Create()
{
return View();
}
The View is also standard MVC:
<div class="form-horizontal">
<h4>TestDB</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.MyProperty1, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MyProperty1, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MyProperty1, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MyProperty2, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MyProperty2, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MyProperty2, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
MyProperty2 should display first, but it does not. I've tried numerous variations of this but can't get "Order" to work. I've had the MetadataType statement in the code and not in the code. I've tried order= -9. I've tried various different values for the order attribute. Display->Name works fine. Apparently, I'm missing some key idea here. Thanks for any and all help!
The Order parameter applies when there's something dynamic operating on the model and generating HTML, like a grid view. Here, you've literally rendered the properties in a given order. Setting Order isn't going to override explicit HTML.
I had made some modules in my Orchard site using MVC 3 and EFW .I had also made contents using Orchard Cms like I made some static pages using CMS . But my module has dynamic data which user can add and change them using site admin area.But my question is that I had to localize my app but how ? I made enable Culture picker module and added po files of my desire language and added translations of every content of my site but when I change culture only my CMS content changes.my custom module which I made using MVC 3 and EntityFrameWork does not have any offect of site Culture how to localize my custom module contents ?
public class ContactUsController : Controller
{
DbEntities context = new DbEntities();
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult SaveContacts(FormCollection frmData) {
try
{
using (new TransactionScope(TransactionScopeOption.Suppress))
{
if (ModelState.IsValid == true)
{
Imidus_ContactUs ob = new Imidus_ContactUs();
ob.UserName = frmData["UserName"];
ob.Subject = frmData["Subject"];
ob.Message = frmData["Message"];
ob.Email = frmData["Email"];
context.Imidus_ContactUs.Add(ob);
context.SaveChanges();
return RedirectToAction("Success", "ContactUs");
}
}
}
catch (Exception ex) {
throw ex;
}
return View("Index");
}
public ActionResult Success()
{
return View();
}
}
<fieldset class="contact-form">
#using (Html.BeginForm("SaveContacts", "ContactUs", FormMethod.Post, new { id = "frmContact" }))
{
#Html.ValidationSummary(true)
<span class="errormsg"></span>
<label for="cname">
Name</label>
<div class="editor-field">
<input id="cname" name="UserName" minlength="2" type="text" required />
</div>
<div class="editor-label">
<label for="cemail">
E-Mail</label>
</div>
<div class="editor-field">
<input id="cemail" type="email" name="Email" required />
#* #Html.EditorFor(model => model.Email, new { Class = "input-xlarge" })
*#
</div>
<div class="editor-label">
<label for="csubject">
Subject</label>
</div>
<div class="editor-field">
<input id="csubject" name="Subject" minlength="2" type="text" required />
#* #Html.EditorFor(model => model.Subject, new { Class = "input-xlarge" })
#Html.ValidationMessageFor(model => model.Subject)*#
</div>
<div class="editor-label">
<label for="cMessage">
Message</label>
</div>
<div class="editor-field">
<input id="cMessage" name="Message" minlength="15" type="text" required />
#* #Html.TextAreaFor(model => model.Message)
#Html.ValidationMessageFor(model => model.Message)*#
</div>
<p>
<input type="submit" value="Submit" class="btn btn-primary block my-btn" />
</p>
}
</fieldset>
I'm trying to create a user registration page for my site using Kohana 3.3 and Kostache as my template system.
I'm having a hard time getting to work the Form Validation to display validation errors on the same page. Right now when i click on the form submit button and sending all empty values in the form (username, email and password) all i get is the form to refresh, when I should be getting validation errors such as username is empty, email is empty etc (im using Model_Auth_User).
I have no clue what am I doing wrong.
Model:
class Model_User extends Model_Auth_User
{
public function rules()
{
return array(
'username' => array(
array('not_empty'),
array('alpha_dash'),
array('min_length', array(':value', 4)),
array('max_length', array(':value', 20)),
array(array($this, 'unique'), array('username', ':value')),
),
'email' => array(
array('not_empty'),
array('min_length', array(':value', 4)),
array('max_length', array(':value', 127)),
array('email'),
),
);
}
}
Controller:
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_User extends Controller {
public function action_index()
{
}
public function action_login()
{
$renderer = Kostache_Layout::factory();
$this->response->body($renderer->render(new View_FrontEnd_User, 'frontend/login'));
}
public function action_signup()
{
$renderer = Kostache_Layout::factory();
$this->response->body($renderer->render(new View_FrontEnd_User, 'frontend/signup'));
}
public function action_createuser()
{
$signupView = new View_FrontEnd_User();
try {
$user = ORM::factory('User');
$user->username = $this->request->post('username');
$user->password = $this->request->post('password');
$user->email = $this->request->post('email');
$user->save();
}
catch (ORM_Validation_Exception $e)
{
$errors = $e->errors();
$signupView->errors = $errors;
}
$renderer = Kostache_Layout::factory();
$this->response->body($renderer->render(new View_FrontEnd_User, 'frontend/signup'));
}
}
View
<?php defined('SYSPATH') or die('No direct script access.');
class View_FrontEnd_User extends View_Main
{
public $errors = array();
}
signup.mustache
<p>
<form action="user/createuser" method="post">
<fieldset style="width: 20em;">
<legend>User Registration</legend>
<label>Enter your username</label>
<input type="text" name="username" />
<label for="username" class="error">
{{#errors}}{{username}}{{/errors}}
</label>
<label>Enter your password</label>
<input type="password" name="password" />
<label for="password" class="error">
{{#errors}}{{password}}{{/errors}}
</label>
<label>Email</label>
<input type="text" name="email" />
<input type="submit" value="Submit" class="nice blue radius button" />
</fieldset>
</form>
{{#errors}}{{.}}{{/errors}}
</p>
Thanks a lot in advance for any pointers you can give me.
I've spent hours on this and still can't get it working :(
Change
$this->response->body($renderer->render(new View_FrontEnd_User, 'frontend/signup'));
to
$this->response->body($renderer->render($signupView, 'frontend/signup'));