Solved

Consuming WCF service with JavaScript in .NET 4.0 application

Posted on 2015-02-11
26
406 Views
Last Modified: 2015-03-09
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

0
Comment
Question by:leskelly
  • 15
  • 5
  • 3
  • +1
26 Comments
 
LVL 10

Expert Comment

by:Najam Uddin
ID: 40603603
Add ResponseFormat = WebMessageFormat.Json after comma in <System.ServiceModel.Web.WebInvoke()>
in operation contract
0
 

Author Comment

by:leskelly
ID: 40603679
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?
0
 

Author Comment

by:leskelly
ID: 40605559
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
0
 
LVL 22

Expert Comment

by:ambience
ID: 40613888
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
0
 
LVL 25

Expert Comment

by:apeter
ID: 40614617
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
0
 

Author Comment

by:leskelly
ID: 40616684
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
0
 

Author Comment

by:leskelly
ID: 40616894
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?
0
 
LVL 22

Expert Comment

by:ambience
ID: 40616907
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.
0
 
LVL 22

Expert Comment

by:ambience
ID: 40616918
Somehow I think that the scriptmanager is pointing to the wrong service URL. Shouldnt that be http://localhost:8732/Design_Time_Addresses/TestLibrary/Service1?
0
 

Author Comment

by:leskelly
ID: 40616922
How would I use Chrome to do this?  Right now I'm running the app in Visual Studio.
0
 

Author Comment

by:leskelly
ID: 40616933
I tried making the change you suggested but I still get the, "JavaScript runtime error: 'HelloServiceReference' is undefined" error.
0
 
LVL 22

Expert Comment

by:ambience
ID: 40616974
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.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:leskelly
ID: 40616983
I think your on the right track.  I looked in view source and found no reference to HelloServiceReference.
0
 

Author Comment

by:leskelly
ID: 40617008
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.
0
 
LVL 22

Expert Comment

by:ambience
ID: 40617060
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
0
 

Author Comment

by:leskelly
ID: 40617081
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.
0
 

Author Comment

by:leskelly
ID: 40626768
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?
0
 

Author Comment

by:leskelly
ID: 40626838
I tried the 1st solution as well and It failed with a "Service call failed: 400Bad Request" error.
0
 
LVL 25

Expert Comment

by:apeter
ID: 40626941
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.
0
 

Author Comment

by:leskelly
ID: 40628080
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
0
 

Author Comment

by:leskelly
ID: 40629034
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.
0
 
LVL 25

Expert Comment

by:apeter
ID: 40629592
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
0
 

Accepted Solution

by:
leskelly earned 0 total points
ID: 40645654
I got a solution from protonic.com.  The code for a working solution is below:

TestLibrary:

app.config:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true"/>
  </system.web>
  <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>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

IHello.vb

mports System.ServiceModel.Web

<ServiceContract(Namespace:="http://localhost/HelloHost2B/Hello.svc")> _
Public Interface IHello

      <OperationContract()> _
      <WebGet(ResponseFormat:=WebMessageFormat.Json)> _
      Function SayHello(ByVal value As String) As String

End Interface

Hello.vb:

Imports System.ServiceModel.Activation

<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)> _
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


HelloHost:

Web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
                  <system.web>
                  <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
      <identity impersonate="false" />
            </system.web>  
            <system.serviceModel>
                  
            <bindings>
      <webHttpBinding>
        <binding name="customWebHttpBinding">
        </binding>
      </webHttpBinding>
    </bindings>
                  
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviour">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="webScriptBehavior">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>
                  
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
                  
    <services>
      <service behaviorConfiguration="ServiceBehaviour" name="TestLibrary.Hello">
        <endpoint address="/javascript" binding="webHttpBinding" behaviorConfiguration="webScriptBehavior" contract="TestLibrary.IHello" bindingConfiguration="customWebHttpBinding" />
      </service>
    </services>
                  
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>

</configuration>

Hello.svc:

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


Hello Client:

Web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
      
  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
        <identity impersonate="false" />
  </system.web>

  <system.webServer>
     <modules runAllManagedModulesForAllRequests="true" />
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
      
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="TestLibrary.Hello">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
            <services>
                  <service name="TestLibrary.Hello">
                        <endpoint address="" binding="wsHttpBinding" contract="TestLibrary.IHello" behaviorConfiguration="TestLibrary.Hello">
                              <identity>
                                    <dns value="localhost" />
                              </identity>
                        </endpoint>
                        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" behaviorConfiguration="TestLibrary.Hello" />
                        <host>
                              <baseAddresses>
                                    <add baseAddress="http://localhost:8732/Design_Time_Addresses/TestLibrary/Service1/" />
                              </baseAddresses>
                        </host>
                  </service>
            </services>
            <bindings />
    <client />
  </system.serviceModel>
            
</configuration>

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">
    <script src="<%=ResolveUrl("~/Scripts/Hello.js")%>" type="text/javascript"></script>
    <script src="scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
    <title></title>
</head>
<body>
   <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Services>
                <asp:ServiceReference Path="http://localhost/HelloHost2B/Hello.svc/javascript"/>
           </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)" />
        </div>
    </form>
</body>
</html>

Hello.js

function fnHello(Name) {
    jQuery.ajax({
        type: "GET",
        url: "http://localhost/HelloHost2B/Hello.svc/javascript/SayHello",
        data: "value=" + Name,
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: function (data)
        {
            alert(data.d);
        },
        error: function (xhr, textStatus, errorMessage)
        {
            alert("error");
        }
    });
    var svc = new localhost.HelloHost2B.Hello.svc.IHello();
   svc.SayHello(Name, function (result, context, functionName)
    {
        window.alert('success 2nd function: ' + result);
    }, function (error, context, methodName)
    {
        window.alert('error from 2nd function: ' + error._message);
    }, null);
}

In Hello.js two different methods are used.  It should be noted that before deploying to a production server if using the jQuery method localhost needs to be replaced with the name of the server in the line url: "http://localhost/HelloHost2B/Hello.svc/javascript/SayHello"

For the other method the same needs to be done in TestHello.aspx for the line <asp:ServiceReference Path="http://localhost/HelloHost2B/Hello.svc/javascript"/>
0
 

Author Closing Comment

by:leskelly
ID: 40653455
I found the solution on my own.
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

This article discusses the difference between strict equality operator and equality operator in JavaScript. The Need: Because JavaScript performs an implicit type conversion when performing comparisons, we have to take this into account when wri…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now