Either or Validation in Razor MVC3 - validation

I have a razor view with a couple of textboxes.
I want want to make it so that you either choose one of the textboxes or 3 of the others and you can't submit unless you enter in text in at least one of those choices...
IE you could enter in a social security number, or you could enter in a persons first, last names and Date Of Birth. For the last option, you must enter in the first, last name and the DOB. Is this possible using unobtrusive validation?
The following is my parial
<div id="searchByDemographicsDiv"style="float: left;width: 50%; display:inline; ">
#*#using(Html.BeginForm("SearchByDemographic", "SearchPatients",FormMethod.Post, new{ id = "searchByDemographics"})){*#
#using (Ajax.BeginForm("SearchByDemographic", "SearchPatients", null, new AjaxOptions { HttpMethod = "POST", LoadingElementId = Url.Content("~/Images/ajax-loader.gif"), OnSuccess = "binddata", OnFailure = "FailAlert" }, new { id = "searchByDemographics" })){
<ul>
<li>#Html.Label("SSN", new { #for = "SSN" }) <br />#Html.TextBox("SSN", null, new { id = "SSN", name = "SSN", #class = "SSN" })</li>
</ul>
<ul>
<p>Or</p>
</ul>
<ul>
<li>#Html.Label("FirstName", new { #for = "FirstName" }) <br />#Html.TextBox("FirstName", null, new { id = "FirstName", #class = "demoGrphcs", name = "FirstName" })</li>
<li>#Html.Label("LastName", new { #for = "LastName" }) <br />#Html.TextBox("LastName", null, new { id = "LastName", #class = "demoGrphcs", name = "LastName" })</li>
<li>#Html.Label("dateOfBirth", new { #for = "dateOfBirth" }) <br />#Html.TextBox("dateOfBirth", null, new { id = "dateOfBirth", #class = "demoGrphcs", name = "dateOfBirth" })</li>
<li>#Html.Label("Address1", new { #for = "Address1" }) <br />#Html.TextBox("Address1", null, new { id = "Address1" })</li>
<li>#Html.Label("Address2", new { #for = "Address2" }) <br />#Html.TextBox("Address2", null, new { id = "Address2" })</li>
<li>#Html.Label("City", new { #for = "City" }) <br />#Html.TextBox("City", null, new { id = "City" })</li>
<li>#Html.Label("State", new { #for = "State" }) <br />#Html.TextBox("State", null, new { id = "State" })</li>
<li>#Html.Label("Country", new { #for = "Country" }) <br />#Html.TextBox("Country", null, new { id = "Country" })</li>
<li>#Html.Label("PostCode", new { #for = "PostCode" }) <br />#Html.TextBox("PostCode", null, new { id = "PostCode" })</li>
</ul>
<input type="submit" value="Search By Demographics" class="button" id="submitDemo"/>
}
</div>
I essentially want the user to be able to search by either SSN or the other Demographic info with firstName lastName and DateOfBirth being required fields. If searching by SSN, I want that to be a required field. very complicated I know.
UPDATED**origninal validation on my form elements **UPDATE
$("#searchByDemographics").validate({
rules: {
SSN: {
require_from_group: [1, ".SSN"]
},
FirstName: {
require_from_group: [1, ".demoGrphcs"]
},
LastName: {
require_from_group: [1, ".demoGrphcs"]
},
DateOfBirth: {
require_from_group: [1, ".demoGrphcs"]
}
},
messages : {
SSN: 'Please Enter either a valid SSN or Demographic Info below',
FirstName: 'First name is required',
LastName: 'Last name is required',
DateOfBirth: 'Date of Birth is required'
}
});

I think simple way is pass all these value from model and check it on POST , do validation according to your requirement.

I'm not sure why you want to go for unobtrusive validation in this case because the validation is very specific. Unobtrusive validation makes much sense when the validation you are trying to accomplish is kind of reusable but that's not in your case.
I would suggest you to implement IValidatableObject in the model for server-side validation and do the client-side validation using plain jquery.

