What I would like to do is to get a simple string array (of numbers) into the Highchart from a webservice. For some reason, the chart is not even rendered and I cannot get any values through this.
In the Highchart's documentation I've found this example of sending data cross domains:
http://docs.highcharts.com/#cross-domain-data
This is their example (using php):
The serverside php file:
<?php
header("content-type: application/json");
$array = array(7,4,2,8,4,1,9,3,2,16,7,12);
echo $_GET['callback']. '('. json_encode($array) . ')';
?>
The JavaScript calling the callback function using jQuery.
$(document).ready(function() {
var options = {
chart: {
renderTo: 'container',
type: 'spline'
},
series: [{}]
};
var url = "http://url-to-your-remote-server/jsonp.php?callback=?";
$.getJSON(url, function(data) {
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
});
And now this is how my WebService.cs looks like:
public WebService () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod(Description = "ID:2")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetSomeValues() {
string[] values = { "3", "5", "6", "7", "3"};
string[][] jaggedTable = new string[values.Count()][];
int i = 0;
foreach (var value in values)
{
jaggedTable[i] = new string[] { value + "" };
i++;
}
JavaScriptSerializer js = new JavaScriptSerializer();
string strJSON = js.Serialize(jaggedTable);
return strJSON;
}
And the Default.aspx:
<script type="text/javascript">
$(document).ready(function () {
var options = {
chart: {
renderTo: 'container',
type: 'spline'
},
series: [{}]
};
var url = "WebService.asmx/GetSomeValues";
$.getJSON(url, function (data) {
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
});
</script>
UPDATE: I've just seen that I'm getting in the console this error:
GET http://localhost:53566/WebService.asmx/GetSomeValues 500 (Internal Server Error)
jquery.min.js:130
c.extend.ajax jquery.min.js:130
c.extend.get jquery.min.js:122
c.extend.getJSON jquery.min.js:122
(anonymous function) highchart.aspx:23
c.extend.ready jquery.min.js:26
Where the anonymous function is:
$.getJSON(url, function (data) {
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
What am I doing wrong?
Related
I have a problem here when I am trying to push data with angularjs controller. But what ever I do (IFormFile file) is always empty. There are only some examples with razor syntax but no examples how to do it with angular or jquery.
HTML:
<form class="form-body" enctype="multipart/form-data" name="newFileForm" ng-submit="vm.addFile()"><input type="file" id="file1" name="file" multiple ng-files="getTheFiles($files)"/></form>
Directive:
(function() {
'use strict';
angular
.module('app')
.directive('ngFiles', ['$parse', function ($parse) {
function fn_link(scope, element, attrs) {
var onChange = $parse(attrs.ngFiles);
element.on('change', function (event) {
onChange(scope, { $files: event.target.files });
});
};
return {
link: fn_link
};
}]);
})();
Controller
var formdata = new FormData();
$scope.getTheFiles = function ($files) {
angular.forEach($files, function (key, value) {
formdata.append(key, value);
});
};
vm.addFile = function () {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader("Content-Type", "undefined");
xhr.send(formdata);
}
Asp.net core webapi:
[HttpPost]
public async Task<IActionResult> PostProductProjectFile(IFormFile file)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
....
return ...;
}
I have also tried to do it with formdata, as it is constructed when you post it with razor syntax. Something like this:
dataService.addFile(formdata, {
contentDisposition: "form-data; name=\"files\"; filename=\"C:\\Users\\UserName\\Desktop\\snip_20160420091420.png\"",
contentType: "multipart/form-data",
headers: {
"Content-Disposition": "form-data; name=\"files\"; filename=\"C:\\Users\\UserName\\Desktop\\snip_20160420091420.png\"",
'Content-Type': "image/png"
},
fileName: "C:\\Users\\UserName\\Desktop\\snip_20160420091420.png",
name: "files",
length : 3563
}
Also instead of formData to provide raw file as I wrote in comment. But still nothing happens
IFormFile will only work if you input name is the same as your method parameter name. In your case the input name is 'files' and the method parameter name is 'file'. Make them the same and it should work.
This is how to do it with angularjs:
vm.addFile = function () {
var fileUpload = $("#file").get(0);
var files = fileUpload.files;
var data = new FormData();
for (var i = 0; i < files.length ; i++) {
data.append(files[i].name, files[i]);
}
$http.post("/api/Files/", data, {
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (data, status, headers, config) {
}).error(function (data, status, headers, config) {
});
}
And in web Api:
[HttpPost]
public async Task<IActionResult> PostFile()
{
//Read all files from angularjs FormData post request
var files = Request.Form.Files;
var strigValue = Request.Form.Keys;
.....
}
Or like this:
[HttpPost]
public async Task<IActionResult> PostFiles(IFormCollection collection)
{
var f = collection.Files;
foreach (var file in f)
{
//....
}
}
You can do it also with kendo upload much simpler:
$("#files").kendoUpload({
async: {
saveUrl: dataService.upload,
removeUrl: dataService.remove,
autoUpload: false
},
success: onSuccess,
files: files
});
From the answer of #Tony Steele.
Here is the code sample (Where to change/take care of)
.NET Core 3.1 LTS
[Route("UploadAttachment")]
[HttpPost]
public async Task<IActionResult> UploadAttachment(List<IFormFile> formFiles)
{
return Ok(await _services.UploadAttachment(formFiles));
}
AngularJS
var formFiles = new FormData();
if ($scope.files != undefined) {
for (var i = 0; i < $scope.files.length; i++) {
formFiles.append('formFiles', $scope.files[i]);
}
}
I'm trying to pass data stored in a dynamically created table to the server, and while I can access the data in my angularJS controller, I am having difficulty learning how to pass this data to the server to process.
Here is my angularjs function that is able to access my table data, its just passing the data and calling my vb.net function that I am having trouble with.
$scope.requestThatCertificatesBeEmailed = function () {
for (index = 0; index < $scope.requests.length; ++index) {
alert('For loop entered')
var submittedEmailAddressString = $scope.requests[index].emailAddress;
var submittedCertificateTypeString = $scope.requests[index].certificateType;
var submittedSearchTypeString = $scope.requests[index].searchType;
var submittedSearchString = $scope.requests[index].submittedNumbers;
alert(submittedSearchTypeString);
$http.post("/Home/NewTextFile", { submittedEmailAddress: submittedEmailAddressString, submittedCertificateType: submittedCertificateTypeString, submittedSearchType: submittedSearchTypeString, submittedSearch: submittedSearchString }).error(function () {
$scope.requests = [];
});
You will need to post/put the data back to the server. If you are working in a ASP.NET WebForms application, you will likely need to pass the value as JSON to the server in a hidden input field. If you are working in an ASP.NET MVC application, you should be able to invoke a controller action sending in the JSON table data from javascript.
Your action method in your MVC Controller should look like this:
<HttpPost> _
Public Function NewTextFile(submittedEmailAddress As String, submittedCertificateType As String, submittedSearchType As String, submittedSearch As String) As ActionResult
'do some work
End Function
Using jQuery, you could invoke the controller action like so:
$.ajax({
url: '/Home/NewTextFile',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
submittedEmailAddress: submittedEmailAddressString,
submittedCertificateType: submittedCertificateTypeString,
submittedSearchType: submittedSearchTypeString,
submittedSearch: submittedSearchString
}),
processData: false,
dataType: 'json'
});
Below is an AngularJS example I whipped together:
On/referenced from the View:
<script type="text/javascript">
angular.module('httpExample', [])
.controller('ContactController', ['$scope', '$http',
function ($scope, $http, $templateCache) {
$scope.contact = { userName: '', firstName: '', lastName: '' };
$scope.get = function () {
$scope.code = null;
$scope.response = null;
$http.get('/Home/Contact').
success(function (data, status) {
$scope.status = status;
$scope.data = data;
$scope.contact = data;
}).
error(function (data, status) {
$scope.data = data || "Request failed";
$scope.contact = { userName: '', firstName: '', lastName: '' }
$scope.status = status;
});
};
$scope.post = function () {
$scope.code = null;
$scope.response = null;
$http.post('/Home/Contact', $scope.contact).
success(function (data, status) {
$scope.status = status;
$scope.data = data;
}).
error(function (data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
};
}]);
</script>
Somewhere in the body:
<div>
<div ng-app="httpExample">
<div ng-controller="ContactController">
<fieldset>
<legend>Contact</legend>
Username: <input type="text" ng-model="contact.userName"/><br/>
Last Name: <input type="text" ng-model="contact.lastName"/><br/>
First Name: <input type="text" ng-model="contact.firstName"/><br/>
</fieldset>
<br />
<button id="getbtn" ng-click="get()">get</button>
<button id="postbtn" ng-click="post()">post</button><br/><br/>
<pre>http status code: {{status}}</pre>
<pre>http response data: {{data}}</pre>
</div>
</div>
</div>
And your MVC server side Home controller has methods that look like this:
<HttpGet> _
Public Function Contact() As JsonResult
Dim contact = New With { .userName = "smithjk", .firstName = "John", .lastName = "Smith" }
Return Json(contact, JsonRequestBehavior.AllowGet)
End Function
<HttpPost> _
Public Function Contact(userName As String, firstName As String, lastName As String) As ActionResult
'do some work
System.Diagnostics.Debug.Print(userName)
Return New EmptyResult()
End Function
I'm facing a strange issue with autocomplete.
First issue:
based on the tutorial found here, only the first letter of the found items is showing in the list of autocomplete items
Here is an illustration:
My action at debug time
Dummy data returned, always the same regardless of the search pattern just for testing
In the rendered view, this is what happens:
The Javascript for autocomplete of this scenario is as follows:
$("#Email").autocomplete('#Url.Action("FindEmail", "Administration")',
{
dataType: 'json',
parse: function(data) {
var rows = new Array();
for (var i = 0; i < data.length; i++) {
rows[i] = {
data: data[i].Value,
value: data[i].Value,
result: data[i].Value
};
}
return rows;
},
width: 300,
minLength: 3,
highlight: false,
multiple: false
});
Second issue:
I've changed my code to work with a more comfortable Ajax call for me that depends on Model mapping rather than sending a q and limit parameters as in the previous tutorial, and as I've seen in many other tutorials, but the Ajax call isn't firing, not even giving me an error.
My code for this scenario is based on this Stack Overflow Answer
Here is my controller and view code related:
//[HttpPost]
[SpecializedContextFilter]
[Authorize]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public JsonResult FindEmail(RegistrationModel model) //Notice the use of model instead of string q and string limit
{
//Just a dummy implementation
var rez = new List<ValueModel>
{
new ValueModel {Description = "atest1#test.com", Value = "atest1#test.com"},
new ValueModel {Description = "atest2#test.com", Value = "atest2#test.com"},
new ValueModel {Description = "atest3#test.com", Value = "atest3#test.com"},
new ValueModel {Description = "atest4#test.com", Value = "atest4#test.com"}
};
//var retValue = rez.Select(r => new { email = r.Value }).OrderBy(x => x).Take(10);
//return Json(retValue, JsonRequestBehavior.AllowGet);
return Json(rez, JsonRequestBehavior.AllowGet);
}
View JavaScript:
$("#Email").autocomplete({
source: function(request, response) {
$.ajax({
url: '#Url.Action("FindEmail", "Administration")',
type: "POST",
dataType: "json",
data: { email: $("#Email").val(), conferenceId: $("#ConferenceId").val() },
success: function(data) {
response($.map(data, function(item) {
return { label: item.Value, value: item.Value, id: item.Value };
}));
},
select: function(event, ui) {
$("input[type=hidden]").val(ui.item.id);
}
});
}
});
Firefox console view:
I've tried a lot of codes for the second scenario, most of them are Stack Overflow answers, but nothing is happening!
I'm my missing anything ?
Note: jQuery plugins are included, Ajax is already working in the same page, so I'm not sure whats the problem
Thanks for any help.
Here is a full working example, see screen grab.
These are the steps that I had take to get the second example working.
Script-references/Markup/Js
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery-ui-1.8.24.min.js"></script>
<input id="ConferenceId" value="1" />
<div class="ui-widget">
<label for="Email">Email: </label>
<input id="Email">
</div>
<script type="text/javascript">
$("#Email").autocomplete({
source: function (request, response) {
$.ajax({
url: '#Url.Action("FindEmail", "Administration")',
type: "POST",
dataType: "json",
data: { email: $("#Email").val(), conferenceId: $("#ConferenceId").val() },
success: function (data) {
response($.map(data, function (item) {
return { label: item.Value, value: item.Value, id: item.Value };
}));
},
select: function (event, ui) {
$("input[type=hidden]").val(ui.item.id);
}
});
}
});
</script>
Models
public class RegistrationModel
{
public string Email { get; set; }
public string ConferenceId { get; set; }
}
public class ValueModel
{
public string Description { get; set; }
public string Value { get; set; }
}
Controller Action
I had to add the [HttpPost] attribute.
[HttpPost]
public JsonResult FindEmail(RegistrationModel model) //Notice the use of model instead of string q and string limit
{
//Just a dummy implementation
var rez = new List<ValueModel>
{
new ValueModel {Description = "atest1#test.com", Value = "atest1#test.com"},
new ValueModel {Description = "atest2#test.com", Value = "atest2#test.com"},
new ValueModel {Description = "atest3#test.com", Value = "atest3#test.com"},
new ValueModel {Description = "atest4#test.com", Value = "atest4#test.com"}
};
return Json(rez, JsonRequestBehavior.AllowGet);
}
Screen grab
I have been all over looking to try and solve my issue. I am thinking it may be on my back end but not sure. I am trying to use autocomplete to fill in a textbox but show in the drop down a description with the value.
My Method for grabbing the Data:
[WebMethod]
public static ArrayList GetQueries(string id)
{
queries q;
var cs = Global.CS;
var con = new SqlConnection(cs);
var da = new SqlDataAdapter(querystring, con);
var dt = new DataTable();
da.Fill(dt);
ArrayList rows = new ArrayList(dt.Rows.Count);
for (int i = 0; i < dt.Rows.Count; i++)
{
var val = dt.Rows[i]["Query_ID"];
var des = dt.Rows[i]["Description"];
q = new queries();
q.label = val.ToString();
q.value = val.ToString() + " -- " + des.ToString();
var json = new JavaScriptSerializer().Serialize(q);
rows.Add(json);
}
return rows;
}
public class queries
{
public string label { get; set; }
public string value { get; set; }
}
It is returning an arraylist.
My JQuery Method to get data and autocomplete.
$("[id$=QueryManager]").change(function () {
var id = $("[id$=QueryManager] :selected").val();
$.ajax({
type: 'POST',
url: 'Upload.aspx/GetQueries',
data: JSON.stringify({ id: id }),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (data) {
fillit(data);
},
error: function (ex) {
alert('Request Status: ' + ex.status + '\n\nStatus Text: ' + ex.statusText + '\n\n' + ex.responseText);
}
});
});
function fillit(data) {
$("#QueryTxt").autocomplete({
delay: 0,
minLength: 0,
source: function (data, response) {
response($.map(data, function (item) {
return {
label: item.label,
value: item.value
}
}));
}
});
};
I have tried it with both the serialize and without to no results. When this code runs it shows that autocomplete is working (via the box showing up below) but there is no data in it.
I am not sure what I am doing wrong, any help is appreciated.
What I'm doing below is that on the "Select" event I take the values returned from the query and set the text of the drop down to the description and Id value from the data brought back. Then I set a dummy textbox's value as the description. "colDescName" is just a variable I was using as my textbox id.
$("#" +colDescName).autocomplete({
minLength: 2,
select: function( event, ui )
{
var rowElement=event.target.id;//Drop down Id
setTimeout(function()
{
$("#"+rowElement).val(ui.item.value+':'+ui.item.id)
},100);//need a slight delay here to set the value
$("#TextBoxId").val(ui.item.value);
//ui.item.value is the description in the drop down.
//ui.item.id is the Id value from the drop down
},
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
lastXhr = $.getJSON("Upload.aspx/GetQueries", request, function (data, status, xhr) {
cache[term] = data;
if (xhr === lastXhr) {
response(data);
}
}).error(function () {
console.log("error");
});
}
});
What object is "$("[id$=QueryManager]")" that you have the change method on? Would you need the change event if you can use the above code?
EDIT
OK an easier way is set your textbox "$("#QueryTxt")" to an autocomplete box before executing any change events on your "QueryManager" manager dropdown. Then when a change event does occur in your "QueryManager" , call:
$(this).autocomplete('search', 'your data here');
That will then execute the search function and call the autocomplete's url with your required data
So I have some javascript code that sends data to my controller:
Javascript:
<script type="text/javascript">
$(document).ready(function () {
$("#newGrade").click(function () {
var newGradeName = $("#newGradeName").val();
var newGradeValue = $("#newGradeValue").val();
var vSchoolID = $("#SchoolID").val();
if (newGradeName != null && newGradeValue != null) {
$.ajax({
url: '#Url.Action("NewGrade", "School")',
data: { gradeName: newGradeName, gradeValue: newGradeValue, schoolID: vSchoolID },
type: 'POST',
traditional: true,
success: function (data) {
if (data.status)
window.location = data.route;
},
error: function () {
return false;
}
});
}
});
});
</script>
Controller:
public ActionResult NewGrade(String gradeName, Int32 gradeValue, Guid schoolID)
{
School school = schoolRepository.GetByID(schoolID);
school.Grades.Add(
new Grade
{
GradeID = Guid.NewGuid(),
Name = gradeName,
NumericalValue = gradeValue
});
schoolRepository.Update(school);
schoolRepository.Save();
if (Request.IsAjaxRequest())
{
var json = new { status = true, route = Url.RouteUrl(new { action = "Edit", id = schoolID }) };
return Json(json, JsonRequestBehavior.AllowGet);
}
return View();
}
My issue now is I want to return to my Edit page (possibly refreshing the page, but not the data, or just refresh the entire page), but my Edit page takes an ID (schoolID). Shown here when pressing the button to get to the Edit page:
<i class="icon-pencil"></i> Edit
Try window.location.href and see what happens.
success: function(data) {
if (data.status)
window.location.href = data.route;
},
This should work fine assuming you are getting a JSON reponse from your action method like
{"status":"true","route":"/School/Edit/1"}
where 1 is the ID of new record.