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:
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;
}
}
}