1

I am trying to scrape a website to automate the download of a report in .csv format. Here is the ajax call from the website that I am trying to do on the server side in c#:

$.ajax(
{
    url: '/my-folder/generate-report',
    data: { model: JSON.stringify(data) },
    type: 'POST',
    dataType: "json",
    success: function (response) { ... },
    error: function (...) { ... }
);

No matter what I do, I get the error message "Value cannot be null."

I first have to log into the site, which works fine. Then I call the generate-report using a post and it always returns Value cannot be null.

new ReportModel() code is not included but can be if needed. It basically just gets the "data" into the exact format that it is in when I view the Http Headers when generating the report through the actual website/browser.

Here is my c# code:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;

class ReportModel
{
    public string SampleProperty1 => "SampleValue";
    public string[] SampleArrayProperty1 => new string[] {};
}

class Program
{
    static void Main(string[] args)
    {
        var baseAddress = new Uri("https://example.com");
        var cookieContainer = new CookieContainer();
        using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
        using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
        {
            var homePageResult = client.GetAsync("/my-folder/");
            homePageResult.Result.EnsureSuccessStatusCode();

            var content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("UserName", "..."),
                new KeyValuePair<string, string>("Password", "..."),
            });
            var loginResult = client.PostAsync("/my-folder/Login", content).Result;
            loginResult.EnsureSuccessStatusCode();

            var myContent = JsonConvert.SerializeObject(new ReportModel());
            var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
            var byteContent = new ByteArrayContent(buffer);
            byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            var reportStep1Result = client.PostAsync("/my-folder/generate-report", byteContent);
            reportStep1Result.Result.EnsureSuccessStatusCode();

            var result = reportStep1Result.Result.Content.ReadAsStringAsync();
        }
    }
}

The result above shows that the report failed to generate and the message is as follows:

{
    "Success":false,
    "Message":"Value cannot be null.\r\nParameter name:value",
    "Html":null,
    "Model":null
}

Since I know the ajax call works fine when called from the web app in the browser, I am thinking there is something I am missing when posting the call.

When I inspect the HTTP Header in Chrome Developer Tools (when called from browser), I see Headers > Form Data > model: { ... json representation of report parameters ... }.

Perhaps I am not sending the json parameters the same way they get sent in the browser?

Let me know if you need further details and I will be glad to provide. Thank you in advance.

Update 12/4/2018 11:53am - Added more detail to ReportModel to show how I am using it just as a convenient way to serialize it into the correct JSON.

Update 12/4/2018 3:04pm - Here is the request details when executing the report in the browser:

