Set Cookie for UIWebView requests
Asked Answered
Q

5

5

I want to embed an UIWebView into my MonoTouch application for an area that is not yet implemented natively.

In order to authenticate with the website I want to set a cookie containing a key for the current session.

I tried creating a NSDictionary with the properties for the Cookie and then create a new NSHttpCookie and add it to the NSHttpCookieStorage.SharedStorage.

Sadly the cookie seems to be empty and not used for the request.

An example of how to build be cookie with properties and a comment on whether or not this is the simplest way to do this would be greatly appreciated.

Quezada answered 22/2, 2012 at 14:29 Comment(0)
V
3

Whenever I need to send cookies and params up to the server I use something like RestSharp or Hammock and then pass the response.Content value into UIWebView's loadHtmlString method:

//setup cookies and params here
var response = client.Execute(req);
_webView = new UIWebView();
_webView.LoadHtmlString(response.Content, new NSUrl(baseUrl));

The NSDictionary API is fairly trivial too:

var props = new NSMutableDictionary ();
props.Add (NSHttpCookie.KeyOriginURL, new
NSString("http://yodawg.com"));
props.Add (NSHttpCookie.KeyName, new NSString("iherd"));
props.Add (NSHttpCookie.KeyValue, new NSString("ulikecookies"));
props.Add (NSHttpCookie.KeyPath, new NSString("/"));
Vexillum answered 22/2, 2012 at 19:8 Comment(6)
This throws an ArgumentNullException when adding the cookie to the storage, because the cookie returned with your code is null.Quezada
It seems I found a bug on the NSHttpCookie binding! I filed it. I'm also updating the answer with a workaround.Vexillum
Thanks, I will have an eye on the bug report and try your solution.Quezada
Ok, I tried yours, and the cookie gets created as expected. I am using localhost as OriginURL (and some reverse proxy to inspect the requests), but the server never receives the cookie. So I looked at NSHttpCookieStorage.SharedStorage.Cookies and it just contains two cookies from Google, nothing more. Any ideas?Quezada
So, I had to use http:// in the OriginURL and set the path, otherwise it wouldn't be added to the cookie storage.Quezada
Yep, updated code to reflect working path. Now you see why it's so much easier to use RestSharp to do the request? ;-)Vexillum
F
7

Following Anuj's bug report I felt bad about how many lines of code were required to create the cookies. So the next MonoTouch versions will have new constructors for NSHttpCookie, similar to System.Net.Cookie that will allow you do to something like:

// this ctor requires all mandatory parameters 
// so you don't have to guess them while coding
var cookie = new NSHttpCookie ("iherd", "ulikecookies", "/", "yodawg.com");

You'll even be able to create a NSHttpCookie from a .NET System.Net.Cookie.

Note: Never hesitate to fill a bug report when an API proves to be way more complicated than it should be :-)

Fluorene answered 23/2, 2012 at 16:25 Comment(0)
V
3

Whenever I need to send cookies and params up to the server I use something like RestSharp or Hammock and then pass the response.Content value into UIWebView's loadHtmlString method:

//setup cookies and params here
var response = client.Execute(req);
_webView = new UIWebView();
_webView.LoadHtmlString(response.Content, new NSUrl(baseUrl));

The NSDictionary API is fairly trivial too:

var props = new NSMutableDictionary ();
props.Add (NSHttpCookie.KeyOriginURL, new
NSString("http://yodawg.com"));
props.Add (NSHttpCookie.KeyName, new NSString("iherd"));
props.Add (NSHttpCookie.KeyValue, new NSString("ulikecookies"));
props.Add (NSHttpCookie.KeyPath, new NSString("/"));
Vexillum answered 22/2, 2012 at 19:8 Comment(6)
This throws an ArgumentNullException when adding the cookie to the storage, because the cookie returned with your code is null.Quezada
It seems I found a bug on the NSHttpCookie binding! I filed it. I'm also updating the answer with a workaround.Vexillum
Thanks, I will have an eye on the bug report and try your solution.Quezada
Ok, I tried yours, and the cookie gets created as expected. I am using localhost as OriginURL (and some reverse proxy to inspect the requests), but the server never receives the cookie. So I looked at NSHttpCookieStorage.SharedStorage.Cookies and it just contains two cookies from Google, nothing more. Any ideas?Quezada
So, I had to use http:// in the OriginURL and set the path, otherwise it wouldn't be added to the cookie storage.Quezada
Yep, updated code to reflect working path. Now you see why it's so much easier to use RestSharp to do the request? ;-)Vexillum
O
2

