SVC Web service consuming from code behind but not from javascript - asp.net

I want to call web service in project (but in same solution) from myClient project.
I have added service reference in myClient project.
When I call scf from code behind it, works but when I try to call it from JavaScript using JSON, I am unable to do so. Guys pls help.
"http://someurl.com/MyWebService.svc/DoWork/" is path of my Service
abovive url someurl is url of localhost
This code is from a.aspx of client application of JSON,
$.ajax(
{
type: 'GET',
url: 'http://someurl.com/MyWebService.svc/DoWork/',
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
alert(jqXHR.responseText);
},
success: function (data) {
alert(data);
}
});
From Code behind
string postData = "http://someurl.com/MyWebService.svc/DoWork/";
int timeout = 10;
//string dwml = string.Empty;
//MyServiceReference.MyWebServiceClient ms = new MyServiceReference.MyWebServiceClient();
//dwml = ms.DoWork();
//System.Net.WebClient webClient = new System.Net.WebClient();
//dwml = webClient.DownloadString(serviceURL);
//Response.Write(dwml);
HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create(postData);
// Set the Method property of the request to POST.
webRequest.Headers.Clear();
webRequest.AllowAutoRedirect = true;
webRequest.Timeout = 1000 * timeout;
webRequest.PreAuthenticate = true;
webRequest.ContentType = "application / x - www - form - urlencoded";
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";
webRequest.Timeout = 150000;
// Create POST data and convert it to a byte array.
WebResponse webResponse = null;
StreamReader objSR;
System.Text.Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
Stream objStream;
string sResponse;
webResponse = (HttpWebResponse)webRequest.GetResponse();
objStream = webResponse.GetResponseStream();
objSR = new StreamReader(objStream, encode, true);
//<<sResponse doesn't contain Unicode char values>>
sResponse = objSR.ReadToEnd();
Response.Write(sResponse); // OR Response.write(HttpUtility.HtmlEncode(sResponse))

Guys this immediate second question (both asked by me only) which only myself has answered or commented. I got ans 4 this from stack overflows old question
Basic example of using .ajax() with JSONP?
Issue was with cross domain web-service call is not allowed through AJAX.
I came across new concept of JSONP, wow feeling great!
But I was expecting quick reply from Stack overflows other members.
I will not be able to rescue myself every time friends!

calling WCF service from RESTclient in different solution without JSONP:
Here I came up with another working solution for, calling WCF service from RESTclient in different solution without using JSONP i.e. Enabling CORS of service (Cross Origin Resource Sharing) policy.
We all must have tried:
Adding Header Access-Control-Allow-Origin in web-config file of Service Project,
Code in web-config :
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" />
<add name="Access-Control-Max-Age" value="1728000" />
</customHeaders>
</httpProtocol>
but anyhow, that didn't worked out for me!
So, there is another way to achieve the same, is to Create a Global.asax in Service Project and Add this code to the Global.asax.cs:
Code in Global.asax.cs :
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
And you can continue with your regular AJAX call from RESTclient solution to WCF service:
Sample AJAX :
$(document).ready(function () {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://localhost:51058/Service1.svc/GetData",
dataType: 'json',
success: function (data) {
//do success part here
alert(data);
},
error: function (e) {
alert(e.message);
}
});
});
The best part is, no need to do any modifications in RESTclient project solution.

here I have tried so far
SVC code file service1.svc.cs :
using System;
namespace TestConnection
{
public class Service1 : IService1
{
public string GetData()
{
return string.Format("You entered: {0}", "Success");
}
}
}
JavaScript function:
<script type="text/javascript">
$(document).ready(function () {
var text;
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: 'Service1.svc/GetData', /*you .svc address : 'http://someurl.com/MyWebService.svc/DoWork/'*/
dataType: "json",
async: false,
success: function (a) {
var response = $.parseJSON(a);
text = response.Table[0];
alert(text);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert('Failure');
}
});
});
</script>
All above code you might have tried, some important note to get this worked is:
1. as WCF .svc works on Representational State Transfer (REST), you have to explicitly mention data get request in service1.svc Markup file,
[OperationContract]
[WebGet()]
//You can use below attributes to make necessary modifications
//RequestFormat = WebMessageFormat.Json,
//ResponseFormat = WebMessageFormat.Json,
//BodyStyle = WebMessageBodyStyle.Bare,
//UriTemplate= "GetData"
//)]
string GetData();
To use WebGet,you will need to add library System.ServiceModel.Web to your service Project.
And if you have issues with basic settings then,
Web.Config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMathService" />
</basicHttpBinding>
</bindings>
</system.serviceModel>
NOTE: This will not work for cross domain, if you want that, its answered Here.

