Где установить CookieContainer в Service Reference?

При добавлении WebService Reference к службе ASMX в проекте .NET 2.0, например,

var objService = new NameSpace.groupservices();

существует,

objService.CookieContainer = new System.Net.CookieContainer();

При добавлении ServiceReference к службе ASMX в проекте .NET 4.0, например,

var objService = new NameSpace.groupservicesSoapClient();

нет никакого свойства CookieContainer для objService

Аналогичный вопрос был задан здесь без положительного решения.

Может ли кто-нибудь указать, где найти свойство?

Ответ 1

В отличие от веб-служб ASMX, привязанных к транспорту HTTP, WCF позволяет использовать различные транспортные протоколы. Поэтому не все параметры протокола (такие как Cookies для HTTP-транспорта) доступны в справочной службе WCF.

Однако вы можете добавить инспектор сообщений, который проверяет сообщения, которые отправляются между клиентом и сервером. Этот article описывает способ отправки файлов cookie на сервер.

Я расширил образец, чтобы использовать CookieContainer. Кроме того, следующий код показывает, как оценить заголовок Set-Cookie, отправленный сервером, чтобы добавить новые куки файлы в контейнер. Обратите внимание, что образец показывает базовый контур, но может потребоваться расширение или еще одна проверка. Однако в простом сценарии это сработало.

В следующем фрагменте показан тестовый метод службы WCF, размещенный в IIS и интегрированный в структуру ASP.NET. Он в основном перекликается с файлами, отправленными на сервер в строке, и добавляет два новых:

public string GetData(int value)
{
    var reply = string.Join(", ", 
                    from x in HttpContext.Current.Request.Cookies.AllKeys 
                    select x + "=" + HttpContext.Current.Request.Cookies[x].Value);
    HttpContext.Current.Response.Cookies.Add(new HttpCookie("Test", "Test123"));
    HttpContext.Current.Response.Cookies.Add(new HttpCookie("Test2", "Test1234"));
    return reply;
}

Следующая тестовая программа создает CookieContainer для файлов cookie, добавляет демонстрационный файл cookie и регистрирует новое поведение для конечной точки службы:

class Program
{
    static void Main(string[] args)
    {
        var cookieCont = new CookieContainer();
        using(var svc = new TestServiceReference.TestServiceClient())
        {
            cookieCont.Add(svc.Endpoint.Address.Uri, new Cookie("TestClientCookie", "Cookie Value 123"));
            var behave = new CookieBehavior(cookieCont);
            svc.Endpoint.EndpointBehaviors.Add(behave);
            var data = svc.GetData(123);
            Console.WriteLine(data);
            Console.WriteLine("---");
            foreach (Cookie x in cookieCont.GetCookies(svc.Endpoint.Address.Uri))
                Console.WriteLine(x.Name + "=" + x.Value);
        }
        Console.ReadLine();
    }
}

Поведение служит для добавления персонализированного инспектора сообщений и передачи CookieContainer:

public class CookieBehavior : IEndpointBehavior
{
    private CookieContainer cookieCont;

    public CookieBehavior(CookieContainer cookieCont)
    {
        this.cookieCont = cookieCont;
    }

    public void AddBindingParameters(ServiceEndpoint serviceEndpoint,
        System.ServiceModel.Channels
        .BindingParameterCollection bindingParameters) { }

    public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint,
        System.ServiceModel.Dispatcher.ClientRuntime behavior)
    {
        behavior.MessageInspectors.Add(new CookieMessageInspector(cookieCont));
    }

    public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint,
        System.ServiceModel.Dispatcher
        .EndpointDispatcher endpointDispatcher) { }

    public void Validate(ServiceEndpoint serviceEndpoint) { }
}

Инспектор сообщений добавляет куки, когда запрос отправляется на сервер в методе BeforeSendRequest и извлекает куки, которые должны быть обновлены в методе AfterReceiveReply. Обратите внимание, что correlationState, возвращаемый BeforeSendRequest, используется для извлечения Uri в AfterReceiveReply:

public class CookieMessageInspector : IClientMessageInspector
{
    private CookieContainer cookieCont;

    public CookieMessageInspector(CookieContainer cookieCont)
    {
        this.cookieCont = cookieCont;
    }

    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,
        object correlationState) 
    {
        object obj;
        if (reply.Properties.TryGetValue(HttpResponseMessageProperty.Name, out obj))
        {
            HttpResponseMessageProperty httpResponseMsg = obj as HttpResponseMessageProperty;
            if (!string.IsNullOrEmpty(httpResponseMsg.Headers["Set-Cookie"]))
            {
                cookieCont.SetCookies((Uri)correlationState, httpResponseMsg.Headers["Set-Cookie"]);
            }
        }
    }

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
        System.ServiceModel.IClientChannel channel)
    {
        object obj;
        if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out obj))
        {
            HttpRequestMessageProperty httpRequestMsg = obj as HttpRequestMessageProperty;
            SetRequestCookies(channel, httpRequestMsg);
        }
        else
        {
            var httpRequestMsg = new HttpRequestMessageProperty();
            SetRequestCookies(channel, httpRequestMsg);
            request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMsg);
        }

        return channel.RemoteAddress.Uri;
    }

    private void SetRequestCookies(System.ServiceModel.IClientChannel channel, HttpRequestMessageProperty httpRequestMessage)
    {
        httpRequestMessage.Headers["Cookie"] = cookieCont.GetCookieHeader(channel.RemoteAddress.Uri);
    }
}

Ответ 2

Откройте файл app.config и добавьте allowCookies = "true" .

Что-то вроде этого:

<binding allowCookies="true" />