Trackbacks never seem to work

Topics: ASP.NET 2.0
Mar 9, 2009 at 7:38 PM
Links to posts at other websites that I embed into my own posts at Coal Energy Now never result in a trackback.  Is there something I am doing wrong?
Coordinator
Mar 9, 2009 at 8:04 PM
Are the websites you're linking to in your blog posts keeping tracking of or displaying trackbacks?  Some websites show trackbacks and some don't.
Mar 9, 2009 at 8:11 PM
Edited Mar 9, 2009 at 8:12 PM
One website specified a specific trackback link.  You can see this website here.  Another is at The Washington Post, with my newest post dealing with this article.  A couple of paragraphs down you will see a Toolbox widget containing a link to find out who is blogging about the article.

By the way, this isn't the first time either.  I have noticed this for a while but I assumed it must be something I was doing wrong.  After doing a little research, however, I am not so sure.
Coordinator
Mar 9, 2009 at 9:21 PM
I looked into it a bit, and the functionality seems to be working with just a quick test.

On the Settings tab in the control panel, do you have the "Send" checkbox checked for both Enable Trackbacks and Enable Pingbacks?
Mar 9, 2009 at 9:24 PM
All check boxes for both Send and Receive have always been checked.  I have no idea what to do.
Coordinator
Mar 10, 2009 at 12:34 AM
I looked into this some more.  I noticed a problem in BlogEngine where the trackback data it sends starts off with a "?" (query string question mark), but it shouldn't include that because the trackback data is sent in a POST, rather than a GET.  GET requests would normally have a leading ? but a POST doesn't need it.  Plus, the example here, shows no ? before the first piece of data.  BlogEngine should also probably be URL encoding the parameters it sends.

I did manually remove the ? and tried manually sending a trackback to the bnet.com article using your post's URL, title, etc.  I actually got back a successful response.  Before removing the leading ? an empty response was coming back.  So with the successful trackback response after removing the leading ? it looked like everything was going to work.  But I still don't see the trackback on bnet.com's article.  It could be because it's not a live report and updates itself every so many hours.  But also when I look back on a few recent posts on bnet.com, they all report "No trackbacks yet".  So maybe their trackback system isn't working?

The bnet.com article also exposes a pingback url in its response header.  BlogEngine probably sent a pingback to bnet.com, but it's possible they're only showing trackbacks, and not pingbacks ... or like I mentioned above, their trackback system might not be working.

I'm honestly not sure how a trackback or pingback with washingtonpost.com works.  They don't have any trackback url in their HTML that can be auto-discovered.  And they also don't have a pingback url in the response header.  I tried manually sending a trackback to the actual URL of the washingtonpost.com article, but it comes back with a 404, not found error.

One other big problem exists.  BlogEngine is designed to auto-discover trackback and pingback URLs.  Well even in the case of bnet.com, you linked to the direct trackback link, but BlogEngine is designed to go to that URL and auto-discover a trackback URL.  BlogEngine doesn't realize that the URL you put in the post is the actual trackback URL.  When BlogEngine goes to the trackback URL you entered, it doesn't find the typical trackback URL that would be in a RDF tag.  So BlogEngine doesn't attempt to send a trackback.  Even if you had linked to the actual bnet.com article (rather than linking to the trackback url they provide), there still isn't any auto-discoverable trackback url in bnet.com's article.

Sorry for the long response ... I'm just sort of documenting the problem.  As I mentioned above, BlogEngine should be improved to not include the leading ? in the trackback POST data and should also url encode its parameters.  But even doing that, as it is now, BlogEngine still wouldn't send trackbacks for these particular websites.  From what I can tell, BlogEngine would need to be slightly re-designed to realize you may be entering the actual trackback URL (as is in the case of bnet.com) and not try to auto-discover the trackback urls.  Maybe it should try to auto-discover, and if it doesn't find anything, then it can try sending a trackback to the direct URL.  While doing a Google search, I also did see a reference to another blog platform that has a separate box where you can enter one or more trackback urls.  This is another possible solution that could be implemented in BlogEngine.
Mar 10, 2009 at 12:46 AM
Don't even apologize to me for long posts - the information you provided is excellent for me.  It is really appreciated.

Do you anticipate that this is something that I should keep an eye out for in the change log for each release?  Maybe it will be fixed in the not-to-distant future?
Coordinator
Mar 10, 2009 at 7:01 AM
Now that I've gone through the trackback logic in BlogEngine, I don't think it would be very time consuming to make the fixes/improvements.  BlogEngine 1.5 should be coming out quite soon, and in an attempt to not disrupt anything in that release, I think making these changes to BlogEngine soon after the 1.5 release would be best.  So yes, please keep an eye out for the list of changes for releases on the Source Code tab.

Also, if you happen to run across any information on how a site like washingtonpost.com receives trackbacks, please let me know!

On the washingtonpost.com article, when clicking on "Links to this article", I noticed the links come from a widget by "sphere".  Earlier today, sphere showed around 2,600 links "related blog posts" to this particular washingtonpost.com article.  Sphere states on their site that their widget finds blog and media articles related to your blog posts.  So maybe they crawl websites indexing information.  And this massive list of 2,600 URLs didn't send a trackback to washingtonpost.com, but sphere is just reporting sites it found while crawling the web.

Right now, the 2,600 or so URL's aren't even showing up.  It says "No Matches Found" ... probably just a temporary problem.  A little lower down under "related blog posts", it says "bloggers linking to this article", where there is only 3 links.  I think there were around only 3 links earlier today too.  I'd be curious to see how these 3 sites got their links on this short list.
Mar 10, 2009 at 5:19 PM
For me to be indexed by Sphere as a blogger, I think I need to obtain this widget from their website.  You'll notice under the image it reads "It will also have the added benefit of registering your site in our index, thus enabling your content to be syndicated and appear on our partner sites."

It is a bit confusing, though.  At first I thought this was a different widget than the one shown here, where they have it labeled as "Related Content Widget".  After further study I realized that it is the same widget.
Mar 13, 2009 at 7:27 PM
I am finding that trackbacks are not working between my 2 blogs (both using BE.NET 1.4.5).  I have trackbacks enabled on both.  IIS logs show no attempt to post the trackback from the originating blog.

...Matt
Coordinator
Mar 13, 2009 at 7:35 PM
Just curious, are you running any of these 2 blogs off your local machine?  One thing I saw in the code the other day is if you are creating/editing a post on the same machine the blog is installed on (like localhost), then an attempt to send a trackback is not done.

Also, do you have the SendPings extension enabled (on the Extensions tab in the control panel)?
Mar 13, 2009 at 7:58 PM
Neither blog are on my local machine.  However, both are hosted by the same webhosting service.

However, some blogs which I've referenced never received the trackbacks either (but which they did in the past), so that's why I tested between my 2 blogs.

I have Send Pings/trackbacks enabled in both extensions and Settings.
Coordinator
Mar 13, 2009 at 9:00 PM
Edited Mar 17, 2009 at 4:08 AM
I tested the trackbacks between two 1.4.5 blogs I have, and it was working.  If you're interested, I put together some modifications of the SendPings.cs file that goes in the App_Code\Extensions folder.  The modifications add some logging to possible see what might be going on.

What you should do is replace the content in your SendPings.cs file with the code I pasted below.  Put this code in the blog installation you will be adding a blog entry to.  Once you've replaced it, then add a new blog post and include a link to a blog post on your other blog installation (or one of the other blogs that used to receive your trackbacks).  After saving the blog post, wait a few seconds (maybe 10 seconds), then check your App_Data folder.  There should be a new file in there named SendPings_Log.txt.  Let me know what content shows up in that file.  What shows up in the log file should help us.  But if there is some problem in the code that actually sends the trackback, that would be in the BlogEngine.Core which would be a little more challenging to debug (but not impossible, of course).

EDITED 3/16/2009 ......

#region using

using System;
using System.Web;
using BlogEngine.Core.Web.Controls;
using BlogEngine.Core;
using System.Net.Mail;
using System.Threading;

#endregion

/// <summary>
/// Pings all the ping services specified on the
/// PingServices admin page and send track- and pingbacks
/// </summary>
[Extension("Pings all the ping services specified on the PingServices admin page and send track- and pingbacks", "1.3", "BlogEngine.NET")]
public class SendPings
{

  /// <summary>
  /// Hooks up an event handler to the Post.Saved event.
  /// </summary>
  static SendPings()
  {
    Post.Saved += new EventHandler<SavedEventArgs>(Post_Saved);
        Page.Saved += new EventHandler<SavedEventArgs>(Post_Saved);
        //BlogEngine.Core.Ping.Trackback.Sending += new EventHandler<EventArgs>(SendingTrackback);
        //BlogEngine.Core.Ping.Trackback.Sent += new EventHandler<EventArgs>(SentTrackback);
  }

  public static void SendingTrackback(object sender, EventArgs e)
  {
      RecordLog(sender, "Sending Trackback");
  }