"request": {
      "method": "POST",
      "url": "https://example.com/my-folder/generate-report",
      "httpVersion": "HTTP/1.1",
      "headers": [
        {
          "name": "Cookie",
          "value": "_ga=...; SearchView=grid; HASH_SearchView=...; _gid=...; ASP.NET_SessionId=...; Emp_Id=...; TimeClockSessionKey=...; TimeClockEmp_Id=...; _gat_tracker1=1; _gat_tracker2=1; Expiration=12/4/2018 8:02:26 PM; SessionKey=..."
        },
        {
          "name": "Origin",
          "value": "https://example.com"
        },
        {
          "name": "Accept-Encoding",
          "value": "gzip, deflate, br"
        },
        {
          "name": "Host",
          "value": "example.com"
        },
        {
          "name": "Accept-Language",
          "value": "en-US,en;q=0.9"
        },
        {
          "name": "User-Agent",
          "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
        },
        {
          "name": "Content-Type",
          "value": "application/x-www-form-urlencoded; charset=UTF-8"
        },
        {
          "name": "Accept",
          "value": "application/json, text/javascript, */*; q=0.01"
        },
        {
          "name": "Referer",
          "value": "https://example.com/my-folder/generate-report/"
        },
        {
          "name": "X-Requested-With",
          "value": "XMLHttpRequest"
        },
        {
          "name": "Connection",
          "value": "keep-alive"
        },
        {
          "name": "Content-Length",
          "value": "5385"
        }
      ],
      "queryString": [],
      "cookies": [
        {
          "name": "_ga",
          "value": "...",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "SearchView",
          "value": "grid",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "HASH_SearchView",
          "value": ".",..
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "_gid",
          "value": "...",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "ASP.NET_SessionId",
          "value": "...",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "Emp_Id",
          "value": "...",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "TimeClockSessionKey",
          "value": "...",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "TimeClockEmp_Id",
          "value": "...",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "_gat_tracker1",
          "value": "1",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "_gat_tracker2",
          "value": "1",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "Expiration",
          "value": "12/4/2018 8:02:26 PM",
          "expires": null,
          "httpOnly": false,
          "secure": false
        },
        {
          "name": "SessionKey",
          "value": "...",
          "expires": null,
          "httpOnly": false,
          "secure": false
        }
      ],
      "headersSize": 1068,
      "bodySize": 0,
      "postData": {
        "mimeType": "application/x-www-form-urlencoded; charset=UTF-8",
        "text": "model=%7B%22LoggedInEmployeeId%22%3A%22%22%2C%22SelectedCompanyIds%22%3A%5B%221%22%5D%2C%22SelectedRouteCodes%22%3A%5B%22NULL%22%2C%22R01%22%5D%2C%22SelectedTerritoryCodes%22%3A%5B%5D%2C%22SelectedZipCodes%22%3A%5B%2260137%22%2C%2260148%22%2C%2260174%22%2C%2260181%22%2C%2260187%22%2C%2260189%22%2C%2260190%22%2C%2260403%22%2C%2260404%22%2C%2260410%22%2C%2260431%22%2C%2260432%22%2C%2260433%22%2C%2260435%22%2C%2260436%22%2C%2260439%22%2C%2260440%22%2C%2260441%22%2C%2260446%22%2C%2260447%22%2C%2260451%22%2C%2260467%22%2C%2260490%22%2C%2260491%22%2C%2260502%22%2C%2260503%22%2C%2260504%22%2C%2260505%22%2C%2260506%22%2C%2260510%22%2C%2260512%22%2C%2260514%22%2C%2260515%22%2C%2260516%22%2C%2260517%22%2C%2260532%22%2C%2260538%22%2C%2260540%22%2C%2260543%22%2C%2260544%22%2C%2260545%22%2C%2260551%22%2C%2260554%22%2C%2260555%22%2C%2260559%22%2C%2260560%22%2C%2260561%22%2C%2260563%22%2C%2260564%22%2C%2260565%22%2C%2260585%22%2C%2260586%22%2C%2299999%22%5D%2C%22SelectedSourceCodes%22%3A%5B%22-1%22%2C%22105%22%2C%2279%22%2C%2285%22%2C%2274%22%2C%2248%22%2C%22112%22%2C%22119%22%2C%22125%22%2C%2293%22%2C%22130%22%2C%2269%22%2C%2263%22%2C%22127%22%2C%2266%22%2C%2265%22%2C%2256%22%2C%228%22%2C%2247%22%2C%2276%22%2C%2290%22%2C%22123%22%2C%2282%22%2C%2294%22%2C%22124%22%2C%2258%22%2C%2271%22%2C%22107%22%2C%2255%22%2C%22101%22%2C%22102%22%2C%22132%22%2C%22122%22%2C%22118%22%2C%2273%22%2C%2254%22%2C%2253%22%2C%2250%22%2C%2284%22%2C%2218%22%2C%2223%22%2C%2243%22%2C%2283%22%2C%2236%22%2C%2224%22%2C%2230%22%2C%2226%22%2C%2233%22%2C%2232%22%2C%2231%22%2C%2277%22%2C%22128%22%2C%2217%22%2C%22115%22%2C%22106%22%2C%22111%22%2C%22113%22%2C%2251%22%2C%2297%22%2C%2299%22%2C%2298%22%2C%2296%22%2C%2245%22%2C%2295%22%2C%22108%22%2C%22121%22%2C%2249%22%2C%22126%22%2C%22114%22%2C%22117%22%2C%2292%22%2C%2281%22%2C%2260%22%2C%2212%22%2C%2222%22%2C%2211%22%2C%2235%22%2C%2237%22%2C%22116%22%2C%2210%22%2C%22131%22%2C%2288%22%2C%2289%22%2C%2219%22%2C%2234%22%2C%229%22%2C%2278%22%2C%2264%22%2C%2244%22%2C%2280%22%2C%2275%22%2C%2286%22%2C%2259%22%2C%2270%22%2C%22129%22%2C%2291%22%2C%22100%22%2C%22120%22%2C%22103%22%2C%2246%22%2C%2240%22%2C%2225%22%2C%2261%22%2C%22109%22%2C%2242%22%2C%2252%22%2C%2241%22%2C%2228%22%2C%22133%22%2C%22110%22%2C%227%22%2C%2257%22%2C%2262%22%2C%2287%22%2C%22104%22%5D%2C%22SelectedBillingTypes%22%3A%5B%22R%22%2C%22M%22%2C%22A%22%2C%22D%22%2C%22C%22%5D%2C%22SelectedCustomerStatuses%22%3A%5B%228%22%2C%229%22%5D%2C%22SelectedTaxCodes%22%3A%5B%5D%2C%22CustomerType%22%3A%22Both%22%2C%22BillToOption%22%3A%22All%22%2C%22Season%22%3A%222018%22%2C%22SelectedPropertyInventory%22%3A%220%22%2C%22StartDate%22%3A%221753-01-01+00%3A00%3A00%22%2C%22EndDate%22%3A%229998-12-31+23%3A59%3A59%22%2C%22DateRangeText%22%3A%22All%22%2C%22BeginCustomerNumberRange%22%3A%220%22%2C%22EndCustomerNumberRange%22%3A%22999999999%22%2C%22BeginMapcodeRange%22%3A%22%22%2C%22EndMapcodeRange%22%3A%22ZZ-ZZ-ZZZ%22%2C%22BeginCarrierRouteRange%22%3A%22%22%2C%22EndCarrierRouteRange%22%3A%22ZZZZ%22%2C%22BeginSizeRange%22%3A%220%22%2C%22EndSizeRange%22%3A%229999999.99%22%2C%22IncludeCustomersWithoutServices%22%3A%22true%22%2C%22SelectedSortOrder%22%3A%22CustomerNumber%22%2C%22SummaryOnly%22%3A%22false%22%2C%22PreviewFlag%22%3A%22false%22%2C%22SelectedFlags%22%3A%22%7B%5C%22with%5C%22%3A%5B%5D%2C%5C%22without%5C%22%3A%5B%5D%7D%22%2C%22AdvanceOptionsDataAsString%22%3A%22%7B%5C%22CustomerPhone%5C%22%3A0%2C%5C%22CustomerEmail%5C%22%3A0%2C%5C%22CustomerCreditHold%5C%22%3A0%2C%5C%22GroupBillingMasterAccounts%5C%22%3A%5B%5D%2C%5C%22WithDocuments%5C%22%3A%5B%5D%2C%5C%22WithoutDocuments%5C%22%3A%5B%5D%2C%5C%22DocumentsStartDate%5C%22%3A%5C%2201%2F01%2F2018%5C%22%2C%5C%22DocumentsEndDate%5C%22%3A%5C%2212%2F31%2F2018%5C%22%2C%5C%22DocumentsDateName%5C%22%3A%5C%22This+year%5C%22%2C%5C%22WithLetters%5C%22%3A%5B%5D%2C%5C%22WithoutLetters%5C%22%3A%5B%5D%2C%5C%22LettersStartDate%5C%22%3A%5C%2201%2F01%2F2018%5C%22%2C%5C%22LettersEndDate%5C%22%3A%5C%2212%2F31%2F2018%5C%22%2C%5C%22LettersDateName%5C%22%3A%5C%22This+year%5C%22%2C%5C%22WithNPS%5C%22%3A%5B%5D%2C%5C%22WithoutNPS%5C%22%3A%5B%5D%2C%5C%22NPSStartDate%5C%22%3A%5C%2201%2F01%2F2018%5C%22%2C%5C%22NPSEndDate%5C%22%3A%5C%2212%2F31%2F2018%5C%22%2C%5C%22NPSDateName%5C%22%3A%5C%22This+year%5C%22%2C%5C%22DontTelemarket%5C%22%3A%5C%220%5C%22%2C%5C%22DontDirectMail%5C%22%3A%5C%220%5C%22%2C%5C%22DontEmail%5C%22%3A%5C%220%5C%22%2C%5C%22DontFollowupByEmail%5C%22%3A%5C%220%5C%22%2C%5C%22DontUpsell%5C%22%3A%5C%220%5C%22%2C%5C%22NoKnock%5C%22%3A%5C%220%5C%22%2C%5C%22CawRegisteredUser%5C%22%3A%5C%220%5C%22%2C%5C%22AutoPay%5C%22%3A%5C%220%5C%22%2C%5C%22PreferredLanguage%5C%22%3A%5C%220%5C%22%2C%5C%22EmailStatements%5C%22%3A%5C%220%5C%22%2C%5C%22EmailPrenotification%5C%22%3A%5C%220%5C%22%2C%5C%22TextPrenotification%5C%22%3A%5C%220%5C%22%2C%5C%22WithContactPreferred%5C%22%3A%5B%5D%2C%5C%22WithoutContactPreferred%5C%22%3A%5B%5D%2C%5C%22WithSourceSize%5C%22%3A%5B%5D%2C%5C%22WithoutSourceSize%5C%22%3A%5B%5D%2C%5C%22WithSubdivisions%5C%22%3A%5B%5D%2C%5C%22WithoutSubdivisions%5C%22%3A%5B%5D%7D%22%2C%22SendToCallLog%22%3A%22false%22%2C%22SendToCallLogData%22%3Anull%2C%22MainGrouping%22%3A%22Ignore%22%2C%22SubGrouping%22%3A%22Ignore%22%2C%22AllRouteCodes%22%3A%22true%22%2C%22AllSourceCodes%22%3A%22false%22%2C%22AllZipCodes%22%3A%22true%22%2C%22AllTerritoryCodes%22%3A%22true%22%2C%22AllTaxCodes%22%3A%22true%22%2C%22ExportToCSV%22%3Atrue%7D",
        "params": [
          {
            "name": "model",
            "value": "%7B%22LoggedInEmployeeId%22%3A%22%22%2C%22SelectedCompanyIds%22%3A%5B%221%22%5D%2C%22SelectedRouteCodes%22%3A%5B%22NULL%22%2C%22R01%22%5D%2C%22SelectedTerritoryCodes%22%3A%5B%5D%2C%22SelectedZipCodes%22%3A%5B%2260137%22%2C%2260148%22%2C%2260174%22%2C%2260181%22%2C%2260187%22%2C%2260189%22%2C%2260190%22%2C%2260403%22%2C%2260404%22%2C%2260410%22%2C%2260431%22%2C%2260432%22%2C%2260433%22%2C%2260435%22%2C%2260436%22%2C%2260439%22%2C%2260440%22%2C%2260441%22%2C%2260446%22%2C%2260447%22%2C%2260451%22%2C%2260467%22%2C%2260490%22%2C%2260491%22%2C%2260502%22%2C%2260503%22%2C%2260504%22%2C%2260505%22%2C%2260506%22%2C%2260510%22%2C%2260512%22%2C%2260514%22%2C%2260515%22%2C%2260516%22%2C%2260517%22%2C%2260532%22%2C%2260538%22%2C%2260540%22%2C%2260543%22%2C%2260544%22%2C%2260545%22%2C%2260551%22%2C%2260554%22%2C%2260555%22%2C%2260559%22%2C%2260560%22%2C%2260561%22%2C%2260563%22%2C%2260564%22%2C%2260565%22%2C%2260585%22%2C%2260586%22%2C%2299999%22%5D%2C%22SelectedSourceCodes%22%3A%5B%22-1%22%2C%22105%22%2C%2279%22%2C%2285%22%2C%2274%22%2C%2248%22%2C%22112%22%2C%22119%22%2C%22125%22%2C%2293%22%2C%22130%22%2C%2269%22%2C%2263%22%2C%22127%22%2C%2266%22%2C%2265%22%2C%2256%22%2C%228%22%2C%2247%22%2C%2276%22%2C%2290%22%2C%22123%22%2C%2282%22%2C%2294%22%2C%22124%22%2C%2258%22%2C%2271%22%2C%22107%22%2C%2255%22%2C%22101%22%2C%22102%22%2C%22132%22%2C%22122%22%2C%22118%22%2C%2273%22%2C%2254%22%2C%2253%22%2C%2250%22%2C%2284%22%2C%2218%22%2C%2223%22%2C%2243%22%2C%2283%22%2C%2236%22%2C%2224%22%2C%2230%22%2C%2226%22%2C%2233%22%2C%2232%22%2C%2231%22%2C%2277%22%2C%22128%22%2C%2217%22%2C%22115%22%2C%22106%22%2C%22111%22%2C%22113%22%2C%2251%22%2C%2297%22%2C%2299%22%2C%2298%22%2C%2296%22%2C%2245%22%2C%2295%22%2C%22108%22%2C%22121%22%2C%2249%22%2C%22126%22%2C%22114%22%2C%22117%22%2C%2292%22%2C%2281%22%2C%2260%22%2C%2212%22%2C%2222%22%2C%2211%22%2C%2235%22%2C%2237%22%2C%22116%22%2C%2210%22%2C%22131%22%2C%2288%22%2C%2289%22%2C%2219%22%2C%2234%22%2C%229%22%2C%2278%22%2C%2264%22%2C%2244%22%2C%2280%22%2C%2275%22%2C%2286%22%2C%2259%22%2C%2270%22%2C%22129%22%2C%2291%22%2C%22100%22%2C%22120%22%2C%22103%22%2C%2246%22%2C%2240%22%2C%2225%22%2C%2261%22%2C%22109%22%2C%2242%22%2C%2252%22%2C%2241%22%2C%2228%22%2C%22133%22%2C%22110%22%2C%227%22%2C%2257%22%2C%2262%22%2C%2287%22%2C%22104%22%5D%2C%22SelectedBillingTypes%22%3A%5B%22R%22%2C%22M%22%2C%22A%22%2C%22D%22%2C%22C%22%5D%2C%22SelectedCustomerStatuses%22%3A%5B%228%22%2C%229%22%5D%2C%22SelectedTaxCodes%22%3A%5B%5D%2C%22CustomerType%22%3A%22Both%22%2C%22BillToOption%22%3A%22All%22%2C%22Season%22%3A%222018%22%2C%22SelectedPropertyInventory%22%3A%220%22%2C%22StartDate%22%3A%221753-01-01+00%3A00%3A00%22%2C%22EndDate%22%3A%229998-12-31+23%3A59%3A59%22%2C%22DateRangeText%22%3A%22All%22%2C%22BeginCustomerNumberRange%22%3A%220%22%2C%22EndCustomerNumberRange%22%3A%22999999999%22%2C%22BeginMapcodeRange%22%3A%22%22%2C%22EndMapcodeRange%22%3A%22ZZ-ZZ-ZZZ%22%2C%22BeginCarrierRouteRange%22%3A%22%22%2C%22EndCarrierRouteRange%22%3A%22ZZZZ%22%2C%22BeginSizeRange%22%3A%220%22%2C%22EndSizeRange%22%3A%229999999.99%22%2C%22IncludeCustomersWithoutServices%22%3A%22true%22%2C%22SelectedSortOrder%22%3A%22CustomerNumber%22%2C%22SummaryOnly%22%3A%22false%22%2C%22PreviewFlag%22%3A%22false%22%2C%22SelectedFlags%22%3A%22%7B%5C%22with%5C%22%3A%5B%5D%2C%5C%22without%5C%22%3A%5B%5D%7D%22%2C%22AdvanceOptionsDataAsString%22%3A%22%7B%5C%22CustomerPhone%5C%22%3A0%2C%5C%22CustomerEmail%5C%22%3A0%2C%5C%22CustomerCreditHold%5C%22%3A0%2C%5C%22GroupBillingMasterAccounts%5C%22%3A%5B%5D%2C%5C%22WithDocuments%5C%22%3A%5B%5D%2C%5C%22WithoutDocuments%5C%22%3A%5B%5D%2C%5C%22DocumentsStartDate%5C%22%3A%5C%2201%2F01%2F2018%5C%22%2C%5C%22DocumentsEndDate%5C%22%3A%5C%2212%2F31%2F2018%5C%22%2C%5C%22DocumentsDateName%5C%22%3A%5C%22This+year%5C%22%2C%5C%22WithLetters%5C%22%3A%5B%5D%2C%5C%22WithoutLetters%5C%22%3A%5B%5D%2C%5C%22LettersStartDate%5C%22%3A%5C%2201%2F01%2F2018%5C%22%2C%5C%22LettersEndDate%5C%22%3A%5C%2212%2F31%2F2018%5C%22%2C%5C%22LettersDateName%5C%22%3A%5C%22This+year%5C%22%2C%5C%22WithNPS%5C%22%3A%5B%5D%2C%5C%22WithoutNPS%5C%22%3A%5B%5D%2C%5C%22NPSStartDate%5C%22%3A%5C%2201%2F01%2F2018%5C%22%2C%5C%22NPSEndDate%5C%22%3A%5C%2212%2F31%2F2018%5C%22%2C%5C%22NPSDateName%5C%22%3A%5C%22This+year%5C%22%2C%5C%22DontTelemarket%5C%22%3A%5C%220%5C%22%2C%5C%22DontDirectMail%5C%22%3A%5C%220%5C%22%2C%5C%22DontEmail%5C%22%3A%5C%220%5C%22%2C%5C%22DontFollowupByEmail%5C%22%3A%5C%220%5C%22%2C%5C%22DontUpsell%5C%22%3A%5C%220%5C%22%2C%5C%22NoKnock%5C%22%3A%5C%220%5C%22%2C%5C%22CawRegisteredUser%5C%22%3A%5C%220%5C%22%2C%5C%22AutoPay%5C%22%3A%5C%220%5C%22%2C%5C%22PreferredLanguage%5C%22%3A%5C%220%5C%22%2C%5C%22EmailStatements%5C%22%3A%5C%220%5C%22%2C%5C%22EmailPrenotification%5C%22%3A%5C%220%5C%22%2C%5C%22TextPrenotification%5C%22%3A%5C%220%5C%22%2C%5C%22WithContactPreferred%5C%22%3A%5B%5D%2C%5C%22WithoutContactPreferred%5C%22%3A%5B%5D%2C%5C%22WithSourceSize%5C%22%3A%5B%5D%2C%5C%22WithoutSourceSize%5C%22%3A%5B%5D%2C%5C%22WithSubdivisions%5C%22%3A%5B%5D%2C%5C%22WithoutSubdivisions%5C%22%3A%5B%5D%7D%22%2C%22SendToCallLog%22%3A%22false%22%2C%22SendToCallLogData%22%3Anull%2C%22MainGrouping%22%3A%22Ignore%22%2C%22SubGrouping%22%3A%22Ignore%22%2C%22AllRouteCodes%22%3A%22true%22%2C%22AllSourceCodes%22%3A%22false%22%2C%22AllZipCodes%22%3A%22true%22%2C%22AllTerritoryCodes%22%3A%22true%22%2C%22AllTaxCodes%22%3A%22true%22%2C%22ExportToCSV%22%3Atrue%7D"
          }
        ]
      }
    },

