JqueryAjax Webservice and Crossdomain problem - asp.net

i am having problem with my Jqueryajax call that will consume one of my web service method via cross domain. i have been trying all the possible way to accomplish but still no success. please help me with what i am doing wrong. may be i need to configure web server for some security settings? below is my code. please let me know if you have any question regarding with my code.
//Using Ajax Post
//Webservice will return JSON Format
//Doesn't work in both FF and IE when host to live server , work in local
//Error : Access is denined in xxxx.js in IE
//Http 403 Forbidden in FF , FF request header is OPTION
//this approach is the simplest and best way for me to use
var myID = $("myID").val();
$.ajax({
type: "POST",
url: "http://www.mywebsite.com/webservice/Webservice.asmx/getInfo",
data: "{myID:'"+ myID + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
Dostuff(data);
},
error: FailureCallBack
});
My webservice will look like this
using System.Web.Script.Services;
[WebService(Namespace = "http://www.mywebsite.com/webservice/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class Webservice : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public object getInfo(string myID)
{
//Do stuff here
return getJSONDataFromDataSet(_DS);
}
}
//second Approch <br/>
//Using Ajax GET , webservice will return XML Format <br/>
//Doesn't work in both FF and IE when host to live <br/>
//Error : Access is denined in xxxx.js in IE <br/>
//returning XML data in FF but showing nothing in page <br/>
var myID = $("myID").val();
$.ajax({
type: "GET",
url: "http://www.mywebsite.com/webservice/Webservice.asmx/getInfo?myID="myID"&callback=?",
success: function(data) {
Dostuff(data);
},
error: FailureCallBack
});
Webservice
public SerializableDictionary<string, object> getInfo(string myID)
{
//Do stuff here
SerializableDictionary<string, object> obj = getJSONFromDataTable(_DS);
return obj;
}
//third Approch
//Using normal GET , webservice will return XML Format
//same problem with second approch
var myID = $("myID").val();
var xmlhttprequest = createRequestObject();
var url = 'http://www.mywebsite.com/webservice/Webservice.asmx/getInfo?myID='myID'';
xmlhttprequest.open("GET", url, true);
xmlhttprequest.onreadystatechange = getData;
xmlhttprequest.send(null);
function getData()
{
if ((xmlhttprequest.readyState == 4) &&( xmlhttprequest.status == 200))
{
var myXml = xmlhttprequest.responseXML;
Dostuff(myXml);
}
}
function createRequestObject()
{
if (window.XMLHttpRequest)
{
return xmlhttprequest = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
return xmlhttprequest = new ActiveXObject("Microsoft.XMLHTTP");
}
}
Webservice is same with second approach
EDIT:
now i am getting Access is denied , javascript error for both POST and GET request in IE.
in fiddler i can see Firefox returning the Xml data but nothing showing in page, so i put a alert box in getData
function, myXml variable value is always null, strange i only put 1 alert box and it show alert 3 times.
below is my code
var myID = $("myID").val();
var xmlhttprequest = createRequestObject();
var encodeUrl = escape(_utf8_encode("http://www.mywebsite.com/webservice/Webservice.asmx/getInfo?myID="myID));
var url = 'http://www.mywebsite.com/webservice/proxy.aspx?url='+encodeUrl;
xmlhttprequest.open("GET", url, true); //**ACCESS IS DENIED HERE in this line!!!!**
xmlhttprequest.onreadystatechange = getData;
xmlhttprequest.send(null);
function getData()
{
var myXml = xmlhttprequest.responseXML;
alert(myXml); //ALWAYS NULL and show alert 3 times????
DoStuff(myXml);
}
Please help.
best regards

For security reasons, the ajax requests will not work cross domain. There are two solutions to this.
Make the request to the same server, and use a server based proxy mechanism to then make the request to the other domain.
Use "JSONP", which is an alternative cross way of making ajax like requests. jQuery supports this via the dataType: jsonp rather than json, and there is further explanation via their api docs. This blog entry may be useful - http://bloggingabout.net/blogs/adelkhalil/archive/2009/08/14/cross-domain-jsonp-with-jquery-call-step-by-step-guide.aspx

you will need to create proxy on your domain and pass through the request, explain here: http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/

thanks so much for all the reply and help.
i have solved the problem :D
solution is to use JSONP and Javascript dynamic injection to html page.
below is code
HTML
<body>
<script type="text/javascript">
var url = "http://www.mywebsite.com/Javascript/MYJS.js";
var script = document.createElement("script");
script.setAttribute("src",url);
script.setAttribute("type","text/javascript");
document.body.appendChild(script);
</body>
</script>
MYJS.js
var myID = $("#myID").val();
var url = "http://www.mywebsite.com/Webservice.aspx/getInfo?myID="+myID+"";
if (url.indexOf("?") > -1)
url += "&jsonp=" ;
else
url += "?jsonp=" ;
url += "ShowInfoCallback" + "&" ; //Important put ur callback function to capture the JSONP data
url += new Date().getTime().toString(); // prevent caching
var script = document.createElement("script");
script.setAttribute("src",url);
script.setAttribute("type","text/javascript");
document.body.appendChild(script);
function ShowInfoCallback(data)
{
DoWhateverYouWant(data);
}
Webservice.aspx.cs
using System.Web.Script.Serialization;
public partial class Webservice : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["myID"]))
this.getInfo();
else
this.getInfoDetails();
}
public void getInfo()
{
string Callback = Request.QueryString["jsonp"];
string encryptedID = Request.QueryString["myID"];
//Dowhateveryouwanthere
object obj = getJSONFromDataTable(myDataSet.Tables[1]);
JavaScriptSerializer oSerializer = new JavaScriptSerializer();
string sJSON = oSerializer.Serialize(obj);
Response.Write(Callback + "( " + sJSON + " );");
Response.End();
}
public void getInfoDetails()
{
//Same as above
//returning 2 tables , Info and InfoDetails
Response.Write(Callback + "( { 'Info' : " + sJSONDetails +",'InfoDetails' : "+ sJSONService + " } );");
Response.End();
}
}
Thanks again

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.

