Было бы неплохо настроить мое приложение Windows Forms на платформу .NET 3.5 SP1 клиент. Но прямо сейчас я использую функции HttpUtility.HtmlDecode и HttpUtility.UrlDecode, и документация MSDN не указывает на какие-либо альтернативы внутри, скажем, System.Net или чего-то еще.
Итак, если не считать отражения исходного кода и его копирования в мою сборку - что, я не думаю, того стоит - есть ли альтернативы внутри клиентской инфраструктуры .NET 3.5 SP1, о которых вы знаете, для замены этого функциональность? Кажется немного странным, что они ограничили эти полезные функции только серверным кодом.





Пакет установки профиля клиента .NET 3.5 SP1 - это «урезанная» версия .NET, которая включает только то, что Microsoft считает «полезными» битами .NET для клиентских приложений. Итак, полезных вещей вроде классов HttpUtility нет.
Для получения дополнительной информации см. Блог ScottGu, найдите «Пакет установки профиля клиента».
Чтобы обойти это, вы всегда можете извлечь System.Web.dll из GAC (он будет в c:\windows\Microsoft.NET\Framework\ ...) и развернуть его с вашим приложением. Однако вам необходимо будет отслеживать обновления и пакеты обновления по мере развертывания.
Возможно, лучше было бы принять на себя удар полного развертывания .NET Framework.
Два основных способа:
Я настоятельно не рекомендую использовать собственную кодировку. Я бы использовал Библиотека сценариев Microsoft Anti-Cross Site Scripting Library, который очень маленький (v1.5 составляет ~ 30 КБ), если HttpUtility.HtmlEncode недоступен.
Что касается декодирования, может быть, вы могли бы использовать процедуру декодирования из Мононуклеоз?
Я перепроектировал класс Microsoft System.Net.WebUtility из .NET 4.0 с помощью Reflector (я думаю, что они с этим справятся, учитывая обстоятельства). Таким образом, вы можете либо использовать .NET 4.0 Client Framework (в котором теперь есть этот новый класс), либо использовать код здесь.
Пока вы используете строгое имя в своей сборке и т. д., Вы будете в достаточной безопасности. Здесь:
/// <summary>
/// Taken from System.Net in 4.0, useful until we move to .NET 4.0 - needed for Client Profile
/// </summary>
public static class WebUtility
{
// Fields
private static char[] _htmlEntityEndingChars = new char[] { ';', '&' };
// Methods
public static string HtmlDecode(string value)
{
if (string.IsNullOrEmpty(value))
{
return value;
}
if (value.IndexOf('&') < 0)
{
return value;
}
StringWriter output = new StringWriter(CultureInfo.InvariantCulture);
HtmlDecode(value, output);
return output.ToString();
}
public static void HtmlDecode(string value, TextWriter output)
{
if (value != null)
{
if (output == null)
{
throw new ArgumentNullException("output");
}
if (value.IndexOf('&') < 0)
{
output.Write(value);
}
else
{
int length = value.Length;
for (int i = 0; i < length; i++)
{
char ch = value[i];
if (ch == '&')
{
int num3 = value.IndexOfAny(_htmlEntityEndingChars, i + 1);
if ((num3 > 0) && (value[num3] == ';'))
{
string entity = value.Substring(i + 1, (num3 - i) - 1);
if ((entity.Length > 1) && (entity[0] == '#'))
{
ushort num4;
if ((entity[1] == 'x') || (entity[1] == 'X'))
{
ushort.TryParse(entity.Substring(2), NumberStyles.AllowHexSpecifier, (IFormatProvider)NumberFormatInfo.InvariantInfo, out num4);
}
else
{
ushort.TryParse(entity.Substring(1), NumberStyles.Integer, (IFormatProvider)NumberFormatInfo.InvariantInfo, out num4);
}
if (num4 != 0)
{
ch = (char)num4;
i = num3;
}
}
else
{
i = num3;
char ch2 = HtmlEntities.Lookup(entity);
if (ch2 != '\0')
{
ch = ch2;
}
else
{
output.Write('&');
output.Write(entity);
output.Write(';');
goto Label_0117;
}
}
}
}
output.Write(ch);
Label_0117: ;
}
}
}
}
public static string HtmlEncode(string value)
{
if (string.IsNullOrEmpty(value))
{
return value;
}
if (IndexOfHtmlEncodingChars(value, 0) == -1)
{
return value;
}
StringWriter output = new StringWriter(CultureInfo.InvariantCulture);
HtmlEncode(value, output);
return output.ToString();
}
public static unsafe void HtmlEncode(string value, TextWriter output)
{
if (value != null)
{
if (output == null)
{
throw new ArgumentNullException("output");
}
int num = IndexOfHtmlEncodingChars(value, 0);
if (num == -1)
{
output.Write(value);
}
else
{
int num2 = value.Length - num;
fixed (char* str = value)
{
char* chPtr = str;
char* chPtr2 = chPtr;
while (num-- > 0)
{
chPtr2++;
output.Write(chPtr2[0]);
}
while (num2-- > 0)
{
chPtr2++;
char ch = chPtr2[0];
if (ch <= '>')
{
switch (ch)
{
case '&':
{
output.Write("&");
continue;
}
case '\'':
{
output.Write("'");
continue;
}
case '"':
{
output.Write(""");
continue;
}
case '<':
{
output.Write("<");
continue;
}
case '>':
{
output.Write(">");
continue;
}
}
output.Write(ch);
continue;
}
if ((ch >= '\x00a0') && (ch < 'Ā'))
{
output.Write("&#");
output.Write(((int)ch).ToString(NumberFormatInfo.InvariantInfo));
output.Write(';');
}
else
{
output.Write(ch);
}
}
}
}
}
}
private static unsafe int IndexOfHtmlEncodingChars(string s, int startPos)
{
int num = s.Length - startPos;
fixed (char* str = s)
{
char* chPtr = str;
char* chPtr2 = chPtr + startPos;
while (num > 0)
{
char ch = chPtr2[0];
if (ch <= '>')
{
switch (ch)
{
case '&':
case '\'':
case '"':
case '<':
case '>':
return (s.Length - num);
case '=':
goto Label_0086;
}
}
else if ((ch >= '\x00a0') && (ch < 'Ā'))
{
return (s.Length - num);
}
Label_0086:
chPtr2++;
num--;
}
}
return -1;
}
// Nested Types
private static class HtmlEntities
{
// Fields
private static string[] _entitiesList = new string[] {
"\"-quot", "&-amp", "'-apos", "<-lt", ">-gt", "\x00a0-nbsp", "\x00a1-iexcl", "\x00a2-cent", "\x00a3-pound", "\x00a4-curren", "\x00a5-yen", "\x00a6-brvbar", "\x00a7-sect", "\x00a8-uml", "\x00a9-copy", "\x00aa-ordf",
"\x00ab-laquo", "\x00ac-not", "\x00ad-shy", "\x00ae-reg", "\x00af-macr", "\x00b0-deg", "\x00b1-plusmn", "\x00b2-sup2", "\x00b3-sup3", "\x00b4-acute", "\x00b5-micro", "\x00b6-para", "\x00b7-middot", "\x00b8-cedil", "\x00b9-sup1", "\x00ba-ordm",
"\x00bb-raquo", "\x00bc-frac14", "\x00bd-frac12", "\x00be-frac34", "\x00bf-iquest", "\x00c0-Agrave", "\x00c1-Aacute", "\x00c2-Acirc", "\x00c3-Atilde", "\x00c4-Auml", "\x00c5-Aring", "\x00c6-AElig", "\x00c7-Ccedil", "\x00c8-Egrave", "\x00c9-Eacute", "\x00ca-Ecirc",
"\x00cb-Euml", "\x00cc-Igrave", "\x00cd-Iacute", "\x00ce-Icirc", "\x00cf-Iuml", "\x00d0-ETH", "\x00d1-Ntilde", "\x00d2-Ograve", "\x00d3-Oacute", "\x00d4-Ocirc", "\x00d5-Otilde", "\x00d6-Ouml", "\x00d7-times", "\x00d8-Oslash", "\x00d9-Ugrave", "\x00da-Uacute",
"\x00db-Ucirc", "\x00dc-Uuml", "\x00dd-Yacute", "\x00de-THORN", "\x00df-szlig", "\x00e0-agrave", "\x00e1-aacute", "\x00e2-acirc", "\x00e3-atilde", "\x00e4-auml", "\x00e5-aring", "\x00e6-aelig", "\x00e7-ccedil", "\x00e8-egrave", "\x00e9-eacute", "\x00ea-ecirc",
"\x00eb-euml", "\x00ec-igrave", "\x00ed-iacute", "\x00ee-icirc", "\x00ef-iuml", "\x00f0-eth", "\x00f1-ntilde", "\x00f2-ograve", "\x00f3-oacute", "\x00f4-ocirc", "\x00f5-otilde", "\x00f6-ouml", "\x00f7-divide", "\x00f8-oslash", "\x00f9-ugrave", "\x00fa-uacute",
"\x00fb-ucirc", "\x00fc-uuml", "\x00fd-yacute", "\x00fe-thorn", "\x00ff-yuml", "Œ-OElig", "œ-oelig", "Š-Scaron", "š-scaron", "Ÿ-Yuml", "ƒ-fnof", "ˆ-circ", "˜-tilde", "Α-Alpha", "Β-Beta", "Γ-Gamma",
"Δ-Delta", "Ε-Epsilon", "Ζ-Zeta", "Η-Eta", "Θ-Theta", "Ι-Iota", "Κ-Kappa", "Λ-Lambda", "Μ-Mu", "Ν-Nu", "Ξ-Xi", "Ο-Omicron", "Π-Pi", "Ρ-Rho", "Σ-Sigma", "Τ-Tau",
"Υ-Upsilon", "Φ-Phi", "Χ-Chi", "Ψ-Psi", "Ω-Omega", "α-alpha", "β-beta", "γ-gamma", "δ-delta", "ε-epsilon", "ζ-zeta", "η-eta", "θ-theta", "ι-iota", "κ-kappa", "λ-lambda",
"μ-mu", "ν-nu", "ξ-xi", "ο-omicron", "π-pi", "ρ-rho", "ς-sigmaf", "σ-sigma", "τ-tau", "υ-upsilon", "φ-phi", "χ-chi", "ψ-psi", "ω-omega", "ϑ-thetasym", "ϒ-upsih",
"ϖ-piv", " -ensp", " -emsp", " -thinsp", "-zwnj", "-zwj", "-lrm", "-rlm", "–-ndash", "—-mdash", "‘-lsquo", "’-rsquo", "‚-sbquo", "“-ldquo", "”-rdquo", "„-bdquo",
"†-dagger", "‡-Dagger", "•-bull", "…-hellip", "‰-permil", "′-prime", "″-Prime", "‹-lsaquo", "›-rsaquo", "‾-oline", "⁄-frasl", "€-euro", "ℑ-image", "℘-weierp", "ℜ-real", "™-trade",
"ℵ-alefsym", "←-larr", "↑-uarr", "→-rarr", "↓-darr", "↔-harr", "↵-crarr", "⇐-lArr", "⇑-uArr", "⇒-rArr", "⇓-dArr", "⇔-hArr", "∀-forall", "∂-part", "∃-exist", "∅-empty",
"∇-nabla", "∈-isin", "∉-notin", "∋-ni", "∏-prod", "∑-sum", "−-minus", "∗-lowast", "√-radic", "∝-prop", "∞-infin", "∠-ang", "∧-and", "∨-or", "∩-cap", "∪-cup",
"∫-int", "∴-there4", "∼-sim", "≅-cong", "≈-asymp", "≠-ne", "≡-equiv", "≤-le", "≥-ge", "⊂-sub", "⊃-sup", "⊄-nsub", "⊆-sube", "⊇-supe", "⊕-oplus", "⊗-otimes",
"⊥-perp", "⋅-sdot", "⌈-lceil", "⌉-rceil", "⌊-lfloor", "⌋-rfloor", "〈-lang", "〉-rang", "◊-loz", "♠-spades", "♣-clubs", "♥-hearts", "♦-diams"
};
private static Dictionary<string, char> _lookupTable = GenerateLookupTable();
// Methods
private static Dictionary<string, char> GenerateLookupTable()
{
Dictionary<string, char> dictionary = new Dictionary<string, char>(StringComparer.Ordinal);
foreach (string str in _entitiesList)
{
dictionary.Add(str.Substring(2), str[0]);
}
return dictionary;
}
public static char Lookup(string entity)
{
char ch;
_lookupTable.TryGetValue(entity, out ch);
return ch;
}
}
}
Сегодня обнаружил из этот вот маленький сайт, что HtmlEncode / Decode может быть выполнен с использованием библиотеки System.Net в профиле клиента C# 4.0:
Uri.EscapeDataString(...)
WebUtility.HtmlEncode(...)
Обновлено: я перечитал, что вопрос относился к 3.5 Client Framework, но, возможно, это может быть полезно тем, кто обновил 4.0 ..
Uri.EscapeDataString был тем, что мне было нужно, и этот является в профиле клиента 3.5, спасибо!
Видимо гугл тоже не смог его найти, поэтому написали там собственную api-совместимую версию:
Вот обходной путь:
Скомпилировать версию Google как библиотеку
wget 'http://google-gdata.googlecode.com/svn/trunk/clients/cs/src/core/HttpUtility.cs'
gmcs -t:library HttpUtility.cs
Отредактируйте your-project.cs, чтобы включить это пространство имен
using Google.GData.Client; // where HttpUtility lives
Перекомпилируйте с помощью библиотеки
gmcs your-project.cs -r:System.Web.Services -r:System.Web -r:HttpUtility
Взглянув на исходный код, можно сделать вывод, что он совместим с .NET 2.0.
Я только вчера написал свой первый привет, мир в csharp и столкнулся с этой проблемой, так что надеюсь, что это поможет кому-то другому.
Согласно комментарию в верхней части файла, похоже, что они использовали Mono.
Лучшее решение этой проблемы! Спасибо!
При обращении к телефон с операционной системой Виндоуси в мире Рабочий стол (Профиль клиента!) Самый быстрый способ, который я нашел, это:
private static string HtmlDecode(string text)
{
#if WINDOWS_PHONE
return System.Net.HttpUtility.HtmlDecode(text);
#else
return System.Net.WebUtility.HtmlDecode(text);
#endif
}
Для меня странным было то, что пространство имен - System.Net, но имя класса отличается в мире телефон с операционной системой Виндоус ... (не люблю использовать System.Web / полный профиль, когда он действительно не нужен, а System.Web не поддерживается на платформу Windows Phone в любом случае ...)
Как человек, использующий .NET, я действительно нашел это полезным. Спасибо!