Remote dataannotation not triggering in front-end with kendo controls - kendo-ui

I have two controls Speed and Speed unit. Speed is a numeric textbox and Speed unit is a dropdown.
The speed field is required if speed unit is filled in and visa versa.
To achieve this validation I'm using the remote data annotation. However in the front-end the validation is not triggering.
My viewmodel:
[AbpDisplayName(OE_TenantConsts.LocalizationSourceName, "idb_Incident.Speed")]
[Range(0.0, double.MaxValue, ErrorMessage = "Please enter a value of {1} or more")]
[Remote(action: "VerifySpeedAndUnit", controller: "Event", AdditionalFields = nameof(SpeedUnitId))]
public decimal? Speed { get; set; }
[AbpDisplayName(OE_TenantConsts.LocalizationSourceName, "idb_Incident.SpeedUnitId")]
[Remote(action: "VerifySpeedAndUnit", controller: "Event", AdditionalFields = nameof(Speed))]
public int? SpeedUnitId { get; set; }
My controller (event controller -> VerifySpeedAndUnit):
[AcceptVerbs("GET", "POST")]
[AllowAnonymous]
public IActionResult VerifySpeedAndUnit(decimal? speed, int? speedUnitId)
{
if ((speed.HasValue && speedUnitId == DropdownConstants.DefaultSelectedSpeedUnitId) || (speed.HasValue && speedUnitId == null))
{
return Json("When entering a speed, you need to select the speed scale as well.");
}
if (speedUnitId != DropdownConstants.DefaultSelectedSpeedUnitId && speed.HasValue && speedUnitId != null)
{
return Json("When selecting a speed scale, you need to enter a speed value as well.");
}
return Json(true);
}
My speed kendo control :
<div class="mb-5 col-md-6 idb_Incident_Speed">
#Html.LabelFor(model => model.Speed, htmlAttributes: new { #class = "control-label col-12" })
<div class="col-12">
<kendo-numerictextbox deferred="true" for="Speed"
format="#.##"
min="0"
name="Speed"
decimals="2"
placeholder="Enter Speed at time of Incident">
</kendo-numerictextbox>
#Html.ValidationMessageFor(model => model.Speed, "", new { #class = "text-danger" })
</div>
</div>
If I inspect the html of the form field I can see the properties are being set. But nothing happens:
What am I missing here?

Doesn't seem like this is supported out of the box. You have to write some custom jquery to get it to work:
#using(Html.BeginForm("FormPost","Home",FormMethod.Post,new {id="myForm"}))
{
<div class="mb-5 col-md-6 idb_Incident_Speed">
#Html.LabelFor(model => model.Speed, htmlAttributes: new { #class = "control-label col-12" })
<div class="col-12">
<kendo-numerictextbox deferred="true" for="Speed"
format="#.##"
min="0"
name="Speed"
decimals="2"
placeholder="Enter Speed at time of Incident">
</kendo-numerictextbox>
#Html.ValidationMessageFor(model => model.Speed, "", new { #class = "text-danger" })
</div>
</div>
#(Html.Kendo().Button()
.Name("btn")
.Content("Submit")
.HtmlAttributes(new {type="submit"})
)
}
#Html.Kendo().DeferredScripts()
<script>
$(document).ready( function () {
var validator = $("#myForm").kendoValidator({
rules: {
remote: function (input) {
if (input.val() == "" || !input.attr("data-val-remote-url")) {
return true;
}
if (input.attr("data-val-remote-recieved")) {
input.attr("data-val-remote-recieved", "");
return !(input.attr("data-val-remote"));
}
var url = input.attr("data-val-remote-url");
var postData = {};
postData[input.attr("data-val-remote-additionalfields").split(".")[1]] = input.val();
var validator = this;
var currentInput = input;
input.attr("data-val-remote-requested", true);
$.ajax({
url: url,
type: "POST",
data: JSON.stringify(postData),
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function (data) {
if (data == true) {
input.attr("data-val-remote", "");
}
else {
input.attr("data-val-remote", data);
}
input.attr("data-val-remote-recieved", true);
validator.validateInput(currentInput);
},
error: function () {
input.attr("data-val-remote-recieved", true);
validator.validateInput(currentInput);
}
});
return true;
}
},
messages: {
remote: function (input) {
return input.attr("data-val-remote");
}
}
}).getKendoValidator();
$("#btn").click(function(e){
e.preventDefault()
if(!validator.validate()){
//submit form
}
})
});
</script>
Special thanks to telerik support for the code sample.

