Link to home
Start Free TrialLog in
Avatar of leskelly
leskellyFlag for United States of America

asked on

Consuming WCF service with JavaScript in .NET 4.0 application

I have a small application developed in Visual Studio 2010 that I'm using to test Consuming a WCF service with JavaScript.  The service takes a single string parameter and returns that parameter prefixed with "Hello " The service is in a WCF Service Library.  The service is hosted in a WCF Service web site.  I access the service from a ASP.NET web application.  I know the  service  is functional as it returns the expected value when I call it from a VB procedure.  When I try to call it from JavaScript I get an error message that says, "JavaScript runtime error: 'HelloServiceReference' is undefined".  My code is below.  The error occurs on the third line, "var HelloClient2 = new HelloServiceReference.HelloClient;" of Hello.js. I have a Service Reference to the service named "HelloServiceReference". I'm assuming I'm missing an attribute of some sort that allows for JavaScript access.  Any assistance would be greatly appreciated.

TestLibrary(WCF Service Library)


IHello.vb
<ServiceContract()>
Public Interface IHello
	<OperationContract()>
	<System.ServiceModel.Web.WebInvoke()> _
	Function SayHello(ByVal value As String) As String
End Interface

Open in new window


Hello.vb
Public Class Hello
	Implements IHello

	Public Function SayHello(ByVal value As String) As String Implements IHello.SayHello
		Return String.Format("Hello {0}", value)
	End Function

End Class

Open in new window


App.config
<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true"/>
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service name="TestLibrary.Hello">
        <endpoint address="" binding="wsHttpBinding" contract="TestLibrary.IHello">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8732/Design_Time_Addresses/TestLibrary/Service1/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <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>
  </system.serviceModel>

</configuration>

Open in new window



HelloHost(WCF Service)


Hello.svc
<%@ ServiceHost Language="VB" Debug="true" Service="TestLibrary.Hello" %>

Open in new window


Web.config
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.0"/>
    <pages>
      <namespaces>
        <add namespace="System.Runtime.Serialization"/>
        <add namespace="System.ServiceModel"/>
        <add namespace="System.ServiceModel.Web"/>
      </namespaces>
    </pages>
  </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="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

Open in new window



Hello Client(ASP.NET web application)


TestHello.aspx
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="TestHello.aspx.vb" Inherits="Hello_Client.TestHello" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <script src="<%=ResolveUrl("~/Scripts/Hello.js")%>" type="text/javascript"></script>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
        <Services>
            <asp:ServiceReference Path="http://localhost/HelloHost/Hello.svc"/>
        </Services>
    </asp:ScriptManager>       
        <div>
            <label id="lblName">Name:</label>
            <input id="txtName" name="tName" type="text" /><br />
            <input id="btnHello" type="button" value="Hello" onclick="fnHello(document.getElementById('txtName').value)" />
            <asp:Button ID="btnASPHello" runat="server" Text="ASP Hello" />
        </div>
    </form>
</body>
</html>

Open in new window


Hello.js
function fnHello(Name)
{
    var HelloClient2 = new HelloServiceReference.HelloClient;
    alert(HelloClient2.SayHello(Name, fnHelloCallBack));
}

Open in new window


TestHello.vb
Public Class TestHello
    Inherits System.Web.UI.Page

	Protected Sub btnASPHello_Click(sender As Object, e As EventArgs) Handles btnASPHello.Click
		Dim TestRun As HelloServiceReference.HelloClient = New HelloServiceReference.HelloClient()
		Dim script As String = "<script type='text/javascript' defer='defer'> alert('" + TestRun.SayHello("Les") + "');</script>"
		ClientScript.RegisterClientScriptBlock(Me.GetType(), "AlertBox", script) 
	End Sub

End Class

Open in new window


Web.config
<?xml version="1.0"?>
<configuration>
	
  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
  </system.web>

  <system.webServer>
     <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
	
  <system.serviceModel>
		<services>
			<service name="TestLibrary.Hello">
				<endpoint address=""
									binding="wsHttpBinding"
									contract="TestLibrary.IHello">
					<identity>
						<dns value="localhost"/>
					</identity>
				</endpoint>
				<endpoint address="mex"
									binding="mexHttpBinding"
									contract="IMetadataExchange"/>
				<host>
					<baseAddresses>
						<add baseAddress="http://localhost:8732/Design_Time_Addresses/TestLibrary/Service1/"/>
					</baseAddresses>
				</host>
			</service>
		</services>
		<bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IHello" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/HelloHost/Hello.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IHello" contract="HelloServiceReference.IHello"
        name="BasicHttpBinding_IHello" />
    </client>
  </system.serviceModel>
		
</configuration>

Open in new window

Avatar of Najam Uddin
Najam Uddin
Flag of United States of America image

