Handle xhr with ASP.NET - asp.net

I would like to send a POST asynchronously from client side (JavaScript) to server side (ASP.Net) with 2 parameters: numeric and long formated string.
I understand the long formated string must have encodeURIComponent() on it befor passing it.
My trouble is I want to embed the long encoded string in body request and later open it from C# on server side.
Please, can you help me? I'm messing too much with ajax, xhr, Request.QueryString[], Request.Form[], ....

First, create an HTTPHandler:
using System.Web;
public class HelloWorldHandler : IHttpHandler
{
public HelloWorldHandler()
{
}
public void ProcessRequest(HttpContext context)
{
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
//access the post params here as so:
string id= Request.Params["ID"];
string longString = Request.Params["LongString"];
}
public bool IsReusable
{
// To enable pooling, return true here.
// This keeps the handler in memory.
get { return false; }
}
}
Then register it:
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.ashx"
type="HelloWorldHandler"/>
</httpHandlers>
</system.web>
</configuration>
Now call it - using jQuery Ajax:
$.ajax({
type : "POST",
url : "HelloWorldHandler.ashx",
data : {id: "1" , LongString: "Say Hello"},
success : function(data){
//handle success
}
});
NOTE Totally untested code but it should be very close to what you need.
I just tested and it works out of the box. This is how I called it:
<script language="javascript" type="text/javascript">
function ajax() {
$.ajax({
type: "POST",
url: "HelloWorldHandler.ashx",
data: { id: "1", LongString: "Say Hello" },
success: function (data) {
//handle success
}
});
}
</script>
<input type="button" id="da" onclick="ajax();" value="Click" />

Related

jQuery Ajax: Parse Error Getting Result to Alert Box

I have a very simple ajax call to my handler from jquery which is failing to retrive data and it gives me parsererror when i try to show the result in alert box.
ASP.NET Handler code:
public void ProcessRequest (HttpContext context) {
string json = new StreamReader(context.Request.InputStream).ReadToEnd();
context.Response.ContentType = "application/json";
context.Response.Write(json);
}
Jquery
$('.submit').on("click",function(e) {
e.preventDefault();
var data1 = { "hi": "hello" };
alert(data1.hi);
$.ajax({
url: "/charity-challenge/CompetitionHelper.ashx",
data: data1,
dataType: 'json',
type: 'POST',
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert("response = " + data);
},
error: function (data, status) {
alert("FAILED:" + status);
}
});
});
Note: I can see the response coming fine in chrome while debugging. BUT somehow when i try to show it in alert box it gives me parsererror.
Also, I want to assign the json data in handler. i dont have any clue how to do that.
i have a sample calss like this in handler. how to loop through the json data and assign values to this variables so i can work on those.
public class userData
{
public string EmailAddress { get; set; }
public string EntryId { get; set; }
}
Found the work around to this.
i added a complete callback and now its showing the result in alertbox. i dont know why it is not working without it BUT if someone knows please post the answer.
here is the complete call back.
complete: function(xhr, status) {
if (status === 'error' || !xhr.responseText) {
alert("Error");
}
else {
var data = xhr.responseText;
alert(data);
//...
}
}
It has to do with your request payload being sent by the ajax call as hi=hello
As a test, try this (requires Newtonsoft.Json nuget):
public void ProcessRequest(HttpContext context)
{
//string json = new StreamReader(context.Request.InputStream).ReadToEnd();
context.Response.ContentType = "application/json";
context.Response.Write(JsonConvert.SerializeObject(new { hi = "hello" }));
}
So I guess you have to parse your input stream e generate the json correctly.
You could also fix this in the client side, by calling using JSON.stringify(data1) in your data parameter in the ajax call.

ASP.NET Handler (.ashx) with long Query String Parameters

I want to know what is the best solution for creating ASP.NET HTTP Handler (.ashx) with long Query string parameters, as i have parameter like "description" which will be a long string which will make a problem in URL when access it by HTTP Request.
if you just want use GET method,you can't solved this problem,you can set it at What is the maximum length of a URL? why.
you can change you .ASHX file accept the POST method.
<httpHandler>
<add path="1.ashx" verb="post" type="" />
</httpHandler>
your server-side code like this :
public void ProcessRequest(HttpContext context)
{
var stream = context.Request.InputStream;
using (StreamReader sr = new StreamReader(stream))
{
var text = sr.ReadToEnd();
}
}
or alternative(based on your client-side how to send data)
public void ProcessRequest(HttpContext context)
{
var text= context.Request.Form["text"];
}
your client-side:
<script type="text/javascript">
$.ajax({
type: 'POST',
url: "1.ashx",
data: { name: "John", time: "2pm" }
});
</script>

Cross Domain Access to ashx service using jQuery

I have an ASP.NET service that I'm access from a asxh file that returns a JSON string. The service works great except when accessed from our blog sub domain which is on a separate server. (blog.laptopmag.com)
Here is my jQuery
$.ajax({
type: "GET",
url: "http://www.laptopmag.com/scripts/service.ashx",
data: { "op": "get_products" },
dataType: "json",
success: function (data) {
alert(data);
}
});
and here is my ashx file
public class service : IHttpHandler {
public void ProcessRequest (HttpContext context) {
string jsonStr = "{}";
string op = context.Request["op"];
// Process request
context.Response.ContentType = "application/json";
context.Response.Write(jsonStr);
}
public bool IsReusable {
get {
return false;
}
}
}
I've tried switching to a jsonp request, but must be doing something wrong because I can't get anything to pull back. Here is what I've tried.
and here is my jsonp attempt that doesn't seem to work when called from blog.laptopmag.com
$.getJSON('http://www.laptopmag.com/scripts/service.ashx?callback=ProcessRequest&op=get_products', function(json) {
console.log(json);
});
OK, I figured out what the problem was with my JSONP request thanks to the following post:
Jquery success function not firing using JSONP
The problem was that the request wasn't getting a response back in the expected format.
Now, my ashx file now looks like this:
public void ProcessRequest (HttpContext context) {
string jsonStr = "{}";
string op = context.Request["op"];
string jsonp = context.Request["callback"];
// Do something here
if (!String.IsNullOrEmpty(jsonp))
{
jsonStr = jsonp + "(" + jsonStr + ")";
}
context.Response.ContentType = "application/json";
context.Response.Write(jsonStr);
}
and the jQuery ajax request looks like this:
$.getJSON('http://www.laptopmag.com/scripts/service.ashx?callback=?&op=get_products', function(json) {
console.log(json);
});
Security restrictions prevent you from making cross-domain jquery ajax calls, but there are workarounds. IMO the easiest way is to create a page on your site that acts as a proxy and hit the page with your jquery request. In page_load of your proxy:
WebClient client = new WebClient ();
Response.Write (client.DownloadString ("your-webservice-url"));
Other solutions can be found by a quick Google search.

Returning JSON from ASMX, and handling it correctly in Javascript

I realize there are tonnes of similar questions already up here but I cannot figure this one out.
I have a Web Service (C#, .net 3.5). The essential Code you need to know of is as follows:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WSMember : System.Web.Services.WebService {
public WSMember () {
}
[WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public string GetMember(string IdMember)
{
//Ignore the parameter for now... I will be looking up a database with it...
//For now just return a minimal object:
Member m = new Member();
m.Surname = "Smith";
m.FirstName = "John";
return new JavaScriptSerializer().Serialize(m);
}
Also, in web.config, I made the following addition (which I just saw on some other post... is this normal/safe?)
<webServices>
<protocols>
<add name="HttpGet" />
<add name="HttpPost" />
</protocols>
</webServices>
Then in Default.aspx, I the two key references...
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="jquery.json-2.2.min.js" ></script>
jquery.json-2.2.min.js was downloaded from google code
And Here is the Javascript:
<script type="text/javascript">
$(document).ready(function() {
$("#button1").click(function(event) {
var myData = { IdMember: "2" };
var encoded = $.toJSON(myData);
alert(encoded);
$.ajax({
type: "POST",
url: "WSMember.asmx/GetMember",
data: encoded,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
alert("worked" + msg.d);
//$("#sidebar").append(msg);
},
error: function(msg) {
alert(msg.d);
//$("#sidebar").append(msg);
}
});
});
});
</script>
When I execute it, the encoded json appears in the message box as expected... i.e. with double quotes:
{ "IdMember":"2" }
However, it always fails. Even for the most basic Hello World with no data being passed in, it fails. I keep getting "undefined" for the message data.
If I just use alert(msg), it displays [object XMLHttpRequest]
Does anyone know where my data is getting lost??
And another question... is there anything fundamentally wrong with what I'm doing?
Thanks a lot.
EDIT:
thanks for the reply guys. I have tried the following so...
UseHttpGet = true is now changed to false. (Again - I saw it somewhere so I tried it... but I knew it couldn't be right :-/ )
Let's say the web service now returns a string. I build the string as follows (seems a bit crazy... serializing it did the exact same thing... )
StringBuilder sb = new StringBuilder();
sb.Append("{");
sb.Append("\"Surname\":");
sb.Append("\"");
sb.Append(m.Surname);
sb.Append("\"");
sb.Append(",\"FirstName\":");
sb.Append("\"");
sb.Append(m.FirstName);
sb.Append("\"");
sb.Append("}");
return sb.ToString();
This code returns something like:
{"Surname":"Smith","FirstName":"John"}
I still get the exact same error...
I have also tried something like returning the object "Member",so the code becomes:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public Member GetMember(string IdMember)
{
Member m = new Member();
m.Surname = "Smith";
m.FirstName = "John";
return m;
}
This too throws the same error.
Sorry to be a pain... I've read both of those links, and others. Just can't see why this any different.
Is there any extra config setting I need to be aware of possibly??
Thanks a lot for replies.
UPDATE:
Problem is fixed. The key mistakes in the above code are:
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
should be
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
Also, on the form, when using a button to call the javascript, I was incorrectly setting the input type...
<input id="button1" type="submit" value="Just a test" />
when it should say:
<input id="button1" type="button" value="Just a test" />
Many thanks to all who helped.
It seems to me that your main problem that you try to manually use JavaScriptSerializer().Serialize instead of returning an object. The response from the web service will be double JSON encoded.
You are right! There are a lot of a close questions. Look at here Can I return JSON from an .asmx Web Service if the ContentType is not JSON? and Can't get jQuery Ajax to parse JSON webservice result and you will (I hope) find the answer.
UPDATED: Sorry, but you have a small error somewhere what you didn't posted. To close the problem I created a small project with an old version of Visual Studio (VS2008) which has practically exactly your code and which work. I placed it on http://www.ok-soft-gmbh.com/jQuery/WSMember.zip. You can download it, compile and verify that it works. Then you can compare your code with my and find your error.
Best regards
If you are doing a post to your data, why are you defining UseHttpGet = true? Shouldn't that be false to match the response type from your request? Also, putting a breakpoint in the ws call to see exactly what the serializer returns would help too... I don't think it should return a JSON object if the return value is a string.
HTH.
Yes, definitely do not manually serialize the object. If you return a Member type, the framework will handle the JSON serialization for you.
When you're seeing the [object XMLHttpRequest] alert, that sounds like it's getting into the error handler in your $.ajax() call, where the response passes in its XHR object as the first parameter. You're probably getting a 500 error on the server.
Here's an example of decoding the ASP.NET AJAX error response in jQuery. Most simply, change your error handler to this:
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(err.Message);
}
That will give you some insight into what the specific error is.
If you are returning any complex object (relational objects with foreign keys), you have 2 options:
Use a DTO object
Write your own specific serialization converter
i have bad english, but this is a solution
----- WSMember.asmx ------
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WSMember : System.Web.Services.WebService {
public WSMember () {
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetMember(int IdMember)
{
Member m = new Member();//Get Member from DB, exam Linq to Sql
m.Surname = "Smith";
m.FirstName = "John";
return string.Format("{{ \"Surname\":\"{0}\",\"FirstName\":\"{1}\" }}",m.Surname,m.FirstName);
}
}
---- Default.aspx ----
Just a test
<script type="text/javascript">
$("#button1").click(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "WSMember.asmx/GetMember",
data: "{IdMember: 2 }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
if (msg.hasOwnProperty('d')) {
msg = msg.d;
}
var json = JSON.parse(msg);
console.log(json.Surname);
console.log(json.FirstName);
},
error: function (xhr, status, error) {
//console.log(xhr);
//console.log(status);
//console.log(error);
}
});
});
</script>