Related

MVC Controller receiving null values from ajax

I'm trying to send an Ajax post to mvc controller contains two parameters.
First parameter: serialized model (Folder)
Second parameter: Array (Periods)
The problem is the controller received null values in the first parameter:
Javascript code :
var data = JSON.stringify({
Folder: $('#Folder').serialize(),
Periods: periodsArr
});
function save(data) {
return $.ajax({
type: 'POST',
//cache: false,
contentType: 'application/json', //Without folder not empty and period is empty
//traditional: true,
//dataType: "json",
url: '#Url.Action("AddOrEditFolder", "Folder")',
data: data,
success: function (result) {
alert(result);
location.reload();
},
error: function () {
alert("Error!" + Error);
}
});
}
Html code:
<div class="card-body">
#using (Html.BeginForm(null, null, new { #id = string.Empty }, FormMethod.Post, new { #id = "Folder" }))
{
#Html.HiddenFor(model => model.FolderID)
<div class="row">
<label for="FirstNameAR" class="col-sm-2 control-label">الإسم الشخصي</label>
<div class="col-sm-4">
#Html.EditorFor(model => model.Trainee.FirstNameAR, new { htmlAttributes = new { #id= "FirstNameAr", #class = "form-control" } })
</div>
<label for="FirstNameFR" class="col-sm-2 control-label">الإسم العائلي</label>
<div class="col-sm-4">
#Html.EditorFor(model => model.Trainee.FirstNameFR, new { htmlAttributes = new { #id = "FirstNameFr", #class = "form-control" } })
</div>
</div> <br />
Controller code:
[HttpPost]
//[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddOrEditFolder(Folder Folder, Period[] Periods)
{
//Folder Folder = JsonConvert.DeserializeObject<Folder>(Obj);
using (InternshipsEntities dbContext = new InternshipsEntities())
{
//Some code here
}
}
How can I solve that problem ?
Use below code to create data object to pass in Ajax request.
var Folder = { };
$.each($('#Folder').serializeArray(), function() {
Folder[this.name] = this.value;
});
var data = {
Folder: Folder
Periods: periodsArr
};

Partial View not printing values in mvc 5

I'm using ajax call to execute partial view controller action to print max batch number. Everything executes, but the value doesn't print in partial view. On selected dropdown list I'm calling ajax method to execute. Below is my code that i'm using.
Models.Batch.cs
[Required]
[StringLength(100)]
[DataType(DataType.Text)]
[Display(Name = "Batch Number")]
public string BatchNumber { get; set; }
BatchController.cs
public PartialViewResult GetBatchNumber(string CourseID)
{
Context.Batches contBatch = new Context.Batches();
Models.Batches b = new Models.Batches();
b.BatchNumber = contBatch.GetallBatchList().ToList().Where(p => p.CourseId == CourseID).Select(p => p.BatchNumber).Max().FirstOrDefault().ToString();
ViewBag.Message = b.BatchNumber;
return PartialView(b);
}
CreateBatch.cshtml
<div class="col-md-10">
#Html.DropDownListFor(m => m.CourseId, Model.Courses, new { id = "ddlCourse" })
<div id="partialDiv">
#{
Html.RenderPartial("GetBatchNumber", Model);
}
</div>
<script>
$("#ddlCourse").on('change', function () {
var selValue = $('#ddlCourse').val();
$.ajax({
type: "GET",
url: '/Batch/GetBatchNumber?CourseId=' + selValue,
dataType: "json",
data: "",
success: function (data) {
$("#partialDiv").html(data);
},
failure: function (data) {
alert('oops something went wrong');
}
});
});
</script>
</div>
GetBatchNumber.cshtml
#model WebApplication1.Models.Batches
<div class="form-group">
#Html.LabelFor(model => model.BatchNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.BatchNumber)
#Html.ValidationMessageFor(model => model.BatchNumber, "", new { #class = "text-danger" })
</div>
</div>

Ajax call always going in error part