Update 12/4/2018 3:48pm - I change the code to URL encode the JSON before passing it:

var myContent = HttpUtility.UrlEncode(JsonConvert.SerializeObject(new model()));
var formUrlEncodedContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("model", myContent) });

var reportStep1Result = client.PostAsync("/my-folder/generate-report", formUrlEncodedContent);
reportStep1Result.Result.EnsureSuccessStatusCode();

var result = reportStep1Result.Result.Content.ReadAsStringAsync();

Here is the new error I get:

{
    "Success":false,
    "Message":"Unexpected character encountered while parsing value: %. Path '', line 0, position 0.",
    "Html":null,
    "Model":null
}

How come the URL encoded JSON shows up twice in the request? Once it shows as the value for "text" and is prefixed with model= and again in the "params" array as the param "value" without the model= prefix?

Update 12/4/2018 4:03pm - Tracking with Fiddler shows:

Inspecting with Fiddler when I call it from c# shows the following:

POST

https://example.com/my-folder/generate-report HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: example.com
Cookie: ASP.NET_SessionId=...; 
SessionKey=...;
Emp_Id=...;
Expiration=12/4/2018 11:57:38 PM; 
TimeClockSessionKey=...;
TimeClockEmp_Id=JJB
Content-Length: 7658
Expect: 100-continue

