facebook  linkedin  Twitter  skype  Rss googlePlus

Creating an ASP.Net Pingback Handler

Feb 06 2004
12962

In a previous article we discussed how to enable your site so it can accept link notifications using trackbacks. In this article we will cover a second method of site notification known as pingbacks.

What's a Pingback

Pingbacks are a method of site notification using XML-RPC.

Here's an outline of the pingback process:

  1. An external site creates a link to a resource contained within your site.
  2. The external site then checks for pingback information within the document in your site;
    first it checks the headers returned by your site to see if the X-Pingback header is there and contains a value;
    if it does not find the X-Pingback header, it then checks the body of the document to see if the following HTML tag appears:
  3. If neither the tag or HTTP header information is found, the external site will then give up and not continue the pingback process.
  4. If the pingback information is found, the site will then execute an XML-RPC command to the site to notify them that the link has been made.
  5. Your site would then receive the method request and check the external site to make sure a link to your site is indeed there and it is valid.
  6. Your site will then retrieve some page data of the page containing the link.
  7. Finally, your site then adds the information to the database and enters the link information to your page.

Now that you understand the pingback process, we are going to provide you with some methods for accepting a pingback notification and making a pingback notification.

Accepting Pingback Notifications

For our pingback handler we will need to create a new class file. In this class we will import our namespace to Cook Computing's XML-RPC.Net object. XML-RPC.Net provides us with the base functionality for making and accepting XML-RPC calls.

Before we get into handling the actual pingback notification, we have to provide the external site with information on how to notify our pingback handler. According to the specifications you should either provide a HTTP header, or add the link to the document. The preferred method is add the HTTP header information. Let's look at some ASP.Net code on how to insert this header information into a response. For the header we need to be able to provide an absolute URI path to our pingback handler. In this case we'll define our handler as "PingBack.aspx". Just keep note here, that there really isn't a pingback.aspx page, we're going to create an HTTPHandler to intercept any requests for the pingback.aspx and process then in our handler class.

In this next code snippet, this is where you provide the absolute URI to your pseudo page for handling the pingbacks. In our example, we generate all content dynamically from a database so in our code we'll insert the HTTP Header X-Pingback and then provide the path to the handler.

Dim sDomain As String = "http://" & Request.ServerVariables("SERVER_NAME")
If Request.ServerVariables("SERVER_PORT") <> "80" Then
    sDomain = sDomain & ":" & Request.ServerVariables("SERVER_PORT")
End If
Response.AddHeader("X-Pingback", sDomain & _
  IIf(Request.ApplicationPath = "/", "", _
  Request.ApplicationPath) & "/PingBack.aspx")
The header solution is the preferred method for pingbacks. Another way of inserting the header is to do it directly via IIS Manager from the MMC snap-in. You can do this by going to computer management, then expand the Internet Information Services node, from there select the Website you want the handler header added, and right-click select properties from the context menu. In the properties dialog box click on the HTTP Headers tab. In the middle of this dialog you can add your custom header with the header name and then enter in the absolute URI for your pingback handler.

Another method is to add the link information directly into the document.

Remember this link needs to be within the first 5k of the document as according the spec.

Now that we have our information available so sites know where to send the pingback notification, we'll create a class to intercept the requests and handle the notification. In this example we'll implement this as a HTTPHandler. So we will need to define our handler within our web.config file in our application like so:

<system.web>
    <httpHandlers>
        <add verb="*" path="PingBack.aspx" type="MyNamespace.PingBackService, MyNamespace" />
    httpHandlers>
</system.web>

Now that we have our application configured, let's go over the final piece and that is creating our PingbackHandler class for responding to pingback notifications.

