autocomplete problems with serverside json - asp.net

For some reason the script below is not working.
This is the code I am using to generate the json data:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Response.Clear()
Response.Write(generate_json_data())
Response.End()
End Sub
This produces the following output on screen:
[ {id:0,value:"c++"}, {id:1,value:"java"}, {id:2,value:"php"}, {id:3,value:"coldfusion"}, {id:4,value:"javascript"}, {id:5,value:"asp"}, {id:6,value:"ruby"} ];
This is the jquery I have so far, which does not seem to work. It does not give an error, when I type into the input field, nothing happens, when it should be displaying some of the data from the json data.
$("input").autocomplete({
source: "serverside_array.aspx",
dataType: "json",
select: function (event, ui) {
$("#txtAllowSearch").val(ui.item.value); // display the selected text
$("#txtAllowSearchID").val(ui.item.id); // save selected id to hidden input
}
});
EDIT 1: The header from the developer tools in chromium 10
Request URL:http://intranet/test_array.aspx?term=j
Request Method:GET
Status Code:200 OK
Request Headers
Accept:application/json, text/javascript, */*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Type:application/x-www-form-urlencoded
Host:intranet
Referer:http://intranet/rights_stage_three.aspx
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/10.0.652.0 Safari/534.17
X-Requested-With:XMLHttpRequest
Query String Parameters
term:j
Response Headers
Cache-Control:private
Content-Length:204
Content-Type:application/json; charset=utf-8
Date:Thu, 27 Jan 2011 16:11:14 GMT
Server:Microsoft-IIS/6.0
X-AspNet-Version:2.0.50727
X-Powered-By:ASP.NET
EDIT 2: looking at the reponse data XHR, I get the following
name test_array.aspx
method get
status 200 ok
type application/json
size 204b
time pending
EDIT 3:
Now I am totally confused. I got it working by simply changing the contenttype generated by the aspx page to:
text/xml
instead of
applicaiton/json
why does it work with text/xml when I am returning json?

Use a webdev tool like Firebug or Operas and Chromes built-in dev-tools which can list HTTP requests and responses to you.
Check if a JavaScript error is logged.
If not, check for the response, and that the responses Content-Type is text/javascript if it’s a callback, or application/json if only JSON data.
Without the content type the ajax request may fail because of security against XSS.

[ {id:0,value:"c++"}, {id:1,value:"java"}, {id:2,value:"php"}, {id:3,value:"coldfusion"}, {id:4,value:"javascript"}, {id:5,value:"asp"}, {id:6,value:"ruby"} ];
The semicolon at the end of the string should not be there. Also the Content-Type of the response should be application/json. And consider to put all values in double quotes. May be it will work without it, but it is not the proper JSON format without it. This is the standard compliant JSON string:
[{"id":0,"value":"c++"}, {"id":1,"value":"java"}, {"id":2,"value":"php"}]

Related

Spring REST Controller is not responding to Angular request

I have an app to create server certificate requests, just as if one were using java keytool or something. I'm trying to return the created certificate request and the key in a zip file, but for the life of me, I can't get my REST controller to respond to the http request. CORRECTION: The controller responds, but the code within the method is never executed.
The server does receive the request, because my CORS filter is executed. But I have a debug set in the controller method, and it's never triggered. Is the signature of the method correct? I need another set of eyes, please?
Here is my controller code:
#RequestMapping(method = RequestMethod.POST, value = "/generateCert/")
public ResponseEntity<InputStreamResource> generateCert(#RequestBody CertInfo certInfo) {
System.out.println("Received request to generate CSR...");
byte[] responseBytes = commonDataService.generateCsr(certInfo);
InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(responseBytes));
System.out.println("Generated CSR with length of " + responseBytes.length);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=certificate.zip")
.contentType(MediaType.parseMediaType("application/zip"))
.contentLength(responseBytes.length)
.body(resource);
}
And here is the Angular request:
generateCertificate(reqBody: GenerateCert) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post(this.urlGenerateCert, JSON.stringify(reqBody), {headers: headers}).subscribe(
(data) => {
let dataType = data.type;
let binaryData = [];
binaryData.push(data);
this.certBlob = new Blob(binaryData);
});
return this.certBlob;
}
And finally, the request and response headers I copied from the Network Panel:
Response
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Requested-With, remember-me
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Thu, 27 Dec 2018 22:48:00 GMT
Expires: 0
Location: http://localhost:8102/login
Pragma: no-cache
Set-Cookie: JSESSIONID=EDACE17328628D579670AD0FB53A6F35; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Request
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 205
Content-Type: application/json
Host: localhost:8102
Origin: http://localhost:4200
Referer: http://localhost:4200/generateCerts
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36
I really struggled with getting CORS working, so maybe that's interfering with the request? I hate to post all that code unless absolutely necessary. Anybody got any ideas?
Listing of request/response headers lack information on URL, method and most important response status code.
Seeing Location: http://localhost:8102/login among response headers I can guess that it could be 401 Unauthorized or anything else that redirects to the login page. Hence, if there is an auth filter in the filter chain, it may be a culprit.
The following request headers
Host: localhost:8102
Origin: http://localhost:4200
suggests that you are doing CORS and the CORS filter may be involved indeed and fulfill response before the request gets routed to the controller. I suggest setting a breakpoint into the CORS filter (and into others if any) and debug it to the point where the response is returned.
define a proxy.conf.json
{
"/login*": {
"target":"http://localhost:8080",
"secure":false,
"logLevel":"debug"
}
}
now in your package.json
"scripts": {
"start":"ng serve --proxy-config proxy.config.json"
}
I think there is issue while getting connection in both webapp.please try .
When Angular encounters this statement
this.http.post(url,body).subscribe(data => # some code
);
It comes back immediately to run rest of the code while service continues to execute. Just like Future in Java.
Here if you
return this.cert;
You will not get the value that may eventually get populated by the this.http service. Since the page has already rendered and the code executed. You can verify this by including this within and outside the Observable.
console.log(“Inside/outside observable” + new Date().toLocalTimeString());
Thanks to everyone who contributed. I discovered the error was due to the headers of my controller method. After changing them, the method was invoked properly. This is what worked:
#RequestMapping(method = RequestMethod.POST, path = "/generateCert",
produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<byte[]> generateCert(#RequestBody CertInfo certInfo) {
byte[] responseBytes = commonDataService.generateCsr(certInfo);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE)
.contentLength(responseBytes.length)
.body(responseBytes);
}

bootstrap-table how do I add a custom request header when using server pagination

I've been using bootstrap table (http://bootstrap-table.wenzhixin.net.cn/) successfully in a typescript project for quite some time.
Unfortunately due to the amount of data returned for one table I want to switch to using server side pagination for that table.
For the most part that seems reasonably straightforward but I need the table to pass a custom request header to the server and cannot see how to do that.
The current headers are as below but I need to get the bootstrap table to add in an authorisation header containing the auth token.
http://localhost/api/1.0/LotsofData?order=asc&offset=0&limit=15&_=1542242900391
Accept: application/json, text/javascript, */*; q=0.01
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en;q=0.5
Cache-Control: no-cache
Connection: keep-alive
Content-Type: application/json
Host: localhost
Origin: http://localhost:53391
Pragma: no-cache
Referer: http://localhost:53391/
User-Agent: {stuff}
How do I add the custom request header to the bootstrap-table's get request
Any assistance would be much appreciated.
Worked it out by searching for help on jquery $.ajax requests. You populate the ajaxOptions as shown in the code snippet.
...
url: controller.ourservice.build_url(scope.id1, scope.id2),
sidepagination: 'server',
ajaxOptions: { headers: { 'Authorization': 'Token ' + localStorage.getItem("access_token") }},
pageSize: 15,
pageList: [5, 15],
...

