Cross Domain call using Ajax, JQuery, JSONP and VB.Net Web Service

Download  

The reason  I posted this article is that  I had experienced difficulties to accomplish cross domain call in my previous project, so I decided  to save this code here for me and for those developers who want to know how to make a cross domain call. Since I’m developing .net web application my solution is to create an asp.net web service API to handle the request from other domain. This API can accept parameters and return a set of data in JSON format.

Let’s start by creating a wcf service application. Open your visual studio then create wcf service application name it xdomainDemo.

 

After you created the wcf service application, right click project -> add -> new item select Web Service name it myAPI.asmx.

 

Add the code that is shown below to the web Web Service. The function getPerson will serialize the person object and return the data in JSON format.

Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.Web.Script.Serialization
Imports System.Web.Script.Services

' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
<System.Web.Script.Services.ScriptService()> _
<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class myAPI
    Inherits System.Web.Services.WebService

    <WebMethod()> _
    <ScriptMethod(UseHttpGet:=True, ResponseFormat:=WebMessageFormat.Json)> _
    Public Function GetPerson(ByVal userid As Integer) As String
        Dim objPerson As New person
        objPerson.FirstName = "Namizake"
        objPerson.LastName = "Minato"
        objPerson.UserID = userid
        Dim js As New JavaScriptSerializer()

        Dim strJSON As String = js.Serialize(objPerson)

        Return strJSON
    End Function

End Class

 

After that, right click project -> add -> class name it person. We use this class as you see in the above code. Add the properties as shown below to our class.

Public Class person
    Private _fname As String
    Private _lname As String
    Private _uid As Integer

    Public Sub New()
    End Sub

    Public Property FirstName As String
        Get
            Return _fname
        End Get
        Set(ByVal value As String)
            _fname = value
        End Set
    End Property
    Public Property LastName As String
        Get
            Return _lname
        End Get
        Set(ByVal value As String)
            _lname = value
        End Set
    End Property
    Public Property UserID As Integer
        Get
            Return _uid
        End Get
        Set(ByVal value As Integer)
            _uid = value
        End Set
    End Property
End Class

 

In your class library add a new reference, right click reference -> reference ->.Net tab find and add the System.web.

 

The next step is to add a new class library right click solution->add->new project select class library name it ContentTypeHttpModule.

 

Add new class or rename the class1.vb to ContentTypeHttpModule.vb. Add the code as shown below, take note if you’re going to use this class to another asmx service you should changes this code resquest.Url.AbsolutePath.Contains("myAPI.asmx") to your new asmx e.g. resquest.Url.AbsolutePath.Contains("myNewAPI.asmx"), you can find it in the OnBeginRequest procedure below.

Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Text
Imports System.Web

Public Class ContentTypeHttpModule
    Implements IHttpModule
    Private Const JSON_CONTENT_TYPE As String = "application/json; charset=utf-8"

#Region "IHttpModule Members"
    Public Sub Dispose() Implements IHttpModule.Dispose
    End Sub

    Public Sub Init(ByVal app As HttpApplication) Implements IHttpModule.Init
        AddHandler app.BeginRequest, AddressOf OnBeginRequest
        AddHandler app.ReleaseRequestState, AddressOf OnReleaseRequestState
    End Sub
#End Region

    Public Sub OnBeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        Dim app As HttpApplication = DirectCast(sender, HttpApplication)
        Dim resquest As HttpRequest = app.Request
        If Not resquest.Url.AbsolutePath.Contains("myAPI.asmx") Then
            Return
        End If

        If String.IsNullOrEmpty(app.Context.Request.ContentType) Then
            app.Context.Request.ContentType = JSON_CONTENT_TYPE
        End If
    End Sub

    Public Sub OnReleaseRequestState(ByVal sender As Object, ByVal e As EventArgs)
        Dim app As HttpApplication = DirectCast(sender, HttpApplication)
        Dim response As HttpResponse = app.Response
        If app.Context.Request.ContentType <> JSON_CONTENT_TYPE Then
            Return
        End If

        response.Filter = New JsonResponseFilter(response.Filter)
    End Sub
End Class

