martes, 5 de marzo de 2013

Error corrector ortográfico de Umbraco

Sintomas

Si intentas utilizar el corrector ortográfico del editor de texto enriquecido de Umbraco (Versión 6) te salta un error.
[ArgumentOutOfRangeException: El índice y la longitud deben hacer referencia a una ubicación en la cadena.
( Index and length must refer to a location within the string)

Solución: 

La solución está esbozada en: http://our.umbraco.org/forum/ourumb-dev-forum/bugs/28540-4711-spell-check-in-RTE.
Lo único que añado en este post son las instrucciones "Using" que faltan en el código del controlador genérico.

Básicamente es:
1.- Modificar /config/tinyMceConfig.config con la línea:
<config key="spellchecker_rpc_url">GSpellChecker.ashx</config>

Y agregar un controlador genérico: /umbraco/GSpellChecker.ashx
using System;
using System.Web;
using umbraco.presentation.umbraco_client.tinymce3.plugins.spellchecker;
using System.Xml;
using System.IO;
using System.Web.Script.Serialization;
using System.Net;
using System.Text;
public class GSpellChecker : SpellChecker, IHttpHandler {
  // Methods
  public override SpellCheckerResult CheckWords(string language, string[] words) {
    XmlDocument document = new XmlDocument();
    string data = string.Join(" ", words);
    string xml = SendRequest(language, data);
    document.LoadXml(xml);
    data = HttpContext.Current.Server.UrlEncode(data);
    SpellCheckerResult result = new SpellCheckerResult();
    foreach (XmlNode node in document.SelectNodes("//c")) {
      XmlElement element = (XmlElement)node;
      result.result.Add(data.Substring(Convert.ToInt32(element.GetAttribute("o")), Convert.ToInt32(element.GetAttribute("l"))));
    }
    return result;
  }

  public override SpellCheckerResult GetSuggestions(string language, string word) {
    XmlDocument document = new XmlDocument();
    string xml = SendRequest(language, word);
    document.LoadXml(xml);
    SpellCheckerResult result = new SpellCheckerResult();
    foreach (XmlNode node in document.SelectNodes("//c")) {
      XmlElement element = (XmlElement)node;
      foreach (string str2 in element.InnerText.Split(new char[] { '\t' })) {
        if (!string.IsNullOrEmpty(str2)) {
          result.result.Add(str2);
        }
      }
    }
    return result;
  }

  public void ProcessRequest(HttpContext context) {
    SpellCheckerInput input = SpellCheckerInput.Parse(new StreamReader(context.Request.InputStream));
    SpellCheckerResult suggestions = null;
    string method = input.Method;
    if (method != null) {
      if (!(method == "checkWords")) {
        if (method == "getSuggestions") {
          suggestions = this.GetSuggestions(input.Language, input.Words[0]);
          goto Label_007C;
        }
      } else {
        suggestions = this.CheckWords(input.Language, input.Words.ToArray());
        goto Label_007C;
      }
    }
    suggestions = new SpellCheckerResult();
  Label_007C:
    suggestions.id = input.Id;
    string s = new JavaScriptSerializer().Serialize(suggestions);
    context.Response.Write(s);
  }

  private static string SendRequest(string lang, string data) {
    string str;
    string requestUriString = string.Format("https://www.google.com:443/tbproxy/spell?lang={0}&hl={0}", lang);
    string s = string.Format("<?xml version=\"1.0\" encoding=\"utf-8\" ?><spellrequest textalreadyclipped=\"0\" ignoredups=\"0\" ignoredigits=\"1\" ignoreallcaps=\"1\"><text>{0}</text></spellrequest>", HttpContext.Current.Server.UrlEncode(data));
    StreamReader reader = null;
    HttpWebResponse response = null;
    Stream requestStream = null;
    try {
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUriString);
      request.KeepAlive = false;
      request.Method = "POST";
      request.ContentType = "application/PTI26";
      request.ContentLength = s.Length;
      WebHeaderCollection headers = request.Headers;
      headers.Add("MIME-Version: 1.0");
      headers.Add("Request-number: 1");
      headers.Add("Document-type: Request");
      headers.Add("Interface-Version: Test 1.4");
      requestStream = request.GetRequestStream();
      byte[] bytes = new ASCIIEncoding().GetBytes(s);
      requestStream.Write(bytes, 0, bytes.Length);
      response = (HttpWebResponse)request.GetResponse();
      reader = new StreamReader(response.GetResponseStream());
      str = reader.ReadToEnd();
    } finally {
      if (requestStream != null) {
        requestStream.Close();
      }
      if (reader != null) {
        reader.Close();
      }
      if (response != null) {
        response.Close();
      }
    }
    return str;
  }

  // Properties
  public bool IsReusable {
    get {
      return false;
    }
  }
}

No hay comentarios: