Sorry for the newbie question, I'm working with KnockoutJS and I am trying to get the base64String value from an observable and store it inside another observable before sending it off.
Why do I need to do that?
Well for some reason when the base64String is passed it has multiple layers to the object which get sent over as NULL.
Any help or suggestion will be appreciated.
var CreateSalesVM = {
UserId: ko.observable(),
Name: ko.observable(),
Phone: ko.observable(),
Email: ko.observable(),
Item: ko.observable(),
Description: ko.observable()
This piece is what I am having the issue with
IMAGETWO: ko.observable({
base64StringArray: ko.observableArray()
}),
IMAGE: ko.computed({
read: function () {
return IMAGETWO().base64StringArray();
},
deferEvaluation: true
}),
/**************\
btnCreateSales: function () {
// IMAGE = this.IMAGETWO().base64StringArray();
console.log("Image text ", this.IMAGE());
//console.log("Host usrl ", urlHostPath);
//console.log("Ko is ", ko.toJSON(this));
$.ajax({
url: urlPath,
type: 'post',
dataType: 'json',
data: ko.toJSON(this),
contentType: 'application/json',
success: function (result) {
//console.log("This was a success");
// window.location.href = urlPath + '/';
alert(ko.toJSON(this));
// console.log("Ko is ", ko.toJSON(this));
},
error: function (err) {
//console.log("Ko is ", ko.toJSON(this));
if (err.responseText == "success")
{
//console.log("This was an erro success", urlPath);
// window.location.href = urlPath + '';
}
else {
alert(err.responseText);
// console.log("This was an error ", urlHostPath );
}
},
complete: function () {
}
});
}
};
ko.applyBindings(CreateSalesVM);
IMAGETWO is a method of your VM object. You must specify the object while calling a function, otherwise it will look in a global scope for it. So, you may use either:
IMAGE: ko.computed({
read: function () {
return this.IMAGETWO().base64StringArray();
},
deferEvaluation: true
}, CreateSalesVM)
or
IMAGE: ko.computed({
read: function () {
return CreateSalesVM.IMAGETWO().base64StringArray();
},
deferEvaluation: true
})
This fails because you didn't specify on which object to call IMAGE (and by default it will be called on window).
In IMAGE, your view model does not exist yet because you are using object notation.
You need to change the way you define your view model, from object to class and add the object in IMAGETWO().base64StringArray(); as follows:
var CreateSalesVM = function () {
var self = this;
this.UserId = ko.observable();
this.Name = ko.observable();
this.Phone = ko.observable();
this.Email = ko.observable();
this.Item = ko.observable();
this.Description = ko.observable();
this.IMAGETWO = ko.observable({
base64StringArray: ko.observableArray()
});
this.IMAGE = ko.computed({
read: function () {
return self.IMAGETWO().base64StringArray();
//^^^^ note this
},
deferEvaluation: true
});
}
var myViewModel = new CreateSalesVM();
Whenever you call ko.toJSON(), you'll get a copy of your VM serialized as JSON. In this case that you need to post your object using ajax, all you have to do is override the toJSON() function to remove the IMAGETWO property and add IMAGE property with the transformation (to base 64) needed.
var CreateSalesVM = {
UserId: ko.observable(),
Name: ko.observable(),
Phone: ko.observable(),
Email: ko.observable(),
Item: ko.observable(),
Description: ko.observable(),
IMAGETWO: ko.observable({base64StringArray: ko.observableArray()})
}
CreateSalesVM.prototype.toJSON = function() {
var copy = ko.toJS(this); // clean copy
copy.IMAGE = this.IMAGETWO().base64StringArray(); // create desired property to send
delete copy.IMAGETWO; //remove the undesired property
return copy; //return the copy
};
Check-out the original post here.
Related
A list of images (treasures) are displayed to the user, here the user will choose a single image which will be stored in the Learner_treauser table:
List<The_Factory_Chante.Models.Treasure> tresh;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
tresh = db2.Treasures.ToList();
foreach (var item in tresh)
{
if (item.itemImage != null)
{
string imageBase = Convert.ToBase64String(item.itemImage);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
}
<img id="#item.treasureID" src="#imageSource" onclick="return MakeSure(#item.treasureID)" />
}
}
The function called when an image is chosen. In this function the image is sent over to a webservice method to be saved to the database, and the page is reload for an update to take place:
function MakeSure(treshID) {
var id = treshID
$.ajax({
url: "../../WebService.asmx/MakeSure",
data: "{ 'id': '" + id + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
window.location.reload();
};
However this is not very pleasant on the user's point of you. A better way would be to update without refreshing the page.
Here is the Webservice method that receives the chosen image id and stores it in the Learner_Treasure table.
public void MakeSure(int id)
{
using (The_FactoryDBContext db = new The_FactoryDBContext())
{
Learner_Treasure learnTreasure = new Learner_Treasure();
learnTreasure.dateCompleted = DateTime.Today;
learnTreasure.learnerID = UserInfo.ID;
learnTreasure.treasureID = id;
db.Learner_Treasure.Add(learnTreasure);
db.SaveChanges();
}
Code to call Learner_Treasure table.
List<The_Factory_Chante.Models.Learner_Treasure> lern;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
<img id="#item.treasureID" src="#imageSource"/>
}
}
This code will show the user all the images they have chosen, however in if I take away window.location.reload(); this code is only updated when the page reloads. Meaning that the user will not see their chosen image immediately after they have chosen it.
What I want to do is update the code that calls the Learner_Table without refreshing the page.
There is another way to approach this problem, you could use the SignalR library.
This is what you would need to do:
View
// Include the SignalR Script
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
// Provide a dynamic proxy for SignalR
<script src="~/signalr/hubs"></script>
// Define hub connection(see below)
var hub = $.connection.yourHub;
// This is what the Hub will call (Clients.All.getImage(imageSource);)
hub.client.getImage = function (img) {
var image = '<img id="' + img.treasureId + '" src="data:image/jpg;base64,' + img.image + '"';
$(image).appendTo("body");
};
// Start the connection to the hub
// Once we have a connection then call the getLearnerTreasureItem on the Hub
$.connection.hub.start().done(function () {
var id = // whatever
hub.server.getLearnerTreasureItem(id);
};
Hub
public class YourHub : Hub
{
public void GetLearnerTreasureItem()
{
// All your code
List<The_Factory_Chante.Models.Learner_Treasure> lern;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
}
}
// This will now call the getImage function on your view.
Clients.All.getImage(imageSource);
}
}
Information on the dynamic proxy
The way I approach this is by making a partial View for the code that needs to be refreshed
public PartialViewResult UserImages(your paramaters here)
{
your code here
}
And then after successful $.ajax I refresh it
var id = treshID
$.ajax({
url: "../../WebService.asmx/MakeSure",
data: "{ 'id': '" + id + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
$.ajax({
url: "/UserImages",
data: your data model here,
success(function(html)){
$("#yourPartialViewWrapperHere").html(html));
}
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
Your problem is the onclick event handler here:
<img id="#item.treasureID" src="#imageSource" onclick="return MakeSure(#item.treasureID)" />
In the MakeSure() function you don't return anything. So you have two options, change your MakeSure() function to return false at the end, or change the onclick event to return false after the first function call in the image element, like this onclick="MakeSure(#item.TreasureID); return false;"
Also you will have to remove the window.location.reload(); from the MakeSure() function.
Side note, it seems you are mixing up your DbContext in your view, if that's the case, this is very bad practice. You should put your data access behind some sort of service layer that serves as a mediator between the view and your data.
Update
Ok after reading your question a few times I understand your problem
The problem is your second piece of code.
List<The_Factory_Chante.Models.Learner_Treasure> lern;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
<img id="#item.treasureID" src="#imageSource"/>
}
}
}
}
This calls the DB and gets a list of Learner_Treasure objects which you use to output on view. Server side code gets executed once every page request, this is exactly what is happening. It will not asynchronously update without a request to the server.
You need to implement an ajax request to pull the latest Learner_Treasure list into the view. Again this comes down to the first side note I gave, the reason is because you are mixing your dbcontext with your view and expecting it to update on the fly. If you implement a layer which serves your view with the data (controller), you could call this asynchronously and have the page update without it reloading.
For instance you could write a call in your controller to get a single LearnerTreasure item in json.
[HttpGet]
public ActionResult GetLearnerTreasureItem(int Id)
{
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) {
learnerTreasureItem = db2.Learner_Treasure.FirstOrDefault(x => x.Id == Id);
return Json(new { image = Convert.ToBase64String(learnerTreasureItem.itemImage), treasureId = learnerTreasureItem.TreasureID }, JsonRequestBehavior.AllowGet);
}
}
And then call it with ajax in your view, like you did with the update.
$.ajax({
cache: false,
type: "GET",
url: '/YOURCONTROLLERNAME/GetLearnerTreasureItem?id=1',
contentType: 'application/json',
dataType: "json",
success: function (data) {
//build image element
var image = '<img id="' + data.treasureId + '" src="data:image/jpg;base64,' + data.image + '"';
//add the image to where you need it.
$(image).appendTo("body");
},
error: function (xhr) {
alert("Error occurred while loading the image.");
}
});
I hope this helps.
Update in treasures images list
<img id="#item.treasureID" src="#imageSource" onclick="return MakeSure(this, #item.treasureID)" />
read that param in MakeSure method. also I just assume Learner_Treasure images listed in ul named 'ulLearnerTreasure'.
function MakeSure(sender,treshID) {
var id = treshID;
var imgSrc = $(sender).attr("src");
$.ajax({
url: "../../WebService.asmx/MakeSure",
data: "{ 'id': '" + id + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
var li = '<li><img id ="'+ treshID +'"src="'+ imgSrc +'" /></li>';
$("#ulLearnerTreasure").append(li);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
};
I would implement it using HtmlHelpers, like so: (as someone suggested, using db code directly is not a good practice, you need to change that.)
public static class HTMLHelpers
{
public static IHtmlString TreasureImages(this HtmlHelper helper, List<The_Factory_Chante.Models.Learner_Treasure> lern)
{
StringBuilder sb = new StringBuilder();
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
sb.Append("<li><img id='#item.treasureID' src='#imageSource'/></li>");
}
}
}
}
return new HtmlString(sb.ToString());
}
}
Placeholder for your images:
<ul id="TreaureImagesSection">
</ul>
In your cshtml page, load the list with this script, the first time or whenever you need the updated list
<script>
$.ajax({
cache: false,
type: "GET",
url: '/YOURCONTROLLER/TreasuresList',
contentType: 'application/json; charset=utf-8',
success: function (data) { // the data returned is List<The_Factory_Chante.Models.Learner_Treasure>
$("#TreaureImagesSection").html('#Html.TreasureImages(data)');
},
error: function (xhr) {
alert("Error occurred while loading the image.");
}
});
</script>
What I'm trying to do:
Create a chart and have it display data from the server (held in a C# object) every x mminutes. From googling using JSON (which I've never used before) would be best practice.
What I have so far:
I have the backend C# (using MVC 5) getting the correct data, lots of objects with lots of properties, some I want to display in the chart, others I don't.
I'v also started on a JSON function in my Index.cshtml which is where my graph is (currently set with static data, it's a simple jQuery plug-in).
The problem:
Unsure how to get specific object properties, to the JSON data and then to the chart data.
What would be the best way of achieving this?
Code:
Controller:
// GET: Graphs
public ActionResult Index()
{
return View();
}
public static List<server> GetServer()
{
Api api = new Api();
List<server> sList = api.GetServerStats();
return sList;
}
Script in INdex:
<script src="~/Scripts/canvasjs.min.js"></script>
<script type="text/javascript">
window.onload = function () {
var chart = new CanvasJS.Chart("someChart", {
title: {
text: "Space left on Server vs Total"
},
data: [
{
type: "column",
name: "Totals",
showInLegend: true,
dataPoints: [
{ label: "Space", y: 20 }
]
},
{
type: "column",
name: "Used",
showInLegend: true,
dataPoints: [
{ label: "Space", y: 10 }
]
}
],
axisY: {
prefix: "",
suffix: "GB"
}
});
chart.render();
}
$(document).ready(function () {
window.onload(function () {
$.ajax({
type: "POST",
url: "GraphController/GetServer",
data: { someParameter: "some value" },// array of values from object or just object
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
// need to push into jQuery function
}
});
});
});
</script>
Returning a serialised list of objects couldn't be easier with MVC, it takes a lot of the heavy lifting out of it for you if you just return a JsonResult:
public ActionResult GetServer() {
var api = new Api();
var = api.GetServerStats();
return Json(sList);
}
Debug the success of your ajax call to find out if result is what you want and expect, and then pass it to your chart script.
NOTE: From your use of wording (i.e. 'lots'), I'd recommend cutting down your list of server properties you return to your view. This is a perfect candidate for creating what's called a view model. This view model would be a kind of 'lite' version of your full server object. It would improve efficiency of serialisation for starters and, semantically, makes more sense.
I was doing same thing with highcharts and here is an approximate solution for you:
public ActionResult GetServer()
{
Dictionnary<server> sList = new Dictionnary<string,object>();
sList.Add("Totals",new{
type= "column",
name= "Totals",
showInLegend= true,
dataPoints= new List<dynamic>(){
new{ label= "Space", y= 20}/*,
new{ label= "label2", y= 30},*/
}
});
sList.Add("Totals",new{
type= "column",
name= "Used",
showInLegend= true,
dataPoints= new List<dynamic>(){
new{ label= "Space", y= 10}/*,
new{ label= "label2", y= 40},*/
}
});
return Json(sList, "text/json", JsonRequestBehavior.AllowGet);
}
Change window.onload=function(){} in
function drawChart(serverData){
var chart = new CanvasJS.Chart("someChart", {
title: {
text: "Space left on Server vs Total"
},
data: serverData,
axisY: {
prefix: "",
suffix: "GB"
}
});
chart.render();
}
$(document).ready(function () {
$.ajax({
type: "POST",
url: "GraphController/GetStuff",
data: { someParameter: "some value" },
// array of values from object or just object
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (serverData) {
// need to push into jQuery function
drawChart(serverData);
}
});
});
This should be simple but I cannot seem to get this to work correctly.
Given a JSON string that looks like this:
{
"?xml":
{
"#version":"1.0",
"#encoding":"ISO-8859-1"
},
"results":
{
"title":"AOL Movies - Closest Theater and Showtimes",
// etc,
"theater":
{
"theaterId":"10650",
"id":"10650",
// etc
},
"movie":
[
{
"studios":"Warner Bros.",
"movieId":"61683"
}
]
}
I continually get undefined objects when trying to get to any value, for example:
data.movie, or data.results.title.
Everything "looks" ok in the output.
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: 'handler.ashx',
data: 'zip=' + postalCodes.join(','),
success: function (payload) {
var data = that.objectifyJSON(payload); // this returns typeof = object
that.constructMoviesArray(data);
},
error: function (error) {
alert(error.responseText);
}
});
this.constructMoviesArray = function (data) {
var key, movie, theater = null;
var movies = {};
movies.items = {};
movies.length = 0;
alert(data[0].movie); // FAIL - there's clearly an array but nothing displays
I hope this is enough information; I am not experienced with JSON and jQuery so I'm struggling to figure out why I can't seem to resolve this.
Add the json dataType. http://api.jquery.com/jquery.ajax/
The server response is probably still a string even though you set the contentType.
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: 'handler.ashx',
data: 'zip=' + postalCodes.join(','),
dataType: 'json', // <--- UPDATE ME
success: function (payload) {
var data = that.objectifyJSON(payload); // this returns typeof = object
that.constructMoviesArray(data);
},
error: function (error) {
alert(error.responseText);
}
});
If that doesn't help, try adding a console.log or a breakpoint to the success callback. You'll be able to take a closer look at what kind of data you are working with in payload.
success: function (payload) {
console.log(payload);
},
Hope that helps!
Try Like
var geocodingAPI = "http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true";
$.getJSON(geocodingAPI, function (json) {
// Set the variables from the results array
var address = json.results[0].formatted_address;
console.log('Address : ', address);
var latitude = json.results[0].geometry.location.lat;
console.log('Latitude : ', latitude);
var longitude = json.results[0].geometry.location.lng;
console.log('Longitude : ', longitude);
// Set the table td text
$('#address').text(address);
$('#latitude').text(latitude);
$('#longitude').text(longitude);
});
Demo
Oh boy what did I get myself into this time. Have to get some KendoUI cascading dropdrown lists working properly but I figure I will start off with two for now. Basically I need to retrieve whatever the user chooses for the first list in the view and send that back to the controller then pass it to an Entity Framework method (which I already have setup). Here is what I have now. The controller then passes back the appropriate 2nd dropdown list based on the first dropdown division value selected. I have tried using the Kendo stringify(data) trick in the parametermap as well as using cascadeFrom: "division", as suggested in the kendoui docs but that hasnt worked so far. Thus leading me to this interesting creation so far.
Any help or Garfield Comics are greatly appreciated.
The JS for the dropdownlists;
var divisions = $("#division").kendoDropDownList({
optionLabel: "Select category...",
dataTextField: "CodeAndDescription",
dataValueField: "Code",
dataSource: {
// type: "odata",
serverFiltering: true,
transport: {
read: {
url: VIPApiUrl + "GetDivision",
dataType: "json",
async: false,
type: "POST",
}, parameterMap: function (options, type) {
// edit VARS passed to service here!
if (type === 'read') {
return {
'division': options.division,
// 'criteria[0].Value': options.value
// ...
};
}
}
}
},
change: function () {
var value = this.value();
alert(value);
if (value) {
itemGroupDataSource.one("change", function () {
itemGroup.current(null);
}).filter({
field: "ID",
operator: "eq",
value: parseInt(value)
});
itemGroup.enable();
} else {
itemGroup.enable(false);
}
itemGroup.select(0);
}
}).data("kendoDropDownList");
var itemGroupDataSource = new kendo.data.DataSource({
//type: "odata",
serverFiltering: true,
transport: {
read: {
url: VIPApiUrl + "GetItemGroup",
dataType: "json",
async: false,
type: "POST",
}
}
});I
My controller where I need to access the json:
#region GetItemGroup
[HttpPost]
public List<ItemGroupsDTO> GetItemGroup(JObject jsonData)
{
dynamic json = jsonData;
string x = null; //intentionally pass null values
string division = json.division;
List<ItemGroupsDTO> ItemGroups = new List<ItemGroupsDTO>();
var ItemGroupEOList = new VIPItemGroupBOList();
ItemGroupEOList.Load(x, x, division, x, x, x, x, x, x, x, false);
foreach (var d in ItemGroupEOList)
{
var ItemGroup = new ItemGroupsDTO();
ItemGroup.Code = d.Code;
ItemGroups.Add(ItemGroup);
}
return ItemGroups;
}
#endregion
Okay I fixed this by changing the parameter map in the itemGroupDataSource to:
parameterMap: function (options, operation) {
return {
division: options.filter.filters[0].value
}
}
and changed the value field to:
dataValueField: "CodeAndDescription",
So I am guessing I partly wasn't giving the EO the right information but hopefully this helps someone in a Jam.
I have a feeling there is a simple answer to this, but I am having a problem when returning my JSON data to the JQuery UI Autocomplete function. I am using the 'label' and 'value' fields so I can store an id field. The problem is I am unable to parse the values in the object once they are passed back to the JQuery function.
in ASP.NET C#, I have an object:
public class AutoCompleteItem
{
public string label { get; set; }
public string value { get; set; }
}
and setting them into a list, formatting as JSON and then returning:
List<AutoCompleteItem> autoCompleteItems = new List<AutoCompleteItem>();
// Loop through data, add objects to list
var oSerializer = new JavaScriptSerializer();
string sJSON = oSerializer.Serialize(autoCompleteItems);
return sJSON;
JSON data after being passed to JQuery:
"[{"label":"Steve","value":"ID4545"},{"label":"Joe","value":"ID1212"},{"label":"Rick","value":"ID6767"}]"
and this is the function i am using to try and get the data from the JSON:
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.label,
value: item.value
}
}));
},
I noticed that before I used the 'label', 'value' format, I had it working with just an IList string. The data passed did not have quotes on the outside, whereas my original example does
["Steve", "Joe", "Rick"]
I don't know if this is related to the problem or not, but I have tried a number of things to no avail. Any help is appreciated!
There's no .d property in the JSON you have shown. So:
success: function (data) {
response(
$.map(data, function (item) {
return {
label: item.label,
value: item.value
};
})
);
},
But if you use an ASP.NET Page method then you have the .d property and you don't need to manually serialize the JSON. For example, you could have the following PageMethod in your code behind:
[WebMethod]
public static List<AutoCompleteItem> GetAutoCompleteValues(string term)
{
// the term variable will contain what the user entered so far
var autoCompleteItems = new List<AutoCompleteItem>();
// Loop through data, add objects to list
return autoCompleteItems;
}
and then:
source: function(request, response) {
$.ajax({
url: '/foo.aspx/GetAutoCompleteValues',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ term: request.term }),
success: function(data) {
response(
$.map(data.d, function(item) {
return {
label: item.label,
value: item.value
};
});
);
})
});
});
You shouldn't need to convert the JSON response - jQuery UI is already expecting those tokens.
From jQuery UI documentation:
$(function() {
function log( message ) {
$( "<div/>" ).text( message ).prependTo( "#log" );
$( "#log" ).scrollTop( 0 );
}
$( "#birds" ).autocomplete({
source: "search.php",
minLength: 2,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.value + " aka " + ui.item.id :
"Nothing selected, input was " + this.value );
}
});
});
You have direct access to the value and id properties of the item(s) as the second parameter jQuery passes to those event handlers (in the documentation example select:). No conversion should be required.
Why use JavaScriptSerializer() in the first place?
You only need
public ActionResult GetUserAutoComplete(string term)
{
var users = _userRepository.GetUsersByTerm(term);
var autoCompleteData = users.Select(x => new { label = x.Name + " " + x.Surname, value = x.Name + " " + x.Surname, id = x.UserId, }).ToArray();
return Json(data, JsonRequestBehavior.AllowGet);
}