سؤال

أنا محتار كيف CookieContainer مقابض المجال ، لذلك أنا خلق هذا الاختبار.هذا الاختبار يبين cookieContainer لا عودة أي بسكويت "example.com" ولكن وفقا RFC ينبغي أن يعود على الأقل 2 ملفات تعريف الارتباط.

أليس هذا الخلل ؟

كيف تجعل من العمل ؟

هنا يتم نقاش عن هذا الخطأ:

http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/c4edc965-2dc2-4724-8f08-68815cf1dce6

<%@ Page Language="C#" %>

<%@ Import Namespace="System.Net" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    CookieContainer getContainer()
    {
        CookieContainer result = new CookieContainer();

        Uri uri = new Uri("http://sub.example.com");
        string cookieH = @"Test1=val; domain=sub.example.com; path=/";
        result.SetCookies(uri, cookieH);

        cookieH = @"Test2=val; domain=.example.com; path=/";
        result.SetCookies(uri, cookieH);

        cookieH = @"Test3=val; domain=example.com; path=/";
        result.SetCookies(uri, cookieH);

        return result;
    }

    void Test()
    {
        CookieContainer cookie = getContainer();
        lblResult.Text += "<br>Total cookies count: " + cookie.Count + " &nbsp;&nbsp; expected: 3";

        Uri uri = new Uri("http://sub.example.com");
        CookieCollection coll = cookie.GetCookies(uri);
        lblResult.Text += "<br>For " + uri + " Cookie count: " + coll.Count + " &nbsp;&nbsp; expected: 2";

        uri = new Uri("http://other.example.com");
        coll = cookie.GetCookies(uri);
        lblResult.Text += "<br>For " + uri + " Cookie count: " + coll.Count + " &nbsp;&nbsp; expected: 2";

        uri = new Uri("http://example.com");
        coll = cookie.GetCookies(uri);
        lblResult.Text += "<br>For " + uri + " Cookie count: " + coll.Count + " &nbsp;&nbsp; expected: 2";

    }

    protected void Page_Load(object sender, EventArgs e)
    {
        Test();
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>CookieContainer Test Page</title>
</head>
<body>
    <form id="frmTest" runat="server">
    <asp:Label ID="lblResult" EnableViewState="false" runat="server"></asp:Label>
    </form>
</body>
</html>
هل كانت مفيدة؟

المحلول

أنا فقط وجدت إصلاح هذا الخلل و مناقشتها هنا:http://dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html

هنا هو الحل:

  1. لا تستخدم .إضافة(كوكي) ، استخدم فقط .إضافة(Uri, كوكي) الأسلوب.
  2. دعوة BugFix_CookieDomain في كل مرة قمت بإضافة ملف تعريف الارتباط إلى الحاوية أو قبل استخدام .GetCookie أو قبل نظام استخدام الحاوية.

    private void BugFix_CookieDomain(CookieContainer cookieContainer)
    {
        System.Type _ContainerType = typeof(CookieContainer);
        Hashtable table = (Hashtable)_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];
            }
        }
    }
    

نصائح أخرى

//bug fix, exists only in 3.5 FW, please wrap it with defines
//http://dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html
if(!value.Contains("://www.")) //we are going to hit the bug
{
    string urlWWW = value.Replace("://", "://www.");
    Uri uriWWW = new Uri(urlWWW);
    foreach (Cookie c in _cookieContainer.GetCookies(uriWWW))
        if (c.Domain.StartsWith("."))
            request.Headers["Cookies"] += c.Name + "=" + c.Value + ";"; //manually add the cookies
}
//~bug fix

وفقدت يوم لي مع هذه القضية. لم استجابة CallMeLaNN لن يساعدني (أنا باستخدام صافي 4.5). في حالتي كانت المشكلة في الترتيب من حيث وضع جسد الطلب وإعدادات ملفات تعريف الارتباط.

في هذه الحالة لن يتم إرسال الكوكيز لالخادم:

            var response = (HttpWebRequest)WebRequest.Create("http://localhost:4433/");

            using (var requestStream = response.GetRequestStream())
            {
               using (var streamWriter = new StreamWriter(requestStream))
               {
                    requestStream.Write(RequestContent);
               }
            }

            response.CookieContainer.Add(new Cookie("Name", "Value"));
            await response.GetResponseAsync();

