How to consume asp.net webapi with knockout - asp.net

I am new to knockout and asp.net webapi, but I am trying to learn. I am missing something, as i cannot perform a get(or a post,put...)
here is my webapi method
public string GetAllData()
{
List<Task> llistTask = new List<Task>();
Task lobjTask = new Task();
lobjTask.title = "some title";
lobjTask.isDone = false;
llistTask.Add(lobjTask);
return Newtonsoft.Json.JsonConvert.SerializeObject(llistTask);
}
my knockout code
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/knockout-2.2.0.js"></script>
<script src="Scripts/jquery-1.8.2.min.js"></script>
</head>
<body>
<h3>Tasks</h3>
<form data-bind="submit: addTask">
Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
<button type="submit">Add</button>
</form>
<ul data-bind="foreach: tasks, visible: tasks().length > 0">
<li>
<input type="checkbox" data-bind="checked: isDone" />
<input data-bind="value: title" />
<%-- Delete--%>
</li>
</ul>
You have <b data-bind="text: incompleteTasks().length"> </b> incomplete task(s)
<span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span>
<script type="text/javascript">
function Task(data) {
this.title = ko.observable(data.title);
this.isDone = ko.observable(data.isDone);
}
function TaskListViewModel() {
// Data
var self = this;
self.tasks = ko.observableArray([]);
self.newTaskText = ko.observable();
self.incompleteTasks = ko.computed(function () {
return ko.utils.arrayFilter(self.tasks(), function (task) { return !task.isDone() });
});
// Operations
self.addTask = function () {
self.tasks.push(new Task({ title: this.newTaskText() }));
self.newTaskText("");
};
self.removeTask = function (task) { self.tasks.remove(task) };
// Load initial state from server, convert it to Task instances, then populate self.tasks
$.getJSON("http://localhost:51958/api/tasks/GetAllData", function (allData) {
var mappedTasks = $.map(allData, function (item) { return new Task(item) });
self.tasks(mappedTasks);
});
}
ko.applyBindings(new TaskListViewModel());
</script>
</body>
</html>
The output is 39 rows of null data, which doesnt make sense to me. what am i missing?

The problem is in the handling results of the $.getJSON() function. It returns you a string, not a JSON object, and when you do $.map() later you're iterating 39 characters of your string, but not the objects you need.
To fix it you need to parse your string as a JSON:
$.getJSON("http://localhost:51958/api/tasks/GetAllData", function (allData) {
allData = $.parseJSON(allData);
var mappedTasks = $.map(allData, function (item) { return new Task(item) });
self.tasks(mappedTasks);
});
Update:
I was really interested, why do you get a string instead of a real object as you should get in case of $.getJSON() function. And the reason is your WebApi method. As far as it returns a string, WebAPI engine converts it additionally to a JSON string (it doesn't care that you've already done it). As a result you have twice JSONified object and jQuery can't parse it.
All you need to do is to return not a string but a List<Task> in your WebAPI method and not to JSON it:
public List<Task> GetAllData()
{
List<Task> llistTask = new List<Task>();
...
return llistTask;
}
And you can leave your JS code as you had it (no additional parseJSON), because now you'll get a real object.

Try using the ko.mapping plugin. It puts the individual objects in form knockout likes.
code would look like
// initial state from server, convert it to Task instances, then populate self.tasks
$.getJSON("http://localhost:51958/api/tasks/GetAllData", function (allData) {
self.tasks = ko.mapping.fromJSON(allData);
});

Related

How to get the dynamic button's id ASP.Net Core