ASP.NET MVC Controller FileContent ActionResult called via AJAX

The setup:
The controller contains a method public ActionResult SaveFile() which returns a FileContentResult.
What works:
The view contains a form, which submits to this action. The result is this dialog:
What doesn't work:
The view contains some javascript to do an AJAX call to the same controller action where the form would post. Rather than triggering the aforementioned dialog, or even the AJAX success function, the response triggers the AJAX error function, and the XMLHttpRequest.responseText contains the file response.
What I need to do:
Make the request for the file using AJAX, and end up with the same result as when submitting a form. How can I make the AJAX request provide the dialog that submitting a form shows?
Here's a quick example I made up. This is the concept LukLed was talking about with calling SaveFile but don't return file contents via ajax and instead redirect to the download.
Here's the view code:
<script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
// hide form code here
// upload to server
$('#btnUpload').click(function() {
$.ajax({
type: 'POST',
dataType: 'json',
url: '<%= Url.Action("SaveFile", "Home") %>',
success: function(fileId) {
window.location = '<%= Url.Action("DownloadFile", "Home") %>?fileId=' + fileId;
},
error: function() {
alert('An error occurred uploading data.');
}
});
});
});
</script>
<% using (Html.BeginForm()) { %>
<div>Field 1: <%= Html.TextBox("field1") %></div>
<div>Field 2: <%= Html.TextBox("field2") %></div>
<div>Field 3: <%= Html.TextBox("field3") %></div>
<button id="btnUpload" type="button">Upload</button>
<% } %>
Here's the controller code:
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public JsonResult SaveFile(string field1, string field2, string field3)
{
// save the data to the database or where ever
int savedFileId = 1;
// return the saved file id to the browser
return Json(savedFileId);
}
public FileContentResult DownloadFile(int fileId)
{
// load file content from db or file system
string fileContents = "field1,field2,field3";
// convert to byte array
// use a different encoding if needed
var encoding = new System.Text.ASCIIEncoding();
byte[] returnContent = encoding.GetBytes(fileContents);
return File(returnContent, "application/CSV", "test.csv");
}
public ActionResult About()
{
return View();
}
}

Resources