لجعلها تعمل تغيير ترتيب مطلوب:

            var response = (HttpWebRequest)WebRequest.Create("http://localhost:4433/");

            response.CookieContainer.Add(new Cookie("Name", "Value"));
            await response.GetResponseAsync();

            using (var requestStream = response.GetRequestStream())
            {
               using (var streamWriter = new StreamWriter(requestStream))
               {
                    requestStream.Write(RequestContent);
               }
            }

ولقد خلقت إصلاح لهذه المشكلة التي يعمل على ويندوز 10 تطبيقات / UWP / كور .NET. المسألة هي أن الأجزاء الداخلية لCookieContainer مختلفة، ولكن فقط كربي كما، لأنها في .NET Framework السليم. وبالتالي فإن الحل المقبول لا تعمل بعد الان.

ولكن بدلا من "إصلاح" في CookieContainer، وأنا كتبت للتو نسخة من GetCookies() أن يحصل على كافة ملفات تعريف الارتباط لمجال معين مع سلسلة، بغض النظر عن الدولة "آمنة" أو إذا كانت مسبوقة أنها مع نقطة. لا تتردد في تعديله النحو الذي تراه مناسبا لاحتياجاتك، وسوف نرى في الحصول على نسخة منه تنفيذها في المستقبل بيان. NET الأساسية.

using System.Collections.Generic;
using System.Reflection;

namespace System.Net
{

    /// <summary>
    /// Contains extensions for the <see cref="CookieContaner"/> class.
    /// </summary>
    public static class CookieContainerExtensions
    {

        /// <summary>
        /// Uses Reflection to get ALL of the <see cref="Cookie">Cookies</see> where <see cref="Cookie.Domain"/> 
        /// contains part of the specified string. Will return cookies for any subdomain, as well as dotted-prefix cookies. 
        /// </summary>
        /// <param name="cookieContainer">The <see cref="CookieContainer"/> to extract the <see cref="Cookie">Cookies</see> from.</param>
        /// <param name="domain">The string that contains part of the domain you want to extract cookies for.</param>
        /// <returns></returns>
        public static IEnumerable<Cookie> GetCookies(this CookieContainer cookieContainer, string domain)
        {
            var domainTable = GetFieldValue<dynamic>(cookieContainer, "_domainTable");
            foreach (var entry in domainTable)
            {
                string key = GetPropertyValue<string>(entry, "Key");

                if (key.Contains(domain))
                {
                    var value = GetPropertyValue<dynamic>(entry, "Value");

                    var internalList = GetFieldValue<SortedList<string, CookieCollection>>(value, "_list");
                    foreach (var li in internalList)
                    {
                        foreach (Cookie cookie in li.Value)
                        {
                            yield return cookie;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Gets the value of a Field for a given object instance.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/> you want the value to be converted to when returned.</typeparam>
        /// <param name="instance">The Type instance to extract the Field's data from.</param>
        /// <param name="fieldName">The name of the Field to extract the data from.</param>
        /// <returns></returns>
        internal static T GetFieldValue<T>(object instance, string fieldName)
        {
            BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
            FieldInfo fi = instance.GetType().GetField(fieldName, bindFlags);
            return (T)fi.GetValue(instance);
        }

        /// <summary>
        /// Gets the value of a Property for a given object instance.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/> you want the value to be converted to when returned.</typeparam>
        /// <param name="instance">The Type instance to extract the Property's data from.</param>
        /// <param name="propertyName">The name of the Property to extract the data from.</param>
        /// <returns></returns>
        internal static T GetPropertyValue<T>(object instance, string propertyName)
        {
            var pi = instance.GetType().GetProperty(propertyName);
            return (T)pi.GetValue(instance, null);
        }

    }

}

وهنا هو الإختراق للالتفاف على هذه الأخطاء: http://social.microsoft. كوم / منتديات / EN-US / netfxnetcom / موضوع / 1297afc1-12d4-4d75-8d3f-7563222d234c ويستخدم التفكير.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top