Public Class JsonResponseFilter
    Inherits Stream
    Private ReadOnly _responseStream As Stream
    Private _position As Long

    Public Sub New(ByVal responseStream As Stream)
        _responseStream = responseStream
    End Sub

    Public Overrides ReadOnly Property CanRead() As Boolean
        Get
            Return True
        End Get
    End Property

    Public Overrides ReadOnly Property CanSeek() As Boolean
        Get
            Return True
        End Get
    End Property

    Public Overrides ReadOnly Property CanWrite() As Boolean
        Get
            Return True
        End Get
    End Property

    Public Overrides ReadOnly Property Length() As Long
        Get
            Return 0
        End Get
    End Property

    Public Overrides Property Position() As Long
        Get
            Return _position
        End Get
        Set(ByVal value As Long)
            _position = value
        End Set
    End Property

    Public Overrides Sub Write(ByVal buffer As Byte(), ByVal offset As Integer, ByVal count As Integer)
        Dim strBuffer As String = Encoding.UTF8.GetString(buffer, offset, count)
        strBuffer = AppendJsonpCallback(strBuffer, HttpContext.Current.Request)
        Dim data As Byte() = Encoding.UTF8.GetBytes(strBuffer)
        _responseStream.Write(data, 0, data.Length)
    End Sub

    Private Function AppendJsonpCallback(ByVal strBuffer As String, ByVal request As HttpRequest) As String
        Return request.Params("callback") & "(" & strBuffer & ");"
    End Function

    Public Overrides Sub Close()
        _responseStream.Close()
    End Sub

    Public Overrides Sub Flush()
        _responseStream.Flush()
    End Sub

    Public Overrides Function Seek(ByVal offset As Long, ByVal origin As SeekOrigin) As Long
        Return _responseStream.Seek(offset, origin)
    End Function

    Public Overrides Sub SetLength(ByVal length As Long)
        _responseStream.SetLength(length)
    End Sub

    Public Overrides Function Read(ByVal buffer As Byte(), ByVal offset As Integer, ByVal count As Integer) As Integer
        Return _responseStream.Read(buffer, offset, count)
    End Function
End Class

 

Next step is to add the class library you created above to xdomainDemo. Right click reference->Add reference-> projects tab add the ContentTypeHttpModule.

 

After that you need to configure the  Web.config file. The configuration should look like below.

<?xml version="1.0"?>
<configuration>

  <system.web>
    <customErrors mode="Off" />
    <compilation debug="true" targetFramework="4.0" />
    <webServices>
      <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
      </protocols>
    </webServices>
    <httpModules>
      <add name="ContentTypeHttpModule"
             type="ContentTypeHttpModule.ContentTypeHttpModule, ContentTypeHttpModule" />
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </httpModules>
  </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>

 

You can run the project in order to check if it’s working. If the web service is running ok then proceed to next step.

Now we need to create an html page to consume the web service, in the page we’re going to create we will use ajax, jquery and jsonp(javascript object notation with padding) to make cross domain call possible. The script of the page should look like below.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>RxCard</title>

<script src="jquery-1.7.1.min.js"></script>
<script>
$(document).ready(function() {
	$('#test').click(function() {

    $.ajax({ url: "http://localhost:2019/myAPI.asmx/GetPerson",
		type: "GET",
		contentType: "application/json; charset=utf-8",	
		 data: {userid:1},
		dataType: "jsonp",
		success: function(json) {
			alert(json.UserID + ' ' + json.FirstName + ' ' + json.LastName);
		},
		error: function() {
			alert("Hit error fn!");
		}
    });

	});
}); // end ready
</script>
</head>
<body>
<input type="submit" name="test" id="test" value="getperson" />
<div class="wrapper">
<div id="result">
</div>
</body>
</html>

 

Now test the page if it’s running ok, make sure the web service is running. Click the getperson button in order to see the result like the picture below.

 

That's all folks!. I hope this article would be helpful to you.

Views : 3912

About the author

Christopher Tubig

Christopher Tubig

Administrator

Christopher Tubig is a software developer who is passionate about web and desktop application development. He is also interested in blogging.

comments powered by Disqus