I am trying to find a way to send the id of the clicked button to the backend. The problem is that I am creating lots of buttons with one method but the id is different.
#foreach (var item in Model.showManager.GetMovies())
{
i++;
#if (Model.user.IsAdmin == true)
{
<input class="btn_confirm" type="submit" id=i value="Delete"/>
}
}
The point is that every button is created with different id and I want to send that id to the backend.
Update
My demo is a MVC project, I have a DynamicButtonController and a Index view:
DynamicButtonController:
public class DynamicButtonController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult Index(int id)
{
return View();
}
}
Index view :
#for (var i = 0; i < 5;i++ )
{
<input class="btn_confirm" type="submit" id=#i value="Delete" />
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
$(".btn_confirm").click(function()
{
var data = (this).id;
$.ajax({
type: "POST",
url: '/DynamicButton/Index/',
data: { id: data }
});
});
</script>
result:
If you use Razor pages, you can refer to the below demo,use asp-route-id="#i"
ButtonIdModel:
public class ButtonIdModel : PageModel
{
public void OnGet()
{
}
public void OnPost(string id)
{
}
}
ButtonId.cshtml:
#page
#model yourproject.Pages.ButtonIdModel
<form method="post">
#for (var i = 0; i < 5;i++ )
{
<input class="btn_confirm" type="submit" id=#i value="Delete" asp-route-id="#i" />
}
</form>
The point is that every button is created with different id and I want
to send that id to the backend.
Well, based on your issue, you want to bind all the button ids then want to pass those Ids in your backend.
However, another answer has guided you how to pass id to your controller. Nonetheless, it doesn't resolve your main concern that is how to pass the list of ids on button submit.
Algorithm:
As said earlier, first you have to get the list of button ids which has been generated from your foreach loop and you have to push them in an array, finally need to pass those in your controller (backend). Here, importantly you have to keep in mind, it doesn't matter how the button been generated, for loop or foreach loop the fact is your button should have class name of same type and the ids for instance: class="myBtnClass btn btn-danger" and id="btnId:#i"
Solution:
View:
#{
ViewData["Title"] = "ViewGetDynamicButtonsID";
}
<div>
#for (var i = 1; i < 5; i++)
{
<input class="myBtnClass btn btn-danger" id="btnId:#i" value="Delete:#i" style="margin-bottom:2px" /> <br />
}
<input type="submit" id="btnSubmit" class="btn btn-success" value="Submit" />
</div>
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script>
$(document).ready(function () {
$("#btnSubmit").on("click", function () {
var ids = [];
$(".myBtnClass").each(function () {
//Getting All Button Ids and Pusing in array
ids.push($(this).attr("id"));
});
$.ajax({
type: "POST",
url: 'http://localhost:5094/stuff/GetAllButtonId',
datatype: "json",
data: { buttonids: ids },
success: function (res) {
console.log(res);
alert("It works")
},
error: function () {
alert("It failed");
}
});
return false;
});
});
</script>
}
Controller:
public IActionResult CreateDynamicButton()// This is for loading the view
{
return View();
}
[HttpPost]
public IActionResult GetAllButtonId(List<string> buttonids) // This for submit the button request.
{
return Ok(buttonids);
}
Note: I have defined Button Ids as List<string> thus you can do it as your convenient type
Output:

how to return a value from JsonResult to the bootstrap fileinput

Good evening, I'm using the api bootstrap fileinput and I wonder if you can return a value with ContetResult and uses it in my View.
my Test Controller method ContentResult (just a test):
public ContentResult upload()
{
string name = "";
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i];
name = file.FileName;
}
return Content("{\"name\":\"" + name + "\"}", "application/json");
}
and my View:
<input id="input-701" name="kartik-input-701[]" type="file" multiple=true class="file-loading" />
<input type="text" class="file_name" />
<script type="text/javascript">
$("#input-upload").fileinput({ 'showUpload': true, 'previewFileType': 'any' });
$("#input-701").fileinput({
uploadUrl: '#Url.Action("upload", "Home")', // server upload action
uploadAsync: false,
maxFileCount: 50,
sucess: function (e, data) {
$('.file_name').html(data.result.name);
}
});
</script>
so I want to do something like this illustrative atributte: sucess
Thanks for the help!
Just Insert value in textbox
$('.file_name').val(data.result.name);

Confusion about how to insert database using XmlHttpRequest object