Related

C# jQuery Ajax Datatables ASP.NET Core 5 MVC

I am attempting to implement ASP.NET Core SignalR. I am looking for assistance. The project is located at: https://github.com/Talsiter/AspNetCore-SignalR-SqlTableDependency
The issue that I am running into is when a datatable is being populated from jQuery AJAX, no data is being populated into the view.
Items model (Item.cs)
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace InAndOut.Models
{
public class Item
{
[Key]
public int Id { get; set; }
public string Borrower { get; set; }
public string Lender { get; set; }
[DisplayName("Item name")]
public string ItemName { get; set; }
}
}
Items view (Index.cshtml)
#model IEnumerable<InAndOut.Models.Item>
<div class="container p-3">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<div class="card-body">
<table id="myTable" class="table table-bordered table-striped">
<thead>
<tr>
<th>Id</th>
<th>Item Name</th>
<th>Borrower</th>
<th>Lender</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
</div>
#section Scripts {
#* These Scrips are Required *#
<script src="~/js/signalr/dist/browser/signalr.js"></script>
#*This one gives me an error of "ItemsHub undefined"*#
#*<script src="~/js/items01.js"></script>*#
#* This gives me an error "DataTable is not a function"
This probably requires the *#
<link href="//cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css" rel="stylesheet" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js"></script>
<script src="~/js/items03.js"></script>
}
Items JS file (items03.js):
// This is from:
//https://stackoverflow.com/questions/51764211/jquery-datatable-loading-using-ajax-asp-net-mvc
// Does Not Display any data
function getAllMessages() {
$('#myTable').DataTable({
processing: true,
serverSide: false,
ordering: true,
paging: true,
searching: true,
columns: [
{ title: "Id" },
{ title: "ItemName" },
{ title: "Borrower" },
{ title: "Lender" },
{ title: "View Data" }
],
columns: [
{ data: "Id" },
{ data: "ItemName" },
{ data: "Borrower" },
{ data: "Lender" },
{
data: null,
defaultContent: "<button class='tblview'>View Id</button><button class='tblDelete'>Delete</button>"
}
],
ajax: {
"url": "/Item/GetItems",
"type": "GET",
"dataSrc": ''
},
"columnDefs": [
{
"targets": 0,
"visible": false
}
]
});
}
Item controller (ItemController.cs):
// This was updated from:
// https://stackoverflow.com/questions/51705732/jquery-datatable-ajax-no-data-available-mvc
public IActionResult GetItems()
{
var items = new List<Item>
{
new Item { Id = 1, ItemName = "Computer", Borrower = "Justin", Lender = "Don"},
new Item { Id = 2, ItemName = "Mouse", Borrower = "Mark", Lender = "Susan"},
new Item { Id = 3, ItemName = "Monitor", Borrower = "Mark", Lender = "Joe"},
new Item { Id = 4, ItemName = "Keyboard", Borrower = "Candace", Lender = "Angela"},
new Item { Id = 5, ItemName = "Printer", Borrower = "Mike", Lender = "Watson"},
};
// JsonRequestBehavior requires Microsoft.AspNet.MVC
// I do not want to reference it. I want to use Microsoft.AspNetCore.Mvc
//return Json(items, JsonRequestBehavior.AllowGet);
// I referenced this to mitigate the above issue
// https://stackoverflow.com/questions/38578463/asp-net-core-the-name-jsonrequestbehavior-does-not-exist-in-the-current-cont
//return Json(items);
// Error: Cannot read property 'style' of undefined
// This was another option
//return Json(items, new Newtonsoft.Json.JsonSerializerSettings());
// Error: Cannot read property 'style' of undefined
// This seems to be returning the correct data format
// Now the data just is not being displayed in the view
// My error seems to be in the JavaScript
return Json(new { data = items });
}
After many attempts, this is about the closest that I am able to get. While debugging the site, I do not receive any errors, but the mock data does not appear in the items view.
I am suspecting that my issue is in the Items JS file in the getAllMessages() method. I am just not sure how to fix it.
The naming convention for response in asp.net core is camel case instead of pascal case. Also you need remove "dataSrc": ''.
Change like below:
columns: [
{ data: "id" },
{ data: "itemName" },
{ data: "borrower" },
{ data: "lender" },
{
data: null,
defaultContent: "<button class='tblview'>View Id</button><button class='tblDelete'>Delete</button>"
}
],
ajax: {
"url": "/Item/GetItems",
"type": "GET",
//"dataSrc": ''
},

