asp-validation-for not working under foreach due to same name issue - asp.net-core

I am using asp-validation-for under foreach and facing following issues. suppose 3 text controls generated with foreach. I am using the [required] model annotation. "objGenExaminationTemplateChoicesModel" object is of ICollection in main model.
if first text controls is empty system is showing error message with
all 3 text controls.
if second or third is empty system is not
showing any message but don't proceed to post page due to model
error.
<table id="dtChoices" class="table table-borderless table-striped">
<thead class="bg-primary">
<tr>
<th class="text-left"><label asp-for="#Model.objGenExaminationTemplateChoicesModel.FirstOrDefault().ChoiseDescription" class="control-label"></label></th>
<th style="width:30px"><span class="sidenav-icon icon icon-plus-square pull-right" style="font-size:large"> </span></th>
</tr>
</thead>
<tbody>
#foreach (var objGenExaminationTemplateChoiceModel in Model.objGenExaminationTemplateChoicesModel)
{
iCounter = iCounter + 1;
<tr>
<td class="text-left form-group form-group-sm">
<input type="text" asp-for="#objGenExaminationTemplateChoiceModel.ChoiseDescription" class="form-control">
<span asp-validation-for="#objGenExaminationTemplateChoiceModel.ChoiseDescription" class="text-danger"></span>
</td>
<td>
<a href="#" class="text-warning btnDeleteRow" data-toggle="modal" data-target="#deleteConfirmationModalAlert">
<span class="sidenav-icon icon icon-trash pull-right" style="font-size:large"> </span>
</a>
</td>
</tr>
}
</tbody>

The objGenExaminationTemplateChoicesModel is a list model,so the model binding system would find the name by [i].propertyName.Change your code like below:
#model TestVmodel
<form>
<table id="dtChoices" class="table table-borderless table-striped">
<thead class="bg-primary">
<tr>
<th class="text-left"><label asp-for="#Model.objGenExaminationTemplateChoicesModel.FirstOrDefault().ChoiseDescription" class="control-label"></label></th>
<th style="width:30px"><span class="sidenav-icon icon icon-plus-square pull-right" style="font-size:large"> </span></th>
</tr>
</thead>
<tbody>
#{ var iCounter = 0;}
#for (int i = 0; i < Model.objGenExaminationTemplateChoicesModel.Count(); i++)
{
iCounter = iCounter + 1;
<tr>
<td class="text-left form-group form-group-sm">
<input type="text" asp-for="#Model.objGenExaminationTemplateChoicesModel[i].ChoiseDescription" class="form-control">
<span asp-validation-for="#Model.objGenExaminationTemplateChoicesModel[i].ChoiseDescription" class="text-danger"></span>
</td>
<td>
<a href="#" class="text-warning btnDeleteRow" data-toggle="modal" data-target="#deleteConfirmationModalAlert">
<span class="sidenav-icon icon icon-trash pull-right" style="font-size:large"> </span>
</a>
</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="aa" />
</form>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
My testing model:
public class TestVmodel
{
public List<ObjGenExaminationTemplateChoicesModel> objGenExaminationTemplateChoicesModel { get; set; }
}
public class ObjGenExaminationTemplateChoicesModel
{
[Required]
public string ChoiseDescription { get; set; }
}
Result:

Related

ASP.NET Core - How would I set a name with ID of HTML element on CSHTML

How would I set a name with ID of HTML element on CSHTML?
<tr>
<td>
#item.Items.ItemID
</td>
<td>
#item.Items.ItemModelDescription
</td>
<td class="text-right">
<input id="#item.Items.ItemID + 'UnitPrice'" class="form-control text-right" value="#item.Items.ItemUnitPrice" />
</td>
<td class="text-right">
<input id="#item.Items.ItemID + 'Quantity'" class="form-control text-right" value="#item.Quantity" oninput="return change_quantity('#item.Items.ItemID')"/>
</td>
<td class="text-right">
#(item.Quantity * item.Items.ItemUnitPrice)
</td>
<td>
<a class="btn btn-sm btn-danger btn-rounded" asp-controller="purchaseorderheader" asp-action="Remove" asp-route-id="#item.Items.ItemID"><span class="fa fa-trash"></span></a>
</td>
</tr>
I can't get the value of HTML element using javascript is there anyway or proper way of setting an id of each quantity input? Or any keywords to search regarding this one.
According to your code and description, I assume you want to calculate the cost based on the Quantity and the ItemUnitPrice. If that is the case, please refer to the following sample code, you can refer it to change your code:
ViewModel:
public class ItemViewModel
{
public int ItemId { get; set; }
public string ItemDescription { get; set; }
public decimal ItemUnitPrice { get; set; }
public decimalc Quantity { get; set; }
}
Index.cshtml: we could set the id attribute like this id='Quantity_#item.ItemId', after rendering, the output like Quantity_XXX:
#model IEnumerable<WebApplication6.Models.ItemViewModel>
<table class="table">
<thead>
<tr>
...
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#item.ItemId
</td>
<td>
#item.ItemDescription
</td>
<td class="text-right">
<input id="ItemUnitPrice_#item.ItemId" class="form-control text-right" type="text" value="#item.ItemUnitPrice" />
</td>
<td class="text-right">
<input id='Quantity_#item.ItemId' class="form-control text-right txtquantity" type="text" value="#item.Quantity" oninput="return change_quantity(this,#item.ItemId)" />
</td>
<td class="text-right">
#(item.Quantity * item.ItemUnitPrice)
</td>
<td>
<a class="btn btn-sm btn-danger btn-rounded" asp-controller="purchaseorderheader" asp-action="Remove" asp-route-id="#item.ItemId"><span class="fa fa-trash"></span></a>
</td>
</tr>
}
</tbody>
</table>
Then at the end of the Index.cshtml page, add the following JavaScript: we could use the parent() and closest() method to find the current row, and then find the relates elements in this row.
#section Scripts{
<script>
function change_quantity(e, itemid) {
//find the item unit price.
var price = $("#" + "ItemUnitPrice_" + itemid).val();
//find the quantity value.
var quantity = $("#" + "Quantity_" + itemid).val();
//calculate the cost and change the html content.
$(e).parent().closest("tr").find(".text-right:last").html((price * quantity).toFixed(2).toString());
}
</script>
}
The output like this:
you can use this approach
#foreach (var item in Model)
{
<tr id="tr-#item.ItemId">
<td>
#item.ItemId
</td>
<td>
#item.ItemDescription
</td>
<td class="text-right">
<input id="ItemUnitPrice_#item.ItemId" class="form-control text-right" type="text" value="#item.ItemUnitPrice" />
</td>
<td class="text-right">
<input id='Quantity_#item.ItemId' class="form-control text-right txtquantity" type="text" value="#item.Quantity" oninput="return change_quantity(this,#item.ItemId)" />
</td>
<td class="text-right">
#(item.Quantity * item.ItemUnitPrice)
</td>
<td>
<a class="btn btn-sm btn-danger btn-rounded" asp-controller="purchaseorderheader" asp-action="Remove" asp-route-id="#item.ItemId"><span class="fa fa-trash"></span></a>
</td>
</tr>
}

How to click on inneHTML String with Selenium?

I am iterating throw a table getting the rows:
<div class="table-responsive">
<table class="table table-striped" id="noteTable">
<thead>
<tr>
<th style="width: 20%" scope="col"></th>
<th style="width: 20%" scope="col">Title</th>
<th style="width: 60%" scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr id="notes" th:each="note : ${notes}">
<td>
<a class="btn btn-success" id="btn-edit-note"
th:onclick="showNoteModal([[${note.id}]],
[[${note.noteTitle}]], [[${note.noteDescription}]])">Edit</a>
<a th:href="#{|/home/delete-note/?title=${note.noteTitle}|}"
id="btn-delete-note" class="btn btn-danger">Delete</a>
</td>
<th scope="row" th:text="${note.noteTitle}"></th>
<td th:text="${note.noteDescription}"></td>
</tr>
</tbody>
</table>
</div>
With this code written below :
public void deleteNote(String title, String description) {
WebDriverWait wait = new WebDriverWait(driver, 2);
WebElement btnDeleteNote;
js.executeScript("arguments[0].click();", tabNotes);
WebElement homeWait = wait.until(webDriver ->
webDriver.findElement(By.id("btn-delete-note")));
for (WebElement note : notes) {
String noteTitle = note.getAttribute("innerHTML");
System.out.println(noteTitle);
if (noteTitle.contains(title)) {
js.executeScript("DELETE NOTE HERE);
}
}
}
When I get the row innerHTML I receive this result as String :
<td>
<a class="btn btn-success" id="btn-edit-note" onclick="showNoteModal(1,
"Note Title Test", "Note Description Test")">Edit</a>
Delete
</td>
<th scope="row">Note Title Test</th>
<td>Note Description Test</td>
- My question is: Thinking that the lines of a Table are Dynamic, how can I click on "< a >" tag element in the string row?
The element has to be unique because it has an id so you can just target it like this:
element = driver.find_element_by_id("btn-delete-note")
print(element.text)

Can not send list of objects from view to controller using tag helper in asp.net core 2.2

I have the following view and I want to send list of object from view to controller and I used asp-for tag helper for data binding but action in controller receives null
#model IEnumerable<GoodsList>
<form method="post" asp-action="SubmitList" asp-controller="Submit">
<table class="table table-bordered">
<thead>
<tr>
<th width="2%">number</th>
<th width="20%">Name</th>
<th width="20%">Brand</th>
<th width="20%">Quantity</th>
<th width="20%">Scale</th>
<th width="8%">operation</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Number</td>
<td><input type="text" readonly="readonly" asp-for="#item.GoodsName" class="form-control" /></td>
<td><input type="text" readonly="readonly" asp-for="#item.BrandName" class="form-control" /></td>
<td><input type="text" readonly="readonly" asp-for="#item.Quantity" class="form-control" /></td>
<td><input type="text" readonly="readonly" asp-for="#item.ScaleName" class="form-control" /></td>
<td>
<select class="form-control" asp-items="#(new SelectList(item.Status,"Id","Name"))">
</select>
</td>
</tr>
}
<tr>
<td colspan="6">
<textarea class="form-control" rows="3" readonly="readonly" cols="5">#Model.Select(s => s.Description).First()</textarea>
</td>
</tr>
</tbody>
</table>
<a class="btn btn-primary">Back</a>
<input type="submit" value="Submit" class="btn btn-success" style="width:auto">
</form>
And Here is my controller which receives null
[HttpPost]
//It receives null
public IActionResult SubmitList(IEnumerable<GoodsList> model)
{
return View();
}
And the Model
public class GoodsList
{
public GoodsList()
{
Status = new List<ApprovalStatus>();
}
public int Number { get; set; }
public string GoodsName { get; set; }
public string BrandName { get; set; }
public int? Quantity { get; set; }
public string UserName { get; set; }
public string RankName { get; set; }
public int? RequestId { get; set; }
public string ScaleName { get; set; }
public IList<ApprovalStatus> Status { get; set; }
}
Any solution?
Thanks in advance
Change your razor view like below:
#model IEnumerable<GoodsList>
<form method="post" asp-action="SubmitList" asp-controller="Submit">
<table class="table table-bordered">
<thead>
<tr>
<th width="2%">number</th>
<th width="20%">Name</th>
<th width="20%">Brand</th>
<th width="20%">Quantity</th>
<th width="20%">Scale</th>
<th width="8%">operation</th>
</tr>
</thead>
<tbody>
#{ var i = 0;}
#foreach (var item in Model)
{
<tr>
<td>#item.Number</td>
<td><input type="text" readonly="readonly" name="[#i].GoodsName" asp-for="#item.GoodsName" class="form-control" /></td>
<td><input type="text" readonly="readonly" name="[#i].BrandName" asp-for="#item.BrandName" class="form-control" /></td>
<td><input type="text" readonly="readonly" name="[#i].Quantity" asp-for="#item.Quantity" class="form-control" /></td>
<td><input type="text" readonly="readonly" name="[#i].ScaleName" asp-for="#item.ScaleName" class="form-control" /></td>
<td>
<select class="form-control" name="[#i].Status[0].Id" asp-items="#(new SelectList(item.Status,"Id","Name"))">
</select>
</td>
</tr>
i++;
}
<tr>
<td colspan="6">
<textarea class="form-control" rows="3" readonly="readonly" cols="5">#Model.Select(s => s.Description).First()</textarea>
</td>
</tr>
</tbody>
</table>
<a class="btn btn-primary">Back</a>
<input type="submit" value="Submit" class="btn btn-success" style="width:auto">
</form>
Result:
Another way:
#model IList<GoodsList> //change this
//..
<tbody>
#for(var i = 0;i<Model.Count();i++)
{
<tr>
<td>#Model[i].Number</td>
<td><input type="text" readonly="readonly" asp-for="#Model[i].GoodsName" class="form-control" /></td>
<td><input type="text" readonly="readonly" asp-for="#Model[i].BrandName" class="form-control" /></td>
<td><input type="text" readonly="readonly" asp-for="#Model[i].Quantity" class="form-control" /></td>
<td><input type="text" readonly="readonly" asp-for="#Model[i].ScaleName" class="form-control" /></td>
<td>
<select class="form-control" asp-for="#Model[i].Status[0].Id" asp-items="#(new SelectList(Model[i].Status,"Id","Name"))">
</select>
</td>
</tr>
}
<tr>
<td colspan="6">
<textarea class="form-control" rows="3" readonly="readonly" cols="5">#Model.Select(s => s.Description).First()</textarea>
</td>
</tr>
</tbody>
</table>
<a class="btn btn-primary">Back</a>
<input type="submit" value="Submit" class="btn btn-success" style="width:auto">
</form>