Are browsers supposed to handle 304 responses automagically?

Might be a silly question, but I haven't found any clear answer yet.
My server handles ETag caching for some quite big JSON responses we have, returning 304 NOT MODIFIED with an empty body if the If-None-Match header contains the same hash as the one newly generated (shallow ETags).
Are browsers supposed to handle this automagically, or do the in-browser client apps consuming the API asynchronously need to implement some logic to handle such responses (i.e. use the cached version if 304 is responded, create/update the cached version otherwise)?
Because so far, I've manually implemented this logic client-side, but I'm wondering whether I just reinvented a square wheel...
In other words, with the Cache-Control header for example, the in-browser client apps don't need to parse the value, check for max-age for instance, stores it somehow, setup a timeout, etc.: everything is handled ahead by the browsers directly. The question is: are browsers supposed to behave the same way when they receive a 304?
Here is how I wrote my client so far (built with AngularJS, running in browsers):
myModule
.factory("MyRepository", ($http) => {
return {
fetch: (etag) => {
return $http.get(
"/api/endpoint",
etag ? { headers: { "If-None-Match": etag } } : undefined
);
}
};
})
.factory("MyService", (MyRepository, $q) => {
let latestEtag = null;
let latestVersion = null;
return {
fetch: () => {
return MyRepository
.fetch(latestEtag)
.then((response) => {
latestEtag = response.headers("ETag");
latestVersion = response.data;
return angular.copy(latestVersion);
})
.catch((response) => {
return 304 === error.status
? angular.copy(latestVersion)
: $q.reject(response)
});
}
};
});
So basically, is the above logic effectively needed, or am I supposed to be able to simply use $http.get("/api/endpoint") directly?
This code above is working fine, which seems to mean that it needs to be handled programmatically, although I've never seen such "custom" implementations on the articles I read.
The 304 responses are automagically handled by browser as such
So I created a simple page
<html>
<head>
<script src="./axios.min.js"></script>
<script src="./jquery-3.3.1.js"></script>
</head>
<body>
<h1>this is a test</page>
</body>
</html>
and the added a test.json file
root#vagrant:/var/www/html# cat test.json
{
"name": "tarun"
}
And then in nginx added below
location ~* \.(jpg|jpeg|png|gif|ico|css|js|json)$ {
expires 365d;
}
Now the results
AXIOS
As you can see the first request is 200 and second one 304 but there is no impact on the JS code
jQuery
Same thing with jQuery as well
From the curl you can see that server didn't send anything on the 2nd 304 request
$ curl -v 'http://vm/test.json' -H 'If-None-Match: "5ad71064-17"' -H 'DNT: 1' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.9' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://vm/' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' -H 'If-Modified-Since: Wed, 18 Apr 2018 09:31:16 GMT' --compressed
* Trying 192.168.33.100...
* TCP_NODELAY set
* Connected to vm (192.168.33.100) port 80 (#0)
> GET /test.json HTTP/1.1
> Host: vm
> If-None-Match: "5ad71064-17"
> DNT: 1
> Accept-Encoding: gzip, deflate
> Accept-Language: en-US,en;q=0.9
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
> Accept: */*
> Referer: http://vm/
> X-Requested-With: XMLHttpRequest
> Connection: keep-alive
> If-Modified-Since: Wed, 18 Apr 2018 09:31:16 GMT
>
< HTTP/1.1 304 Not Modified
< Server: nginx
< Date: Wed, 18 Apr 2018 09:42:45 GMT
< Last-Modified: Wed, 18 Apr 2018 09:31:16 GMT
< Connection: keep-alive
< ETag: "5ad71064-17"
<
* Connection #0 to host vm left intact
So you don't need to handle a 304, browser will do that work for you.
Yes, probably all modern major browsers handle response validation using conditional requests well. Relevant excerpt from The State of Browser Caching, Revisited article by Mark Nottingham:
Validation allows a cache to check with the server to see if a stale stored response can be reused.
All of the tested browsers support validation based upon ETag and Last-Modified. The tricky part is making sure that the 304 Not Modified response is correctly combined with the stored response; specifically, the headers in the 304 update the stored response headers.
All of the tested browsers do update stored headers upon a 304, both in the immediate response and subsequent ones served from cache.
This is good news; updating headers with a 304 is an important mechanism, and when they get out of sync it can cause problems.
For more information check HTTP Caching article by Ilya Grigorik.

Kendo upload not working in IE 8

Context
I am using asynchronous Kendo UI Upload (docs) in my application with HTML frontend and Java servlet at server side. When servlet returns nothing in response, it’s working perfectly. Uploading triggers progress change to “Done” on success, complete callback method is called.
Problem
I need to return some data such as GUID="SDR2334" from the server on successful upload. When I send response from the servlet, Kendo UI Upload control does not work/render as expected/as shown in Kendo demo site at all.
progress not getting changed to “Done” when uploading
complete method not being called
Attempted solution
I tried to add GUID with response header instead of response body. Still it’s not working.
Code I used
<form method="post" action="submit" style="width:45%">
<div class="demo-section">
<input name="files" id="files" type="file" />
</div>
</form>
$("#files").kendoUpload({
async: {
saveUrl: "http:111.11.11.111/fileupload",
autoUpload: false
},
multiple: false,
showFileList: true,
upload: function (e) {
e.data = { sessionid: CurrentSession.sessionId };
},
complete: function (e) {
alert(e.data);
$(".k-widget.k-upload").find("ul").remove();
}
});
Request header
Key Value
Request POST /services/fileUploadWithoutResponse HTTP/1.1
Accept application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer http://111.11.11.11:8090/WebClient/
Accept-Language en-US
User-Agent Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Content-Type multipart/form-data; boundary=---------------------------7de38b1219073a
Accept-Encoding gzip, deflate
Host 172.16.17.100:8090
Content-Length 114034
DNT 1
Connection Keep-Alive
Cache-Control no-cache
Response header
Key Value
Response HTTP/1.1 200 OK
Server Apache-Coyote/1.1
X-Powered-By Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Access-Control-Allow-Origin *
guId f6ac7203-5bd6-433b-a632-548ca5b048cf
Content-Type application/json;charset=utf-8
Content-Length 0
Date Fri, 03 Jan 2014 13:00:19 GMT
Notice the guId header here.
I made it by setting the response content-type to text/plain.
Also I realized I need success event instead of complete event to get the contents of response body (e.response).

SignalR routing issue, get 200 ok but response empty

I have an existing MVC application which I am integrating a hub into, now I have setup the hub like so:
routeTable.MapHubs("myapp/chat/room", new HubConfiguration { EnableCrossDomain = true, EnableDetailedErrors = true, EnableJavaScriptProxies = true });
Then in the clientside I am connecting like so:
var connection = $.hubConnection(SystemConfiguration.ServiceUrl + "/myapp/chat/room", { useDefaultPath: false });
var hub = this.Connection.createHubProxy("ChatHub"); // Same name as on the hub attribute
connection.start().done(function(){ /* do stuff */});
Then I see the HTTP Request like so:
http://localhost:23456/myapp/chat/room/negotiate?_=1374187915970
Response Headers
Access-Control-Allow-Cred... true, true
Access-Control-Allow-Head... content-type, x-requested-with, *
Access-Control-Allow-Meth... GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Orig... http://localhost:34567, http://localhost:34567
Access-Control-Max-Age 10000
Cache-Control no-cache
Content-Length 420
Content-Type application/json; charset=UTF-8
Date Thu, 18 Jul 2013 22:52:18 GMT
Expires -1
Pragma no-cache
Server Microsoft-IIS/8.0
X-AspNet-Version 4.0.30319
X-Content-Type-Options nosniff
Request Headers
Accept application/json, text/javascript, */*; q=0.01
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Host localhost:23456
Origin http://localhost:34567
Referer http://localhost:34567/myapp/chat?chatId=1764a2e3-ff6f-4a17-9c5f-d99642301dbf
User-Agent Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0
The response though contains no body, its got a 200 status though... I am debugging on the server and the hub methods are never hit. The only non standard thing in this scenario is that I have a custom CORS HttpModule which intercepts traffic and appends the CORS required headers, as you can see in the response, so not sure if this confuses SignalR's CORS support in some way. Anyway I can see the HttpModule being hit so it goes past there fine, but is somehow lost between there and the hub.
Tried googling but not much info on this topic...
The issue seems to be down to my CORS handling at HttpModule level, it must somehow conflict with SignalR... if I put a check in the module to see if the URL contains "chat/room" and just ignore the request if needed it then works fine, however it feels like a hack, but at least it works now.

Resources