Creating an ASP.Net Pingback Handler
2/6/2004 1:47:09 PM
We've talked about trackbacks and accepting notifications to your site. The other half of site notifications are pingbacks. In this article we'll provide you with a method to implement a pingback handler as well as send pingback notifications from your site.
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:
- An external site creates a link to a resource contained within your site.
- 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:
<link rel="pingback" href="http://www.somesite.com/xmlrpcserver">
- If neither the tag or HTTP header information is found, the external site
will then give up and not continue the pingback process.
- 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.
- 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.
- Your site will then retrieve some page data of the page containing the
link.
- 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.
<link rel="pingback" href="http://www.somesite.com/xmlrpcserver">
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"
<XmlRpcMethod("pingback.ping")> _
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 = "<head.*?>.*<title.*?>(.*)</title.*?>.*</head.*?>"
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
<XmlRpcUrl("http://rpc.weblogs.com/RPC2")> Public Interface IWebLogsUpdate
<XmlRpcMethod("weblogUpdates.ping")> 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.
By: Patrick Santry, Microsoft MVP (ASP/ASP.NET), developer of this site, author of books on Web technologies, and member of the DotNetNuke core development team. If you're interested in the services provided by Patrick, visit his company Website at Santry.com.
|