Error TokenMismatchException in VerifyCsrfToken.php line 68:

I want to do multiple edit, I want to edit from the data I checked following script .blade, I found the TokenMismatchException error in VerifyCsrfToken.php line 68: when updating.
<form name="form" action="{{url('/update-kb')}}" method="post" onsubmit="return deleteConfirm();"/>
<div class="table table-responsive">
<table id="example1" class="table table-bordered">
<thead>
<tr class="info">
<th width="3%"><input type="checkbox" name="select_all" id="select_all" value=""/></th>
<th>No</th>
<th>Data lengkap</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php $i = 1; ?>
#foreach( $datasiswa as $row )
<tr>
<td>
<label class="checkbox-inline"><input type="checkbox" name="checked_id[]" class="checkbox" value="{{$row->id}}"/>
</label>
</td>
<td width="5%">{{ $i }}</td>
<td width="95%">
<table class="table">
<tr>
<td class="info">Nama panggilan</td>
<td>{{$row->nm_panggilan}}</td>
<td class="warning">Pekerjaan ibu</td>
<td>{{$row->pekerjaan_ibu}}</td>
</tr>
<tr>
<td class="info">Jenis kelamin</td>
<td>{{$row->jenis_kelamin}}</td>
<td class="warning">No. Handphone</td>
<td>{{$row->hp_ibu}}</td>
</tr>
<tr>
<td class="info">Tempat, Tanggal lahir</td>
<td>{{$row->tempat}}, {{$row->tanggal_lahir}}</td>
<td class="warning">Alamat</td>
<td>{{$row->alamat}}</td>
</tr>
<tr>
<td class="info">Status anak</td>
<td>{{$row->status_anak}}</td>
<td class="warning">Golongan darah</td>
<td>{{$row->goldar}}</td>
</tr>
<tr>
<td class="info">Agama</td>
<td>{{$row->agama}}</td>
<td class="warning">Nama wali</td>
<td>{{$row->nm_wali}}</td>
</tr>
<tr>
<td class="info">Kewarganegaraan</td>
<td>{{$row->kewarganegaraan}}</td>
</tr>
<tr>
<td class="info">Anak ke-</td>
<td>{{$row->anak_ke}}</td>
</tr>
<tr>
<td class="info">Kelas</td>
<td>{{$row->kelas}}</td>
</tr>
</table>
</td>
<td>
<a href="{!! url('/'.$row->id.'/edit-siswa') !!}">
<button class="btn btn-default btn-block"><i class="fa fa-edit"></i></button><br>
</a>
<a href="{!! url('/'.$row->id.'/delete-siswa') !!}">
<button class="btn btn-danger btn-block"><i class="fa fa-trash"></i></button>
</a>
</td>
</td>
</tr>
<?php $i++; ?>
#endforeach
</tbody>
</table>
<div class="col-md-3">
<input type="submit" class="btn btn-danger" name="delete_submit" value="Hapus"/>
</div>
</div>
</form>
But I still have error, what causes it?
public function updatekb($id, Request $request)
{
$data = Datasiswa::find($id);
if (isset($request->delete_submit)) {
$idArr = $request->checked_id;
foreach ($idArr as $id) {
DB::update('update tb_siswa, tb_pernyataan set tb_pernyataan.kelas = "cekcek" where tb_pernyataan.kelas = "TK A" and tb_siswa.sekolah = "KB TK KHALIFAH 25" and id = "' . $id . '" ');
}
return back();
Session::flash('sukses', 'Data berhasil di update', compact('data'));
}
}
Add below to your form element.
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
Some answers are suggesting to disable csrf protection which is possible but NOT RECOMENDED. This leaves your application vulnureable.
Laravel use CSRF token to verify user request. so you have to use it on yevery request if you want to disable it then you can disable it from See here how to disable it or you can use it as
{{ csrf_field() }}
or
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
You can resolve this issue in two ways:-
First One:-
{{ csrf_field() }}
or
<input type="hidden" name="_token" value="{{ csrf_token() }}"/> // add this in form
Or the other (simpler) way, inside your app\Http\Middleware/VerifyCsrfToken.php add
protected $except = [
'update-kb', // your route name
];
Hope it helps!

How to get the updated count of rows in a table after changing the page number

Actually in the table i'm working on there is pagination. I could get the count of rows present in the first page.
When i change the page number, table row count is not getting updated as per the second page.
How to force selenium to update the count after changing the page number. page refresh is not the solution as i need to navigate to second page again
public Boolean checkMessageIsFailed(String message, String channelNameToCheck, String channelTypeToCheck) {
UIPublish uiPublish = new UIPublish(driver);
Boolean isMessageSent = null;
SimplifyUtils.waitTillElementFound(uiPublish.currentPageNumber, 60);
//getting the page count
int pageCount = Integer.parseInt( uiPublish.totalPages.getText());
for (int j=1; j< pageCount;pageCount++)
{
//getting the rows present in the table
int messagesCount = uiPublish.listOfTextInMessages.size();
for (int i = 0; i < messagesCount; i++)
{
//getting the text from each row to match
//matching the text of the required message sent with the messages present in the sent messages
if (uiPublish.listOfTextInMessages.get(i).getText().equalsIgnoreCase(message))
{
String currentChannel = driver.findElements(By.xpath("//*[#id='inbox-wrapper']//tr["+ (i + 1)+ "]")).get(i).getAttribute("data-original-title");
}
}
//navigating to naxt page if the condition is not matched
uiPublish.navigateToNextPage.click();
}
return isMessageSent;
}
<div class="grid simple">
<div class="grid-body no-border email-body">
<br>
<div class="row-fluid">
<div id="email-list" class="table-responsive">
<form id="schMsgFORM" name="schMsgFORM" action="/viewSentSchMessage.action"
method="post">
<table class="table table-striped table-hover" id="emails">
<thead>
<tr>
<th>
</th>
<th>Social Channel
</th>
<th>Message
</th>
<th>Scheduled Time
</th>
<th>Actions
</th>
</tr>
</thead>
<tbody>
<tr id="outputWTFrUjUyYlE1d1piNG1XUmNuUFBnUT09">
<td class="small-cell v-align-middle" style="width: 2%">
<div class="checkbox check-success ">
<input name="msgcheckbox" id="chkboxWTFrUjUyYlE1d1piNG1XUmNuUFBnUT09"
value="WTFrUjUyYlE1d1piNG1XUmNuUFBnUT09" type="checkbox">
<label for="chkboxWTFrUjUyYlE1d1piNG1XUmNuUFBnUT09"></label>
</div>
</td>
<td style="width: 150px">
<div class="account-sent">
<div class="row">
<div class="display-inline">
<div class="profile-pic" data-toggle="tooltip" title=""
data-original-title="galloway360">
<img class="account-profile"
src="http://pbs.twimg.com/profile_images/378800000473105984/b0ad2b50b4fb81303d32720afea274ea_normal.png"
alt="">
<div class="social-icon-pub">
<span
class="social-icon-twitter img-responsive social-icon-box">
</span>
</div>
</div>
</div>
</div>
</div>
</td>
<td style="width: 50%">
<div class="muted message-wrap">
<br>
Source: Auto 2016/12/08 17:35:30 Message: How's your day?
</div>
<p class="sch-details">
Sent by: Nagarjuna reddy
<em>Scheduled from Profile :
NA
</em>
</p>
</td>
<td style="width: 15%">
<p class="muted m-t-5">
2016-12-08 05:35 PM
</p>
<p class="region">
(Asia/Calcutta)
</p>
</td>
<td style="width: 10%">
<a
href="/social/editUpdate?s360securetoken=SU0wxc4jrR8DE8Lf5hzKnRYasjg&schMsgId=WTFrUjUyYlE1d1piNG1XUmNuUFBnUT09&pageSource=publish"
data-toggle="tooltip" title="" type="button"
class="btn btn-success btn-small" data-original-title="Edit">
<i class="fa fa-pencil">
</i>
</a>
</td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
</div>
</div>