Related

Unable to get headers from jQuery AJAX request in ASP.NET Web API

I have an ASP.NET Web API which is hosted on Azure. I have integrated HTTP Message handler to that API. The message handler is getting hit when I am hitting it using AJAX call. I am also sending some request header in my AJAX call. The problem is I am not getting header sent from AJAX call to Message Handler integrated in Web API. Refer image: Debugger screenshot
Below is the code of my AJAX request:
$.ajax({
url: "https://someservicename.azurewebsites.net/Service/RequestHandler",
beforeSend: function (xhr) {
xhr.setRequestHeader('Token', '86810e135958961ad4880ad');
},
type: "POST",
crossDomain: true,
data: {
param: "Passed Parameter"
},
success: function (msg) {
console.log(msg);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(textStatus);
}
});
The message handler in Web API looks like below:
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string authToken;
try
{
authToken = request.Headers.GetValues("Token").FirstOrDefault();
if (authToken != "86810e135958961ad4880ad")
{
return await Task.Factory.StartNew(() =>
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Unauthorized access!")
};
});
}
else
{
return await base.SendAsync(request, cancellationToken);
}
}
catch (System.InvalidOperationException)
{
return null;
}
}
When I run the the code from my IIS localhost the request which is sent is something like below:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:token
Access-Control-Request-Method:POST
Connection:keep-alive
Host:someservicename.azurewebsites.net
Origin:http://localhost:12522
Referer:http://localhost:12522/pocppd.html
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
And the response which I getting in console is:
https://someservicename.azurewebsites.net/Service/RequestHandler. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:12522' is therefore not allowed access. The response had HTTP status code 500.
With POSTMAN client the request works fine but from localhost it returns an error. Please let me know the reason for not getting header in my message handler?
You have to add this in your Web.config (you can change values as you need):
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, Authorization, Token" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE" />
</customHeaders>
</httpProtocol>
Before your request, an OPTIONS request is sent to ensure that you are allowed to perform the request. As the error says, "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.". Adding above lines in Web.config will pass the needed header.
MDN says: "Unlike simple requests (discussed above), "preflighted" requests first send an HTTP OPTIONS request header to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data."
Try this
$.ajax({
url: "https://someservicename.azurewebsites.net/Service/RequestHandler",
headers: {
"Token": "86810e135958961ad4880ad"
},
type: "POST",
crossDomain: true,
data: {
param: "Passed Parameter"
},
success: function (msg) {
console.log(msg);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(textStatus);
}
});

Ajax Webservice call