  public static void SentTrackback(object sender, EventArgs e)
  {
      RecordLog(sender, "Sent Trackback");
  }

  public static void RecordLog(object sender, string msg)
  {
      if (sender != null)
      {
          Uri UrlToNotifyTrackback = sender as Uri;
          if (UrlToNotifyTrackback != null)
          {
              msg += " ... UrlToNotifyTrackback = " + UrlToNotifyTrackback.ToString();
          }
      }

      string log = DateTime.Now.ToString() + " - MSG = " + msg + "\r\n";

      string logFile = System.IO.Path.Combine(BlogSettings.Instance.StorageLocation, "SendPings_Log.txt");
      logFile = System.Web.Hosting.HostingEnvironment.MapPath(logFile);

      System.IO.File.AppendAllText(logFile, log);

  }

  /// <summary>
  /// Sends the pings in a new thread.
  /// <remarks>
  /// It opens a new thread and executes the pings from there,
  /// because it takes some time to complete.
  /// </remarks>
  /// </summary>
  private static void Post_Saved(object sender, SavedEventArgs e)
  {
        if (e.Action == SaveAction.None || e.Action == SaveAction.Delete)
            return;

    IPublishable item = (IPublishable)sender;

    RecordLog(null, "Determine if Ping stuff should be done.");

    if ((HttpContext.Current == null || !HttpContext.Current.Request.IsLocal) && item.IsVisible)    
    {
        Uri url = item.AbsoluteLink;

        RecordLog(null, "Before calling Ping");
        Ping(item, url);        
        RecordLog(null, "After calling Ping");

    }
    else
    {
        RecordLog(null, "Don't need to do Ping Stuff.");
    }
  }

  /// <summary>
  /// Executes the pings from the new thread.
  /// </summary>
  private static void Ping(IPublishable item, Uri itemUrl)
  {
        try
        {
            RecordLog(null, "Before PingService.Send()");

            // Ping the specified ping services.
            BlogEngine.Core.Ping.PingService.Send(itemUrl);

            RecordLog(null, "Is pingback/trackback enabled?");

            // Send trackbacks and pingbacks.
            if (!BlogSettings.Instance.EnableTrackBackSend && !BlogSettings.Instance.EnablePingBackSend)
                return;

            RecordLog(null, "Check for link");

            if (item.Content.ToUpperInvariant().Contains("\"HTTP"))
            {
                RecordLog(null, "Link found ... calling SendTrackbacksAndPingbacks");
                SendTrackbacksAndPingbacks(item, itemUrl);
            }
            else
                RecordLog(null, "No link found.");
        }
        catch (Exception ex)
        {
            RecordLog(null, "Error in Ping() ... " + ex.Message);
          // We need to catch this exception so the application doesn't get killed.
        }
  }

  public static void SendTrackbacksAndPingbacks(IPublishable item, Uri itemUrl)
  {
      System.Collections.Generic.List<Uri> urls = GetUrlsFromContent(item.Content);

      string msg = "Found " + urls.Count.ToString() + " URLs in message";

      for (int counter = 0; counter < urls.Count; counter++)
      {
          msg += "\r\n" + "URL #" + (counter + 1).ToString() + " - " + urls[counter].ToString();
      }
      RecordLog(null, msg);

      foreach (Uri url in urls)
      {
          string pageContent = ReadFromWeb(url);
          Uri trackbackUrl = GetTrackBackUrlFromPage(pageContent);
          bool isTrackbackSent = false;

          if (trackbackUrl == null)
              RecordLog(null, "No trackback url found for " + url.ToString());
          else
              RecordLog(null, "Trackback URL for " + url.ToString() + " is " + trackbackUrl.ToString());

          if (trackbackUrl != null)
          {
              BlogEngine.Core.Ping.TrackbackMessage message = new BlogEngine.Core.Ping.TrackbackMessage(item, trackbackUrl, itemUrl);
              RecordLog(null, "About to send trackback to " + message.UrlToNotifyTrackback.ToString());
              isTrackbackSent = SendTrackback(message);
              RecordLog(null, "Trackback sent status = " + isTrackbackSent.ToString());
          }

          if (!isTrackbackSent)
          {
              RecordLog(null, "About to send pingback for " + url.ToString());
              SendPingback(itemUrl, url);
          }
      }
  }