Sent form (list object) to controller AJAX MVC

I want sent form (list of object) with ajax. But the function serialize() in JS doesnt read in controller
JS File:
function save() {
$.ajax({
url: "/Ocena/AddOcene",
method: "POST",
dataType: "html",
data: {
id: $("#KlasaDDL option:selected").val(),
dodaj: $('#formOceny').serializeArray()
},
success: function (html) {
$('#load').html(html);
}
})
}
$(function () {
var llBtn = $('#saveForm');
llBtn.click(function () {
save();
});
});
In controller I have parametrs:
public ActionResult AddOcene(string id, List<Dodaj_ocene> dodaj)
View:
#model List<biblioteka.Dodaj_ocene>
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "formOceny" }))
{
#Html.DropDownListFor(x => Model[0].Przedmiot, (SelectList)ViewBag.Przedmiot, "--Dostępne przedmioty--", new { #class = "form-control" })
#*#Html.DropDownList(m => Model[0].Przedmiot, *#
<p>Wprowadź rodzaj</p>
#Html.TextBoxFor(m => Model[0].Rodzaj, new { #class = "form-control" })
<p>Wprowadź Opis</p>
#Html.TextBoxFor(m => Model[0].Opis, new { #class = "form-control" })
<p>Wybierz wagę ocen:</p>
#Html.DropDownListFor(m => Model[0].Waga, new SelectListItem[] {
new SelectListItem{ Value = "5", Text = "V", Selected = Model[0].Waga == 5 } ,
new SelectListItem{ Value = "4", Text = "IV", Selected = Model[0].Waga == 4 } ,
new SelectListItem{ Value = "3", Text = "III" , Selected =
}, new { #class = "form-control" })
<br /> <br />
<table class="table">
<tr>
</tr>
#for (var index = 0; index < Model.Count; index++)
{
<tr>
<td>#Model[index].ImieNazwisko </td>
<td>
#Html.DropDownListFor(m => Model[index].Wartosc, new SelectListItem[]{
new SelectListItem{ Value = "0", Text = "Brak oceny", Selected = Model[index].Wartosc == 0 } ,
new SelectListItem{ Value = "1", Text = "1" , Selected = Model[index].Wartosc == 1 }
} , new { #class = "form-control" })
</td>
</tr>
}
</table>
<div class="form-group">
<div></div>
<button type="button" class="btn btn-info" id="saveForm">Zapisz</button>
</div>
}
I would be very grateful for a Apparently

How can I prevent a partial view from disappearing upon submit?

I’m using BeginForm inside of a child view. When I submit the form I’m still on the parent view but the child view goes away. I would like for the information to be submitted but the form to remain until the user wants to load another partial view or move away from the page entirely. Is there a way to prevent the page from disappearing upon submit? Here’s what my BeginForm looks like:
using (Html.BeginForm("Action", "Controller", new { fromTeacherPage = true, searchTeacher = instructorName, selectedDepartment = Model.Assignments.FirstOrDefault().departmentNumber, id = Model.Assignments.FirstOrDefault().InstructorId, strCategoryName = #ViewBag.categoryname }, FormMethod.Post, new { #name = "formName", #class = "nameOfClass" }))
{
//code for form here
<button id="submitButton" class="submitButton">Submit</button><br />
}
UPDATE:
<script type="text/javascript">
$(document).ready(function () {
$("#datep").datepicker({ showOn: "both", buttonText: "Select Date", changeMonth: true, changeYear: true, yearRange: "-2:+2", showOtherMonths: true, onSelect: function (date, datepickder) {
var sltdDate = { selectedDate: date };
$.ajax({
type: "GET",
url: "/Schedule/GetSchedule",
data: sltdDate,
datatype: "html",
success: function (data) {
$("#returnedData").html(data);
$("#returnedData #dateContainer").remove();
$("<button>Hide</button>").appendTo("#homeworkUpdateId-0")
}
});
}
});
});
</script>
#{
int? intTeacherID = Convert.ToInt32(HttpContext.Current.Session["intTeacherId"]);
string instructorName = (from x in Model.Enrollments where x.InstructorId == intTeacherID select x.InstructorFullName).FirstOrDefault();
}
<div id="dateContainer">
<label for ="datep">Date: </label><input id="datep" />
</div>
<div id="returnedData">
#if (Model.Assignments != null)
{
using (Html.BeginForm("Action", "Controller", new { fromTeacherPage = true, searchTeacher = instructorName, selectedDepartment = Model.Assignments.FirstOrDefault().departmentNumber, id = Model.Assignments.FirstOrDefault().teacherId, strCategoryName = #ViewBag.categoryname }, FormMethod.Post, new { #name = "formName", #class = "submitAttendance" }))
{
<table>
<tr>
<th>
Grade
</th>
<th>
Attendance
</th>
<th>
Clas Day
</th>
<th>
Assignment Type
</th>
<th>
Overall Grade
</th>
</tr>
#foreach (var assignment in Model.Assignments.Select((x, i) => new { Data = x, Index = i }))
{
int asgnIndex = assignment.Index;
<tr id="rowId+#asgnIndex">
<td>
<div id="homeworkUpdateId-#asgnIndex">
#Html.TextBox("HomeworkGrade", assignment.Data.HomeworkGrade.ToString(), new { style = "width:55px; text-align: center" })
</div>
</td>
</table>
<button id="submitButton" class="submitButton">Submit </button><br />
}
}
</div>
You are using
using(Html.BeginForm()){}
this will refresh the whole page if you only want to reload some section inside your view you have to use
using (Ajax.BeginForm("Action", "Controller", null, new AjaxOptions {UpdateTargetId = "divToUpdate", InsertionMode = InsertionMode.Replace, HttpMethod = "GET"}, new {id = "someIdFOrm"}))

using ajax loading search data to existing data grid

this is my action method
public ViewResult Index(string firstName)
{
// get the list of employees according to the user name
if (firstName == null)
{
return View((from e in db.Employees
where e.IsActive == true
select e).ToList());
}
else
{
return View((from e in db.Employees
where e.IsActive == true && e.FirstName.Contains(firstName )
select e).ToList());
}
}
This is my view
#{
var grid = new WebGrid(source: Model,
defaultSort: "UserName",
rowsPerPage: 15, ajaxUpdateContainerId: "grid");
}
#using (Html.BeginForm())
{
<div class="btn_align">
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Administrator"))
{
<h2>#Html.ActionLink("Create New", "Create")</h2>
}
</div>
<div class="btn_align">
<p>
Find by name:<input class="inputStyle_S" id="firstName" name="firstName" type="text" value="" data-autocomplete= "#Url.Action("QuickSearchFirstName", "ApplyLeave")" />
<input type="submit" id="txtSearch" value="Search" class="btn"/>
</p>
</div>
<div id="grid">
#grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("User Name", format: (item) => item.FirstName + ' ' + item.LastName),
grid.Column("EmployeeType.Type", "Employee Type"),
grid.Column(header: "Action", format: (item) =>
Html.ActionLink("Details", "Details", new { id = item.id}))
)
)
</div>
}
</div>
<div class="leaveChart_bottom"></div>
I used web grid for representing data
I want get search results to exixting grid without refreshing page , after submiting search button (Search by name)
this is the ajax method I used ,but its not working.Can anyone helpme?
you should use #Ajax.BeginForm it will update your grid without refreshing the page. create a partial class for Grid so that you will get it's RenderHtmlString at server side.
In PartailClass
//GridPartail.cshtml
#model SomeModel
#{
var grid = new WebGrid(source: SomeModel,
defaultSort: "UserName",
rowsPerPage: 15, ajaxUpdateContainerId: "grid");
}
<div id="grid">
#grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("User Name", format: (item) => item.FirstName + ' ' + item.LastName),
grid.Column("EmployeeType.Type", "Employee Type"),
grid.Column(header: "Action", format: (item) =>
Html.ActionLink("Details", "Details", new { id = item.id}))
)
)
</div>
now modified your View
#using (#Ajax.BeginForm("Index", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "gridResult" }))
{
<div class="btn_align">
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Administrator"))
{
<h2>#Html.ActionLink("Create New", "Create")</h2>
}
</div>
<div class="btn_align">
<p>
Find by name:<input class="inputStyle_S" id="firstName" name="firstName" type="text" value="" data-autocomplete= "#Url.Action("QuickSearchFirstName", "ApplyLeave")" />
<input type="submit" id="txtSearch" value="Search" class="btn"/>
</p>
</div>
<div id="gridResult">
#html.Partail("GridPartail",Model)
</div>
}
NOTE: instead of using Html.BeginForm use Ajax.BeginForm.in your case you have not bind text box to model so that you will get it's value in formCollection
In Controller
[HttpPost]
public ActionResult Index(formCollection coll)
{
string firstName = coll["firstName"];
// get the list of employees according to the user name
if (firstName == null)
{
var result = from e in db.Employees
where e.IsActive == true
select e).ToList();
return PartailView("GridPartail",result );
}
else
{
//"GridPartail.cshtml" is partial viewName
var result = (from e in db.Employees
where e.IsActive == true && e.FirstName.Contains(firstName )
select e).ToList();
return View("GridPartail",result );
}
}
as in AjaxOption i have mention action method POST and you must be pass UpdateTargetId which specify where your result will appear on the view.