Add ResponseFormat = WebMessageFormat.Json after comma in <System.ServiceModel.Web.WebInvoke()>
in operation contract
Avatar of leskelly

ASKER

Hello Najam,

Thank you for your response. I changed the code in IHello.vb to read:

Imports System.ServiceModel.Web
<ServiceContract()>
Public Interface IHello
      <OperationContract()>
      <System.ServiceModel.Web.WebInvoke()> _
      <WebGet(ResponseFormat:=WebMessageFormat.Json)> _
      Function SayHello(ByVal value As String) As String
End Interface

Unfortunately I still get the same error.  Do you have any other thoughts?
Hello Najam,

When I made the change you suggested I neglected to remove the line, "<System.ServiceModel.Web.WebInvoke()> _".  I did so but it didn't make any difference.  Any other ideas?

Thanks,
Les
Avatar of ambience
Are you using any Javascript library for interacting with the service?

    var HelloClient2 = new HelloServiceReference.HelloClient;
    alert(HelloClient2.SayHello(Name, fnHelloCallBack));

Open in new window


I'm not aware of any feature in ASP.NET that allows you to generate scripts from service definition.

You may have to use jQuery to make HTTP calls to the specified method. See this for example: http://www.codeproject.com/Articles/132809/Calling-WCF-Services-using-jQuery
Are you particular with wcf ? did  you had a chance to look into asp.net web api ?

Hope below blog helps you, http://weblogs.asp.net/ricardoperes/calling-wcf-web-services-from-javascript
Hello ambience and apeter,

I posted a comment yesterday thanking you both for your responses but when I checked this morning the comment wasn't showing.  Anyway I'm in the process of looking at the links you suggested and will get back to you.

Thanks,
Les
Hello again,

I've checked out the two links you suggested and they are very informative but they both deal with calling a service that is in the same solution, which I've been able to do, but what I'm trying to do is call a service from a different solution.  Do you have any suggestions?
The code in the link I gave does not depend on the ScriptManager and is therefore usable irrespective of the service being in the same project or not.

I dont have much experience with using ScriptManager to generate Javascript code for accessing the service from client-side therefore cant say what might be wrong. Have you used developer tools to check whether the Javascript does contain a definition for HelloServiceReference.HelloClient? You can use Firebug on Firefox or Chrome tools if using Chrome. This would really help figure out whats going on with ScriptManager.
Somehow I think that the scriptmanager is pointing to the wrong service URL. Shouldnt that be http://localhost:8732/Design_Time_Addresses/TestLibrary/Service1?
How would I use Chrome to do this?  Right now I'm running the app in Visual Studio.
I tried making the change you suggested but I still get the, "JavaScript runtime error: 'HelloServiceReference' is undefined" error.
Well, open the developer's debug console in Chrome/IE/FF and then open the page. You should be able to see console messages as well as downloaded resources and scripts. OR you can just also "View Source" on the page and find the reference to HelloServiceReference.

You could be running into cross-domain call issues.
I think your on the right track.  I looked in view source and found no reference to HelloServiceReference.
As HelloServiceReference is a reference to the service within the application it seems that the path in the ScriptManager should point to it but I haven't been able to get it to.
Your service is in a different application and domain. It is more than likely a failure because of that. See if the suggestions here make a difference

http://pranayamr.blogspot.com/2011/06/calling-cross-domain-wcf-service-using.html
The service and application are both on the same machine, my development computer so they are not in different domains but I will check out the link anyway.
Hello ambience,

I downloaded the source files from the link you suggested and the resulting project ran as expected but the service and the calling project are both in the same solution.  I modified my project using the 2nd solution he had described but I still get the same error it's not finding the service.  Any other suggestions?
I tried the 1st solution as well and It failed with a "Service call failed: 400Bad Request" error.
Cross domain is not on different machines. If there is a URL change in the url it is cross domain. Also please deploy them to a site and test, instead of testing in "iis express". it has limitations.
Hello apeter,

I'm not sure what you mean by, "a URL change in the url".  Could you clarify.  Also I'm not using IIS express but I will try deploying the app.

Thanks,
Les
I deployed to our Intranet but now when I click on the button to run the JavaScript I don't get an error but nothing gets returned.  I put alerts in the JavaScript to make sure it is being run and it is but no results.  I've spent to much time on this so for now I'm giving up.  My goal was to have a service that would authenticate users for any app on our Intranet but I'm just going to put the authentication code in each app.  Thanks for your suggestions.
Though the service and application are running in the same machine, they will have different url, so it is a cross domain.

Did you saw in the developers tools from the browser, to see whether right call is made ?

Also enable tracing in your WCF to know more about your error which happens at service side. https://msdn.microsoft.com/en-us/library/ee517292.aspx
ASKER CERTIFIED SOLUTION
Avatar of leskelly
leskelly
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I found the solution on my own.