Imports CookComputing.XmlRpc
Imports System
Imports System.Net
Imports System.Web
Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Web.Services
 
    Public Class PingBackService
        Inherits XmlRpcService
        Private Const defaultTimeout = 60000
        Private Const referer = "http://www.wwwcoder.com/"
        Private Const userAgent = "RDM 3.0(WWWCoder.com) for DotNetNuke"
 
         _
        Function pingBack(ByVal sourceURI As String, ByVal targetURI As String) As String
            Dim strBody As String
            Try
                Dim postId As Integer = 0
                Dim pageTitle As String = ""
                If Not CheckForURL(sourceURI, targetURI, pageTitle) = "0" Then
                    'check to see if they linked to site.
                    Throw New XmlRpcFaultException(17, "Not a valid link!")                   
                Else
                    'they linked so add the comment and link to the blog.
                    Try
                        'since we generate articles based on the id in the database.
                        'we'll parse the id out of the url sent by the external site
                        'to our pingback handler. We'll handle both friendly URLs and
                        'querystrings.
                        Dim articleID As Integer = 0
                        Dim tmpString As String
                        If targetURI.IndexOf("/site/") <> 0 Then
                            tmpString = Mid(targetURI, targetURI.IndexOf("/site/") + 6)
                            tmpString = Mid(tmpString, tmpString.IndexOf("/") - 1)
                            articleID = CType(tmpString, Integer)
                        ElseIf targetURI.IndexOf("&site=") <> 0 Then
                            tmpString = Mid(targetURI, targetURI.IndexOf("&site=") + 6)
                            tmpString = Mid(tmpString, tmpString.IndexOf("&") - 1)
                            articleID = CType(tmpString, Integer)
                        End If
                        If articleID <> 0 Then
                            'insert the comments into your db.
                        End If
                    Catch ex As Exception
                        Throw New XmlRpcFaultException(17, "Not a valid link!")
                    End Try
                    Return "thanks for the pingback on " + sourceURI
                End If
            Catch ex As Exception
                'handler the error
            End Try
 
        End Function
 
        Public Function CheckForURL(ByVal sURI As String, _
            ByVal tURI As String, ByVal pageTitle As String) As String
            Try
                Dim page As String = GetPageHTML(sURI)
                If (page.Trim = "") Or (page.IndexOf(tURI) < 0) Then
                    Return "0"
                Else
                    Dim pat As String = ".*(.*).*"
                    Dim reg As Regex = New Regex(pat, RegexOptions.IgnoreCase.Singleline)
                    Dim m As Match = reg.Match(page)
                    If m.Success Then
                        pageTitle = m.Result("$1")
                        Return pageTitle
                    End If
                End If
            Catch ex As Exception               
                Return "0"
            End Try
            Return pageTitle
        End Function
 
        Public Function GetPageHTML(ByVal inURL As String) As String
            Dim req As WebRequest = WebRequest.Create(inURL)
            Dim Null As Object
            Dim wreq As HttpWebRequest = req
            If Not (wreq Is Null) Then
                wreq.UserAgent = "My User Agent String"
                wreq.Referer = "http://www.wwwcoder.com/"
                wreq.Timeout = 60000
            End If
            Dim response As HttpWebResponse = wreq.GetResponse
            Dim s As Stream = response.GetResponseStream
            Dim enc As String = response.ContentEncoding.Trim
            If enc = "" Then enc = "us-ascii"
            Dim encode As Encoding = System.Text.Encoding.GetEncoding(enc)
            Dim sr As StreamReader = New StreamReader(s, encode)
            Return sr.ReadToEnd
        End Function
    End Class

Much of this code is similar to the code for handling trackbacks, this is especially so when we check to see if the link actually exists within the external document. The primary difference here is the use of XML-RPC for the transaction instead of a basic HTTP POST or GET transaction.

Then compile your code, and you should now be able to respond to pingback notifications.

Sending a Pingback Notification

In this block of code we will provide a method of sending a pingback notification. In this specific example we will pingback weblogs.com to notify them that our site has changed. First we'll create a Pingback class to handle the pingback notifications. Then we'll call the Ping method to send a ping to weblogs.com.

Imports CookComputing.XmlRpc
Imports System
   Public Class Pingback
      Public Function Ping(ByVal WeblogName As String, _
         ByVal WeblogURL As String) As WeblogsUpdateResponse
         Dim proxy As IWebLogsUpdate
         proxy = XmlRpcProxyGen.Create(GetType(IWebLogsUpdate))
         Return proxy.Ping(WeblogName, WeblogURL)
      End Function
      Structure WeblogsUpdateResponse
         Public flerror As Boolean
         Public message As String
      End Structure
       Public Interface IWebLogsUpdate
         Function Ping(ByVal _
           WeblogName As String, ByVal WeblogURL As String) As WeblogsUpdateResponse
      End Interface
   End Class
Then in my code behind for my aspx form:
Private Sub cmdPingWeblogs_Click(ByVal sender As Object, ByVal e As _
   System.EventArgs) Handles cmdPingWeblogs.Click
   Dim objPing As New Pingback
   Dim sResponse As Pingback.WeblogsUpdateResponse
   sResponse = objPing.Ping("WWWCoder.com - ASP.Net Tutorials", http://www.wwwcoder.com)
   lblStatus.Text = sResponse.message
End Sub

The call to the ping method can be extended to loop through all the links within the content of your document and instead of notifying weblogs.com, make a request to the site that you linked to in order to find out if the response contains pingback information. Once you find the pingback information then use the above class to notify their pingback handler.

About the Author, Patrick Santry

Patrick Santry, has two decades of experience in enabling businesses to take advantage of the digital landscape. A well rounded experience in technology, and business is what sets me apart from the rest of the pack. When it comes to an overall digital strategy my experience is impressive.

BS in Computer Information Systems. Four time recipient of the Microsoft MVP Award, and author of several books and magazine articles on digital technologies.


blog comments powered by Disqus

Latest Podcast

New Podcast: Apple, Disqus, and More!

 

Subscribe to Pat's Digital Podcast on iTunes! Latest Podcast

Listen to Pat's Podcast

 

Thank you for visiting our site, before you leave, please visit some of the areas or information you may have missed.