Issue with adding multiple cookies to Response in WCF service
I've managed to add multiple cookies in the WCF service outgoing response by adding "Set-Cookie" attribute in the response header. It works great and the cookie is available in all subsequent requests only if there is one cookie but not for multiple cookies.Please refer my below implementation. I'm adding the cookies into the response header by implementing IDispatchMessageInspector interface in order to add cookies in all WCF service method calls if there any pending cookies to be updated in the response.
Sample of Cookies output in the response header and request header
1 Cookie: foo=testcookie1; path=/ --> available in all the subsequent request calls 2 or more cookies: foo=testcookie1; path=/;, foo2=testcookie2; path=/;, foo3=testcookie3; path=/; --> --> only the first cookie available in all the subsequent request calls but not others
For example:
after the setting the cookies, my response header will look like Set-Cookie: foo1=testcookie1;,foo2=testcookie2;, foo3=testcookie3;. If I make another request then the request header cookie contains only foo1=testcookie1; but not these cookies foo2=testcookie2; foo3=testcookie3;. This is where the issue comes. If I set more than one cookie in the response header then it always takes only the first cookie in the subsequent request call.
Please help me to resolve this issue. Thanks in advance for your kind replies.
IMPLEMENTATION
public class CookieManagerServiceBehaviorAttribute : Attribute, IServiceBehavior
{
#region IServiceBehavior Members
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channelDispatch in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatch in channelDispatch.Endpoints)
{
endpointDispatch.DispatchRuntime.MessageInspectors.Add(CookieManagerMessageInspector.Instance);
}
}
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
return;
}
#endregion
}
public class CookieManagerMessageInspector : IDispatchMessageInspector
{
private static CookieManagerMessageInspector instance;
private CookieManagerMessageInspector() { }
public static CookieManagerMessageInspector Instance
{
get
{
if (instance == null)
{
instance = new CookieManagerMessageInspector();
}
return instance;
}
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
HttpResponseMessageProperty httpResponse;
if (!reply.Properties.ContainsKey(HttpResponseMessageProperty.Name))
{
reply.Properties.Add(HttpResponseMessageProperty.Name, new HttpResponseMessageProperty());
}
httpResponse = (HttpResponseMessageProperty)reply.Properties[HttpResponseMessageProperty.Name];
foreach (Cookie cookie in RenderContext.Current.PendingCookies)
{
if (cookie.Expi开发者_如何学Gores > DateTime.Now)
httpResponse.Headers.Add(HttpResponseHeader.SetCookie, "{0}={1}; expires={2}".StringFormat(cookie.Name, cookie.Value, DateTime.Now.AddYears(1).ToUniversalTime()) + ";");
else
httpResponse.Headers.Add(HttpResponseHeader.SetCookie, "{0}={1};".StringFormat(cookie.Name, cookie.Value));
}
}
}
While building a web proxy I ran into the same problem. I needed to relay the Set-Cookie header from the target HttpWebResponse to the proxy HttpListenerResponse. If there were multiple cookies in the Set-Cookie header then only the first one would register in the browser.
I was able to get it to work when I iterated through the set of values of the header (or in your case the collection of Cookies) and used the response.AppendHeader(header, value) form.
string[] cookies = response.Headers.GetValues("Set-Cookie");
foreach (string value in cookies)
clientResponse.AppendHeader("Set-Cookie", value);
So in your case I would change the end of your code to:
if (cookie.Expires > DateTime.Now)
httpResponse.AppendHeader(HttpResponseHeader.SetCookie, "{0}={1}; expires={2}".StringFormat(cookie.Name, cookie.Value, DateTime.Now.AddYears(1).ToUniversalTime()) + ";");
else
httpResponse.AppendHeader(HttpResponseHeader.SetCookie, "{0}={1};".StringFormat(cookie.Name, cookie.Value));
精彩评论