JSON WebService in ASP.NET - asp.net

How do I create an ASP.NET web service that returns JSON formatted data?

The most important thing to understand is to know how to represent data in JSON format.
Please refer http://www.json.org/ to know more about it.
Once you understand this, then the rest part is pretty straight forward.
Please check the following URL for an example of the same.
http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=264
http://code.msdn.microsoft.com/JSONSampleDotNet
http://www.phdcc.com/xml2json.htm
I recommend Jquery library for this. It's a lightweight rich library which supports calling web services, handle json data format output etc.
Refer www.jquery.com for more info.

.NET 3.5 has support built-in. For .NET 2.0, extra libraries are needed. I used the Jayrock library.
I recently delivered an application that uses pure Javascript at the browser (viz. using AJAX technology, but not using Microsoft AJAX or Scriptaculous etc) which marries up to Microsoft webservices at the back end. When I started writing this I was new to the world of .NET, and felt overwhelmed by all the frameworks out there! So I had an urge to use a collection of small libraries rather than very large frameworks.
At the javascript application, I call a web service like this. It directly reads the output of the web service, cuts away the non JSON sections, then uses https://github.com/douglascrockford/JSON-js/blob/master/json2.js to parse the JSON object.
This is not a standard approach, but is quite simple to understand, and may be of value to you, either to use or just to learn about webservices and JSON.
// enclosing html page has loaded this:
<script type="text/javascript" src="res/js/json2.js"></script>
// Invoke like this:
// var validObj = = callAnyWebservice("WebServiceName", "");
// if (!validObj || validObj.returnCode != 0) {
// alert("Document number " + DocId + " is not in the vPage database. Cannot continue.");
// DocId = null;
// }
function callAnyWebservice(webserviceName, params) {
var base = document.location.href;
if (base.indexOf(globals.testingIPaddr) < 0) return;
gDocPagesObject=null;
var http = new XMLHttpRequest();
var url = "http://mywebserver/appdir/WebServices.asmx/" + webserviceName;
//alert(url + " " + params);
http.open("POST", url, false);
http.setRequestHeader("Host", globals.testingIPaddr);
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http.setRequestHeader("Content-Length", params.length);
// http.setRequestHeader("Connection", "close");
//Call a function when the state changes.
http.onreadystatechange = function() {
if (http.readyState == 4 ) {
if (http.status == 200) {
var JSON_text = http.responseText;
var firstCurlyQuote = JSON_text.indexOf('{');
JSON_text = JSON_text.substr(firstCurlyQuote);
var lastCurlyQuote = JSON_text.lastIndexOf('}') + 1;
JSON_text = JSON_text.substr(0, lastCurlyQuote);
if (JSON_text!="")
{
//if (DEBUG)
// alert(url+" " +JSON_text);
gDocPagesObject = eval("(" + JSON_text + ")");
}
}
else if (http.readyState == 4)
{alert(http.readyState + " " + http.status + " " + http.responseText)}
}
}
http.send(params);
if (gDocPagesObject != null) {
//alert(gDocPagesObject.returnCode + " " + gDocPagesObject.returnString);
return gDocPagesObject;
}
else
return "web service unavailable: data not ready";
}

In our project the requirements were as follow -- ASP.NET 2.0 on the server, and pure Javascript on the browser (no JQuery libs, or .NET AJAX)
In that case on the server side, just mark the webmethod to use JSON. Note that both input and output params are json formatted
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public String Foo(String p1, String p2)
{
return "Result: p1= " + p1 + " p2= " + p2;
}
On the javascript side, use the regular XmlHttpRequest object, make sure you format your input params as JSON and do an 'eval' on output parms.
var httpobj = getXmlHttpRequestObject();
//Gets the browser specific XmlHttpRequest Object
function getXmlHttpRequestObject()
{
if (window.XMLHttpRequest)
return new XMLHttpRequest();
else if(window.ActiveXObject)
return new ActiveXObject("Microsoft.XMLHTTP");
}
CallService()
{
//Set the JSON formatted input params
var param = "{'p1' : 'value1', 'p2' : 'value2'}";
//Send it to webservice
if(httpobj.readyState == 4 || httpobj.readyState == 0)
{
httpobj.open("POST", 'service.asmx/' + 'Foo', true);
//Mark the request as JSON and UTF-8
httpobj.setRequestHeader('Content-Type','application/json; charset=utf-8');
httpobj.onreadystatechange = OnSuccess;
httpobj.send(param);
}
}
OnSuccess()
{
if (httpobj.readyState == 4)
{
//Retrieve the JSON return param
var response = eval("(" + httpobj.responseText + ")");
}
}

