WCF WebSocket Service needs to be secure TLS/SSL WSS - wcf

We have an existing WCF Web Service used for WebSockets. We distribute our solution to our customers who host the application in IIS. I have been tasked to make the service work with port 443 (WSS/HTTPS). I have tried updating the Web.Config of the customBinding to use httpsTransport, but I haven't been able to connect successfully to the service using wss://. I have uploaded a simplified sample of our application to https://github.com/kevmoens/WcfWebSocketService which uses ws://.
Here is the Web.Config updated to try to use httpsTransport
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.2" />
<httpRuntime targetFramework="4.6.2"/>
</system.web>
<system.serviceModel>
<services>
<service name="WcfWebSocketService.ConnectService"
behaviorConfiguration="WcfWebSocketService.ConnectService">
<endpoint address=""
binding="customBinding"
bindingConfiguration="webSocket"
contract="WcfWebSocketService.IConnectService"/>
</service>
</services>
<bindings>
<customBinding>
<binding name="webSocket">
<byteStreamMessageEncoding />
<httpsTransport>
<webSocketSettings transportUsage="Always"
createNotificationOnConnection="true"
/>
</httpsTransport>
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="WcfWebSocketService.ConnectService">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Here is a sample client that works if I change it to use WS://.
<!doctype html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
<meta content="utf-8" http-equiv="encoding" />
<meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<title>Web Socket Demo</title>
<style type="text/css">
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 200, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="txtBox" autocomplete="off" /><button>Send</button>
</form>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.js" ></script>
<script type="text/javascript">
var CONNECTION;
window.onload = function () {
// open the connection to the Web Socket server
CONNECTION = new WebSocket('wss://localhost:51462/ConnectService.svc');
// When the connection is open
CONNECTION.onopen = function () {
$('#messages').append($('<li>').text('Connection opened'));
};
// when the connection is closed by the server
CONNECTION.onclose = function () {
$('#messages').append($('<li>').text('Connection closed'));
};
// Log errors
CONNECTION.onerror = function (e) {
console.log('An error occured');
};
// Log messages from the server
CONNECTION.onmessage = function (e) {
$('#messages').append($('<li>').text(e.data));
};
};
// when we press the Send button, send the text to the server
$('form').submit(function(){
CONNECTION.send($('#txtBox').val());
$('#txtBox').val('');
return false;
});
</script>
</body>
</html>

I found that the client would not work with localhost when working with IIS and Require SSL. I was correct on the assumption that the httpTransport needed to change to httpsTransport. Also I didn't need to add anything in the Web.Config about the certificate as it inherits the certificate from IIS.
CLIENT
Before
CONNECTION = new WebSocket('wss://localhost/ConnectService.svc');
After
CONNECTION = new WebSocket('wss://<MACHINENAME>/ConnectService.svc');
WEB.CONFIG
Before
<httpTransport>
<webSocketSettings transportUsage="Always"
createNotificationOnConnection="true"
/>
</httpTransport>
After
<httpsTransport>
<webSocketSettings transportUsage="Always"
createNotificationOnConnection="true"
/>
</httpsTransport>

Related

WCF Works from internal network address but returns error when external

