call GP Service with C#

140
7
Jump to solution
03-31-2020 11:28 AM
Highlighted
Frequent Contributor

I am doing to below from JavaScript API.

Passing parameters from Javascript to a GPService in ArcGIS Server

Is there a way to do the same from C# in .Net framework?  if so how?

var gpUrl = "https://xxxxx.gov/arcgis/rest/services/Test/createGeometry/GPServer/Geometry";

var gp = new Geoprocessor(gpUrl);


for (var f = 0; f < text.length; f++) {
obj = JSON.parse(text);

varaddress = obj.employees[f].address;
vardistance = obj.employees[f].distance;
varid = obj.employees[f].id;

var params = {
address: varaddress,
distance: vardistance,
uniqueid: varid
};

gp.execute(params);
}
Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Esri Contributor

Hi jay kapalczynski‌,

For this kind of custom web request call, I normally hack by reading the network traffic.

My best candidate is fiddler.

First step, I only the gptask, execute task page, 

Second I open the fiddler. to track that post request call and, I will click [Execute Task (Post)] button from the page.

Third try to find from the fiddler the post request call.

Final step : I try and write same post request call with C#, try and capture the .net web request call network traffic with fiddler as well.

Capturing Traffic from .NET Services with Fiddler 

And then I compare this two traffic and tweak the c# code, mostly paramstring part. 

Good luck, this is my trick  

I have update your total code after I played with a GPTask with c# a few changes. That should be good now

 protected void btnPassParameters_Click(object sender, EventArgs e)
{
string gpUrl = "https://xxxa.gov/arcgis/rest/services/Test/Counties/GPServer/create";
string requestUrl = gpUrl + "/execute";

//make sure requestUrl end with execute **
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(requestUrl ));

request.KeepAlive = true;
request.Method = "POST";

request.AllowAutoRedirect = true;
request.CookieContainer = new System.Net.CookieContainer();

request.ContentType = "application/x-www-form-urlencoded";// my mistake should be form

StringBuilder paramString = new StringBuilder();

string inputParam = "{\"employees\":[{\"address\":\"1520 Split Oak Ln, Henrico, Virginia, 23229\",\"distance\":\"10\",\"id\":\"9a35172e071f4a33b191172a9b4b02ae\"}]}";

// for this inputParam part, instead of escaping the string how about you save json text into a file and read like that , string inputParam = System.IO.File.ReadAllText("your file path")

paramString.Append($"request="+ inputParam);//no need ?

paramString.Append($"&f=json");

byte[] data = Encoding.ASCII.GetBytes(paramString.ToString());
request.ContentLength = data.Length;

Stream requestStream = request.GetRequestStream();

requestStream.Write(data, 0, data.Length);
requestStream.Close();

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

string responseStr = getStringFromWebResponse(response);

Response.Write(responseStr);


}

View solution in original post

7 Replies
Highlighted
Frequent Contributor

think i found it here..

Run a geoprocessing task—ArcGIS Runtime SDK for .NET | ArcGIS for Developers 

have not done this before an not sure what I have to install along with Visual Studio or reference or include in my code.

Reply
0 Kudos
Highlighted
Frequent Contributor

I am having a hard time with this.....

I have a .NET webform C# project.  I want to call a GP Service, pass it parameters and get results back 

I am currently doing the below in JavaScript and it works great....

but I want to be in a form loop in C# and call it directly from there....

What SDK? API? do I use?  I am trying to create a website, so can I even do this with the SDKs?

What  are all the little references I need to reference to get the code to work?

I have never done this from C# before....

Can someone show me how to reference what I need to reference and make this simple call?

    window.JsController = {
btnGISPush_Click: function () {

var dictstring = document.getElementById(JSONstring).value;

var params = {
request: dictstring
};

window.gpJSON.execute(params).then(function (resultVal) {
finalGPResults = resultVal.results[0].value;
document.getElementById('resultsreturnedfromGPService').value = finalGPResults;
},
function (err) {
console.log(err);
}
);

} // END OF BUTTON CLICK FUNCTION
}; // END OF JS CONTROLLER‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Reply
0 Kudos
Highlighted
Esri Contributor

Hi jay kapalczynski‌,

Yes you are in right track, you can use nugget arcgis runtime sdk.

Alternatively you can perform simple web request as well. (Post request is recommended)

Below is the simple code snippet, will need to modify based on your gptask params.

string gpUrl = "xxxxx//GPServer/GPTaskName";
string requestUrl = gpUrl + "/execute";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(gpUrl));

request.KeepAlive = true;
request.Method = "POST";

request.AllowAutoRedirect = true;
request.CookieContainer = new System.Net.CookieContainer();


request.ContentType = "application/json";
StringBuilder paramString = new StringBuilder();

/**
*
* var params = {
request: dictstring
};
**/

string requestParamString = "[your json request param string]";
paramString.Append($"request={requestParamString}");
paramString.Append($"&f=json");//append like that if you need additional param //f=json to get as json response string, and you can do the same for additional gptask param value


byte[] data = Encoding.ASCII.GetBytes(paramString.ToString());
request.ContentLength = data.Length;

Stream requestStream = request.GetRequestStream();
requestStream.Write(data, 0, data.Length);
requestStream.Close();


HttpWebResponse response = (HttpWebResponse)request.GetResponse();

string responseStr = getStringFromWebResponse(response);
Console.WriteLine(responseStr);


getStringFromWebResponse method

