ajax call to wcf from asp.net mvc - ajax

I have two apps. The first is WCF Service, the second is asp.net MVC 3 app.
In the WCF app I have a interface:
[ServiceContract]
public interface IService1
{
[OperationContract]
string HelloWorld(string personName);
}
And a class:
public class Service1 : IService1
{
public string HelloWorld(string personName)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize("Hello " + personName);
}
}
Now, in the asp.net mvc app I want call this method via Ajax:
<script type="text/javascript">
var personName = "John";
var dataIn = '{' + '"input":"' + personName + '"}';
$.ajax({
url: "http://localhost:7215/Service1.svc/HelloWorld",
type: "POST",
contentType: "application/json; charset=utf-8",
data: dataIn,
dataType: "json",
success: function (data) {
var object = JSON.parse(data.d);
if (object.Error == '') {
$("#response").html(object);
}
},
error: function (error) {
alert("Error: " + error);
}
});
</script>
But in the Firebug I get error: 400 Bad Request.
How to call HelloWorld method properly?
Thanks.

So you are trying to consume a WCF service from JavaScript?
The first problem I see is, your service is not yet ready to be consumed from JavaScript :(. You have to make the following changes..
Configure the Service1 class with the AspNetCompatibilityRequirements behavior.
Mark the service method HelloWorld in interface with WebGet attribute.
[You need reference to System.SericeModel.Web assembly]
After making the two changes..
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
string HelloWorld(string personName);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public string HelloWorld(string personName)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
// you are not returning data in proper JSON format, wrap the text in
// an anonymous object before serializing.
return serializer.Serialize(new { text = "Hello " + personName });
}
}
Next..
Configure webHttpBinding for the service (Make sure you change the service and contract names!).
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJsonP" />
</webHttpBinding>
</bindings>
<services>
<service name="MvcApplication3.Service1">
<endpoint address="" binding="webHttpBinding"
bindingConfiguration="webHttpBindingWithJsonP"
contract="MvcApplication3.IService1"
behaviorConfiguration="webHttpBehavior"/>
</service>
</services>
</system.serviceModel>
So now the service is ready!
Lets do the changes in the client-side (You are getting some data from the service so why POST?)
<script type="text/javascript">
var personName = "John";
var dataIn = '{' + '"input":"' + personName + '"}';
$.ajax({
url: "http://localhost:50623/Service1.svc/HelloWorld",
type: "GET",
contentType: "application/json; charset=utf-8",
data: dataIn,
dataType: "json",
success: function (data) {
var jsonData = JSON.parse(data);
$("#response").html(jsonData.text);
},
error: function (error) {
alert("Error: " + error);
}
});
</script>
Till now I've assumed that both the WCF service and the MVC app are running in the same domain.
But if that's not the case then you will gete a 405(Method Not Allowed) error due to CROSS-DOMAIN BARRIER.
There are different ways to overcome this problem!
1. Use JSONP
In this case you have to set the crossDomainScriptAccessEnabled property to true in the binding and you have to make JSONP calls from jQuery.
<binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
Then change the dataType from "json" to "jsonp" in the $.ajax method.
<script type="text/javascript">
var personName = "John";
var dataIn = '{' + '"input":"' + personName + '"}';
$.ajax({
...
dataType: "jsonp",
...
});
</script>
2. Using CORS
Refer this..
http://www.w3.org/TR/cors/
https://developer.mozilla.org/en/http_access_control

The first thing that you need to ensure is that you are not violating the same origin policy that's built in browsers. This policy prevents you from sending cross domain AJAX request. Since you mentioned that you have 2 applications I suspect that you are hitting this limitation because you have for example the first application hosted on http://localhost:1234/ (the one that contains the javascript file) and you are attempting to send an AJAX request to http://localhost:7215/ (same domain, different port => same origin policy is violated).
There are several workarounds. One of them consists into configuring the service to send a JSONP response instead of JSON. Here's a sample WCF service application on MSDN which illustrates how you could configure it. Basically you need to enable the crossDomainScriptAccessEnabled switch as shown in this blog post.

Related

How to correctly handle an AJAX request using Spring MVC? Why doesn't this example work in my project?