How could i pass parameters to method in a controller through jquery ajax calls

I am working on asp.net web api. I am trying to make a call to controller(Security) using jquery ajax calls. I have a method in my controller with 3 parameters like,
public WebRequest GetRequest(string method,string type,string endpoint)
{
RSACryptoServiceProvider rsa=new RSACryptoServiceProvider();
var request = WebRequest.Create(endpoint);
request.Method = method;
request.ContentType = type;
UnicodeEncoding enc = new UnicodeEncoding();
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
request.Headers.Add("Authorization-Token", RSAClass.StringConverter(RSAClass.RSAEncrypt(enc.GetBytes("User1"), rsa.ExportParameters(false), false)));
return request;
}
and i am making a jquery ajax call like,
CreateRequest("GET", "application/json;charset=utf-8", "http://localhost:49847/api/Security", function (request) { alert("Hello"); });
function CreateRequest(method, type, endpoint, callback) {
$.ajax({
url: "api/Security",
data: { method: method, type: type, endpoint: endpoint },
type: "GET",
contentType: "application/json;charset=utf-8",
statusCode: {
200: function (request) {
callback(request);
}
}
});
and also i have customfilterattribute class to validate authorization token like,
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
string token;
try
{
token = actionContext.Request.Headers.GetValues("Authorization-Token").First();
}
catch
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest) { Content = new StringContent("missing authorization token") };
return;
}
try
{
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
UnicodeEncoding enc = new UnicodeEncoding();
AuthUsersRepository.GetAllUsers().First(x => x.Name ==enc.GetString(RSAClass.RSADecrypt(RSAClass.ByteConverter(token), RSA.ExportParameters(true), false)));
base.OnActionExecuting(actionContext);
}
catch
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden) { Content = new StringContent("Unauthorized User") };
return;
}
}
when iam making first request it asking me for authorization token. and also showing null values in the 3 parameters(method,type,endpoint). guide me.
You need this:
data: { 'method': method, 'type': type, 'endpoint': endpoint },
This passes the values in the request, although in your example I'm not sure why you would need to pass endpoint as a parameter to the method if its value is the URL of the controller / action?
You either need to
1) change your GET to POST the data as JSON. GET cannot have content.
2) Pass the data as query string parameters
If I am to do it myself, I would go for case 2:
http://localhost:49847/api/Security?method=someMethod&type=someType&endpoint=someendpoint
Since this is security related, it has to be HTTPS.
But I would not do it myself, instead use what security experts have developed: "Thinktecture.IdentityModel.40"
https://github.com/thinktecture/Thinktecture.IdentityModel.40

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>

consume a asp.net web service that returns json from an stand alone html page

I've developed a web service in asp.net and am able to test it from an in-project aspx page and can readily display the information that was returned in JSON format.
I now need to consume the web service from a stand-alone html page.
Does someone have experience with this? I'm puzzled by the part that would replace this
<asp:ScriptManager ID="ScriptManager" runat="server">
<Services>
<asp:ServiceReference Path="~\MyService.asmx" />
</Services>
</asp:ScriptManager>
If this is not possible with straight html and javascript, can someone show me a stand-alone php page that would do it?
See this link:
http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/
Use JQuery
www.jquery.org
Essentially, you make your Web Service script callable, just an attribute in your Web Service definition and you do:
$.ajax({
type: "POST",
url: "~/MyService.asmx/MyMethod",
data: "{parameterName:'" aStringArgument + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
var data = msg.d
// Now var is an object with properties just like your object
}
});
Use JQUery.
You can use Javascript to access your webservice.
For example - if you have a json webservice defined like this:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public String Foo(String p1, String p2)
{
return "Hello World";
}
you could call it as follow:
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);
}
}
//Called on successfull webservice calls
OnSuccess()
{
if (httpobj.readyState == 4)
{
//Retrieve the JSON return param
var response = eval("(" + httpobj.responseText + ")");
}
}
If you do not want to use the ScriptManager (which adds over 100k of JS to your page), you can use this method to use jQuery to connect to your web services.

Resources