If condition or for loop in a webgrid

I am using this webgrid in my view.
<div class="grid">
#{
var grid = new WebGrid(Model.SearchResults, canPage: true, rowsPerPage: 15);
grid.Pager(WebGridPagerModes.NextPrevious);
#grid.GetHtml(
htmlAttributes: new { #style = "width:100%", cellspacing = "0" },
columns: grid.Columns(
grid.Column(header: "Customer Name", format: (item) => Html.ActionLink((string)item.FullName, "ShowContracts", new { id = item.UserId }, new { #style = "color: 'black'", #onmouseover = "this.style.color='green'", #onmouseout = "this.style.color='black'" })),
grid.Column(header: "SSN", format: item => item.SSN)
))
}
</div>
I search with SSN and display the results in a webgrid. The displayed data is dummy data.
I have a bool AccountVerified in my viewmodel, now I should not give action link to the accounts which are not verified and display text next to them saying account verification pending. Can someone help me on this?
Try the following:
grid.Column(
header: "Customer Name",
format: (item) =>
(bool)item.AccountVerified
? Html.ActionLink(
(string)item.FullName,
"ShowContracts",
new {
id = item.UserId
},
new {
style = "color: 'black'",
onmouseover = "this.style.color='green'",
onmouseout = "this.style.color='black'"
}
)
: Html.Raw("pending")
)
or write a custom HTML helper to avoid this monstrosity and simply:
grid.Column(
header: "Customer Name",
format: item => Html.PendingLink(item)
)

Resources