I am pretty new in Spring MVC and AJAX and I have the following problem.
Into a page my application perform this JavaScript function that perform an AJAX GET request:
function caricaDettaglioRegione(regioneSelezionata) {
var codiceRegione = regioneSelezionata.getAttribute("data-reveal-id");
var nomeRegione = regioneSelezionata.getAttribute("data-nome-regione");
alert("codiceRegione: " + codiceRegione + " - nomeRegione: " + nomeRegione);
$.ajax({
type: "GET",
data: {'codiceRegione' : codiceRegione
},
url: "riepilogoDettaglioRegione",
contentType:"application/json"
}).done(function(response) {
alert("DONE");
}).error(function(xhr) {
alert("ERROR");
manageError(xhr);
});
}
As you can see in the Http GET request is passed the value of the codiceRegione as request paramether (named codiceRegione) by this line:
data: {'codiceRegione' : codiceRegione
},
So now I want to handle this AJAX request and I have implement this controll method into a #Controller class:
#RequestMapping(value = "/riepilogoDettaglioRegione", method = RequestMethod.GET)
public String riepilogoDettaglioRegione(#RequestParam("codiceRegione") String codiceRegione, Model model) {
System.out.println("INTO riepilogoDettaglioRegione()");
return "blabla";
}
As you can see it handle the GET requesto toward previous resource (/riepilogoDettaglioRegione) and I try to retrieve the codiceRegione request parameter by #RequestParam("codiceRegione")
But it can't work and this method is not performed when the previous AJAX request is performed.
What am I missing? How can I solve this issue?
You're explicitly saying that the codiceRegione is a parameter not the request body.
So for that you will need to change your ajax call like:
$.ajax({
type: "GET",
url: "riepilogoDettaglioRegione?codiceRegione=blah",
contentType:"application/json"
}).done(function(response) {
alert("DONE");
}).error(function(xhr) {
alert("ERROR");
manageError(xhr);
});
Or wrap codiceRegione in an object and then change the annotation #RequestParam for #RequestBody.
Hope it helps.
Solved by myself.
The problem was that the project used Spring Security and that this resource have to be accessible also to not logged user so I have to insert something like this
<intercept-url pattern="/riepilogoDettaglioRegione" access="permitAll" />
into the authernticationManager configuration into the spring-security.xml file.

ASP.NET web API HTTP Delete 405 Method Not Allowed

I already worked with web API and had a lot of problems like posting multiple parameters. I upgraded to WebApi2 to use routing attributes and now have problems like:
"message":"The requested resource does not support http method 'DELETE'."
I spent all day searching Stack Overflow and the web to solve the problem:
Removed webdav
In http protocol allow all get,put,post,delete
Added the [HTTPDelete] attribute
Added name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0"
Searched Google for the necessary help here
Can someone please guide me on this?
I had the same problem. Adding the below code to your web.config should fix the problem under the system.webserver section:
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
I had the same problem, because my controller was like this:
[HttpDelete]
public HttpResponseMessage Delete(string Id)
{
....
}
And on the client I used the send the ID as request body:
var url = '/api/upload';
var data = JSON.stringify({ 'Id': id }); // <-- In the body
$.ajax({
url: url,
type: 'DELETE',
data: data, // <-- in the body
contentType: 'application/json'
})
When I changed the client to use it as URL parameter instead it worked:
var url = '/api/upload/' + id; // <- In the URL
$.ajax({
url: url,
type: 'DELETE',
contentType: 'application/json'
});
The JavaScript code for the DELETE verb must be like this:
$.ajax({
**url: "/api/SomeController/" + id,**
type: "DELETE",
dataType: "json",
success: function(data, statusText) {
alert(data);
},
error: function(request, textStatus, error) {
alert(error);
debugger;
}
});
Do NOT use something like this,
...
data: {id:id}
...
as when you are using the POST method.

Primitive types (string) as parameter- wcf method via ajax post doesn't work (works in fiddler)

