i intend to send a cross-domain request to a soap web service using Ajax
The url of the web service is: http://example1.asmx?op=GetVOD
My code:
var url = 'http://example1.asmx?op=GetVOD';
var xhr = new XMLHttpRequest();
var strRequest = "<?xml version='1.0' encoding='utf-8'?>" +
"<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>" +
"<soap:Body>" +
"<getVODTypeList xmlns='http://tv21.com/' />" +
"</soap:Body>" +
"</soap:Envelope>"
xhr.open('POST', url, true);
xhr.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xhr.setRequestHeader("SOAPAction", "http://tv21.com/getVOD");
xhr.send(strRequest);
On the IIS 7 server side, i've already add these lines to the file web.config
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
when i run the client code on Chrome, i have an 405 error:
http://example1.asmx?op=GetVOD 405 (Method Not Allowed)
http://example1.asmx?op=GetVOD Invalid HTTP status code 405
Does anyone know how to solve this ?
Thank in advance
Sounds like Web DAV is getting in the way. Here's the config to remove it:
http://brockallen.com/2012/10/18/cors-iis-and-webdav/
Related
I have an MVC 5 ViewController which does not accept headers from an Ajax call. The ajax call origin is a different website then the controller.
The Ajax call looks like:
window.jQuery.ajax({
url: 'http://localhost:54155/TestView',
headers: {'Authorization': 'token'},
cache: false,
contentType: 'application/json; charset=utf-8',
method: 'Get',
dataType: 'json',
data: {}
}).success(alert('succes?'))
.error(alert('failed'))
});
Cors is enabled on the controller side:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="*"/>
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
</customHeaders>
</httpProtocol>
And I'm trying to reach this controller:
public class TestViewController : Controller
{
public ActionResult Index()
{
var keys = Request.Headers.AllKeys;
return View();
}
}
If I send the request to a WebApi based on a WEP API 2 controller, the headers are ok. If I send a request with postman to the mvc controller the headers are ok as well.
The Headers contain the header Access-Control-Request-Headers, which has the value authorization. But Request.Headers["Authorization"] is null.
Custom headers like X-MyHeader turn up as value from Access-Control-Request-Headers, but when used like a key, they are all null.
Which part am I missing?
I had a same kind of issue - but this might resolve your problem
Install Microsoft.AspNet.WebApi.Cors from NuGet - Run this command
(Install-Package Microsoft.AspNet.WebApi.Cors) in your package
manager console - this will install your Cors
Remove your access allow origin code from your Web.config file
If it is Web Api add the below cod in your WebApiConfig.cs if not try to add in your Gloabl.asax
var cors = new EnableCorsAttribute("*", "*", "*", "*");
config.EnableCors(cors);
You will be wondering where that method EnableCors() will come using System.Web.Http.Cors; add this line in your using and see the magic
This might solve your problem - Finally its not a good idea to access your MVC controller from different domain try you use WebApi
If you want to access your MVC controller try out your ajax code form the same domain
Because WebApi is stateless but MVC is kind of session - Thanks happy coding !!
Empty web.api project, install Microsoft.aspnet.webapi.cors 5.2.3, add
config.EnableCors();
to webapiconfig. make controller and action
public class HomeController : ApiController
{
[EnableCors("*" , "*" , "*")]
public async Task<string> Get()
{
return await Task.FromResult("omg");
}
}
Debug app and Load up fiddler and do a request to http://localhost:61939/api/Home
there are no CORS headers present. web.config contains:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
what am I missing? Why would this not insert an Access-Control-Allow-Origin header in all request to my Get method?
Also the answer of defining CORS in web.config isn't an answer ... At some point I will need to add origin checking and potentially even checking the HTTP Method something like:
if(requestContext.HttpMethod == "POST" && (origin == "https://someplace.com" || origin == "http://localhost"))
What you've done is enough to enable CORS, you can also enable CORS on all the controllers using this code :
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
I'm not sure how you're testing it, but note that only once the request contains the Origin header, it returns the Access-Control-Allow-Origin header in reponse. If you omit the origin header in the request, the response wouldn't contain the Access-Control-Allow-Origin.
So this Kendo UI Upload worked well when I send files to MVC controller, but I have to change it and send the file directly to API controller, but it fails.
This is the Kendo Upload init code:
$("#files").kendoUpload({
async: {
saveUrl: "#WebApiHelper.GetUrl("Notification/UploadFile")",
removeUrl: "remove",
autoUpload: true
},
success: function(),
error: function()
}
On Chrome console it shows Load Canceled on the Status text of the request in Network tab:
The result of the request is like shown below:
Request URL:http://localhost:45706/api/Notification/UploadFile
Request Method:OPTIONS
Status Code:200 Ok
Request Headers
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:origin, content-type
Access-Control-Request-Method:POST
Host:localhost:45706
Origin:http://localhost:1654
Proxy-Connection:keep-alive
Referer:http://localhost:1654/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Response Headers
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:origin, accept, content-type
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:*
allow-access-from domain:*
Cache-Control:no-cache
Content-Length:0
Date:Fri, 03 May 2013 16:53:30 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcVXNlcnNcR0F0ZWNcRG9jdW1lbnRzXEdBdGVjXE9kaXNzZWlhXEFwcGxpY2F0aW9uXEdBdGVjLkFncm9XZWIuQ29yZVxHQXRlYy5BZ3JvV2ViLkNvcmUuQVBJXGFwaVxOb3RpZmljYXRpb25cVXBsb2FkRmlsZQ==?=
Note that the status code is 200 because I returned it in the method. So it reaches the API method...
[HttpPost][HttpOptions]
public HttpResponseMessage UploadFile(HttpPostedFileBase files)
...but the files parameter is aways null.
This is the CORS related attributes on API webconfig file:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="allow-access-from domain" value="*" />
<add name="Access-Control-Allow-Headers" value="origin, accept, content-type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
Any thoughts ? Any help will be very appreciated!
This code worked for me.
public ActionResult Document_Create([DataSourceRequest] DataSourceRequest request, Customer obj, IEnumerable<HttpPostedFileBase> Docs)
{
foreach (var Doc in Docs)
{
string newFileName = Path.GetFileName(Doc.FileName).Replace(" ",""); //Guid.NewGuid().ToString() + Path.GetExtension(Doc.FileName);
var physicalPath = Path.Combine(Server.MapPath("~/Documents/"), newFileName);
Doc.SaveAs(physicalPath);
}
return Json(new[] { obj }.ToDataSourceResult(request, ModelState));
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
WCF Web Service returns “Bad Request” error when invoked through Javascript
I have a simple WCF web service Service1 with just one method Test() which returns a string. I have deployed this web service on a test machine, but when I try to invoke the Test method from the browser I simply get a 400 Bad Request error. The same happens when I try to invoke the method through an AJAX GET request. But surprisingly, the method returns the correct result when invoked through the WCFTestClient.
Here is the code:
[ServiceContract]
public interface IService1
{
// This method can be called to get a list of page sets per report.
[OperationContract]
[WebGet]
string Test();
}
public class Service1 : IService1
{
public string Test()
{
return "test";
}
}
This is my AJAX request:
var serverUrl1 = 'http://' + baseUrl + ':86/Service1.svc';
function GetTestString()
{
var methodUrl = serverUrl1 + "/Test";
$.ajax({
async: false,
type: "GET",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: methodUrl,
beforeSend: function (XMLHttpRequest) {
//ensures the results will be returned as JSON.
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
success: function (data) {
ShowQRGSlides(data.d);
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
alert("ERROR: GetAvailablePages() Check your browsers javascript console for more details." + " \n XmlHttpRequest: " + XmlHttpRequest + " \n textStatus: " + textStatus + " \n errorThrown: " + errorThrown);
}
});
}
Here is the web.config file for my web service:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
This is just the simple web.config which gets automatically generated. I am unable to figure out why this simple web service method is not accessible through the browser or ajax. The same method returns the result when accessed through the WCFTestClient.
Any inputs will be greatly appreciated! Thanks.
You need to add service section to your web.config file. Host does not know that you want to use webHttpBinding unless you tell him.
<services>
<service name="Service1">
<endpoint address=""
binding="webHttpBinding"
contract="IService1" />
</service>
</services>
Link below provides detailed instructions for hosting service in IIS (with wsHttpBinding). You just need to use webHttpBinding instead of wsHttpBinding -
http://msdn.microsoft.com/en-us/library/ms733766.aspx
This is my AJAX Application where i need to contact my Webservice running in server .
function sendRequest(method, url)
{
method == 'post';
{
http.open(method,url,true);
http.onreadystatechange = handleResponse;
http.send(null);
}
}
This is the SOAP Request which i picked up from the SOAP UI , which was working fine
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.bayer.tata.com/" xmlns:tkw="http://tata.com/bayer" xmlns:chim="http://tata.com/chimera">
<soapenv:Header/>
<soapenv:Body>
<ser:strategy>
<!--Optional:-->
<request>
<xmlMessage>
<![CDATA[<test>or like this</test>]]>
</xmlMessage>
</request>
</ser:strategy>
</soapenv:Body>
</soapenv:Envelope>
Please tell me how can i use use this SOAP XML message within the sendRequest function .
I am using only plain Java Script AJAX ( Nothing like Jquery , DOJO , or any )
I think this Post can help you. But most of web servers allows you to invoke webservices using plain HTTP Post (without SOAP format in the body request) if the request doesn't need SOAP headers or other weird things.
An example in .NET and plain javaScript:
.NET web service
<System.Web.Services.WebService(Namespace:="http://JuntaEx/Agricultura/SegurInfo/GestorFirmaExterno/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class GestorFirmaExterno
Inherits System.Web.Services.WebService
<WebMethod(Description:="Retorna los documentos originales asociados a un identificador de firma pasado como parámetro.")> _
Public Function ObtenerDocumentoOriginal(ByVal idFirma As String) As DocumentoED()
//code
End Function
End Class
web.config:
<webServices>
<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/> <!-- Allows plain HTTP Post -->
<add name="HttpSoap12"/>
<!-- Documentation enables the documentation/test pages -->
<add name="Documentation"/>
</protocols>
</webServices>
JavaScript request:
function crearRequest(url) {
if (window.XMLHttpRequest) {
peticion_http = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
peticion_http = new ActiveXObject('Microsoft.XMLHTTP');
}
peticion_http.open('POST', url, true); //sync
peticion_http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
return peticion_http;
}
peticion_http = crearRequest('http://localhost/wspuenteFirma/serviciopuente.asmx/ObtenerDocumentoOriginal');
peticion_http.onreadystatechange = obtenerDocHandler;
var query_string = 'IdFirma=' + encodeURIComponent(docId);
peticion_http.setRequestHeader('Content-Length', query_string.length);
peticion_http.send(query_string);
You send this request to the server:
POST /wsGestorFirmaExterno/GestorFirmaExterno.asmx/ObtenerDocumentoOriginal HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: length
idFirma=string
and recive this response from the server:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDocumentoED xmlns="http://JuntaEx/Agricultura/SegurInfo/GestorFirmaExterno/">
<DocumentoED>
<hash>string</hash>
</DocumentoED>
<DocumentoED>
<hash>string</hash>
</DocumentoED>
</ArrayOfDocumentoED>
Parse it with javascript to obtain the info you need.
PS: You can configure the server and the browser request to send and recive JSON data instead of XML.
I hope it's helps.