  public static void SendPingback(Uri sourceUrl, Uri targetUrl)
  {
      if (!BlogSettings.Instance.EnablePingBackSend)
          return;

      if (sourceUrl == null || targetUrl == null)
          return;

      try
      {
          System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(targetUrl);
          request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
          System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();

          string pingUrl = null;
          foreach (string key in response.Headers.AllKeys)
          {
              if (key.Equals("x-pingback", StringComparison.OrdinalIgnoreCase) ||
                  (key.Equals("pingback", StringComparison.OrdinalIgnoreCase)))
              {
                  pingUrl = response.Headers[key];
                  break;
              }
          }

          Uri url;
          if (!string.IsNullOrEmpty(pingUrl) && Uri.TryCreate(pingUrl, UriKind.Absolute, out url))
          {
              RecordLog(null, "Sending pingback ... " + url.ToString());
              request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
              request.Method = "POST";
              request.Timeout = 10000;
              request.ContentType = "text/xml";
              request.ProtocolVersion = System.Net.HttpVersion.Version11;
              request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)";
              AddXmlToRequest(sourceUrl, targetUrl, request);
              request.GetResponse();
              RecordLog(null, "Sent pingback ... " + url.ToString());
          }
          else
            RecordLog(null, "No pingback URL found for " + targetUrl.ToString());
      }
      catch (Exception)
      {
          // Stops unhandled exceptions that can cause the app pool to recycle
      }
  }

  private static void AddXmlToRequest(Uri sourceUrl, Uri targetUrl, System.Net.HttpWebRequest webreqPing)
  {
      System.IO.Stream stream = (System.IO.Stream)webreqPing.GetRequestStream();
      using (System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(stream, System.Text.Encoding.ASCII))
      {
          writer.WriteStartDocument(true);
          writer.WriteStartElement("methodCall");
          writer.WriteElementString("methodName", "pingback.ping");
          writer.WriteStartElement("params");

          writer.WriteStartElement("param");
          writer.WriteStartElement("value");
          writer.WriteElementString("string", sourceUrl.ToString());
          writer.WriteEndElement();
          writer.WriteEndElement();

          writer.WriteStartElement("param");
          writer.WriteStartElement("value");
          writer.WriteElementString("string", targetUrl.ToString());
          writer.WriteEndElement();
          writer.WriteEndElement();

          writer.WriteEndElement();
          writer.WriteEndElement();
      }
  }

  private static readonly System.Text.RegularExpressions.Regex trackbackLinkRegex = new System.Text.RegularExpressions.Regex("trackback:ping=\"([^\"]+)\"", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Compiled);
  private static Uri GetTrackBackUrlFromPage(string input)
  {
      string url = trackbackLinkRegex.Match(input).Groups[1].ToString().Trim();
      Uri uri;

      if (Uri.TryCreate(url, UriKind.Absolute, out uri))
          return uri;
      else
          return null;
  }


  private static string ReadFromWeb(Uri sourceUrl)
  {
      string html;
      using (System.Net.WebClient client = new System.Net.WebClient())
      {
          client.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
          html = client.DownloadString(sourceUrl);
      }
      return html;
  }

  //private static readonly Regex urlsRegex = new Regex(@"\<a\s+href=""(http://.*?)"".*\>.+\<\/a\>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
  //private static readonly System.Text.RegularExpressions.Regex urlsRegex = new System.Text.RegularExpressions.Regex(@"<a[^(href)]?href=""([^""]+)""[^>]?>([^<]+)</a>", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Compiled);
  private static readonly System.Text.RegularExpressions.Regex urlsRegex = new System.Text.RegularExpressions.Regex(@"<a.*?href=[""'](?<url>.*?)[""'].*?>(?<name>.*?)</a>", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Compiled);
  private static System.Collections.Generic.List<Uri> GetUrlsFromContent(string content)
  {
      System.Collections.Generic.List<Uri> urlsList = new System.Collections.Generic.List<Uri>();
      foreach (System.Text.RegularExpressions.Match myMatch in urlsRegex.Matches(content))
      {
          string url = myMatch.Groups["url"].ToString().Trim();
          //string url = myMatch.Groups[1].ToString().Trim();
          Uri uri;
          if (Uri.TryCreate(url, UriKind.Absolute, out uri))
              urlsList.Add(uri);
      }

      return urlsList;
  }

  public static bool SendTrackback(BlogEngine.Core.Ping.TrackbackMessage message)
  {
      if (!BlogSettings.Instance.EnableTrackBackSend)
          return false;

      if (message == null)
          throw new ArgumentNullException("message");

      RecordLog(null, "Sending trackback ... " + message.UrlToNotifyTrackback.ToString());

      bool result = true;
      System.Net.HttpWebRequest request = null;

      string trackbackMsg = string.Format(System.Globalization.CultureInfo.InvariantCulture,
          "title={0}&url={1}&excerpt={2}&blog_name={3}", message.Title, message.PostUrl, message.Excerpt, message.BlogName);

      try
      {
          request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(message.UrlToNotifyTrackback); //HttpHelper.CreateRequest(trackBackItem);
          request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
          request.Method = "POST";
          request.ContentLength = trackbackMsg.Length;
          request.ContentType = "application/x-www-form-urlencoded";
          request.KeepAlive = false;
          request.Timeout = 10000;

          using (System.IO.StreamWriter myWriter = new System.IO.StreamWriter(request.GetRequestStream()))
          {
              myWriter.Write(trackbackMsg);
          }
      }
      catch (Exception ex)
      {
          string msg1 = ex.Message;
          while (ex.InnerException != null)
          {
              ex = ex.InnerException;
              if (!string.IsNullOrEmpty(ex.Message))
                  msg1 += " ... Inner Exception = " + ex.Message;
          }
          RecordLog(null, "Error in SendTrackback (sending Request).  Error: " + msg1);
          result = false;
      }

      if (!result)
          return false;

      result = false;

      System.Net.HttpWebResponse response;
      try
      {
          response = (System.Net.HttpWebResponse)request.GetResponse();
          RecordLog(null, "Sent trackback ... " + message.UrlToNotifyTrackback.ToString());
          string answer;
          using (System.IO.StreamReader sr = new System.IO.StreamReader(response.GetResponseStream()))
          {
              answer = sr.ReadToEnd();
          }

          if (response.StatusCode == System.Net.HttpStatusCode.OK)
          {
              //todo:This could be a strict XML parsing if necesary/maybe logging activity here too
              if (answer.Contains("<error>0</error>"))
              {
                  result = true;
              }
              else
              {
                  RecordLog(null, "Response when sending trackback was not a success, it was ... " + (answer ?? string.Empty));
                  result = false;
              }
          }
          else
          {
              RecordLog(null, "HttpStatusCode when sending trackback was " + response.StatusCode.ToString());
              result = false;
          }
      }
      catch (Exception ex)
      {
          string msg1 = ex.Message;
          while (ex.InnerException != null)
          {
              ex = ex.InnerException;
              if (!string.IsNullOrEmpty(ex.Message))
                  msg1 += " ... Inner Exception = " + ex.Message;
          }
          RecordLog(null, "Error in SendTrackback (getting Response).  Error: " + msg1);
          result = false;
      }
      return result;
  }

}
Mar 13, 2009 at 9:08 PM
The entire contents of the log file is:

3/13/2009 2:06:54 PM - MSG = Determine if Ping stuff should be done.
Coordinator
Mar 13, 2009 at 9:21 PM
That's a little informational.  There could be a problem when the Ping Services are pinged.  This same SendPings.cs file handles sending trackbacks, pingbacks and also notifying the ping services of your new post.  At any rate, I modified the SendPings.cs code in the previous message.  I added a couple of more logging statements.  When you have a chance, try the updated code in my edited message above.
Mar 13, 2009 at 9:32 PM
Edited Mar 13, 2009 at 9:43 PM
New Round of logs:

3/13/2009 2:30:44 PM - MSG = Determine if Ping stuff should be done.
3/13/2009 2:30:44 PM - MSG = Before add to ThreadPool
3/13/2009 2:30:44 PM - MSG = After add to ThreadPool

I also did a quick edit of the code you provided to get the number of available threads in the threadpool: it says 398.
Coordinator
Mar 13, 2009 at 9:54 PM
The QueueUserWorkItem() function returns a true/false value indicating if the method is successfully queued.  You could capture that result and add it to the log.  The snippet below does that.  I also added a try/catch block to it to see if an error is occuring there.


        RecordLog(null, "Before add to ThreadPool");
        bool result = false;
        try
        {
            result = ThreadPool.QueueUserWorkItem(delegate { Ping(item, url); });
        }
        catch (Exception ex)
        {
            RecordLog(null, "Error adding to ThreadPool - " + ex.Message);
        }
        
        RecordLog(null, "After add to ThreadPool");
        RecordLog(null, "ThreadPool result = " + result);