AFAIK every application has its own cookie storage so try to use this code before rendering the page in the UIWebView

        NSHttpCookie cookie = new NSHttpCookie()
        {
            Domain = "yourdomain.com",
            Name = "YourName",
            Value = "YourValue" //and any other info you need to set
        };
        NSHttpCookieStorage cookiejar = NSHttpCookieStorage.SharedStorage;
        cookiejar.SetCookie(cookie);

I'm not in a MAC right now so im not able to test it hope this helps


okay sorry, i wasn't able to test it before posting, anyways I won't get home until tonight so give this a spin

var objects = new object[] { "http://yoururl.com", "CookieName", "CookieValue", "/" };
var keys = new object[] { "NSHTTPCookieOriginURL", "NSHTTPCookieName", "NSHTTPCookieValue", "NSHTTPCookiePath" };
NSDictionary properties = (NSDictionary) NSDictionary.FromObjectsAndKeys(objects, keys);
NSHttpCookie cookie = NSHttpCookie.CookieFromProperties(properties);
NSHttpCookieStorage.SharedStorage.SetCookie(cookie);

As you stated above, in the case that doesn't work might be a bug on monotouch binding so you can bind it manually by doing this

var objects = new object[] { "http://yoururl.com", "CookieName", "CookieValue", "/" };
var keys = new object[] { "NSHTTPCookieOriginURL", "NSHTTPCookieName", "NSHTTPCookieValue", "NSHTTPCookiePath" };
NSDictionary properties = (NSDictionary) NSDictionary.FromObjectsAndKeys(objects, keys);
NSHttpCookie cookie = (NSHttpCookie) Runtime.GetNSObject(Messaging.IntPtr_objc_msgSend_IntPtr(new Class("NSHTTPCookie").Handle, new Selector("cookieWithProperties:").Handle, properties.Handle))
NSHttpCookieStorage.SharedStorage.SetCookie(cookie);

also don't forget to include using MonoTouch.ObjCRuntime; if manually binding it

if manually binding works please don't forget to post a bug report on https://bugzilla.xamarin.com/

Alex

Ogre answered 22/2, 2012 at 16:5 Comment(2)
Sadly Domain, Name and Value properties are readonly, so I cannot make use of a high-level NSHttpCookie API. That's why I fiddled with NSDictionary but haven't figured out the internals yet, how to set the properties for a new cookie.Quezada
Many good hints in your post: I needed to prefix the OriginURL with http:// and also set the path to /. Thanks!Quezada
A
0

I’ve wrote the NSMutableURLRequest+XSURLRequest catagory and XSCookie class to do this;-) http://blog.peakji.com/cocoansurlrequest-with-cookies/

Alberto answered 23/2, 2012 at 1:59 Comment(1)
Sorry, but this is about MonoTouch. The general concept on how to use cookies was clear, but the implementation apparently had some problems.Quezada
E
0

This might give you a lead. Previously I used a similar strategy to make a

WebRequest to a site and collect cookies which were stored in the .Net/Mono CookieStore. Then when loading a url in the UIWebView I copied those cookies over to the NSHttpCookieStorage.

public NSHttpCookieStorage _cookieStorage; 

    /// <summary>
    /// Convert the .NET cookie storage to the iOS NSHttpCookieStorage with Login Cookies
    /// </summary>
    void DotNetCookieStoreToNSHttpCookieStore()
    {
        foreach (Cookie c in _cookies.GetCookies(new Uri(UrlCollection["Login"], UriKind.Absolute))) {
            Console.WriteLine (c);
            _cookieStorage.SetCookie(new NSHttpCookie(c));
        }
    }
Ellingston answered 1/4, 2015 at 14:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.