I have the below code in my ASPX page to get some data from a webservice. I cannot use WCF so I am using the ASMX and .Net 3.5. However, what I get back is the yellow ASP.net error page talking about setting the web.config error tag to OFF. If I call my method from code behind and response.write it to the page I get a Json string that I have viewed in JSON Viewer and it parses fine. My issue here is the URL format. What am I doing wrong here. Every example I have found uses the webservice.asmx/Method format. I have also added the protocols to my web.config
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
Page Script:
$.ajax({
type: 'GET',
contentType: "application/json; charset=utf-8",
url: 'http://myserver/mywebservice.asmx/MyMethod',
dataType: 'jsondata',
success: function (msg) {
var table = "<table><tr><th>ID</th><th>Title</th></tr>"
for (var i = 0; i <= msg.length - 1; i++) {
var row = "<tr>";
row += "<td>" + msg[i].ID + "</td>";
row += "<td>" + msg[i].Title + "</td>";
row += "</tr>";
table += row;
}
table += "</table>";
$("#myDiv").html(table);
},
complete: function () {
alert("complete");
}
});
Webservice:
<WebMethod(), ScriptMethod(ResponseFormat:=ResponseFormat.Json, UseHttpGet:=True)> _
Public Function MyMethod() As String
'removed for shorter post
End Function
UPDATE: So using the dev tools in Chrome I have found that part of my problem was the server was returning a 403 Forbidden error. After som tweaking I have come up with a partial solution that gives me back my data with json formatting. However, that json formatted text is now wrapped in XML. :-(
I have yet been able to figure out how to get the XML out of my json. Any ideas?
You should have
contentType: "application/json; charset=utf-8",
url: 'http://myserver/mywebservice.asmx/MyMethod',
dataType: 'jsondata',
similar to:
contentType: "application/json",
url: '/folderonmyserver/mywebservice.asmx/MyMethod',
dataType: 'json',
data: "{}", // needed for .Net not to blow up sometimes - or send real data
and in your success: reference msg.d (or have a translation to isolate that for .Net) given your .net version
success: function (msg) {
var mydata = msg.d;
var table = "<table><tr><th>ID</th><th>Title</th></tr>"
for (var i = 0; i <= mydata.length - 1; i++) {

XML Parsing Error: no element found

I have an ASP.Net 4.0 Web Service method that returns a well-formed XML document. I am successfully displaying the XML in a browser locally and once deployed on the production server.
When I try to call the method via jQuery ajax I'm getting the error:
XML Parsing Error: no element found Location: moz-nullprincipal:{6c0c99b3-0fed-454f-aa6e-e0fca93a521c} Line Number 1, Column 1:
$.ajax(
{
url: 'http://mywebservice.com/WebService/Service.asmx/UserData',
type: 'GET',
contentType: "text/html; charset=utf-8",
dataType: "xml",
data: 'authorizedId=1234&authorizedUser=Test&authorizedCode=xyz',
'success': function (data) {
$('#XMLContent').html(data.responseText);
},
'error': function (xhr, status) {
alert(status);
},
'complete': function (xhr) {
}
});
I've tried changing the contentType but same results.
However, I can make the call in C# like this and I get my well-formed XML:
XmlDocument document = new XmlDocument();
document.Load("http://mywebservice.com/WebService/Service.asmx/UserData?authorizedId=1234&authorizedUser=Test&authorizedCode=xyz");
ViewData["XMLData"] = document.OuterXml;
In my web service web.config:
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
Thanks...
If the web service is not on the same domain as the page, you can not use AJAX calls to fetch data from other domains.
You can create a proxy web service in your aplication which calls your external web service, then call your own proxy from AJAX/jQuery.
http://forum.jquery.com/topic/jquery-ajax-and-xml-issues-no-element-found
Hope that helps
Thanks bgs264...
Now in my aspx page:
$.ajax(
{
url: '/Home/WebService',
type: 'GET',
contentType: "text/html",
dataType: "html",
data: 'authorizedId=1234&authorizedUser=Test&authorizedCode=xyz',
'success': function (data) {
alert(data);
$('#XMLContent').html(data);
},
'error': function (xhr, status) {
alert(status);
},
'complete': function (xhr) {
}
});
In my MVC controller:
public ActionResult WebService(string authorizedId, string authorizedUser, string authorizedCode)
{
XmlDocument document = new XmlDocument();
document.Load("http://mywebservice.com/WebService/Service.asmx/UserData?authorizedId=" + authorizedId + "&authorizedUser=" + authorizedUser + "&authorizedCode=" + authorizedCode);
ViewData["XMLData"] = document.OuterXml;
return PartialView();
}

using jQuery AJAX with asp.net webservices always goes to error: instead of success:

Issue
I have an aspx page with jQuery code to send an ajax request over to an asmx web service file (on the same website). The response that comes back is not consistent, however, it consistently fires the "error" jQuery callback as opposed to the "success" call back. The status code inconsistently varies between 200, 12030, and 12031. The responseText of the message to the callback inconsistently varies between [blank] and the actual XML that the json webservice returns. I debugged the code, and the webservice does actually execute without any exceptions.
ASPX Code
//Code omitted for brevity
<script type="text/javascript">
jQuery(document).ready(function()
{
jQuery.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "CallDequeue.asmx/Dequeue",
data: "{}",
dataType: "json",
success: function(Msg)
{
alert('success:' + Msg.responseText);
},
error: function(Msg)
{
alert('failed:' + Msg.status + ':' + Msg.responseText);
}
});
});
</script>
//Code ommitted for brevity
Web Service Code
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class CallDequeue : System.Web.Services.WebService
{
[WebMethod]
public string Dequeue()
{
return "{\"d\":{\"FirstName\":\"Keivan\"}}";
}
}
When you mark the service as a ScriptService, it automatically handles the JSON serialization. You shouldn't manually serialize the response.
If you want the return to come back as "FirstName", then you can use a DTO class to control the syntax. Just returning a string, it would come back as {'d':'Keivan'} instead of {'d':{'FirstName':'Keivan'}}.
[ScriptService]
public class CallDequeue : System.Web.Services.WebService
{
public class PersonDTO
{
public string FirstName;
}
[WebMethod]
public PersonDTO Dequeue()
{
var p = new PersonDTO();
p.FirstName = "Keivan";
return p;
}
}
A few changes to the calling syntax:
jQuery(document).ready(function() {
jQuery.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "CallDequeue.asmx/Dequeue",
data: "{}",
dataType: "json",
success: function(Msg) {
// Unless you're using 2.0, the data comes back wrapped
// in a .d object.
//
// This would just be Msg.d if you return a string instead
// of the DTO.
alert('success:' + Msg.d.FirstName);
},
error: function(Msg) {
alert('failed:' + Msg.status + ':' + Msg.responseText);
}
});
});
You can read more about ASP.NET AJAX's .d wrapper here, if you're interested.
Update:
Using ASP.NET 2.0, you need to install the ASP.NET AJAX Extensions v1.0. Additionally, make sure your web.config is configured for ASP.NET AJAX (most specifically the HttpHandlers section).
This question will most likely help you.
Otherwise, I converted this web service to a page method and it worked immediately. Do you have that option?
CS:
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static string Dequeue()
{
return "{\"d\":{\"FirstName\":\"Keivan\"}}";
}
}
ASPX:
<script type="text/javascript">
jQuery(document).ready(function()
{
jQuery.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "test.aspx/Dequeue",
data: "{}",
dataType: "json",
success: function(Msg)
{
alert('success:' + Msg.responseText);
},
error: function(Msg)
{
alert('failed:' + Msg.status + ':' + Msg.responseText);
}
});
});
Check this and other Encosia articles out for more information.
you say it's json, but it returns xml. i see a slight disconnect there.
Such a simple answer. My web.config wasn't ajax enabled so all calls (regardless of my webservice being a scriptservice) were returning XML instead of pure json.
Try marking up your web method with [ScriptMethod]
As in:
[WebMethod]
[ScriptMethod]
My thanks to all the responders here.
Be sure to add these attributes in front of the methods to be used
[WebMethod]
[ScriptMethod]
Not sure when the ScriptMethod is needed ?
Curiously, he did NOT have the [Script Service] and the [WebMethod] in his download code.
Anyway, the aJax 500 12030 12031 errors are gone after the above changes.