Mar 13, 2009 at 9:57 PM
3/13/2009 2:56:23 PM - MSG = Determine if Ping stuff should be done.
3/13/2009 2:56:23 PM - MSG = Before add to ThreadPool
3/13/2009 2:56:23 PM - MSG = GetAvailableThreads 399 400
3/13/2009 2:56:23 PM - MSG = After add to ThreadPool
3/13/2009 2:56:23 PM - MSG = ThreadPool result = True
Coordinator
Mar 14, 2009 at 12:53 AM
I think the number of available threads shouldn't be a problem at all.  On my machine, I show 199 200 right before QueueUserWorkItem() and 198 200 right after QueueUserWorkItem().  Your 399 400 should be okay.

Do you have any special extensions or widgets you've added to your blog?  I'm wondering if some other code might be running in another extension when the post is saved that is causing a problem.  You could try temporarily disabling other extensions to see if it makes a difference.

Also, although unlikely, I'm wondering if the call to Ping() is calling some other piece of code somewhere else.  Not likely, but you could try changing the Ping() function name to TestPing().

result = ThreadPool.QueueUserWorkItem(delegate { TestPing(item, url); });
  ... and ...
private static void TestPing(IPublishable item, Uri itemUrl)
Mar 16, 2009 at 2:57 PM
I tried the TestPing thing, no dice.

I also have only the standard BE.NET extensions installed except for the rtur.net commentator extension.  I disabled all except SendPings, still no luck.

...Matt
Coordinator
Mar 16, 2009 at 6:32 PM
Are trackbacks working from your other blog to this blog?  What if you use the SendPings.cs code from above on your other blog and write a blog post linking to the first blog we've been working with?  I'd be curious to see if we get the same output in the log file.

Even though you disabled extensions, if an error were to occur somewhere else, like in the newsletter widget (for example), that could potentially intefere with trackback sending (theoretically, at least).  Are you using the newsletter widget or any other widgets that do something when a post is saved?
Mar 16, 2009 at 8:19 PM
Going the other way, I get the same problem.  The 2 blogs are hosted by the same company, but on different domains.

On the one blog, I'm using the following widgets:
Admin
Search
Recent Posts
Tags
Categories
Blog Roll
Recent Comments
Page List
Text
Coordinator
Mar 16, 2009 at 8:52 PM
Those widgets look pretty safe.  Something's obviously not right ... I actually just tested the trackbacks again with two different BE installations I hadn't tested in my initial tests.  Trackbacks are working in both directions.

I'm running out of ideas (can you tell?) :)

This too probably wouldn't make a difference, but you could try adding a Thread.Sleep before TestPing() (or Ping()) is called.

ThreadPool.QueueUserWorkItem(delegate { Thread.Sleep(10000); TestPing(item, url); });

This would add a 10 second delay before calling TestPing().

The next option would be to bypass sending trackbacks on a separate thread.  So instead of ThreadPool.QueueUserWorkItem(), you could just call Ping() directly which I'm guessing would work.
Mar 16, 2009 at 9:55 PM
If I call Ping directly, I get this:

3/16/2009 2:39:14 PM - MSG = Determine if Ping stuff should be done.
3/16/2009 2:39:14 PM - MSG = Before add to ThreadPool
3/16/2009 2:39:14 PM - MSG = GetAvailableThreads 399 400
3/16/2009 2:39:14 PM - MSG = Before sleep
3/16/2009 2:39:16 PM - MSG = After sleep, before PingService
3/16/2009 2:39:21 PM - MSG = Is pingback/trackback enabled?
3/16/2009 2:39:21 PM - MSG = Check for link
3/16/2009 2:39:21 PM - MSG = After add to ThreadPool

This is definitely progress, and since post don't happen all too often, I think I can live with this.

However, the trackback is still not getting to the other blog.  The logs on my other blog still show no access to post to the log.
Coordinator
Mar 16, 2009 at 10:16 PM
Yes, that's definitely progress.  Does your blog entry have an actual <a> link to the other blog?  That's what the next line of code is checking for:

if (item.Content.ToUpperInvariant().Contains("\"HTTP"))

It's looking for "http (with a leading quotation mark).  So if your post contained:

<a href="http://linkToOtherBlogPost ....

Then that would be a match.  But if your post just has a url to the other blog without being in an <a> tag, that there wouldn't be a match.

You could add another RecordLog to see if the match is working:

            if (item.Content.ToUpperInvariant().Contains("\"HTTP"))
            {
                RecordLog(null, "Link found ... calling Manager.Send()");
                BlogEngine.Core.Ping.Manager.Send(item, itemUrl);
            }
            else
                RecordLog(null, "No link found.");