Related

Kendo UI Grid - Parsing query params into DataSourceRequest without using MVC

I am trying to create DataSourceRequest without actually running on ASP.NET MVC.
If I were on MVC, I could use:
public ActionResult GetResults([DataSourceRequest]DataSourceRequest request)
{
...
But, I cannot use MVC (reasons, you know...) so what I am looking for is something like AmazingParsingKendoLibrary.ParseFromQueryString() which will return DataSourceRequest
Is there any support for programmatic parsing like this?
This method works as I use it to replicate the grid when doing a custom file export:
setRequestObject: function () {
var grid = $("#YOUR_GRID_ID").data("kendoGrid");
this.requestObject = (new kendo.data.transports["aspnetmvc-server"]({ prefix: "" }))
.options.parameterMap({
page: grid.dataSource.page(),
sort: grid.dataSource.sort(),
filter: grid.dataSource.filter()
});
var pageArg = "page=" + (this.requestObject.page || '~');
var sortArg = "sort=" + (this.requestObject.sort || '~');
var psizeArg = "pageSize=" + grid.dataSource._pageSize;
var filterArg = "filter=" + (this.requestObject.filter || '~');
this.exportFileUrl = pageArg + "&" + sortArg + "&" + psizeArg + "&" + filterArg;
},
I hope this helps. Good luck

Angular2 routing and intercepting calls (changes in HTTP API somewhere from version 2.1.0 to version 2.2.3.)

(This question is the result of the changes in the HTTP API somewehere in between versions 2.1.0 and 2.2.3. It may be best to just look at the answer, as the effects of the changes are explained there.)
Here is the sequence I have:
I intercept a call, ..., refresh a token if needed, and make a second Http call:
intercept(observable: Observable<Response>): Observable<Response> {
return observable.catch((err: any, caught: Observable<Response>) => {
...
return this.refreshtoken().flatMap((res) =>
this.returnLastMethod(returnMethod, returnUrl, returnData));
In refreshToken():
localStorage.setItem('accessToken', x);
In one of the methods inside the returnLastMethod i do a
let accessToken = localStorage.getItem('accessToken')
and as a result I always get the access token from one Http call before. Now this is a code that worked before switching to Angular ver: 2.2.3, and still does, but obviously I am missing something here as it is not working in Angular-2.2.3.
Here is the Chrome Output:
That is when I use the private variable to create new headers. For some reason the Http call uses some other value, as if it just repeats the old Http call (in console log is shown that the new value is that what I give to the method).
The code of the function where I give the new value to the second Http call:
private returnLastMethod(typ: number, url: string, data?: any): Observable<Response> {
let lastMethodOptions = new RequestOptions();
lastMethodOptions.headers = new Headers();
let accessToken1 = this.currentAccessToken;
console.log(accessToken1 + ' - set to Bearer');
lastMethodOptions.headers.append('Authorization', 'Bearer ' + accessToken1);
lastMethodOptions.headers.append('Content-Type', 'application/json');
switch (typ) {
case 1:
console.log('url: ' + url + ' options: ');
for (let i = 0; i < lastMethodOptions.headers.values().length; i++) { console.log(lastMethodOptions.headers.values()[i]); };
return super.request(url, lastMethodOptions);
case 3:
console.log('url: ' + url + ' options: ');
for (let i = 0; i < lastMethodOptions.headers.values().length; i++) { console.log(lastMethodOptions.headers.values()[i]); };
return super.put(url, data, lastMethodOptions);
case 4:
console.log('url: ' + url + ' options: ');
for (let i = 0; i < lastMethodOptions.headers.values().length; i++) { console.log(lastMethodOptions.headers.values()[i]); };
return super.post(url, data, lastMethodOptions);
case 5:
console.log('url: ' + url + ' options: ');
for (let i = 0; i < lastMethodOptions.headers.values().length; i++) { console.log(lastMethodOptions.headers.values()[i]); };
return super.delete(url, lastMethodOptions);
default:
console.log('url: ' + url + ' options: ');
for (let i = 0; i < lastMethodOptions.headers.values().length; i++) { console.log(lastMethodOptions.headers.values()[i]); };
return super.get(url, lastMethodOptions);
};
}
I do not understand what I'm doing wrong. The new Http call should use the new value that is displayed in the console log, but it seems as if it doesn't?
The problem was the following. Before switching to Angular-2.2.3, I used functions like the following:
request(url: string, options?: RequestOptionsArgs): Observable<Response> {
...
return this.intercept(super.request(url, this.getRequestOptionsArgs(options)));
}
This worked, but after switching to Angular-2.2.3, url is not just a string any more, it is an object, and it holds token inside, as well.
When I wanted to make a new request to return the last visited page (with the new headers, and new token), this was not used to make the call. Instead, because I was using the url which had the token inside, this token was used.
After using url['url'] all problems disappeared.
Update
I have done some refactoring, and in the process have found out the following:
In request function is url an object, in the others methods is url the string.
So if you look down:
request(url: string|Request, options?: RequestOptionsArgs) : Observable<Response>
It says that url can take also the whole request inside, and that is what it does.
In my code, i had something like:
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
this.lastMethod = 5;
this.lastUrl = url;
return this.intercept(super.delete(url, this.getRequestOptionsArgs(options)));
}
The similar for get,post,put...
Somehow, after them (get,put,post...) is the request command called, and this command now has the whole request inside itself, and that created problems in my code, as my function was expecting string at this place.
As i repeat, this functioned differently before, probably without the call to request method, as this problem was nonexistent before...

Asynchronous multipart uploads to Amazon S3 with ASP.NET

I am able to initiate asynchronous uploads to S3, however they are somehow not ending up as a file inside my S3 bucket and I see an error 'WithPartETags cannot be empty'. Here is the complete code
InitiateMultipartUploadRequest initRequest =
new InitiateMultipartUploadRequest()
.WithBucketName(existingBucketName)
.WithKey(Path.Combine(S3Path + "/", finfo.Name));
InitiateMultipartUploadResponse initResponse =
s3Client.InitiateMultipartUpload(initRequest);
// 2. Upload Parts.
long contentLength = finfo.Length;
long partSize = 15728640;//52428800-50MB 104857600- 100 MB - 5242880 - 5 MB
try
{
long filePosition = 0;
for (int i = 1; filePosition < contentLength; i++)
{
// Create request to upload a part.
UploadPartRequest uploadRequest = new UploadPartRequest()
.WithBucketName(existingBucketName)
.WithKey(Path.Combine(S3Path + "/", finfo.Name))
.WithUploadId(initResponse.UploadId)
.WithPartNumber(i)
.WithPartSize(partSize)
.WithFilePosition(filePosition)
.WithFilePath(finfo.FullName);
// Upload part and add response to our list.
//uploadResponses.Add(s3Client.UploadPart(uploadRequest));
IAsyncResult ar = s3Client.BeginUploadPart(uploadRequest, null, null);
ListObj.Add(new ThreadList() { _iasyncResult = ar });
filePosition += partSize;
Console.WriteLine("Length Written - " + filePosition + " .Content Length - " + contentLength);
}
bool uploadsComplete = false;
while (!uploadsComplete)
{
bool individualuploadscomplete = true;
foreach (var obj in ListObj)
{
if (!obj._iasyncResult.IsCompleted)
{
individualuploadscomplete = false;
break;
}
}
if (individualuploadscomplete)
{
uploadsComplete = true;
}
}
foreach (var obj in ListObj)
{
s3Client.EndUploadPart(obj._iasyncResult);
}
//// Step 3: complete.
CompleteMultipartUploadRequest compRequest =
new CompleteMultipartUploadRequest()
.WithBucketName(existingBucketName)
.WithKey(Path.Combine(S3Path + "/", finfo.Name))
.WithUploadId(initResponse.UploadId);
//.WithPartETags(uploadResponses);
CompleteMultipartUploadResponse completeUploadResponse =
s3Client.CompleteMultipartUpload(compRequest);
Not sure why you have the setting of the PartETags commented out for the complete multipart upload call but you need to add that code back in. Also when you are calling the EndUploadPart method you need to capture that UploadResponse that comes back from that.
You also might want to look into the TransferUtility found in the Amazon.S3.Transfer namespace. Its upload methods are designed to handle what you are attempting to accomplish for large objects, see Using the High-Level .NET API for Multipart Upload for details and example snippets.

Document Scanning from ASP.net Web Application

I have a ASP.Net C# 4.0 Web Application
I need to Add a scanning feature for my users.
This is what I want to achieve
On my web application
user clicks on a button
opens a window with preview of document in Scanning device attached to the client system
User confirms the Scan
this will save the Scanned document in jpg/pdf format on the server
then do the OCR on document
Can any one suggest a way to achieve this.
I read about this https://www.leadtools.com/sdk/engine/imaging not sure how much this can work. Can any one suggest a best way to get this done.
Thanks
update
tried leadtools from https://www.leadtools.com/support/forum/posts/m28036-Re--Scan-and-Upload-v16--NET-with-Caspol-exe-deployment as LEAD Support suggested but it is missing references not sure where and how to get those references
HaBo,
This is LEAD support. Since you mentioned our LEADTOOLS toolkit, the answer to your question is yes. Our toolkit can be used to implement either of the 2 approaches mentioned by tgolisch.
For the click-once approach, you simply use our Windows Forms controls that contain Twain support and package your application for ClickOnce deployment. This is done, for example, in this demo project:
LEADTOOLS ClickOnce Demos
For the custom control approach, see the example code projects on our forums that perform Scan and Upload
Solution is here:
In ASP.Net/Core Project you send message to call winform project:
var start = function () {
var i = 0;
var wsImpl = window.WebSocket || window.MozWebSocket;
window.ws = new wsImpl('ws://localhost:8181/');
ws.onmessage = function (e) {
$('#submit').hide();
$('#scanBtn').hide();
$('.loader').show();
if (typeof e.data === "string") {
//IF Received Data is String
}
else if (e.data instanceof ArrayBuffer) {
//IF Received Data is ArrayBuffer
}
else if (e.data instanceof Blob) {
i++;
var f = e.data;
f.name = "File" + i;
storedFiles.push(f);
formdata.append(f.name, f);
var reader = new FileReader();
reader.onload = function (e) {
var html = "<div class=\"col-sm-2 text-center\"
style=\"border: 1px solid black; margin-left: 2px;\"><img
height=\"200px\" width=\"200px\" src=\"" + e.target.result + "\"
data-file='" + f.name + "' class='selFile' title='Click to
remove'><br/>" + i + "</div>";
selDiv.append(html);
$('#submit').show();
$('#scanBtn').show();
$('.loader').hide();
}
reader.readAsDataURL(f);
}
};
ws.onopen = function () {
//Do whatever u want when connected succesfully
};
ws.onclose = function () {
$('.dalert').modal('show');
};
}
window.onload = start;
function scanImage() {
ws.send("1100");
};
https://javascript.info/websocket
In Winforms Project you scan document and send graphic data back to Asp.Net/Core project:
public partial class Form1 : Form
{
ImageCodecInfo _tiffCodecInfo;
TwainSession _twain;
bool _stopScan;
bool _loadingCaps;
List allSockets;
WebSocketServer server;
public Form1()
{
InitializeComponent();
if (NTwain.PlatformInfo.Current.IsApp64Bit)
{
Text = Text + " (64bit)";
}
else
{
Text = Text + " (32bit)";
}
foreach (var enc in ImageCodecInfo.GetImageEncoders())
{
if (enc.MimeType == "image/tiff") { _tiffCodecInfo = enc; break; }
}
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
allSockets = new List<IWebSocketConnection>();
server = new WebSocketServer("ws://0.0.0.0:8181");
server.Start(socket =>
{
socket.OnOpen = () =>
{
Console.WriteLine("Open!");
allSockets.Add(socket);
};
socket.OnClose = () =>
{
Console.WriteLine("Close!");
allSockets.Remove(socket);
};
socket.OnMessage = message =>
{
if (message == "1100")
{
this.Invoke(new Action(()=> {
this.WindowState = FormWindowState.Normal;
}));
}
};
});
}
Link to project.
https://github.com/mgriit/ScanAppForWeb
You can remake this project, as you want.
Web browsers don't have permissions to use system devices like this(major security issue). There are 2 common ways of getting around this:
Make a custom control to run in your browser (flash, silverlight, java applet).
Make a "click-once deployment app" that a user launches from your page.
Both approaches would send the data back to your server via web
services or WCF, etc.

Asp.net WebApi supports json, xml, jsonp?

This question is specific to Asp.Net WebApi.
In my global file, I've put:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonpMediaTypeFormatter());
JsonpMediaTypeFormatter is custom Jsonp formatter that I have.
After this, when i call,
function jsonpCallback(data) {
alert('in' + data);
var list = $('#courses');
for (var i = 0; i < data.length; i++) {
var course = data[i];
list.append('<li>' + course.name + '</li>');
}
}
$.getJSON("http://localhost:64009/api/courses?callback=?", null, jsonpCallback);
It worked.
But, from my global file, if I remove
GlobalConfiguration.Configuration.Formatters.Clear();
Then it doesn't work.
What if i want to support multiple formatters?
As I can use HttpClient for CORS and ask for xml or json or jsop?
Can someone please advice?

Resources