public string getStringFromWebResponse(WebResponse response)
{
// Get the stream containing content returned by the server.
Stream responseDataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(responseDataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();

// Clean up the streams.
reader.Close();
responseDataStream.Close();
response.Close();
return responseFromServer;
}

import shall be

using System;
using System.IO;
using System.Net;
using System.Text;
Reply
0 Kudos
Highlighted
Frequent Contributor

Having an issue....trying to pass this string

{"employees":[{"address":"2125 Baldwin Avenue,Crofton,MD, 21114","distance":"50","id":"4e0e9919-b88f-4073-a621-1279de2a3579"}] }       

 

it could be this as well...

{"employees":[{"address":"2125 Baldwin Avenue,Crofton,MD, 21114","distance":"50","id":"4e0e9919-b88f-4073-a621-1279de2a3579"}, {"address":"1245 Baldwin Avenue,Crofton,MD, 21114","distance":"50","id":"4e0e9919-b88f-4073-a621-1279de2a3579"}] }

If I put " "  around my parameter it does not like it....

string requestParamString = "   {"employees":[{"address":"2125 Baldwin Avenue, #40,Crofton,MD, 21114","distance":"50","id":"4e0e9919-b88f-4073-a621-1279de2a3579"}] }  "

Reply
0 Kudos
Highlighted
Frequent Contributor

Than Aung

2nd Loaded Last question....

Where can I read up more on this solution?  Is there decent documentation and some hello world examples?

Can I also work with map like the arcgis JavaScript api 4.14?  Query, return results write to graphics layer etc?

I am trying to deal with the " "  in my string as such...

string inputParam = "{\"employees\":[{\"address\":\"1520 Split Oak Ln, Henrico, Virginia, 23229\",\"distance\":\"10\",\"id\":\"9a35172e071f4a33b191172a9b4b02ae\"}]}";

Should I have to use a ? like this

paramString.Append($"?request="+ inputParam);

I can go into the RestEndpoint and input as such and it works great.....BUT for some reason the way I am passing the parameter its not working....

IT works from the restendpoint fine but does not work from C#

This is my total code

        protected void btnPassParameters_Click(object sender, EventArgs e)
{
string gpUrl = "https://xxxa.gov/arcgis/rest/services/Test/Counties/GPServer/create";
string requestUrl = gpUrl + "/execute";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(gpUrl));

request.KeepAlive = true;
request.Method = "POST";

request.AllowAutoRedirect = true;
request.CookieContainer = new System.Net.CookieContainer();

request.ContentType = "application/json";
StringBuilder paramString = new StringBuilder();

string inputParam = "{\"employees\":[{\"address\":\"1520 Split Oak Ln, Henrico, Virginia, 23229\",\"distance\":\"10\",\"id\":\"9a35172e071f4a33b191172a9b4b02ae\"}]}";

paramString.Append($"?request="+ inputParam);
//paramString.Append($"request={requestParamString}");
paramString.Append($"&f=json");

byte[] data = Encoding.ASCII.GetBytes(paramString.ToString());
request.ContentLength = data.Length;

Stream requestStream = request.GetRequestStream();

requestStream.Write(data, 0, data.Length);
requestStream.Close();

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

string responseStr = getStringFromWebResponse(response);

Response.Write(responseStr);


}


public string getStringFromWebResponse(WebResponse response)
{
// Get the stream containing content returned by the server.
Stream responseDataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(responseDataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();

// Clean up the streams.
reader.Close();
responseDataStream.Close();
response.Close();
return responseFromServer;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Reply
0 Kudos
Highlighted
Esri Contributor

Hi jay kapalczynski‌,

For this kind of custom web request call, I normally hack by reading the network traffic.

My best candidate is fiddler.

First step, I only the gptask, execute task page, 

Second I open the fiddler. to track that post request call and, I will click [Execute Task (Post)] button from the page.

Third try to find from the fiddler the post request call.

Final step : I try and write same post request call with C#, try and capture the .net web request call network traffic with fiddler as well.

Capturing Traffic from .NET Services with Fiddler 

And then I compare this two traffic and tweak the c# code, mostly paramstring part. 

Good luck, this is my trick  

I have update your total code after I played with a GPTask with c# a few changes. That should be good now

 protected void btnPassParameters_Click(object sender, EventArgs e)
{
string gpUrl = "https://xxxa.gov/arcgis/rest/services/Test/Counties/GPServer/create";
string requestUrl = gpUrl + "/execute";

//make sure requestUrl end with execute **
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(requestUrl ));

request.KeepAlive = true;
request.Method = "POST";

request.AllowAutoRedirect = true;
request.CookieContainer = new System.Net.CookieContainer();

request.ContentType = "application/x-www-form-urlencoded";// my mistake should be form

StringBuilder paramString = new StringBuilder();

string inputParam = "{\"employees\":[{\"address\":\"1520 Split Oak Ln, Henrico, Virginia, 23229\",\"distance\":\"10\",\"id\":\"9a35172e071f4a33b191172a9b4b02ae\"}]}";

// for this inputParam part, instead of escaping the string how about you save json text into a file and read like that , string inputParam = System.IO.File.ReadAllText("your file path")

paramString.Append($"request="+ inputParam);//no need ?

paramString.Append($"&f=json");

byte[] data = Encoding.ASCII.GetBytes(paramString.ToString());
request.ContentLength = data.Length;

Stream requestStream = request.GetRequestStream();

requestStream.Write(data, 0, data.Length);
requestStream.Close();

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

string responseStr = getStringFromWebResponse(response);

Response.Write(responseStr);


}

View solution in original post

Highlighted
Frequent Contributor

Thank you much for the info Than Aung‌ it is greatly appreciated.

New to this implementation from C# and then helps a ton...

One thing that I am lacking in is using the tools you described to track my requests....I am learning one day at a time...I thank you greatly for your help and guidance.

So if I am reading the change correctly the main failure was the format I was passing my parameter in.  I was escaping the string and it was expecting a json string.  

Used when Escaping the string

request.ContentType = "application/x-www-form-urlencoded";//

Used when passing a JSON string

request.ContentType = "application/json";