model=%257b%2522LoggedInEmployeeId%2522...

Note that the Fiddler version starts with %25. The browser one starts with %7b. %25 is the URL encoding of % - so it seems like it is getting URL encoded 2x. I will change it to StringContent instead of FormUrlEncodedContent, and manually encode just the JSON and see if that works....

I fixed this issue with the double URL encoding. Now the model is equal on both the web browser and the c# calls. Still getting the error. The headers are different between the 2. Does anything stand out??

HEADER FROM C# CONSOLE APP:

POST
https://example.com/my-folder/generate-report HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: example.com
Cookie: ASP.NET_SessionId=...; 
SessionKey=...;
Emp_Id=...;
Expiration=12/5/2018 3:04:35 AM;
TimeClockSessionKey=...;
TimeClockEmp_Id=...
Content-Length: 5386
Expect: 100-continue

HEADER FROM BROWSER:

POST https://example.com/my-folder/generate-report HTTP/1.1
Host: example.com
Connection: keep-alive
Content-Length: 5385
Accept: application/json, text/javascript, */*; q=0.01
Origin: https://example.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: https://example.com/my-folder/generate-report/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: _ga=...;
SearchView=grid;
HASH_SearchView=...;
_gid=...;
ASP.NET_SessionId=...;
LoginRedirectTo=https%3A%2F%2Fexample.com%2Fmy-folder%2Fgenerate-report%2F; 
_gat_tracker1=1;
_gat_tracker2=1;
Emp_Id=...; 
TimeClockSessionKey=...;
TimeClockEmp_Id=...;
Expiration=12/5/2018 3:06:22 AM; 
SessionKey=...
Jeremy
  • 175
  • 2
  • 10
  • 1
    I am not seeing you send any parameters. You create an empty model and serialize that. Also why use `ByteArrayContent` and not `StringContent` to post the JSON? That ajax code also looks suspect. – Nkosi Dec 04 '18 at 17:41
  • 2
    I'm not sure that server method is expecting application/json... I think it might be expecting a form with a `model` key with a value equal to the JSON content – sellotape Dec 04 '18 at 17:47
  • @Nkosi the parameters are passed in a class with hard coded property values as I am currently just trying to get it to succeed before making the properties dynamic. I will post more pieces of the ReportModel class to show what I mean. I already tried using StringContent as well, but it gave the same error. I cannot change the ajax code as it is a 3rd party website. – Jeremy Dec 04 '18 at 17:52
  • 1
    @Jeremy then go with `FormUrlEncodedContent` again adding a `model` key with your JSON value. – Nkosi Dec 04 '18 at 17:54
  • @sellotape - that is what i am looking for. I will see if I can try to change the code to pass it in as a form key/value pair with the JSON as the value and "model" as the name. I will update if that works. – Jeremy Dec 04 '18 at 17:55
  • I changed it to use FormUrlEncodedContent. I get the following error: [code] {"Success":false,"Message":"Unexpected character encountered while parsing value: {. Path 'ComplexProperty1', line 1, position 1841.","Html":null,"Model":null} [/code] I noticed when JSON Serializer executes, it doesn't escape double-quotes in my complext types (i.e., ComplexProperty1). In the browser developer tools it looks like this: "ComplexProperty1":"{\"with\":[],\"without\":[]}" But in my c# JSON it looks like this: "ComplexProperty1":"{"with":[],"without":[]}" – Jeremy Dec 04 '18 at 18:27
  • It wouldn't let me edit the above comment. Correction - in the c# JSON, the complex type looks like "ComplexProperty1":{"with":[],"without":[]} – Jeremy Dec 04 '18 at 18:35
  • Looks like maybe they built the complex types' JSON manually and treat it as a string. I got past that parse error but then I still get the same original error: {"Success":false,"Message":"Value cannot be null.\r\nParameter name: value","Html":null,"Model":null} – Jeremy Dec 04 '18 at 18:43
  • 2
    Maybe what you should do is allow the Ajax post to happen in Chrome, and in the dev tools inspect the exact HTTP message being posted (in the Network tab IIRC); then you'll know exactly what it wants. (It shows the full content and headers there as well). If you add it to your question we can probably see the issue. – sellotape Dec 04 '18 at 18:54
  • @sellotape not sure how much or which parts to post, but I saved it from Chrome developer tools > Network as an har file and see this in it: "postData": { "mimeType": "application/x-www-form-urlencoded; charset=UTF-8", "text": "model=%7B%22PropertyName1... – Jeremy Dec 04 '18 at 19:28
  • 1
    That looks good, but too long for the comment; can you add it to the bottom of your question? I'm after all the request headers and the request body. You can obfuscate an authorization header, if any. – sellotape Dec 04 '18 at 19:37
  • 1
    @Jeremy are you able to show what the raw request looks like when sent from the browser. that should determine what needs to be done in code to replicate the desired behavior – Nkosi Dec 04 '18 at 20:53
  • I added the request directly from the browser. Let me know if I need anything else. – Jeremy Dec 04 '18 at 21:09
  • 1
    Okay so it's definitely a form post. I think the only part you were missing was to URL-encode the JSON. When I put that value (for model) into https://www.urldecoder.org, it comes out as the expected JSON. – sellotape Dec 04 '18 at 21:17
  • You can also run Fiddler on your machine while you make your own post to compare to the Ajax one. – sellotape Dec 04 '18 at 21:18
  • Last point of note is that their JSON contains a **lot** of data, much, perhaps all, of which you'll have to supply, depending on what the server requires. – sellotape Dec 04 '18 at 21:21
  • @sellotape I added some updates to the question. Looks like I've got it down to just the header values being different. Looks like the model is the same now. Still getting the null error. – Jeremy Dec 05 '18 at 01:22
  • All I can suggest is keep comparing your request (using Fiddler) to theirs and keep adding in more things to make it identical until you find the one that is the fix. There is also the possibility that their server uses measures to intentionally prevent you doing exactly this. – sellotape Dec 05 '18 at 08:41
  • https://stackoverflow.com/questions/38114553/are-async-console-applications-supported-in-net-core. – Danny Fardy Jhonston Bermúdez Dec 05 '18 at 14:47
  • @DannyFardyJhonstonBermúdez changing it to use c# 7.1 and using async Task on the Main signature did not help. I am still getting the same error. It is possible the API that generates the report is doing something to prevent this from working. I will try to get the HTTP header to match more closely, but it may be a wasted effort. – Jeremy Dec 05 '18 at 15:39
  • @Jeremy did you try replacing `=>` to `=` in the ReportModel declaration? I can't execute your class. – Danny Fardy Jhonston Bermúdez Dec 05 '18 at 20:44
  • @DannyFardyJhonstonBermúdez I believe the => is a c# 6 feature. – Jeremy Dec 05 '18 at 20:46
  • I got the c# HTTP request as identical as possible to the web browser HTTP request and still I get the same “Value cannot be null.” error. For now I am giving up as I beliwvw there may be some type of security in place which is restricting the api calls to the IP address of the web server or something like that. For now I am forced to manually export the reports to csv and crunch them that way. The normal posts on the site work fine (ie logging in), but the ones that generate the reports use a 3rd party reporting tool which must have the built-in security. Thank you all for the input. – Jeremy Dec 11 '18 at 05:27
  • Changjng two of the empty array parameters from [] to [“NULL”] fixed the error and got it working. Not sure who to mark as the right answer as you all provided good assistance. – Jeremy Jan 31 '19 at 20:32

0 Answers0