I am following this tutorial: https://www.codeproject.com/Articles/424461/Implementing-Consuming-ASP-NET-WEB-API-from-JQuery
to help me implement my web API. But I have something different. This is my index:
#model IEnumerable<dsr_vaja1.Models.Kosarica.Kosarica>
#{
ViewBag.Title = "kosarica";
Layout = "~/Views/Shared/MasterStran.cshtml";
}
<div id="accordion">
<h3>Igre</h3>
<div>
<table class="table table-hover ">
<tr>
<th>
#Html.DisplayNameFor(model => model.ime_igre)
</th>
<th>
#Html.DisplayNameFor(model => model.cena_igre)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ime_igre)
</td>
<td>
#Html.DisplayFor(modelItem => item.cena_igre)
</td>
</tr>
}
</table>
<button onclick="AddEmployee();return false;">Add Employee</button>
</div>
</div>
As you can see, here I have a LIST of items named Kosarica. This is my web api:
public void Post(Nakup nakup)
{
nakup.Id = 1;
nc.Nakupi.Add(nakup);
nc.SaveChanges();
}
My web api and everything works completely fine, now I would just like to know how I would use this function:
function AddGame() {
jQuery.support.cors = true;
var game = {
ID: model.id,
ime_igre: model.ime_igre,
};
$.ajax({
url: 'http://localhost:8080/API_SVC/api/EmployeeAPI',
type: 'POST',
data:JSON.stringify(employee),
contentType: "application/json;charset=utf-8",
success: function (data) {
WriteResponse(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
FOR ALL of the items in the list after the user clicks a button.
**edit
Isn't there a simpler way to do this? I just realized that the first line of code is a list
#model IEnumerable
model is a list of objects. As you can see below in the foreach loop, I loop through the items in model. So can I just pass the model to the jquery function somehow?
Create a javascript function, eg :
function AddGamesForAllItems(){
// Select the table through JQuery Selector Here
//loop through the elements of the table Here
//Call the AddGame function passing by paremeters the needed elements from the table... You have to declare parameters inside you AddGame function
}
Call the AddGamesForAllItems function when you need it eg: Button click event.
Hope it could help !
Related
Hello guys i am working on a projekt where i can add articles to a cart. My cart is a partialview.When i add a Article to my cart the old data isnt stored and only one (the new article) article is added to my cart.
This is the code for the Post in my codebehind Im adding a Postition with RandomNumbers for testing
[BindProperty]
public List<Position> ArticlePositions { get; set; } = new List<Position>();
public PartialViewResult OnPostAddPosition(List<Position> articlePositions)
{
Random myObject = new Random();
Random myObject1 = new Random();
articlePositions.Add(new Position
{
ArticleAmount = myObject1.Next(10, 100),
ArticleId = myObject.Next(10, 100)
});
var partialViewResult = new PartialViewResult()
{
ViewName = "_ArticlePositonsPartial",
ViewData = new ViewDataDictionary<List<Position>>(ViewData, articlePositions),
};
return partialViewResult;
}
This is my Partialview with the Model:
#model List<Rechnungen.Models.Position>
<div class="tableFixHead">
<table class="table table-striped text-center table-sm ">
<thead class="table-dark ">
<tr>
<th style="width:72.5px" class="">Anzahl</th>
<th style="width:72.5px" class="">ID</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr id="">
<td style="width:72.5px" class="pt-2 ">
<span class="TBarticleAmount">#item.ArticleAmount</span>
</td>
<td style="width:72.5px" class="pt-2 ">
<span class="TBarticleType">#item.ArticleId</span>
</td>
</tr>
}
</tbody>
</table>
</div>
Where i render the Partial:
<div id="MyPartialView">
#{
await Html.RenderPartialAsync("_ArticlePositonsPartial", Model.ArticlePositions, ViewData);
}
</div>
How i add A Position to cart:
#Html.AntiForgeryToken()
<button class="btn btn-outline-secondary" onclick="GetPartialView()"><i class="fa-solid fa-plus"></i>Hinzufügen</button>
And this is my Javascript for it:
function GetPartialView() {
$.ajax({
type: "POST",
url: '?handler=AddPosition',
dataType: "html",
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
success: function(data) {
$("#MyPartialView").html(data);
},
error: function(result) {
alert("fail");
}
});
}
My code is working so far, when i add something to my cart my site is looking like this=>
When i click a second time on the add button my site looks like this=>
So my problem is that the Data in ArticlePositions isnt stored. When i Debugg my Code the ArticlePositions are NULL when the Post Method is called.
HTTP is stateless, so any state created in your OnPostAddPosition method is destroyed at the end of the request. You have to implement strategies to persist state across requests. There are a number of options available in Razor Pages. You should research them to identify the most suitable one for your application:
https://www.learnrazorpages.com/razor-pages/state-management
I have here a view model which has two list objects. I will display them as two tables in my view. I've already created EditorFor for them. I'll place four buttons (move one right, move all right, move one left, move all left) for the exchange operations. I've googled everywhere and no goal on how to accomplish that, because I need to move the entire object, replace all "name" and "id" tags, reorder indexes and so on, because this way my lists will be posted correctly. I'm using Datatables.net and jQuery too.
Does anybody have a clue on how to do that?
Thank you in advance. The code goes below
EDIT
Since list elements on ASP.NET MVC are indexed like "ListName_0__Code"(for Id) and "ListName[0].Code" (for name) how to properly reorder these indexes?
EditorFor
#model ViewModels.UserPermissionDetails
<tr id="#Model.Id">
<td>
#Html.HiddenFor(m => m.Code)
#Html.HiddenFor(m => m.Login)
#Html.HiddenFor(m => m.Name)
#Html.HiddenFor(m => m.IdEmpUser)
#Html.DisplayFor(m => m.Code)
</td>
<td>#Html.DisplayFor(m => m.Login)</td>
<td>#Html.DisplayFor(m => m.Nome)</td>
</tr>
View
<table id="tbBlock">
<thead>
<tr>
<th>Code</th>
<th>Login</th>
<th>Name</th>
</tr>
</thead>
<tbody>
#Html.EditorFor(model => model.BlockList)
</tbody>
</table>
<table id="tbAllow">
<thead>
<tr>
<th>Code</th>
<th>Login</th>
<th>Name</th>
</tr>
</thead>
<tbody>
#Html.EditorFor(model => model.AllowList)
</tbody>
</table>
Exchange method (jQuery)
function addElement(OriginTableId, DestinyTableId, OriginListName, DestinyListName) {
var originTb = $(OriginTableId).DataTable(); //initialize DataTable.Net for origin table
var destinyTb = $(DestinyTableId).DataTable(); //initialize DataTable.Net for destiny table
var objectLine = $('#' + originTb.$('tr.selected').attr('id')); //get selected line that will be moved
//Name replacing code piece
var elementsFromLine = $(objectLine.children()[0]).children().toArray();
elementsFromLine.forEach(function (item, index, array) {
$(item).attr('id', $(item).attr('id').replace(OriginListName, DestinyListName)); //Replace 'OriginListName_0' with 'DestinyListName_0'
$(item).attr('name', $(item).attr('name').replace(OriginListName, DestinyListName)); //Replace 'OriginListName[0]' with 'DestinyListName[0]'
});
//Reordering code piece here, how to?
$(DestinyTableId + ' tbody').append(objectLine.clone(true, true));
objectLine.parent().remove();
}
It will be much easier for you to calculate and set the name values with the index only before you submit the form, not for every move action.
#Html.HiddenFor(m => m.Code, new { #class = "code" } })
// same for all the inputs you send to server
$("button[type='submit']").on("click", function (e) {
e.preventDefault();
updateIndexes();
$("form").submit();
});
function updateIndexes() {
$("#tbAllow").find("tbody").children("tr").each(function (i) {
var prefix = "BlockList[" + i + "].";
var $tr = $(this);
$tr.find("input.code").attr("name", prefix + "Code");
$tr.find("input.login").attr("name", prefix + "Login");
// same for all the inputs you send to server
});
};
I have a very huge form in my application with a lot of different inputs and a lot of lists in my model. So i will try to add/delete the lists without sending the complete model to the server.
I tried several ways now but i don´t find a clean way. You can imagine my model like:
public class EditSomething
{
public string name { get; set;}
public List<something> somethingList { get; set;}
// a lot other fields...
public EditSomething(EditSomethingFromDatabase editSomethingFromDatabase)
{
name = editSomethingFromDatabase.Name;
somethingList = new List<SomethingModel>();
foreach(var something in editSomethingFromDatabase.Something)
{
somethingList.Add(new SomethingModel(editSomethingFromDatabase.Something));
}
}
}
The other model looks similar but without lists.
In the view i have a table for the model:
<h2>Something</h2>
<div id="SomethingDiv">
<table id="SomethingTable">
<thead>
<tr>
<th>#Html.Label("SomethingName")</th>
<th>#Html.Label("SomethingID")</th>
<th></th>
</tr>
</thead>
<tbody id="SomethingTableBody">
#Html.EditorFor(x => x.somethingList)
</tbody>
</table>
<p>
<input type="button" name="addSomething" value="Add Something" id="AddSomething">
</p>
</div>
the jquery of the addSomething is:
$('#AddSomething').click(function () {
$.ajax({
url: '#Url.Action("AddSomething", "SomethingModels")',
data: { tableSize: $('#SomethingTable tr').length },
cache: false,
success: function (html) { $('#SomethingTable tr:last').after(html); }
});
The controller method AddSomething is:
public ActionResult AddSomething (int tableSize)
{
SomethingModel something= new SomethingModel(null, (-2) * (tableSize + 1));
return PartialView(""~/Views/EditorTemplates/EditSomethingModel.cshtml"", something);
}
And at least i have a editor template in EditorTemplates as for editorfor and partialview. This have the important informations i want to send to the server:
#model SomethingModel
<tr>#TextBoxFor(m=>m.SomethingName)<td>
#TextBoxFor(m=>m.SomethingID)
So the problem now is, that the submit of the first view only post the SomethingModel to the server who already existed while opening the view but the new SomethingModel from the AddMutation method aren´t in the post. Someone an idea to fix this?
Edit: Changed the path to the editor template so i only need one view for the EditorFor and PartialView.
Edit2: To solve the main problem i created a view as following and use it as partial view. Now the data is send to the server correctlly. Only the validation on client side is still not working:
#model SomethingModel
<tr>#TextBoxFor(m=>m.SomethingName, new{Name="somethingList["+ViewBag.ListId+"].SomethingName")<span class="field-validation-valid" data-valmsg-for="somethingList[#ViewBag.ListId].SomethingName" data-valmsg-replace="true"></span><td>
<tr>#TextBoxFor(m=>m.SomethingID, new{Name="somethingList["+ViewBag.ListId+"].SomethingID")<span class="field-validation-valid" data-valmsg-for="somethingList[#ViewBag.ListId].SomethingID" data-valmsg-replace="true"></span><td>
</tr>
In the AddSomething method i added the ViewBag.ListId with the id of the next element in the list.
It seems a reasonable enough approach, but You've not shown your EditorTemplate, so I'm going to assume its something like:
#model List<something>
#for(int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Html.DisplayFor(m => m[i].Id) #Html.HiddenFor(m => m[i].Id)</td>
<td>#Html.EditorFor(m => m[i].Name)</td>
</tr>
}
Your ajax method should return the HTML of a row - and this is important... the form fields need to be named 1 above the last one in the table.
So when you view the rendered source of your table (before adding any new fields it might look like:
...
<tbody>
<tr>
<td>1 <input type="hidden" name="something[0].Id" value="1"/></td>
<td><input type="text" name="something[0].Name" value="somename" /></td>
</tr>
</tbody>
You need to ensure the html returned by the ajax method for your new row is:
<tr>
<td>2 <input type="hidden" name="something[1].Id" value="2"/></td>
<td><input type="text" name="something[1].Name" value="somenewname" /></td>
</tr>
ie. the number inside the brackets is the next index for the items in something. If there is a gap in the indexes (or they overlap) then the new items will not get parsed.
EDIT - to get client side validation to work for the new fields alter your jquery ajax success callback as follows:
$('#AddSomething').click(function () {
$.ajax({
url: '#Url.Action("AddSomething", "SomethingModels")',
data: { tableSize: $('#SomethingTable tr').length },
cache: false,
success: function (html) {
$('#SomethingTable tr:last').after(html);
$.validator.unobtrusive.parse('#SomethingTable');
}
});
I have a small problem.
My action is :
public ViewResult SearchForRooms(int HotelDDL)
{
List<Room> roomsInHotel = bl.ReturnRoomsPerHotel(HotelDDL);
return View(roomsInHotel);
}
Here is the jquery that is calling the action:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#HotelDDL").change(function () {
var text = $("#HotelDDL option:selected").text();
var value = $("#HotelDDL option:selected").val();
alert("Selected text=" + text + " Selected value= " + value);
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
});
});
});
</script>
And finally, here is the View that should be called:
#model IEnumerable<RoomReservation.Entities.Entities.Room>
#{
ViewBag.Title = "Search";
}
<h2>Result</h2>
<table>
<tr>
<th>
City
</th>
<th>
Hotel
</th>
<th>
Room label
</th>
<th>
Number of beds
</th>
<th>
Price per night
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelitem=>item.Hotel.City.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Hotel.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.NumberOfBeds)
</td>
<td>
#Html.DisplayFor(modelItem => item.PricePerNight)
</td>
</tr>
}
</table>
Everthing is working ok (databse return all rooms correctly) except final view rendering.
I have tried Phil's tool but it doesn't give me any suspicious hints:
RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
So, why is it not showing after jscript send it's post method to SearchForRooms()?
Thank you
P.S. If you need any other piece of code please just say so.
Note that doing an ajax post will not refresh or redirect the page like a classic post would.
The view is not showing because there is no where to place it. You post successfully, and return a view successfully but then do nothing with it. If you want to show the returned view, then you have to append it to the dom somehow. Here is a common method:
<div id="successDiv"></div>
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#HotelDDL").change(function () {
var text = $("#HotelDDL option:selected").text();
var value = $("#HotelDDL option:selected").val();
alert("Selected text=" + text + " Selected value= " + value);
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
}, function(result){//add callback for success - result is the returned view
$("#successDiv").html(result);//place the view inside of the div
});
});
});
</script>
Comment Response
#TunAntun - You should use a classic post if you want the view to have its own page. There is no way to accomplish this from ajax. You could do this with javascript though
$.post("/Home/SearchForRooms",
{
HotelDDL: $("#HotelDDL option:selected").val()
}, function(result){//add callback for success - result is the returned view
$("#successDiv").html(result);//place the view inside of the div
});
would become
var postForm = document.createElement("form");
postForm.setAttribute("method","post");
postForm.setAttribute("action","/Home/SearchForRooms");
var postVal = document.createElement("input");
postVal.setAttribute("type","hidden");
postVal.setAttribute("name","HotelDDL");
postVal.setAttribute("value",$("#HotelDDL option:selected").val() );
postForm.appendChild(postVal);
document.body.appendChild(postForm);
$(postForm).submit();
This will dynamically issue the post you wanted. Then in your controller it will properly redirect or return a view. It is highly suggested that when returning a view from a [HttpPost] that you use RedirectToAction and then return the view from a [HttpGet] method in order to prevent refresh from reposting old data.
Hi I'm working on a table
I cannot atm update the table without the site refreshing.
I need a way to easily
Add a row ,Delete a row, Modify a row in a table's content.
my table is build like this.
{....}
#using (Html.BeginForm())
{
<fieldset>
<legend>ShiftTypes</legend>
<table class="EditableTable" id="EditableTableShiftTypes">
<thead>
<tr>
<th>
#:
</th>
<th>
ShiftName:
</th>
<th>
ShiftCode:
</th>
<th>
Suplement:
</th>
<th>
ExtraSuplement:
</th>
<th>
</th>
</tr>
</thead>
<tbody>
#foreach (BPOPortal.Domain.Models.ShiftTypeView type in Model.ShiftTypeList)
{
<tr>
<td>
#type.ID
</td>
<td>
#type.ShiftName
</td>
<td>
#type.Name
</td>
<td>
#type.Supplement
</td>
<td>
#type.OneTimePayment
</td>
<td>
<button>
Delete</button>
</td>
</tr>
}
<tr>
<td>
<label>
</label>
</td>
<td>
#Html.Editor("ShiftName")
</td>
<td>
#Html.Editor("ShiftCode")
</td>
<td>
#Html.Editor("Suplement")
</td>
<td>
#Html.DropDownList("ExtraSuplement", new SelectListItem[] { new SelectListItem() { Text = "yes", Value = "true", Selected = false }, new SelectListItem() { Text = "No", Value = "false", Selected = false } }, "--Choose--")
</td>
<td>
<button id="AddButton">
Add</button>
</td>
</tr>
</tbody>
</table>
<button type="submit" id="Gem">
Save</button>
</fieldset>
{....}
I've Tried to use Ajax in the following way but it refreshes the entire page.
{....}
var ID= 2;
$("#AddButton").click(function(){
var ShiftName= $('#ShiftName').attr('value');
var ShiftCode= $('#ShiftCode').attr('value');
var Suplement= $('#Suplement').attr('value');
var ExtraSuplement= $('#ExtraSuplement').attr('value');
$.ajax({
url: '#Url.Action("AddData", "ShiftTypesConfiguration")',
data: { ID: ID.toString(), ShiftName: $('#ShiftName').attr('value'), ShiftCode: $('#ShiftCode').attr('value'), Suplement: $('#Suplement').attr('value'), ExtraSuplement: $('#ExtraSuplement').attr('value') },
type: 'POST',
// contentType: 'application/json; charset=utf-8;',
dataType: 'json',
success: function (response)
{
function fnClickAddRow() {
$('#EditableTableShiftTypes').dataTable().fnAddData([
response.ID,
response.ShiftName,
response.ShiftCode,
response.Suplement,
response.ExtraSuplement,
"<button>Delete</button>"]); }
}
});
ID++;
});
{....}
</script>
My Method in the Controller that should handle the request.
public JsonResult AddData(string ID, string ShiftName, string ShiftCode, string Suplement, string ExtraSuplement)
{
TableViewModel tableViewModel = new TableViewModel();
tableViewModel.ID = ID;
tableViewModel.ShiftName= ShiftName;
tableViewModel.ShiftCode= ShiftCode;
tableViewModel.Suplement= Suplement;
tableViewModel.ExtraSuplement= ExtraSuplement;
return Json(tableViewModel);
}
However it doesn't seem to work Now I'm asking For Ideas and ways to make this better/easier/Working
Edit:saw a copy past Error
EDIT2: I've now changed it slightly I found that I had a error in how my script was running this is the latest. there are still problems but at least now I can see and describe the error.
this is what I changed the script is now
$("#AddButton").click(function (event) {
event.preventDefault();
var ShiftName = $('#ShiftName').attr('value');
var ShiftCode = $('#ShiftCode').attr('value');
var Suplement = $('#Suplement').attr('value');
var ExtraSuplement = $('#ExtraSuplement').attr('value');
$.ajax({
url: '#Url.Action("AddData", "ShiftTypesConfiguration")',
data: { ID: ID.toString(), ShiftName: ShiftName, ShiftCode: ShiftCode, Suplement: Suplement, ExtraSuplement: ExtraSuplement },
type: 'POST',
// contentType: 'application/json; charset=utf-8;',
dataType: 'json',
success: function (response) {
function fnClickAddRow() {
$('#EditableTableShiftTypes').dataTable().fnAddData([
response.ID,
response.ShiftName,
response.ShiftCode,
response.Suplement,
response.ExtraSuplement,
"<button>Delete</button>"]);
}
}
});
ID++;
});
now with the help of firebug I've seen that the values are back on the page but before I can see them the page is refreshed.
I am not writing in code here, but here is how you should do it.
On Add/Edit/Delete make an ajax call to your action. In your Action implement your operation (Add/Edit/Delete) and depending on operation completed successfully or failed due to some error, return a true/false flag as json.
Then in the success function success: function (response){} of the ajax call, check wether the value returned is a true/false which means success or error.
And then using some jquery you can add a row or delete a row from the table.
Check out these links : http://viralpatel.net/blogs/dynamically-add-remove-rows-in-html-table-using-javascript/