0

I am working on automating a consent/sign-in Google Form utilizing our campus CAS system by creating a front end for the Google Form in order to allow admins to still keep all the analytics given by google from the google sheet it uses.

I am currently using the WebClient approach below and have had success with getting every field submit successfully through the POST request except the responses from a multi-select checkbox. When I try to send anything that does not match a response on my google form EX: Google Form has checkbox with value "Other" and I try and send a parameter containing the value "Other X1231" the client.UploadValues fails. Following this I am unable to send no more than one value from the checkbox which defeats the purpose of having a multiple-select checkbox. My current approach is utilizing info from this question How to post data to specific URL using WebClient in C#

EDIT: After further investigation I was able to get the prefilled link google uses and I was able to see what the URL looks like with checkbox values. Here it is. As you can see there are infact multiple entry.33031323's being sent. I found out that NameValueCollections do not allow duplicate keys which is what I need to do in order for this to work as far as I can see.

https://docs.google.com/forms/d/e/1FAIpQLScojrZli-0eNGABtqHUmoClqu14R07lhcwkn6ZaHXB0t5wS0g/viewform?usp=pp_url&entry.1441757426=lala&entry.1952327001=232&entry.112478472=Faculty/Staff&entry.1683121781=Swenson+Pool&entry.745164965=HIIT+IT!&entry.1194649100=5:30+PM&entry.33031323=Social+Media&entry.33031323=Website&entry.33031323=Word-of-Mouth&entry.33031323=Print+Media&entry.33031323=Other

using (WebClient client = new WebClient())
        {
            var reqparm = new System.Collections.Specialized.NameValueCollection();
            reqparm.Add("entry.2041020761", consentText);
            reqparm.Add("entry.1441757426", participantFullName.Text);
            reqparm.Add("entry.1952327001", wNumber.Text);
            reqparm.Add("entry.112478472", demographicDD.SelectedValue.ToString());
            reqparm.Add("entry.1683121781", classLocationDD.SelectedValue.ToString());
            reqparm.Add("entry.745164965", classTypeDD.SelectedValue.ToString());
            reqparm.Add("entry.1194649100", classTimeDD.SelectedValue.ToString());
            reqparm.Add("entry.33031323", "Word-of-Mouth");
            reqparm.Add("entry.33031323", "Other");
            byte[] responsebytes = client.UploadValues("https://docs.google.com/forms/u/0/d/e/1FAIpQLScojrZli-0eNGABtqHUmoClqu14R07lhcwkn6ZaHXB0t5wS0g/formResponse", "POST", reqparm);
            string responsebody = Encoding.UTF8.GetString(responsebytes);
        }

entry.XXXX corresponds to fields on the google form. If I run the code above with two reqparm.Add("entry.33031323", "Other"); the result I get is pictured below.

enter image description here

However, if I just have one entry.33031323 like the following the form is accepted and recorded on the Google Sheet connected to the Google Form pictured below.

using (WebClient client = new WebClient())
        {
            var reqparm = new System.Collections.Specialized.NameValueCollection();
            reqparm.Add("entry.2041020761", consentText);
            reqparm.Add("entry.1441757426", participantFullName.Text);
            reqparm.Add("entry.1952327001", wNumber.Text);
            reqparm.Add("entry.112478472", demographicDD.SelectedValue.ToString());
            reqparm.Add("entry.1683121781", classLocationDD.SelectedValue.ToString());
            reqparm.Add("entry.745164965", classTypeDD.SelectedValue.ToString());
            reqparm.Add("entry.1194649100", classTimeDD.SelectedValue.ToString());
            reqparm.Add("entry.33031323", "Word-of-Mouth");
            byte[] responsebytes = client.UploadValues("https://docs.google.com/forms/u/0/d/e/1FAIpQLScojrZli-0eNGABtqHUmoClqu14R07lhcwkn6ZaHXB0t5wS0g/formResponse", "POST", reqparm);
            string responsebody = Encoding.UTF8.GetString(responsebytes);
        }

enter image description here

I am able to get all the items from the checkbox through looping through/LINQ, however if I try and send that string of responses to entry.33031323 it throws the same error EX: "Word-of-Mouth Other Website" != any response on the form like "Website". How can I make this all work?

This is my CheckBoxList control

 How did you hear about the GroupX program? (Optional)
        <asp:CheckBoxList ID="howDidYouHearAboutUsCBL" runat="server">
            <asp:ListItem Text="Social Media" Value="Social Media"></asp:ListItem>
            <asp:ListItem Text="Website" Value="Website"></asp:ListItem>
            <asp:ListItem Text="Word-of-Mouth" Value="Word-of-Mouth"></asp:ListItem>
            <asp:ListItem Text="Print Media" Value="Print Media"></asp:ListItem>
            <asp:ListItem Text="Other" Value="Other"></asp:ListItem>
        </asp:CheckBoxList>

This is the checkbox group on the Google Form i'm using to test. enter image description here

1 Answers1

0

I was able to solve this by using a HttpWebRequest shown below.

 string consentText = "";
        
        if (rbConsent.Checked)
        {
            consentText = rbConsent.Text;
        }

        //address form is submitted to
        string sAddress = "https://docs.google.com/forms/u/0/d/e/1FAIpQLScojrZli-0eNGABtqHUmoClqu14R07lhcwkn6ZaHXB0t5wS0g/formResponse";
        string sContent = "entry.2041020761=" + consentText +
                          "&entry.1441757426=" + participantFullName.Text +
                          "&entry.1952327001=" + wNumber.Text +
                          "&entry.112478472=" + HttpUtility.UrlEncode(demographicDD.SelectedValue.ToString()) +
                          "&entry.1683121781=" + HttpUtility.UrlEncode(classLocationDD.SelectedValue.ToString()) +
                          "&entry.745164965=" + HttpUtility.UrlEncode(classTypeDD.SelectedValue.ToString()) +
                          "&entry.1194649100=" + classTimeDD.SelectedItem.Text;

        //iterate through howDidYouHearAboutUsCBL and append checked items to sContent
        foreach (ListItem item in howDidYouHearAboutUsCBL.Items)
        {
            if (item.Selected)
            {
                sContent += "&entry.33031323=" + item.Value;
            }
        }
        
        sContent += "&submit=";
        string sResponse = "";

        System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(sAddress);
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
        req.Timeout = 10 * 1000;
        req.AllowAutoRedirect = true;
        byte[] bPayload = System.Text.Encoding.UTF8.GetBytes(sContent);
        req.ContentLength = bPayload.Length;
        System.IO.Stream str = req.GetRequestStream();
        str.Write(bPayload, 0, bPayload.Length);
        str.Close();

        System.Net.HttpWebResponse res;
        res = (System.Net.HttpWebResponse)req.GetResponse();
        System.IO.StreamReader rdr = new System.IO.StreamReader(res.GetResponseStream(), System.Text.Encoding.Default);
        sResponse = rdr.ReadToEnd();
        rdr.Close();
        res.Close();

I iterate through my checkbox and append a new "&entry.33031323=" for each checked item. sContent is then URL encoded and posted.