I'm going nuts here - I'm on my 6th day of trying to trouble shoot this and I'm loosing my mind.
Basically internally, the service works 100% as expected. I create a "consume" client on my external test line and I go to test it and it returns with
"The content type text/html; charset=UTF-8 of the response message does not match the content type of the binding (multipart/related; type=\"application/xop+xml\"). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: '<HTML>
<HEAD>
<link rel=\"alternate\" type=\"text/xml\" href=\"http://myexternaladdress.com/FileUploadService.svc?disco\"/>
<STYLE type=\"text/css\">
#content{ FONT-SIZE: 0.7em; PADDING-BOTTOM: 2em; MARGIN-LEFT: 30px}BODY{MARGIN-TOP: 0px; MARGIN-LEFT: 0px; COLOR: #000000; FONT-FAMILY: Verdana; BACKGROUND-COLOR: white}P{MARGIN-TOP: 0px; MARGIN-BOTTOM: 12px; COLOR: #000000; FONT-FAMILY: Verdana}PRE{BORDER-RIGHT: #f0f0e0 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #f0f0e0 1px solid; MARGIN-TOP: -5px; PADDING-LEFT: 5px; FONT-SIZE: 1.2em; PADDING-BOTTOM: 5px; BORDER-LEFT: #f0f0e0 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #f0f0e0 1px solid; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e5e5cc}.heading1{MARGIN-TOP: 0px; PADDING-LEFT: 15px; FONT-WEIGHT: normal; FONT-SIZE: 26px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 3px; MARGIN-LEFT: -30px; WIDTH: 100%; COLOR: #ffffff; PADDING-TOP: 10px; FONT-FAMILY: Tahoma; BACKGROUND-COLOR: #003366}.intro{MARGIN-LEFT: -15px}</STYLE>
<TITLE>
FileUploadService Service</TITLE>
</HEAD>
<BODY>
<DIV id=\"co'."}
Basically this is all I got it has an issue with the disco http://myexternaladdress.com/FileUploadService.svc?disco
Here is my service .config
<?xml version="1.0"?>
<configuration>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
>
<listeners>
<add name="xml"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\temp\WCFDiagnosticsExample.svclog" />
</sharedListeners>
</system.diagnostics>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="uploadDirectory" value="C:\temp\upload" />
</appSettings>
<system.web>
<compilation targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true"
maxMessagesToLog="3000"
/>
</diagnostics>
<extensions>
<behaviorExtensions>
<add name="applyAddressFilterModeBehavior"
type="Test.Behaviors.ApplyAddressFilterModeBehaviorElement, Test.Behaviors,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<services>
<service behaviorConfiguration="myBehavior" name="myWCF.FileUploadService">
<endpoint address="" binding="wsHttpBinding" contract="myWCF.IFileUploadService" bindingConfiguration="myBinding"></endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="myBinding" messageEncoding="Mtom" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None"/>
</binding>
</wsHttpBinding>
<basicHttpBinding>
<binding name="FileUploadServiceBinding" transferMode="Streamed" messageEncoding="Mtom" maxReceivedMessageSize="99108864" maxBufferSize="65536" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="myBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<applyAddressFilterModeBehavior/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="204800000"></requestLimits>
</requestFiltering>
</security>
</system.webServer>
</configuration>
The only difference is when I come externally I add the service via my external address which comes through a load balancer and redirects to https and then sends the traffic to a specific server and port. And I can even .Open my service fine. My error occurs when i call a method. Can someone please tell me how to retrieve the full message not just 1024 characters or point out what i'm doing wrong?
I tried adding enabledhttps and httpsuri and that did not resolve the issue.
Thanks! I owe a lot of points to who ever helps me solve this one.
Binding of your service seems to use wsHttpBinding binding. What is the purpose of the binding called FileUploadServiceBinding? It seems that it is not using.
Your WCF service probably gets an exception. You can get the error detail if you add these lines into web.config file of your service host.
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Critical, Error" propagateActivity="true">
<listeners>
<add type="System.Diagnostics.DefaultTraceListener" name="Default">
<filter type="" />
</add>
<add name="ServiceModelTraceListener">
<filter type="" />
</add>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="c:\error.svclog" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
<filter type="" />
</add>
</sharedListeners>
After adding these lines in your web.config, execute your client application once more. If an exception occurs, the exception details write in error.svclog file. You can use the svclog util of the .Net Framework to inspect the error details.

WCF Websocket service “could not find a base address that matches schema http” error