Once the code gets into Manager.Send(), it will extract that link from your post.  It will then fetch the blog post at that link to get trackback information.  If it gets trackback information, it will try sending a trackback.  With our modified SendPings.cs, we've subscribed to the Trackback.Sending and Trackback.Sent events.  Log records should get created when those events occur.  Here's my complete log below for a successful trackback.  It includes log records for a couple of other events I added last week.

3/16/2009 2:12:43 PM - MSG = Determine if Ping stuff should be done.
3/16/2009 2:12:43 PM - MSG = Before add to ThreadPool
3/16/2009 2:12:43 PM - MSG = Available threads before, workerThreads = 199, completionPortThreads = 200
3/16/2009 2:12:43 PM - MSG = Max threads before, workerThreads = 200, completionPortThreads = 200
3/16/2009 2:12:43 PM - MSG = Available threads after, workerThreads = 199, completionPortThreads = 200
3/16/2009 2:12:43 PM - MSG = Max threads after, workerThreads = 200, completionPortThreads = 200
3/16/2009 2:12:43 PM - MSG = After add to ThreadPool
3/16/2009 2:12:43 PM - MSG = ThreadPool result = True
3/16/2009 2:12:53 PM - MSG = Before sleep
3/16/2009 2:12:55 PM - MSG = After sleep, before PingService
3/16/2009 2:13:02 PM - MSG = Is pingback/trackback enabled?
3/16/2009 2:13:02 PM - MSG = Check for link
3/16/2009 2:13:02 PM - MSG = Link found ... calling Manager.Send()
3/16/2009 2:13:02 PM - MSG = Sending Trackback ... UrlToNotifyTrackback = http://localhost/blog/trackback.axd?id=9aa5311f-9a83-42ab-832d-6cefbff4f5e4
3/16/2009 2:13:02 PM - MSG = Sent Trackback ... UrlToNotifyTrackback = http://localhost/blog/trackback.axd?id=9aa5311f-9a83-42ab-832d-6cefbff4f5e4
Coordinator
Mar 17, 2009 at 2:11 AM
For the sake of completeness, I modifed the SendPings.cs code in the previous message (about 10 posts up from this one).  This new SendPings.cs file contains ALL the trackback and pingback sending code.  I copied it from the BlogEngine core into SendPings.cs.  I added a number of RecordLog() calls.  Try using the new SendPings.cs file.  It does all the sending itself, so we should be able to get a good idea what's going on.  The modified SendPings.cs doesn't use ThreadPool.QueueUserWorkItem, by the way.
Mar 17, 2009 at 2:11 AM
Since my log does not contain "No Link Found", I would assume that it's getting into Manager.Send(), but failing somewhere in there because I'm not getting the other events.

...Matt
Coordinator
Mar 17, 2009 at 2:12 AM
Wow, we just posted at the same time :)  You're right ... your log doesn't contain "No Link Found".  So please see my last message.
Mar 17, 2009 at 3:01 AM
Here's something weird...  I had the BE.NET source for 1.4.5 from back when I had to do a fix for syndacation.axd, so I modified Manager.cs.  When I built and uploaded that binary, it worked.  The trackback was sent.  When I put the original back (which I previously built from the exact same source), it stopped working.

Here's the log after your modified SendPings.cs

3/16/2009 7:58:23 PM - MSG = Determine if Ping stuff should be done.
3/16/2009 7:58:23 PM - MSG = Before calling Ping
3/16/2009 7:58:23 PM - MSG = Before PingService.Send()
3/16/2009 7:58:28 PM - MSG = Is pingback/trackback enabled?
3/16/2009 7:58:28 PM - MSG = Check for link
3/16/2009 7:58:28 PM - MSG = Link found ... calling SendTrackbacksAndPingbacks
3/16/2009 7:58:28 PM - MSG = Found 1 URLs in message
URL #1 - http://visual.houser.ca/post/2009/03/16/Review-Trivial-Pursuit-for-XBox-360.aspx
3/16/2009 7:58:28 PM - MSG = Trackback URL for http://visual.houser.ca/post/2009/03/16/Review-Trivial-Pursuit-for-XBox-360.aspx is http://visual.houser.ca/trackback.axd?id=0d1fc8f6-d4ff-4041-a894-99c9235f48ac
3/16/2009 7:58:28 PM - MSG = About to send trackback to http://visual.houser.ca/trackback.axd?id=0d1fc8f6-d4ff-4041-a894-99c9235f48ac
3/16/2009 7:58:28 PM - MSG = Sending trackback ... http://visual.houser.ca/trackback.axd?id=0d1fc8f6-d4ff-4041-a894-99c9235f48ac
3/16/2009 7:58:39 PM - MSG = Trackback sent status = False
3/16/2009 7:58:39 PM - MSG = About to send pingback for http://visual.houser.ca/post/2009/03/16/Review-Trivial-Pursuit-for-XBox-360.aspx
3/16/2009 7:58:39 PM - MSG = No pingback URL found for http://visual.houser.ca/post/2009/03/16/Review-Trivial-Pursuit-for-XBox-360.aspx
3/16/2009 7:58:39 PM - MSG = After calling Ping
Mar 17, 2009 at 3:03 AM
To add... I did get a POST /trackback.axd this time in my other blog's log.  But the trackback did not appear in the article.
Mar 17, 2009 at 3:23 AM
I also found that, when I print the content and it's as follows, your regex does not find the link:

3/16/2009 8:15:45 PM - MSG = Link found ... calling SendTrackbacksAndPingbacks
3/16/2009 8:15:45 PM - MSG = <p><a title="Review- Trivial Pursuit for XBox 360" href="http://visual.houser.ca/post/2009/03/16/Review-Trivial-Pursuit-for-XBox-360.aspx">Review- Trivial Pursuit for XBox 360</a></p>
3/16/2009 8:15:45 PM - MSG = Found 0 URLs in message

But modifying the post:

3/16/2009 8:19:27 PM - MSG = Link found ... calling SendTrackbacksAndPingbacks
3/16/2009 8:19:27 PM - MSG = <p><a href="http://visual.houser.ca/post/2009/03/16/Review-Trivial-Pursuit-for-XBox-360.aspx">Review- Trivial Pursuit for XBox 360</a></p>
3/16/2009 8:19:27 PM - MSG = Found 1 URLs in message

and this time:

3/16/2009 8:19:32 PM - MSG = Trackback sent status = True

It seems rather arbitrary whether it works or not.
Mar 17, 2009 at 3:27 AM
And now I know why my trackback didn't work with another blog (not mine)...

<?xml version="1.0" encoding="utf-8"?>
<response>
  <error>2</error>
  <message>Failed to save Trackback.</message>
</response>
Mar 17, 2009 at 3:33 AM
Edited Mar 17, 2009 at 3:34 AM
I think having some diagnostics like this in the release version (can be disabled/enabled) would be very good to log error responses from pings and trackbacks. It looks like pings and trackbacks don't always work for people and some diagnostics would be helpful.

...Matt
Coordinator
Mar 17, 2009 at 4:12 AM
Yeah, bringing in all the BE core code into SendPings.cs made this much easier.

Regarding the URL matching, that's a problem with the RegExp.  A better RegExp would get the URL correctly.  I just found one that works better ... it catches the URLs you posted that had "title" attributes in them.  I also noticed when going through all this (and saw in your log too) that the Pingback URL detection wasn't working because the pingback URL in the response header was X-Pingback, and BE was looking for x-pingback ... which is the same, except for it has upper and lower case characters.  It should do a case insensitive search.  That's why your log said "No pingback URL found for ...".  My log said that too.

It's possible the reason you got the "Failed to save Trackback" message was because of the problem I noticed back on March 9th (very top of this thread), where BE is prefixing the trackback data its sending with a ? (question mark).  After BE 1.5 is released (should be pretty soon), one of the changes I plan on making is removing that leading question mark.

I just modified the SendPings.cs code we've been working with.  The modified code removes the leading question mark.  It also contains the improved RegExp, and it also does a case-insensitive search for the Pingback URL.  The Pingback URL is only checked for if the trackback isn't sent successfully.  So if you have time and are curious, you could try using the modified SendPings.cs code above to see if the trackback to the other site works now that it doesn't include the leading question mark.

It's also possible too that with the better BE binary you have, that the strange ThreadPool.QueueUserWorkItem() problem might be gone now.  Or, that might be a separate issue ... not sure.
Mar 17, 2009 at 3:27 PM
The new code does not improve the trackback to the other blog.  It may be an issue on their end.

Also, I still cannot get it to work asynchonously.  For now, I can live with it being synchonous.

Thanks for your help,
...Matt
Mar 23, 2009 at 10:17 PM
Edited Mar 23, 2009 at 10:21 PM
I'have the same problem, the trackbacks aren't working.

When I use the script from BenAmada for sendpings.cs I get the following error: Compilerfehlermeldung: CS0101

Could you help me? thx ben

Mar 23, 2009 at 10:36 PM
lol, solved had a copie up!!! sry I'm new in .net