everybody.I am trying to learn how to use XmlHttpRequest object and look for some examples on the net .I have found this code below and made some changes .Then create a table and added single field called "name"with value varchar .Everything seemed ok .But When i exacute that code I have notice that nothing inserted to the database.So I am wondering is that something wrong or missing in this code or any problem with database I have created .I have no idea
<title></title>
<script type="text/javascript">
function XmlHttpObj() {
var xhr = null;
// Tarayıcımızın ActiveXObject desteği olup olmadığını kontrol ediyoruz.
// İnternet Explorer'da gerçekleştirmek için Microsoft.XMLHTTP
try {
xhr = new ActiveXObject("MsXml2.XMLHTTP");
}
catch (e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
if (typeof XMLHttpRequest != "undefined") {
xhr = new XMLHttpRequest();
}
}
}
return xhr;
}
var talep = XmlHttpObj();
function Listen() {
if (talep.readyState == 4 && talep.status == 200) {
var sonuc = talep.responseText;
if (sonuc != null) {
alert("Kayıt Eklendi");
}
else {
alert("Hata Meydana Geldi");
}
}
}
//veritabanına ürün ekleme yapacağımız fonksiyon
//onreadystatechange ile durum değişikliği kontrolü yaptık.
function Ekle() {
talep.open("POST", "Webform1.aspx");
talep.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
talep.onreadystatechange = Listen;
talep.send("mail=" + document.all.Text1.value);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input id="Text1" type="text" /><br />
<input id="Button1" type="button" value="Ürün Ekle" onclick="Ekle()"/>
And this is aspx.cs file
if (!string.IsNullOrEmpty(Request.Form["mail"]))
{
try
{
//SqlConnection sqlcon = new SqlConnection("server=.\\sqlexpress;database=northwind;trusted_connection=true");
//SqlCommand sqlcmd = new SqlCommand("insert into productss (name) values (#ad)", sqlcon);
//sqlcmd.Parameters.AddWithValue("#ad", Request.Form["mail"]);
//sqlcon.Open();
//sqlcmd.ExecuteNonQuery();
//sqlcon.Close();
}
catch (Exception)
{
throw;
}
}
I strongly recommend that you do not use XmlHttpRequest directly. It has many complexities and it is very difficult to get it to work on all browsers. I would recommend using PageMethods. It can be done using a ScriptManager or, better yet, using jQuery. For a good article about the latter, see this: Using jQuery to directly call ASP.NET AJAX page methods

How to populate asp:LinkButton from Json data response

first of all apologies for my english.
I'm a newby in json area.
My problem is that i can't parse the data recived in a json response into a asp:LinkButton or whatever asp:element, coz i can't create a correct sintax.
Especifically, What I'm trying to do, is this:
<script type="text/javascript">
$.getJSON("http://www.carqueryapi.com/api/0.3/?callback=?", { cmd: "getMakes", min_year:"1941", max_year:"2012"}, function (data) {
var makes = data.Makes;
for (var i = 0; i < makes.length; i++) {
($("<asp:LinkButton ID=\"lb" + i +"\" runat=\"server\" />").text(makes[i].make_display )).appendTo("#lbProva");
}
});
<script>
<ul id="lbProva" class="lb_prova" >
</ul>
I hope that someone could help me coz i've tryed many possibilities but no one was the right one.
Thank u in advance.
You can't create asp.net server controls in javascript on client side. If you want to use json data on client side, you must apply it to already generated html controls.
Actually, you can create server controls only on a server. So the question is how to pass AJAX call response to server and enforce it to refresh desired area on a page.
First variant
<script type="text/javascript">
$(function () {
$.getJSON("http://www.carqueryapi.com/api/0.3/?callback=?", { cmd: "getMakes", year: "2009" },
function (data) {
//The 'data' variable contains all response data.
var makes = $.map(data.Makes, function (make) { return make.make_display; }).join(";");
document.getElementById("<%= CarMakersHiddenField.ClientID %>").value = makes;
__doPostBack("<%= CarMakersUpdatePanel.ClientID %>", "");
});
});
</script>
<asp:UpdatePanel runat="server" ID="CarMakersUpdatePanel" UpdateMode="Conditional">
<ContentTemplate>
<asp:HiddenField runat="server" ID="CarMakersHiddenField" />
<asp:BulletedList runat="server" ID="MakersList" DisplayMode="LinkButton">
</asp:BulletedList>
</ContentTemplate>
</asp:UpdatePanel>
Server code:
protected void Page_Load(object sender, EventArgs e)
{
MakersList.Items.Clear();
foreach (var maker in CarMakersHiddenField.Value.Split(';'))
{
MakersList.Items.Add(maker);
}
}
Second approach is more siutable if you need to pass to server some complex object like array of makers objects. In that case you can serialize this object to JSON string on client and deserialize it on server. Looks like previous version with bit changes:
<script type="text/javascript">
$(function () {
$.getJSON("http://www.carqueryapi.com/api/0.3/?callback=?", { cmd: "getMakes", year: "2009" },
function (data) {
//The 'data' variable contains all response data.
var serializedString = Sys.Serialization.JavaScriptSerializer.serialize(data.Makes);
document.getElementById("<%= CarMakersHiddenField.ClientID %>").value = serializedString;
__doPostBack("<%= CarMakersUpdatePanel.ClientID %>", "");
});
});
</script>
Markup left the same as in the first version.
Server code:
[Serializable]
public class Make
{
public string make_id;
public string make_display;
public bool make_is_common;
public string make_country;
}
protected void Page_Load(object sender, EventArgs e)
{
MakersList.Items.Clear();
if (!String.IsNullOrEmpty(CarMakersHiddenField.Value))
{
var serializer = new DataContractJsonSerializer(typeof(Make[]));
using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(CarMakersHiddenField.Value)))
{
var makes = serializer.ReadObject(stream) as Make[];
if (makes != null)
{
foreach (var maker in makes)
{
MakersList.Items.Add(new ListItem(maker.make_display, maker.make_id));
}
}
}
}
}

