Windows Phone 7 Mango保存一个cookicontainer的状态
本文关键字:一个 cookicontainer 状态 Phone Mango 保存 Windows | 更新日期: 2023-09-27 18:09:38
update1:经过更多的研究,我不确定这是可能的,我创建了一个UserVoice条目来修复它。
我试图保存CookieContainer在应用程序退出或墓碑发生时,但我遇到了一些问题。
我尝试在AppSettings中保存CookieContainer,但是当加载时,cookie消失了。
Researching this internally, DataContractSerializer cannot serialize cookies.
This seems to be a behavior that Windows Phone inherited from Silverlight's DataContractSerializer.
在做了更多的研究之后,似乎解决办法是从容器中抓取饼干并以另一种方式保存它们。在我遇到另一个问题之前,一切都很顺利。我无法用。mydomain.com的Uri获取cookie。我想是因为这个虫子。我可以在domaintable中看到cookie。mydomain.com,但是GetCookies对特定的cookie不起作用。
这个错误在这里再次发布。
从容器中取出饼干也有一个问题当域以。:
开头时
CookieContainer container = new CookieContainer();
container.Add(new Cookie("x", "1", "/", ".blah.com"));
CookieCollection cv = container.GetCookies(new Uri("http://blah.com"));
cv = container.GetCookies(new Uri("http://w.blah.com"));
我找到了一个工作,使用反射来迭代domaintable并删除'。"前缀。
private void BugFix_CookieDomain(CookieContainer cookieContainer)
{
System.Type _ContainerType = typeof(CookieContainer);
var = _ContainerType.InvokeMember("m_domainTable",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.GetField |
System.Reflection.BindingFlags.Instance,
null,
cookieContainer,
new object[] { });
ArrayList keys = new ArrayList(table.Keys);
foreach (string keyObj in keys)
{
string key = (keyObj as string);
if (key[0] == '.')
{
string newKey = key.Remove(0, 1);
table[newKey] = table[keyObj];
}
}
}
只有当InvokeMember被调用时,在SL中抛出了一个MethodAccessException。这并不能真正解决我的问题,因为我需要保留的cookie之一是HttpOnly,这是CookieContainer的原因之一。
如果服务器发送HTTPOnly cookie,您应该创建一个System.Net.CookieContainer上保存cookie的请求,尽管您将无法看到或访问这些cookie
有什么想法吗?我是不是错过了什么简单的东西?是否有另一种方法来保存状态的CookieContainer或我需要保存用户信息,包括密码和重新认证他们每次应用程序启动,当从墓碑回来?
我已经专门编写了一个CookieSerializer来解决这个问题。序列化器粘贴在下面。对于一个工作的项目和场景,请访问项目的CodePlex站点。
public static class CookieSerializer
{
/// <summary>
/// Serializes the cookie collection to the stream.
/// </summary>
/// <param name="cookies">You can obtain the collection through your <see cref="CookieAwareWebClient">WebClient</see>'s <code>CookieContainer.GetCookies(Uri)</code>-method.</param>
/// <param name="address">The <see cref="Uri">Uri</see> that produced the cookies</param>
/// <param name="stream">The stream to which to serialize</param>
public static void Serialize(CookieCollection cookies, Uri address, Stream stream)
{
using (var writer = new StreamWriter(stream))
{
for (var enumerator = cookies.GetEnumerator(); enumerator.MoveNext();)
{
var cookie = enumerator.Current as Cookie;
if (cookie == null) continue;
writer.WriteLine(address.AbsoluteUri);
writer.WriteLine(cookie.Comment);
writer.WriteLine(cookie.CommentUri == null ? null : cookie.CommentUri.AbsoluteUri);
writer.WriteLine(cookie.Discard);
writer.WriteLine(cookie.Domain);
writer.WriteLine(cookie.Expired);
writer.WriteLine(cookie.Expires);
writer.WriteLine(cookie.HttpOnly);
writer.WriteLine(cookie.Name);
writer.WriteLine(cookie.Path);
writer.WriteLine(cookie.Port);
writer.WriteLine(cookie.Secure);
writer.WriteLine(cookie.Value);
writer.WriteLine(cookie.Version);
}
}
}
/// <summary>
/// Deserializes <see cref="Cookie">Cookie</see>s from the <see cref="Stream">Stream</see>,
/// filling the <see cref="CookieContainer">CookieContainer</see>.
/// </summary>
/// <param name="stream">Stream to read</param>
/// <param name="container">Container to fill</param>
public static void Deserialize(Stream stream, CookieContainer container)
{
using (var reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
var uri = Read(reader, absoluteUri => new Uri(absoluteUri, UriKind.Absolute));
var cookie = new Cookie();
cookie.Comment = Read(reader, comment => comment);
cookie.CommentUri = Read(reader, absoluteUri => new Uri(absoluteUri, UriKind.Absolute));
cookie.Discard = Read(reader, bool.Parse);
cookie.Domain = Read(reader, domain => domain);
cookie.Expired = Read(reader, bool.Parse);
cookie.Expires = Read(reader, DateTime.Parse);
cookie.HttpOnly = Read(reader, bool.Parse);
cookie.Name = Read(reader, name => name);
cookie.Path = Read(reader, path => path);
cookie.Port = Read(reader, port => port);
cookie.Secure = Read(reader, bool.Parse);
cookie.Value = Read(reader, value => value);
cookie.Version = Read(reader, int.Parse);
container.Add(uri, cookie);
}
}
}
/// <summary>
/// Reads a value (line) from the serialized file, translating the string value into a specific type
/// </summary>
/// <typeparam name="T">Target type</typeparam>
/// <param name="reader">Input stream</param>
/// <param name="translator">Translation function - translate the read value into
/// <typeparamref name="T"/> if the read value is not <code>null</code>.
/// <remarks>If the target type is <see cref="Uri">Uri</see> , the value is considered <code>null</code> if it's an empty string.</remarks> </param>
/// <param name="defaultValue">The default value to return if the read value is <code>null</code>.
/// <remarks>The translation function will not be called for null values.</remarks></param>
/// <returns></returns>
private static T Read<T>(TextReader reader, Func<string, T> translator, T defaultValue = default(T))
{
var value = reader.ReadLine();
if (value == null)
return defaultValue;
if (typeof(T) == typeof(Uri) && String.IsNullOrEmpty(value))
return defaultValue;
return translator(value);
}
}
在WP7中,即使使用反射,也不能访问程序集之外的私有成员。这是一种安全措施,确保你不能调用内部系统api。
看来你运气不好。