I have a problem to make my WCF websocket service working. Until now I cannot find how to establish a connection. Both client and server side are really simple. So I think I miss something obvious here.
I currently have one WCF service running properly in my solution. The web services are hosted under IIS, the connection is properly handled using https and using basic authentication.
Here is my web.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<authentication mode="Forms" />
</system.web>
<system.serviceModel>
<!--webHttpBinding allows exposing service methods in a RESTful manner-->
<services>
<service behaviorConfiguration="secureRESTBehavior" name="MyApp.Services.MyService">
<endpoint address="" behaviorConfiguration="RESTfulBehavior" binding="webHttpBinding" bindingConfiguration="webHttpTransportSecurity" contract="MyApp.Services.IMyService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<!--WCF Service Behavior Configurations-->
<behaviors>
<endpointBehaviors>
<behavior name="RESTfulBehavior">
<webHttp defaultBodyStyle="WrappedRequest" defaultOutgoingResponseFormat="Json" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="secureRESTBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization principalPermissionMode="Custom" serviceAuthorizationManagerType="MyApp.Security.CustomAuthorizationManager, MyApp">
<authorizationPolicies>
<add policyType=" MyApp.Security.AuthorizationPolicy, MyApp" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>
</behaviors>
<!--WCF Service Binding Configurations-->
<bindings>
<webHttpBinding>
<binding name="webHttpTransportSecurity" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="Streamed" sendTimeout="00:05:00">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport" />
</binding>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="CORSModule" type="Security.CORSModule" />
</modules>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://myapp.com" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
<add name="Access-Control-Allow-Methods" value="GET, DELETE, POST, PUT, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Now I'm trying use WebSocketHost to host a WebSocket server as a WCF service.
Here is my factory:
public class TRWebSocketServiceFactory: ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
try
{
WebSocketHost host = new WebSocketHost(serviceType, baseAddresses);
host.AddWebSocketEndpoint();
return host;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw ex;
}
}
}
Here is the service:
public class EchoWSService : WebSocketService
{
public override void OnOpen()
{
this.Send("Welcome!");
}
public override void OnMessage(string message)
{
string msgBack = string.Format(
"You have sent {0} at {1}", message, DateTime.Now.ToLongTimeString());
this.Send(msgBack);
}
protected override void OnClose()
{
base.OnClose();
}
protected override void OnError()
{
base.OnError();
}
}
Here is my Global.asax file:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute(
"Echo", new TRWebSocketServiceFactory(), typeof(EchoWSService)));
}
}
Here is the client side who try to establish a connection:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>WebSocket Chat</title>
<script type="text/javascript" src="Scripts/jquery-2.0.2.js"></script>
<script type="text/javascript">
var ws;
$().ready(function () {
$("#btnConnect").click(function () {
$("#spanStatus").text("connecting");
ws = new WebSocket("wss://MyServer/Echo");
ws.onopen = function () {
$("#spanStatus").text("connected");
};
ws.onmessage = function (evt) {
$("#spanStatus").text(evt.data);
};
ws.onerror = function (evt) {
$("#spanStatus").text(evt.message);
};
ws.onclose = function () {
$("#spanStatus").text("disconnected");
};
});
$("#btnSend").click(function () {
if (ws.readyState == WebSocket.OPEN) {
ws.send($("#textInput").val());
}
else {
$("#spanStatus").text("Connection is closed");
}
});
$("#btnDisconnect").click(function () {
ws.close();
});
});
</script>
</head>
<body>
<input type="button" value="Connect" id="btnConnect" /><input type="button" value="Disconnect" id="btnDisconnect" /><br />
<input type="text" id="textInput" />
<input type="button" value="Send" id="btnSend" /><br />
<span id="spanStatus">(display)</span>
</body>
</html>
On the line:
host.AddWebSocketEndpoint();
I always got the error:
Could not find a base address that matches scheme http for the endpoint with binding CustomBinding. Registered base address schemes are [https].
I'm a bit confused about the following points:
how to fix this error?
should I exose the EchoWSService in my web.config file as other services?
how the basic authentication is managed with web sockets?
Thanks!
I was missing:
Binding binding = WebSocketHost.CreateWebSocketBinding(true);
before:
host.AddWebSocketEndpoint();
Now the endpoint is correct.

Couldn't access Wcf service hosted in a server through ajax call, but can access the same Wcf service hosted in local machine

Created a Wcf Restful service and hosted in local Server. Another user is trying to consume the WCF Rest service from HTML5 page through ajax call. However always it is throwing failure message
Configuration Settings:
1.The WCF Rest Service is hosted in http://jtl_109.com/mob/AppService.svc/GetUserAuthendication
2.Created a HTML5 Application and deployed it in another server. The URL is http://jtl_110.com/SampleApplication.html
WCF Hosting Configuration Settings:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="ConnectionString" value="Data Source=ServerDatabase; Initial Catalog=NewDataBase; User ID=pras; Password=rita" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<authentication mode="Windows" />
<roleManager enabled="true" />
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="tSeyvaWCFEndPointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="tSeyvaServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="AppServices.AppService" behaviorConfiguration="tSeyvaServiceBehavior">
<endpoint address="" behaviorConfiguration="tSeyvaWCFEndPointBehavior"
bindingConfiguration="crossDomain" binding="webHttpBinding"
contract="AppServices.IAppService">
</endpoint>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
<handlers accessPolicy="Read, Execute, Script" />
</system.webServer>
</configuration>
And the ajax call is
var data = { 'logindetails': { 'UserName': UN, 'Password': PW } };
var st = JSON.stringify(data);
debugger;
$.ajax({
type: "POST",
url: "http://jtl_109/mob/AppService.svc/GetUserAuthendication",
data: st,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
ServiceSucceeded(result);
//// Play with response returned in JSON format
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR + "-" + textStatus + "-" + errorThrown);
}
});
Can any one Please suggest how to consume the WCF Reset Service from another Site?
Check that the port on the server isn't being blocked by the firewall. An easy way to check is to simply type into your local machine's browser address bar the URL of the web service - http:/ /ServerName:8001/ServiceClass/ServiceMethod
If you get a 404 error or something like that, check the Firewall settings (inbound) to see that port is open. However, if you get a good response in your browser, then you know it's not the Firewall.
OK, so here's a very simple htm/JavaScript program I wrote as a test harness to ping a WCF web service.
<title>SOAP JavaScript Client Test</title>
<script type="text/javascript">
function Ping() {
//set up varable
var sContent;
sContent= "<SoapXML><Your Content></XML>";
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', Demo.URL.value, true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4||xmlhttp.readyState == 0) {
//alert("Ready state: " + xmlhttp.readyState.toString());
if (xmlhttp.status == 200) {
//alert("good");
Demo.pingresponse.value = "Response: " +xmlhttp.responseText;
}
if (xmlhttp.status !=200){
//alert("bad");
Demo.pingresponse.value = "Error: " +xmlhttp.status.toString() +" response text: " +xmlhttp.responseText;
}
} else {
//alert("readystate bad");
}
}
//send request
xmlhttp.setRequestHeader("POST http:localhost:8085/ServiceName HTTP/1.1");
xmlhttp.setRequestHeader("VsDebuggerCausalityData","uI8ACQAA");
xmlhttp.setRequestHeader("SOAPAction","\"http://SoapRequestHeader\"");
xmlhttp.setRequestHeader("Host","localhost:8085");
xmlhttp.setRequestHeader("Expect","100-continue");
xmlhttp.setRequestHeader("Accept-Encoding","gzip, deflate");
xmlhttp.setRequestHeader("Connection","Keep-Alive");
xmlhttp.setRequestHeader("Content-Length","639");
xmlhttp.setRequestHeader("Content-type", "text/xml; charset=utf-8");
xmlhttp.send(sContent);
}
</script>
</head>
<body>
<form name="Demo" action="" method="post">
<div>
Web Service URL (i.e. http://ServerName:8085/ServiceName <br />
<input id="URL" type="text" size="140" value="http:/ /localhost:8085/ServiceName " />
<br />
<input type="button" value="Ping" onclick="Ping();" /><br />
<textarea id="pingresponse"cols="100" rows="10">
</textarea> <br />
</div>
</form>
</body>
<html>
Obviously, this won't work for your site, but with some tweaks for the URL, Port and expected content, this might be a good starting point.

Calling WCF REST Service using JQuery Ajax not working

I am learning WCF service. I am trying to call an RESTful service from Jquery. My Service is as below
Service Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
namespace RESTfulServiceLib
{
[AspNetCompatibilityRequirements(RequirementsMode
= AspNetCompatibilityRequirementsMode.Allowed)]
public class RestFullService : IRestFullService
{
public string Welcome(string Name)
{
return "Welcome to Restful Service " + Name;
}
}
}
Interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;
namespace RESTfulServiceLib
{
[ServiceContract]
public interface IRestFullService
{
[OperationContract]
[WebInvoke(UriTemplate="/Welcome/{Name}",Method="GET",ResponseFormat=WebMessageFormat.Json)]
string Welcome(string Name);
}
}
I have created a service host and the svc file goes like this
<%# ServiceHost Language="C#" Debug="true" Service="RESTfulServiceLib.RestFullService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
I have the following config settings
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="EndPBhvr">
<webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json"
faultExceptionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="SvcBhvr">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="RESTfulServiceLib.RestFullService">
<endpoint address="" behaviorConfiguration="EndPBhvr"
binding="webHttpBinding" bindingConfiguration="" name="EP1"
contract="RESTfulServiceLib.IRestFullService" />
</service>
</services>
</system.serviceModel>
</configuration>
After running the application , when I am browsing the url "http://localhost:2319/RESTFullService.svc/welcome/Mahesh"
it is returning the value as
"Welcome to Restful Service Mahesh"
I have tried to call this service using Jquery. But I am getting
error 200 undefined
The script is as follows
<!DOCTYPE html>
<html>
<head>
<script src="jquery-1.6.4.min.js"></script>
<script >
function ajaxcall()
{
$.ajax({
url: "http://localhost:2319/RESTFullService.svc/welcome/mahesh",
type: "GET",
contentType: "application/json; charset=utf-8",
dataType:"jsonp",
data:{},
processdata : true,
success: function(response)
{
var data= response.d;
alert(data);
},
error: function(e)
{
alert('error '+e.status + ' ' + e.responseText);
}
});
}
$().ready(function(){
$('#btntest').click(ajaxcall);
})
</script>
</head>
<body>
<button id="btntest" >Click Me</button>
</body>
</html>
What is wrong in my coding? Please help me...
Thanks
Mahesh
In the Success of your jQuery you have used
// var data= response.d;
but your are not returning a valid json.
there is no "d" in your response.
It is due to the Cross Domain Issue. I did a couple of changes in config file and it worked fine
The config file after changes. Added new Binding Configuration with crossDomainScriptAccessEnabled="true" and added to the endpoint. And put the aspNetCompatibilityEnabled="false"
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<standardEndpoints />
<bindings>
<webHttpBinding>
<binding name="Bind1" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="EndPBhvr">
<webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json"
faultExceptionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="SvcBhvr">
<serviceMetadata httpGetEnabled="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
<services>
<service behaviorConfiguration="SvcBhvr" name="RESTfulServiceLib.RestFullService">
<endpoint address="" behaviorConfiguration="EndPBhvr" binding="webHttpBinding"
bindingConfiguration="Bind1" name="EP1" contract="RESTfulServiceLib.IRestFullService" />
</service>
</services>
</system.serviceModel>
</configuration>
Modified script, i have added "?callback=?" at the end of the URL to get the output in JSON instead of JSONP. JSONP will work without giving the callback in the URL
<!DOCTYPE html>
<html>
<head>
<script src="jquery-1.6.4.min.js"></script>
<script type="text/javascript" language="javascript">
function ajaxcall()
{
$.ajax({
url: "http://localhost:2319/RESTFullService.svc/welcome/mahesh?calback=?",
type: "GET",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: {},
processdata: true,
success: function (response) {
var data = response;
alert(data);
},
error: function (e) {
alert('error ' + e.status + ' ' + e.responseText);
}
});
}
$().ready(function(){
$('#btntest').click(ajaxcall);
})
</script>
</head>
<body>
<button id="btntest" >Click Me</button>
</body>
</html>
Thanks to my colleague Mrs.Poorani in Calsoft Labs for helping me in solving this issue
function CallService(sucessData) {
$.ajax({
// Add code for Cross Domain
headers: getHeaders(),
type: varType, //GET or POST or PUT or DELETE verb
url: varUrl, // Location of the service
data: varData, //Data sent to server
contentType: varContentType, // content type sent to server
dataType: varDataType, //Expected data format from server
processdata: varProcessData, //True or False
crossDomain: true,
cache: varCache,
timeout: 200000,
success: sucessData,
error: function (xhr) {// When Service call fails
fancyAlert("Error: " + xhr.responseText);
//fancyAlert('Error occured in Service Call');
}
});
}

Scalabilty issues with Restful WCF

Hi I have built a simple WCF application I am using to query data back and forth from Mobile app.
Everything else works Fine But When I try to Upload large binary video upload it gives me weird error, I am successfully able to upload binary streams upto 3-4 MB but larger than that
I get one of the following error randomly
1.
<html>
<BODY>
<FONT face="Helvetica">
<big><strong></strong></big><BR>
</FONT>
<blockquote>
<TABLE border=0 cellPadding=1 width="80%">
<TR><TD>
<FONT face="Helvetica">
<big>Network Error (tcp_error)</big>
<BR>
<BR>
</FONT>
</TD></TR>
<TR><TD>
<FONT face="Helvetica">
A communication error occurred: ""
</FONT>
</TD></TR>
<TR><TD>
<FONT face="Helvetica">
The Web Server may be down, too busy, or experiencing other problems preventing it from responding to requests. You may wish to try again at a later time.
</FONT>
</TD></TR>
<TR><TD>
<FONT face="Helvetica" SIZE=2>
<BR>
For assistance, contact your network support team.
</FONT>
</TD></TR>
</TABLE>
</blockquote>
</FONT>
</BODY>
</html>
2.
<html>
<body>
<div id="header"><h1>Server Error</h1></div>
<div id="content">
<div class="content-container"><fieldset>
<h2>404 - File or directory not found.</h2>
<h3>The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.</h3>
</fieldset></div>
</div>
</body>
</html>
Here is my Web.Config
<?xml version="1.0"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<bindings>
<webHttpBinding>
<binding transferMode="Streamed" maxBufferSize="5242880" maxReceivedMessageSize="2147483647" openTimeout="05:25:00" closeTimeout="00:25:00" sendTimeout="00:25:00" receiveTimeout="0:25:00"
name="webBinding"
/>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="RestBehavior" name="EyePlots.Videos">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="webBinding"
contract="EyePlots.IVideos" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="RestBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="100"
maxConcurrentInstances="100" maxConcurrentSessions="100" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Could it be issue with the scalability of the system? I can post my code snippets if you guys want? Thanks!
I think 4 megs is an IIS throttle.
Have you set (IIS7+)
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
Here's a post listing out some more throttles to try opening up. WCF problem with uploading large file, hosted in IIS