I have demo in mvc where I want to fetch user details based on dropdown, i am using ajax for selectedindex changed event of dropdown to show userdetails in partial view, but ajax call is always going in error part..
Controller :-
public ActionResult Index()
{
var usermodel = new UserModel();
usermodel.listuser = GetUserData();
usermodel.UserId = usermodel.listuser.First().UserId;
usermodel.UserName = usermodel.listuser.First().UserName;
usermodel.UserSalary = usermodel.listuser.First().UserSalary;
return View(usermodel);
}
public PartialViewResult GetUserRecord(int UserId)
{
var userModel = new UserModel();
userModel.listuser = GetUserData();
var user = userModel.listuser.Where(e => e.UserId == UserId).FirstOrDefault();
userModel.UserId = user.UserId;
userModel.UserName = user.UserName;
userModel.UserSalary = user.UserSalary;
return PartialView("_UserTestPartial.cshtml", userModel);
}
private List<UserModel> GetUserData()
{
var listuser = new List<UserModel>();
var user1 = new UserModel();
user1.UserId = 1;
user1.UserName = "Abcd";
user1.UserSalary = 25000;
var user2 = new UserModel();
user2.UserId = 2;
user2.UserName = "bcde";
user2.UserSalary = 35000;
var user3 = new UserModel();
user3.UserId = 1;
user3.UserName = "cdef";
user3.UserSalary = 45000;
listuser.Add(user1);
listuser.Add(user2);
listuser.Add(user3);
return listuser;
}
Model:-
public class UserModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public double UserSalary { get; set; }
public List<UserModel> listuser { get; set; }
public IEnumerable < SelectListItem > UserListItems
{
get
{
return new SelectList(listuser, "UserId", "UserName");
}
}
}
Index View:-
#Html.DropDownListFor(m => m.UserId, Model.UserListItems, "---Select User--- ", new { Class = "ddlStyle", id = "ddlUser" })
<div id="partialDiv">
#Html.Partial("_UserTestPartial")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#ddlUser").on("change", function () {
$.ajax(
{
url: '/User/GetUserRecord?UserId=' + $(this).attr("value"),
type: 'GET',
data: " ",
contentType: 'application/json; charset=utf-8',
success: function (data) {
$("#partialDiv").html(data);
},
error: function () {
alert("error");
}
});
});
});
</script>
Partial View:-
#model Dropdowndemo.Models.UserModel
<fieldset>
<legend>UserModel</legend>
<div class="display-label">
<strong> #Html.DisplayNameFor(model => model.UserId) </strong>
</div>
<div class="display-field">
#Html.DisplayFor(model => model.UserId)
</div>
<div class="display-label">
<strong> #Html.DisplayNameFor(model => model.UserName) </strong>
</div>
<div class="display-field">
#Html.DisplayFor(model => model.UserName)
</div>
<div class="display-label">
<strong> #Html.DisplayNameFor(model => model.UserSalary) </strong>
</div>
<div class="display-field">
#Html.DisplayFor(model => model.UserSalary)
</div>
</fieldset>
Please remove the data: " ", attribute from ajax, if you're not passing any in it.
In the Index remove
#Html.Partial("_UserTestPartial")
This will throw error since you are not passing any model to the partial view in this way.
As you were binding the partial view via ajax call to #partialDiv it will work fine

Posting model data from one View to another in mvc3 using ajx