Ok this one should be easy for someone who knows this sort of thing better. I am going to limit the scope of the code I provide because this works in one variation (fiddler).
This problem is simple to explain: I have a method in WCF that takes a string as a parameter. The method expects a request with a wrapped body style. If I create a simple object in fiddler and send it over it works. Something like {"submission":"something"}. If I do this in via ajax in JSON it does not work. I get a bad request error saying it is not allowed... this is cross domain but this is not the problem, I add the appropriate headers in the method to handle this. In this case the method is never being called (it is like it is an issue with the signature).
Here is the thing though... if I make a really simple class with one property of a string and pass in an object it works fine. Passing objects in a wrapped body style work fine. Trying to do this with a "primitive type" such as a string does not... any ideas?
THIS DOES NOT WORK (but does work via fiddler)....
var datain = new Object();
datain.submission = "mysubmission";
var dataToSend2 = JSON.stringify(datain);
$.ajax({
type: "POST",
url: "http://localhost:8000/ServiceModelSamples/Service/rest/Reflect",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: dataToSend2,
success: function (item) {
debugger;
alert(item);
},
error: function (xhr) {
debugger;
alert(xhr);
}
});
WITH THIS CONTRACT....
[OperationContract]
[WebInvoke(Method = "*",
RequestFormat = WebMessageFormat.Json,
BodyStyle=WebMessageBodyStyle.WrappedRequest)]
string Reflect(String submission);
THIS DOES WORK....
var spec = new Object();
spec.submission = "mysubmission";
var dataToSend3 = '{"thespecial":' + JSON.stringify(spec) + '}';
$.ajax({
type: "POST",
url: "http://localhost:8000/ServiceModelSamples/Service/rest/Reflecting",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: dataToSend3,
success: function (item) {
debugger;
alert(item);
},
error: function (xhr) {
debugger;
alert(xhr);
}
});
WITH THIS CONTRACT...
[OperationContract]
[WebInvoke(Method = "*",
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string Reflecting(Special thespecial);
Yes, you can't send the primitive data types without wrapping in xml.
you can check the complete request structure after enabling the help in endpoint behavior
suppose you have endpoint name "api" for webHttpBinding then you can enable the help using following
< webHttp helpEnabled = "true " />
After configuring it you can see the help as follow
http://localhost:<port>/test.svc/api/help
This will show the actual request format.
Like to pass string you can use the following format wrapper
<string xmlns="http://schemas.microsoft.com/2003/10/
Serialization/">Hello World</string>
or you can use stream input parameter
Click here to implement streaming

Dotnetnuke WebService with jquery Post

I am developing a dotnetnuke module and have lots of issues connecting to a webservice through javascript to retrieve data.
I have the folloiwng javascript:
function Test() {
$.ajax({
type: "POST",
url: 'http://localhost/DNN11/service1.asmx/TestMethod',
data: "{'data':'" + "abc" + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
alert("success");
},
error: function(e) {
alert("error");
}
});
}
Then the following WebMethod in my webservice
[WebMethod]
public string TestMethod(String data)
{
return "Hello World";
}
However when the post is not being called successfully, I am not able to get through my webservice. It keeps giving me a 500 Internal Server error page.
What could be wrong please? Is there any other way I need to go about this?
Thanks
[Edit]
This is the entire code
<script type="text/javascript">
function Test() {
$.ajax({
type: "POST",
url: '<%=ResolveUrl("~/DesktopModules/ModuleTest/WebService1.asmx/TestMethod")%>',
data: '{ data: "test" }',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
alert("Success: " + msg);
},
error: function(msg) {
alert("Failed: " + msg.status + ": " + msg.statusText);
}
});
}
</script>
<div>
<input type="button" value="Load" onclick="Test(); return false;" />
</div>
[System.Web.Script.Services.ScriptService]
public class WebService1 : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod()]
public string TestMethod(string data)
{
return "Hello World";
}
}
I have tried putting the Webservice in the DotNetNuke folder in a new folder and both in the local project.. I also put the ScriptMethod() Tag in the WebService which allows scripts to call it.. but still nothing
Looks like your problem is the cross domain calls. In case if your page hosted on the same server with the web service, your code should be fine. If you need to interact with the service from another domains you have to use jsonp requests. Look at this good step-by-step guide with the code example here.
UPDATE
In case if everything on the same app try to use relevant URL. Instead of url: '<%=ResolveUrl("~/DesktopModules/ModuleTest/WebService1.asmx/TestMethod")%>' try to url: '/DesktopModules/ModuleTest/WebService1.asmx/TestMethod'.
In order to post to a DNN webservice from the page you're going to have to pass in the Context of the module. I have some sample code that works against DNN6 at
http://slidepresentation.codeplex.com/SourceControl/changeset/view/69709#1181962
Mainly the
servicesFramework: $.ServicesFramework(<%=ModuleContext.ModuleId %>)
line
I haven't tested that against DNN7 though with the latest service framework WebAPI changes.

Retrieving HTML string via WCF Service through Cross Domain JSONP AJAX call

I have a WCF Service which returns a string. I am trying to call it using a cross domain JsonP request. This is working in IE but no other browser. I get a parser error back in Firefox and Chrome.
From reading through various articles i seem to think that maybe the service needs to be returning the result back as a different format. Any ideas would be helpful, here is my code.
WCF Service Code
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
public string SponsorLayout2(string projectScope, int projectYear, int imageHeight)
{
// Mock data
projectScope = "uk";
projectYear = 2012;
imageHeight = 42;
// Get projectId
var project = Projects.GetProjectByProjectScopeAndYear(projectScope, projectYear);
// Get project sponsor layouts
var projectSponsorLayout = ProjectSponsorLayouts.GetProjectSponsorLayout(project.Id, imageHeight);
// Return the sponsors
if (projectSponsorLayout != null)
return projectSponsorLayout.Body;
return null;
}
Jquery Ajax Call
$.ajax({
cache: false,
type: "GET",
async: false,
data: {},
url: "http://127.0.0.1:8082/HtmlService.svc/SponsorLayout2",
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
alert("success");
},
error: function (xhr) {
alert("error");
alert(xhr.statusText);
},
complete: function(jqXHR, textStatus) {
alert(textStatus);
}
});
I found out why I was getting the problem stated above and thought I would share this with you.
For some reason there was a conflict between this attribute
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
which sits on top of my class
public class MyClass
and this rule in my web.config file
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
I have ended up commenting the rule out in my web.config and everything come to life. Because my service is an AJAX ready service, the attribute is added above the class out of the box. Anyway this worked for me and hope it helps anyone else in the same situation.

Resources