Co to jest pingback? Jest to rodzaj notyfikacji dotyczącej umieszczenia linku do danego źródła w tekście. Notyfikację tę my możemy zarówno wysłać jak i otrzymać.
Dziś napiszę jak my możemy odebrać taki pingback i co musi zostać spełnione, zaś następnym razem opisze sposób wysyłania takiej notyfikacji.
To co będziemy potrzebować (choć nie jest to konieczne) to biblioteka XML-RPC.NET – ułatwi nam ona znacząco implementację – gdyż komunikacja odbywa się poprzez XML-RPC, oczywiście dla hardcorów istnieje opcja napisania tego samemu, ale po co?
Implementacja
By móc otrzymać pingback musimy zaimplementować metodę pingback.ping – nie jest ona jakoś trudna do implementacji, ale wymaga pewnego sprawdzania po naszej stronie.
Metoda ta przyjmuje jedynie dwa parametry:
- URL skąd pochodzi request
- URL jakiego zasobu u nas on tyczy
W zależności od tego czy parametry są podane czy też nie, można zwracać różne błędy opisane w specyfikacji protokołu.
Kod nie jest skomplikowany, wymaga trochę sprawdzania itp. Pominąłem kilka kwestii jak i nie dałem pełnego kodu – na przykład ExistsOn powoduje pobranie strony z netu jeżeli jest ona mniejsza niż rozmiar X i sprawdza czy nasz link istnieje tam.
using System;
namespace SomeNamespace
{
// http://www.hixie.ch/specs/pingback/pingback
public interface IPingbackService
{
[XmlRpcMethod("pingback.ping")]
string pingback(string sourceUri, string targetUri);
}
public class PingbackService : XmlRpcService, IPingbackService
{
public PingbackService()
{
// we can initializers here - db etc
}
string IPingbackService.pingback(string sourceUri, string targetUri)
{
if (sourceUri.IsNullOrEmpty())
{
throw new XmlRpcFaultException(16, "The source URI does not exist.");
}
if (targetUri.IsNullOrEmpty())
{
throw new XmlRpcFaultException(32, "The specified target URI does not exist.");
}
// check if url (target) exists on page that is linking to us (we do not want to have spam comments)
// title is read from the loaded resources from sourceUri and used as comment title
var title = string.Empty;
if (targetUri.ExistsOn(sourceUri, out title) == false)
{
throw new XmlRpcFaultException(17, "The source URI does not contain a link to the target URI, and so cannot be used as a source.");
}
var slug = get_slug(targetUri);
// open db connection
using (var session = db.Open())
{
var post = new Post(); // execute query to get post
if (post == null)
{
throw new XmlRpcFaultException(33, "The specified target URI cannot be used as a target. It either doesn't exist, or it is not a pingback-enabled resource.");
}
var comments = post.Comments;
// check if comments are allowed
if (comments.AreCommentsClosed()|| post.AllowComments == false)
{
throw new XmlRpcFaultException(33, "The specified target URI cannot be used as a target. It either doesn't exist, or it is not a pingback-enabled resource.");
}
// check if comment from sourceUri already exists - we do not want to have duplicates
var exists = comments.UrlExists(sourceUri);
if (exists)
{
throw new XmlRpcFaultException(48, "The pingback has already been registered.");
}
// create new comment and assign values to it
var comment = new PostComment();
// comment.Title = "Pingback from: {0}".FormatWith(title);
// if needed check if this comment is a spam (Aksiment etc)
// if everything is ok, add comment and save data
post.Comments.Add(comment);
// exeute save
}
// return some string
return "Your ping request has been received successfully.!";
}
private string get_slug(string url)
{
var start = url.LastIndexOf("/") + 1;
var slug = url.Substring(start).ToLowerInvariant();
return slug;
}
}
}
Konfiguracja
Mają już kod, musimy go jakoś udostępnić, tutaj przydaje się ASP.NET Handler – ASHX/AXD. Wystarczy albo zdefiniować go w Web.Config:
<system.web>
<httpHandlers>
<add verb="*" path="pingback.axd" type="Namespace.PingbackService, AssemblyNam" validate="false"/>
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Read, Write, Script, Execute">
<add name="Pingback" verb="*" path="pingback.axd" type="Namespace.PingbackService, AssemblyName" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode"/>
</handlers>
</system.webServer>
Lub po prostu dodajemy plik o nazwie PingbackService.ashx do projektu z treścią:
<%@ WebHandler="" Language="C#" Class="Namespace.PingbackService" %>
Autowykrywanie
Ostatnim krokiem jaki musimy zrobić to dodać kod do naszej strony WEB który poinformuje usługę wysyłającą, pingback o tym, że my go przyjmujemy.
Tutaj mamy kilka opcje, jedną z nich jest dodanie nagłówka do response zawierającego wartość X-Pingback z pełnym URL do serwisu/handler.
Można to osiągnąć w metodzie Application_BeginRequest w HttpApplication lub za pomocą Web.config:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var urlHelper = new UrlHelper(Context.Request.RequestContext);
Context.Response.AddHeader("X-Pingback", urlHelper.AbsoluteContent("~/services/pingback.ashx"));
}
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Pingback" value="http://FULL_URL/pingback.ashx" />
</customHeaders>
</httpProtocol>
</system.webServer>
Możemy także dodać element link do strony z rel="pingback" i href który odwołuje się do pełnego adresu URL serwisu/handler.
<link rel="pingback" href="http://FULL_URL/pingback.ashx" />
Podsumowanie
Dodanie tego nie jest trudne, jak już wiadomo o co chodzi i jak to ma działać. Mi osobiście najwięcej zajęło zrozumienie co to jest pingback i na
jakiej zasadzie on działa. Jak już to zrozumiałem to napisanie kodu było kwestią kilku minut.
Następnym razem napiszę jak wysyłać pingbacki z naszej strony, a tym czasem – jakieś uwagi? Sugestie? :)















Sądząc po pierwszym komentarzu działa :)
dotnetomaniak wysyla trackbacki – tutaj musialem recznie poprawic bo w trackback mialem buga ;) to ze wysyla trackbacki mozna zobaczyc przy postcie z odbieraniem :)
Comments are closed.