I want to transfer model data from one View to another View (in a dialog) using Ajax.Actionlink were i am getting null values on Post Action
This is my View
#using (Ajax.BeginForm("", new AjaxOptions { }))
{
for (int i = 0; i < Model.city.Count; i++)
{
<div class="editor">
<p>
#Html.CheckBoxFor(model => model.city[i].IsSelected, new { id = "check-box-1" })
#Html.HiddenFor(model => model.city[i].Id)
#Ajax.ActionLink(Model.city[i].Name, "PopUp", "Home",
new
{
#class = "openDialog",
data_dialog_id = "emailDialog",
data_dialog_title = "Cities List",
},
new AjaxOptions
{
HttpMethod = "POST"
})
#Html.HiddenFor(model => model.city[i].Name)
</p>
</div>
}
}
On using Ajax.Actionlink i am creating a dialog using ajax scripting
My controller class for this View is
public ActionResult Data()
{
var cities = new City[] {
new City { Id = 1, Name = "Mexico" ,IsSelected=true},
new City { Id = 2, Name = "NewJersey",IsSelected=true },
new City { Id = 3, Name = "Washington" },
new City { Id = 4, Name = "IIlinois" },
new City { Id = 5, Name = "Iton" ,IsSelected=true}
};
var model = new Citylist { city = cities.ToList() };
//this.Session["citylist"] = model;
return PartialView(model);
}
another View for displaying Post action data is
#model AjaxFormApp.Models.Citylist
#{
ViewBag.Title = "PopUp";
}
<h2>
PopUp</h2>
<script type="text/javascript">
$(function () {
$('form').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
var checkedAtLeastOne = false;
$('input[id="check-box-2"]').each(function () {
if ($(this).is(":checked")) {
checkedAtLeastOne = true;
// alert(checkedAtLeastOne);
}
});
if (checkedAtLeastOne == true) {
// alert("Test");
$('#div1').show();
$(".dialog").dialog("close");
}
else {
// alert("NotSelected");
$('#div1').hide();
$('#popUp').html(result);
$('#popUp').dialog({
open: function () { $(".ui-dialog-titlebar-close").hide(); },
buttons: {
"OK": function () {
$(this).dialog("close");
}
}
});
}
}
});
return false;
});
});
</script>
<div style="display: none" id="div1">
<h4>
Your selected item is:
</h4>
</div>
#using (Ajax.BeginForm(new AjaxOptions { }))
{
for (int i = 0; i < Model.city.Count; i++)
{
<div class="editor">
<p>
#Html.CheckBoxFor(model => model.city[i].IsSelected,new { id = "check-box-2" })
#Html.HiddenFor(model => model.city[i].Id)
#Html.LabelFor(model => model.city[i].Name, Model.city[i].Name)
#Html.HiddenFor(model => model.city[i].Name)
</p>
</div>
}
<input type="submit" value="OK" id="opener" />
}
#*PopUp for Alert if atleast one checkbox is not checked*#
<div id="popUp">
</div>
and my post controller action result class is
[HttpPost]
public ActionResult PopUp(Citylist model)
{
if (Request.IsAjaxRequest())
{
//var model= this.Session["citylist"];
return PartialView("PopUp",model);
}
return View();
}
My model class is
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class Citylist
{
public IList<City> city { get; set; }
}
You are calling Popup action from actionlink. Instead you should place submit button out of for loop. And give your form right action parameters

How to do Jquery ajax post to controller mvc

I just can't figure out what I am not doing right,From a viewmodel,I try to grab from user {**Tousername and messagebody},#ToUserName** is correctly sent while #Body is null in controller when I debug .I have the following Jquery code:
$("#SendMessage").click(function () {
var message = GrabMessage();
var jsonData = JSON.stringify(message, null, 2);
$.ajax({
url: '#Url.Content("~/Message/Compose/")',
type: 'POST',
data: jsonData,
datatype: 'json',
contentType: 'application/json; charset=utf-8',
success: function () {
$('#default_message').append("message sent ");
switchToSentMessagesTab();
},
error: function (request, status, err) {
alert(status);
alert(err);
}
});
return false;
});
function switchToSentMessagesTab() {
$('a[href="#default_message"]').click();
}
function GrabMessage() {
var touser = $("#ToUserName").val();
var text = $("#Body").val();
var result =
{
Body: text,
ToUserName: touser
};
return result;
}
});
And the razer View:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.ToUserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ToUserName, new { #class ="autocomplete"})
#Html.ValidationMessageFor(model => model.ToUserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Body)
#Html.ValidationMessageFor(model => model.Body)
</div>
<p>
<input id="SendMessage" type="submit" value="Send" />
</p>
}
and controller Action:
[HttpPost]
public ActionResult Compose(PrivateMessageViewModel m)
{
if (User.Identity.IsAuthenticated )
{
if (ModelState.IsValid)
{
var ToUserName = users.Profiles.First(x => x.UserName == m.ToUserName);
PrivateMessage message = new PrivateMessage
{
//do some stuff here:
};
db.SendMessage(message);
return RedirectToAction(//Some view here...)
}
}
return PartialView(m);
}

Resources