Authenticate windows user using jquery

MyMasterPage.master
<head runat="server">
<script type="text/javascript">
$(document).ready(function() {
var userName = '<%# System.Web.HttpContext.Current.Request.ServerVariables["AUTH_USER"].ToString() %>';
alert(userName);
$.ajax({ type: "POST",
url: "DemoWebService.asmx/GetFulName",
contentType: "application/json; charset=utf-8",
dataType: "xml",
dataType: "json",
data: "{'networkId':'" + userName + "'}",
processData: false,
error: function(XMLHttpRequest, textStatus, errorThrown) { ajaxError(XMLHttpRequest, textStatus, errorThrown); },
success: function(xml) { ajaxFinish(xml); }
});
});
</script>
</head>
Even though the userName variable is blank, I get the logged in user from my WebMethod:
[WebMethod]
public string GetFulName(string networkId)
{
//return networkId + " Full Name";
return networkId + " From Server: " + System.Web.HttpContext.Current.Request.ServerVariables["AUTH_USER"].ToString();
}
Since I am checking on the master page, what is the best practice to store the authentication result so that I do not have to check on everypage. Prior to using jquery I was storing in Session.
Thanks
web.config
<authentication mode="Windows"/>
<webServices>
<protocols>
<add name="HttpPost"/>
<add name="HttpGet"/>
</protocols>
</webServices>
You could store the result in a cookie, and then check that cookie on subsequent pages to get the logged in user's name. You would want to make sure and delete the cookie if the user logged out or their authenticated session expired.
There is a plugin available for jQuery to support reading/writing/deleting cookies.

Resources