MVC 1.0 Ajax.BeginForm() submit inside an Html.BeginForm()

I have a View for creating a new account in my application. This view starts with Html.BeginForm() and hits the right controller (Create) no problems.
I decided to add an Ajax.BeginForm() so that I could make sure an account with the same name doesn't already exist in my application.
When I click the submit using either button it goes to the same controller (Create). To try and differentiate which submit button was clicked, I put in a check to see if the request is Ajax then try to run a different code path. But Request.IsAjaxRequest() doesn't fire. What is my best bet to implement this functionality in an existing form with MS Ajax?
<% using (Html.BeginForm()) {%>
..............
<% using(Ajax.BeginForm("Echo",
new AjaxOptions() { UpdateTargetId = "EchoTarget" }))
{ %>
Echo the following text:
<%=Html.TextBox("echo", null, new { size = 40 })%>
<input type="submit" value="Echo" />
<% } %>
<div id="EchoTarget">
controller code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(User newUser)
{
if (Request.IsAjaxRequest())
{
return Content("*you hit the ajax button");
}
else
{ //regular create code here.....
}
</div>
If you insist on multiple form usage..use Javascript in a some function like this
<SCRIPT>
function InnerFormSubmitter(dataForm, actionForm) {
actionForm.innerHTML = dataForm.innerHTML;
actionForm.submit();
}
</SCRIPT>
<form name="yourButton" action="ValidateSomething" method="post"></form>
<form name="mainForm" action="SavedData" method="post">
<input type="textbox" name="text1">
<input type="textbox" name="text2">
<button name="validateUserButton" id="FormButton" onChange=
"InnerFormSubmitter (this.form, document.getElementById('yourButton'))">
</button>
</form>
Hope this helps!
Addendum on jQuery usage for your scenario:
Since you wanted a link:
Check Availability
function isValidUser(userId) {
var url = "<CONTROLLER>/<ACTION>/" + userId;
$.post(url, function(data) {
if (data) {
// callback to show valid user
} else {
// callback to show error/permission
}
});
}
And you controller should have:
[AcceptVerbs("POST")]
public bool IsValidUser(int id) {
// check availability
bool allow = CheckUser();
// if allow then insert
if (allow) {
//insert user
return true;
} else {
return false;
}
}
Further Update on jQuery:
Instead of
document.getElementById('UserIdent').value
you can use
$('#UserIdent').val();
Update on JSON usage
The JsonResult class should be used in the Controller and $.getJson function in the View.
$(function() {
$('#yourLinkOrButton').click(function() {
$.getJSON("<CONTROLLER>/GetUserAvailability/", null, function(data) {
$("#yourDivorLablel").<yourFunctionToUpdateDiv>(data);
});
});
public JsonResult GetUserAvailability()
{
//do all validation and retrieval
//return JsonResult type
}
You cannot nest forms, ever, in any HTML page, no matter how you generate the form. It isn't valid HTML, and browsers may not handle it properly. You must make the forms siblings rather than children.

Resources