Input validation generating data-* attributes ONLY on Primary key and checkbox type input tags - asp.net-mvc

I've created a sample ASP.NET MVC Core 1.1 web app created using VS2015-Update3. It generates input tags with data -* attributes only on a model property that is a Primary Key, and on a property that is of type bool. For instance, in the following example the generated html (shown below) is showing the data-attributes only on the input tag generated for properties MyEntityId and Prop2 of the model. NOTE: I'm using the default ASP.NET Core Web Application template that automatically installs Jquery, Bootstrap, etc.
Model:
public class MyEntity
{
public int MyEntityId { get; set; }
public string Prop1 { get; set; }
[Column(TypeName = "char(2)")]
[RegularExpression(#"^[0-9]{2,2}$", ErrorMessage = "Must enter two digit numbers"), StringLength(2)]
public string TestCode { get; set; }
public DateTime? StartDate { get; set; }
public bool Prop2 { get; set; }
}
View
<form asp-controller="TestController" asp-action="TestAction" method="post" class="form-horizontal">
<div asp-validation-summary="All" class="text-danger"></div>
<div><input type="hidden" asp-for="MyEntityId" /></div>
<div class="form-group">
<label asp-for="Prop1" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Prop1" class="form-control" style="margin-top:15px;" />
<span asp-validation-for="Prop1" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="TestCode" class="col-md-2 control-label"></label>
<div class="col-md-2">
<input asp-for="TestCode" class="form-control" />
<span asp-validation-for="TestCode" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="StartDate" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="StartDate" type="date" class="form-control" />
<span asp-validation-for="StartDate" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Prop2" class="col-md-2 control-label"></label>
<div class="col-md-1">
<input asp-for="Prop2" class="form-control" style="zoom:0.5;margin-top:25px;" />
<span asp-validation-for="Prop2" class="text-danger"></span>
</div>
</div>
<button type="submit" name="submit" value="testVal">Save</button>
</form>
Generated Html:
<div><input type="hidden" data-val="true" data-val-required="The MyEntityId field is required." id="MyEntityId" name="MyEntityId" value="54321"></div>
<div class="form-group">
<label class="col-md-2 control-label" for="StateName">Prop1</label>
<div class="col-md-2">
<input class="form-control" readonly="" type="text" id="Prop1" name="Prop1" value="TestVal">
<span class="text-danger field-validation-valid" data-valmsg-for="Prop1" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="TestCode">TestCode</label>
<div class="col-md-2">
<input class="form-control" type="text" id="TestCode" name="TestCode" value="">
<span class="text-danger field-validation-valid" data-valmsg-for="TestCode" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="StartDate">Start Date</label>
<div class="col-md-10">
<input type="date" class="form-control" id="StartDate" name="StartDate" value="2015-10-01">
<span class="text-danger field-validation-valid" data-valmsg-for="StartDate" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="Prop2">Test Prop2</label>
<div class="col-md-1">
<input class="form-control" data-val="true" data-val-required="Test Prop2 is required." id="Prop2" name="Prop2" style="zoom:0.5;margin-top:25px;" type="checkbox" value="true">
<span class="text-danger field-validation-valid" data-valmsg-for="Prop2" data-valmsg-replace="true"></span>
</div>
</div>

I'm assuming your issue is that TestCode does not have validation on it, despite having both RegularExpression and StringLength attributes applied. MyEntityId and Prop2 are non-nullable, so there's an implicit required validation for those, while Prop1 and StartDate are nullable and do not have any explicit validation applied. As a result, those are rightly not validated.
TestCode is weird, though. I'm not sure you'd actually get data-* attributes, as both the regular expression and string length can be satisfied using the HTML attributes pattern and maxlength, respectively. But, you should then have pattern and maxlength applied to the input for TestCode which is not the case.
According to the docs, the code you have should work, and at the least, it seems that StringLength is applied via data-val-maxlength rather than (or perhaps in addition to) using the maxlength attribute. There's either some bug at play, or there's something else in your codebase that is preventing the correct behavior from occurring. However, without more code, it's impossible to say.

Related

ASP.NET MVC hidden field still getting name and passing to controller

I have this control that is hidden and the user need to check the input control for it to be show. I am getting the model fill with data and I wanted to see how I can only get data in the controller if it is selected ?
View
<input type="checkbox" value="91" name="chkProduct">
<label>Other</label>
<input type="hidden">
<input type="hidden" asp-for="Other">
<div id="sourceSection_91" style="">
<div class="row" id="ddRow_6" data-source="sourceSection_91">
<div class="col-md-11 !important">
<div class="form-group">
<label class="control-label source-label">Other</label>
<input class="form-control" id="enteredOtherSource" name="enteredOtherSource[0].Other" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="enteredOtherSource[0].Other" data-valmsg-replace="true"></span>
<input value="91" data-val="true" data-val-number="The field SourceId must be a number." data-val-required="The SourceId field is required." id="SourceId" name="enteredOtherSource[0].SourceId" type="hidden">
</div>
</div>
<div class="col-md-1 deleteBtn">
</div>
</div>
Model
public class OtherSourceModel
{
public int SourceId { get; set; }
public string Other { get; set; }
}
Controller
foreach (var ordermaterial in model.enteredOtherSource)
{
ProjectMaterialUse _SelectedOtherProjectMaterial = new ProjectMaterialUse();
_SelectedOtherProjectMaterial.Source = new Values();
_SelectedOtherProjectMaterial.Source.Value = ordermaterial.SourceId;
_SelectedOtherProjectMaterial.Other = ordermaterial.Other;
_SelectedOtherProjectMaterial.IntendedUse = new Values();
_SelectedOtherProjectMaterial.IntendedUse = model.selectedIntendedUseId;
_permissionrequestWeb.SelectedProjectMaterial.Add(_SelectedOtherProjectMaterial);
}

ASP.NET Core MVC validate not required fields

My page is validating a field that is not required when I submit, even though there is no validation configured for this field.
Create.cshtml
#model Lawtech.App.ViewModels.ProcessoViewModel
#{
ViewData["Title"] = "Novo processo";
}
<h3 style="padding-top: 10px">#ViewData["Title"] </h3>
<hr />
<div class="row">
<div class="col-md-12">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="row">
<div class="form-group col-md-4">
<label asp-for="Numero" class="control-label"></label>
<input asp-for="Numero" class="form-control" />
<span asp-validation-for="Numero" class="text-danger"></span>
</div>
<div class="form-group col-sm-4">
<label asp-for="IdArea" class="control-label"></label>
<div class="input-group">
<select id="slcArea" asp-for="IdArea" class="form-control select2"></select>
<div class="input-group-btn">
<a asp-action="CreateArea" class="btn btn-info" style="border-radius:0 0.25rem 0.25rem 0" data-modal="">
<span class="fa fa-plus"></span>
</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-6 mt-4">
<input type="submit" value="Cadastrar" class="btn btn-sm btn-primary" />
<a class="btn btn-sm btn-info" asp-action="Index">Voltar</a>
</div>
</div>
</form>
</div>
</div>
<div id="myModal" class="modal fade in">
<div class="modal-dialog">
<div class="modal-content">
<div id="myModalContent"></div>
</div>
</div>
</div>
ViewModel
public class ProcessoViewModel
{
[Key]
public int Id { get; set; }
[DisplayName("Número")]
[Required(ErrorMessage = "O campo número é obrigatório")]
public string Numero { get; set; }
[DisplayName("Área")]
public int IdArea { get; set; }
}
Controller
In Controller Create method, nothing happens, because all validation takes place on the client side.
[Route("novo-processo")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(ProcessoViewModel processoViewModel)
{
try
{
if (!ModelState.IsValid) return View(processoViewModel);
await _processoBLL.Insert(_mapper.Map<ProcessoDTO>(processoViewModel));
if (!ValidOperation()) return View(processoViewModel);
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
Inspecting in Chrome I see this generated html for the field that I didn't require validation, I don't know if it could be something related to Jquery.Unobtrusive but I can't remove it either because other fields will be validated.
<select id="slcArea" class="form-control select2 select2-hidden-accessible input-validation-error" data-val="true" data-val-required="The Área field is required." name="IdArea" data-select2-id="slcArea" tabindex="-1" aria-hidden="true" aria-describedby="slcArea-error" aria-invalid="true"></select>
Why is this validation taking place that I have not defined the field as required?
Not nullable properties (that is properties with value types) are always required. Use nullable types (reference types) for properties if they should not be required - eg. int?.
You can always use formnovalidate on any input you don't want validated.
<input asp-for="Numero" formnovalidate="formnovalidate" class="form-control" />
This way there is no need to change your model. This is demonstrated at W3Schools

How to load value of last employeeid + 1 in add action

I have controller name emp have action add
i need when action add view loaded display last value increased by one in
employeeid textbox .
meaning suppose i have in employee table employeeid value 1 then when action add
view loaded employeeid must have 2 .
so that how to do that please ?
in action what i write
[httpget]
Hide Copy Code
public IActionResult Create()
{
what i write here
}
on view add
what i write here
<div class="form-group">
<label asp-for="EmployeeId" class="control-label"></label>
<input asp-for="EmployeeId" class="form-control" />
<span asp-validation-for="EmployeeId" class="text-danger"></span>
</div>
What I have tried:
var results = _context.GetAll().Where(Employee => Employee.EmployeeId> Employee.EmployeeId).OrderBy(Employee => Employee.EmployeeId).FirstOrDefault();
and i pass model to view
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="EmployeeId" class="control-label"></label>
<input asp-for="EmployeeId" class="form-control" />
<span asp-validation-for="EmployeeId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BranchCode" class="control-label"></label>
<input asp-for="BranchCode" class="form-control" />
<span asp-validation-for="BranchCode" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmployeeName" class="control-label"></label>
<input asp-for="EmployeeName" class="form-control" />
<span asp-validation-for="EmployeeName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmployeeAge" class="control-label"></label>
<input asp-for="EmployeeAge" class="form-control" />
<span asp-validation-for="EmployeeAge" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="JoinDate" class="control-label"></label>
<input asp-for="JoinDate" class="form-control" />
<span asp-validation-for="JoinDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BirthDate" class="control-label"></label>
<input asp-for="BirthDate" class="form-control" />
<span asp-validation-for="BirthDate" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="Active" /> #Html.DisplayNameFor(model => model.Active)
</label>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
Please don't use .GetAll() , it'll be cause for performance issue. it means you are loading all employee records to the application side, then you are actually querying to loaded employee data. just think about if you have 50K+ employee. So, you have to use LINQ IQueryable extension methods, which will generate the SQL operation based on your design query.
Help Link:.NET Entity Framework - IEnumerable VS. IQueryable
Please Try This, if you want to do some other expressions.
context.Employee.Select(x => x.EmployeeId).DefaultIfEmpty(0).Max()+1
If your model have property EmployeeId then set this value to it like below.
public IActionResult Create()
{
var model = new Employee();
model.EmployeeId = _context.GetAll().Max(Employee => Employee.EmployeeId).FirstOrDefault() + 1;
return View(model);
}
Or if you don't have Model to pass to View then use ViewBag.
ViewBag["maxEmployeeId"] = _context.GetAll().Max(Employee => Employee.EmployeeId).FirstOrDefault() + 1;

RowVersion value is not getting binded in form data, mvc 5

I am trying to implement concurrency using EF6 in MVC 5.
#Html.HiddenFor(model => model.RowVersion)
On my edit page I am able to see the rowversion value in input type hidden.
<input id="RowVersion" name="RowVersion" type="hidden" value="AAAAAAAAF3M=">
But on $('form').serializeArray() I am not getting RowVersion data, on posting the form also I am getting null value of RowVersion property.
I had added RowVersion column in database table later and updated the edmx after that, I have set concurrency mode to fixed in the primary key column property my table in edmx.
Is there something extra that needs to be done for rowversion ?
Any help would be appreciated.
Update : adding html code
Jquery : I am checking it in console using : $('form').serializeArray()
html output from browser :
<form action="/Master/EditBookMaster/13" method="post"><input name="__RequestVerificationToken" type="hidden" value="Y04ae_LHgfG9Tw9hy2TcHIYbxk_EX_vykyphV7Sm9Wwiz6_f8PpGUY2SULyiZbCdJv4fgBloOlx_QRUz1FQNvXTZUorLt6_EvA9XLxcFsxbQqUlmY9XOCduHa__q1kdRQJpFAx4wOuj5tRu48TLh9A2" /> <div class="form-horizontal">
<h4>BookMaster</h4>
<hr />
<input data-val="true" data-val-number="The field BookMasterId must be a number." data-val-required="The BookMasterId field is required." id="BookMasterId" name="BookMasterId" type="hidden" value="13" />
<div class="form-group">
<label class="control-label col-md-2" for="BookName">BookName</label>
<div class="col-md-10">
<input class="form-control text-box single-line" id="BookName" name="BookName" type="text" value="C Programming" />
<span class="field-validation-valid text-danger" data-valmsg-for="BookName" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Count">Count</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-number="The field Count must be a number." data-val-required="The Count field is required." id="Count" name="Count" type="number" value="10" />
<span class="field-validation-valid text-danger" data-valmsg-for="Count" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Publisher">Publisher</label>
<div class="col-md-10">
<input class="form-control text-box single-line" id="Publisher" name="Publisher" type="text" value="Dennis-Ritchie" />
<span class="field-validation-valid text-danger" data-valmsg-for="Publisher" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Subject">Subject</label>
<div class="col-md-10">
<select class="form-control text-box single-line" data-val="true" data-val-number="The field SubjectId must be a number." data-val-required="The SubjectId field is required." id="SubjectId" name="SubjectId"><option value="1">Fiction</option>
<option value="2">Biography</option>
<option value="3">Science</option>
<option value="4">Research</option>
<option selected="selected" value="5">Software developement</option>
</select>
<span class="field-validation-valid text-danger" data-valmsg-for="SubjectId" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="AvailableCount">AvailableCount</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-number="The field AvailableCount must be a number." id="AvailableCount" name="AvailableCount" type="number" value="8" />
<span class="field-validation-valid text-danger" data-valmsg-for="AvailableCount" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
Back to List
</div>
<input id="RowVersion" name="RowVersion" type="hidden" value="AAAAAAAAF3M=" />
$(":input,:hidden").serialize();
code instead of
$('form').serializeArray()

Best way to prevent HTML Code in Textbox MVC Razor View

I have following code on my view.
This HTML code is used for search in website.
This view is not strongly typed view, so I can apply use DataAnnotation through model.
What is best view to validate that, this textbox should accept only alpha numeric characters?
HTML
<form action="Search" method="post" >
<div class="col-md-8">
<input type="text" name="name" placeholder="search" class="fullwidth" onkeypress="return BlockingHtml(this,event);" />
</div>
<div class="col-md-4">
<input type="submit" title="Search" value="Search" />
</div>
</form>
Javascript
function BlockingHtml(txt) {
txt.value = txt.value.replace(/[^a-zA-Z 0-9\n\r.]+/g, '');
}
Model:-
[StringLength(100)]
[Display(Description = "Name")]
[RegularExpression("(/[^a-zA-Z 0-9\n\r.]+/g", ErrorMessage = "Enter only alphabets and numbers of Name")]
public string Name{ get; set; }
Updated:-
View:-
<form action="Search" method="post" >
<div class="col-md-8">
<input type="text" name="name" id="txt" placeholder="search" class="fullwidth" onkeypress="BlockingHtml(this);" />
</div>
<div class="col-md-4">
<input type="submit" title="Search" value="Search" />
</div>
</form>
function BlockingHtml(txt) {
txt.value = txt.value.replace(/[^a-zA-Z 0-9\n\r.]+/g, '');
}
<form action="Search" method="post" >
<div class="col-md-8">
<input type="text" name="name" placeholder="search" class="fullwidth" onblur="return BlockingHtml(this,event);" />
</div>
<div class="col-md-4">
<input type="submit" title="Search" value="Search" />
</div>
</form>
Changed event onkeypress to onblur.

Resources