Add list of entity as parameter - c#

Is it possible to retrieve a list of entities as a parameter for an action in c# odata?
Tried the following but it casues the entire controller to not work:
[HttpPost]
[NhSessionManagement()]
[ODataRoute("BatchUpdate")]
public async Task<IHttpActionResult> BatchUpdate(List<Item> items, bool updateDefaultJSONFile)
{
return Ok();
}
This is the config:
{
var action = builder.EntityType<Item>().Collection.Action("BatchUpdate");
action.CollectionParameter<Item>("items");
action.Parameter<bool>("updateDefaultJSONFile");
}
This is how I then send the data:
$http.post(appConfig.serviceUrl + "api/items/Service.BatchUpdate", { items: itemsToUpdate, updateDefaultJSONFile: true}).success(function (data, status, headers, config) {
debug("Successfully saved");
}).error(function (data, status, headers, config) {
debug("Failed to save");
});
In fiddler:
POST http://192.168.20.108/api/items/Service.BatchUpdate HTTP/1.1
Host: 192.168.20.108
Connection: keep-alive
Content-Length: 83114
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://192.168.20.108
Authorization: Bearer ****
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://192.168.20.108/
Accept-Encoding: gzip, deflate
Accept-Language: sv-SE,sv;q=0.9,en-US;q=0.8,en;q=0.7
{"items":[{"Key":"helpful","Text":"test"}],"updateDefaultJSONFile":false}

Specify collection parameters as an array, not a list:
[HttpPost]
[NhSessionManagement()]
[ODataRoute("BatchUpdate")]
public async Task<IHttpActionResult> BatchUpdate(Item[] items, bool updateDefaultJSONFile)
{
return Ok();
}
Config is correct, good job.

Related

C# Http WebRequest JSON

I'm new to WebRequests and I tried this:
string json = #"{""Gebruikersnaam"":""user"",""Wachtwoord"":""pass"",""IngelogdBlijven"":true}";
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://pontessg.magister.net/api/sessies");
httpWebRequest.ContentType = "application/json";
httpWebRequest.ContentLength = json.Length;
Console.WriteLine(json.Length);
Console.WriteLine(json);
Console.Read();
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
}
My code is keep returning me ERROR (400) and I don't really know why I think I forgot something, but I don't know what
(The Headers)
Request URL:https://pontessg.magister.net/api/sessies
Request Method:POST
Status Code:200 OK
Remote Address:[...]
Response Headers
view parsed
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 76
Content-Type: application/json; charset=utf-8
Expires: -1
Date: Sat, 25 Feb 2017 21:45:33 GMT
X-Frame-Options: DENY
Strict-Transport-Security: max-age=[...]
Request Headers
view parsed
POST /api/sessies HTTP/1.1
Host: pontessg.magister.net
Connection: keep-alive
Content-Length: 88
Accept: application/json, text/plain, */*
X-API-Client-ID: 12D8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Origin: https://pontessg.magister.net
Content-Type: application/json;charset=UTF-8
DNT: 1
Referer: https://pontessg.magister.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: SESSION_ID=[...]; M6UserName=user; username=pass; Magister.UserName=user; [...]
Request Payload
{"Gebruikersnaam":"user","Wachtwoord":"pass","IngelogdBlijven":true}
When I try the JS code below in the console of my browser, it returns 200 OK
$.ajax({
url: "https://pontessg.magister.net/api/sessies",
type: "POST",
data: "{\"Gebruikersnaam\":\"user\",\"Wachtwoord\":\"pass\",\"IngelogdBlijven\":true}",
contentType: "application/json;charset=utf-8",
success: action_Succeeded,
error: action_Failed
});
function action_Succeeded(r) {
console.log("succes");
}
function action_Failed(r1, r2, r3) {
alert("fail");
}
If someone could help me with this, I would like that

Ajax success function won't execute

I have an apache cordova project where I'm trying to post form data from the client to the database. I can see the json I send going out to my API which then sends the data to the DAL and then to the database. The entry correctly updates the table and then returns a 1 or -1 based on whether or not a previous entry exists. This value is then sent to the client. I can see the exact response being sent back, but my ajax success function won't fire.
Ajax:
$("#submit").click(function () {
var info = {
Username: $("#username").val(),
Password: $("#password").val(),
Firstname: $("#firstname").val(),
Lastname: $("#lastname").val(),
Email: $("#email").val()
};
info = JSON.stringify(info);
event.preventDefault();
$.ajax({
type: "POST",
dataType: "json",
async: false,
url: "http://localhost:57207/api/User/RegisterUser",
data: info,
success: function(data) {
console.log(data);
},
error: function(input) {
console.log(JSON.stringify(input));
}
})
});
Controller:
[System.Web.Http.HttpPost]
public JObject RegisterUser(JObject obj)
{
RegisterUsers user = new RegisterUsers();
user = JsonConvert.DeserializeObject<RegisterUsers>(((JProperty)obj.First).Name);
var temp = DataAccessLayer.RegisterUser(user.Username, user.Password, user.Firstname, user.Lastname, user.Email, null, null);
JObject jobj = new JObject();
jobj.Add("output", temp.ToString());
return jobj;
}
I have been using fiddler to check my response and request, and here is the raw data:
Request:
POST http://localhost:57207/api/User/RegisterUser HTTP/1.1
Host: localhost:57207
Connection: keep-alive
Content-Length: 125
Accept: text/html, */*; q=0.01
Origin: http://evil.com/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:4400/test.html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
{"Username":"johndoe","Password":"password!!!","Firstname":"john","Lastname":"doe","Email":"johndoe#random.com"}
Response:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
Access-Control-Allow-Origin: *
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRGV2ZWxvcG1lbnRcVGV4dDJQaG9uaWNzXFJlc3RBUElcYXBpXFVzZXJcUmVnaXN0ZXJVc2Vy?=
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,OPTIONS
Access-Control-Allow-Headers: Content-Type, soapaction
Date: Wed, 08 Feb 2017 19:52:43 GMT
Content-Length: 15
{"output":"-1"}
My error function is the one that fires, and here is the output:
console.log:
{"readyState":0,"status":0,"statusText":"NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://localhost:57207/api/User/RegisterUser'."}
Update:
I was able to set the async to true and my new error message is this:
{"readyState":0,"status":0,"statusText":"error"}
Try instead returning an IHttpActionResult or IActionResult, Ok() for a 200 response.
public IActionResult RegisterUser(JObject obj)
{
RegisterUsers user = new RegisterUsers();
user = JsonConvert.DeserializeObject<RegisterUsers>(((JProperty)obj.First).Name);
var temp = DataAccessLayer.RegisterUser(user.Username, user.Password, user.Firstname, user.Lastname, user.Email, null, null);
JObject jobj = new JObject();
jobj.Add("output", temp.ToString());
return Ok(jobj);
}
If it continues to fail, try just return a simple string like return Ok("Hello World!");. If it succeeds with simple string, then the serialization of the object may be failing or is coming out as invalid JSON.

The request contains an entity body but no Content-Type header

I'm getting a 415 Unsupported Media Type error trying to POST data. The response has "The inferred media type 'application/octet-stream' is not supported for this resource." although the content-type is set application/json.
Does anyone see what's going wrong here?
ApiController:
[HttpPost]
[Route( #"api/Assignments/{id:int}" )]
public HttpResponseMessage Save( int id, [FromBody] Assignment assignment )
{
try
{
int result = 0;
.
.
.
return Request.CreateResponse( HttpStatusCode.OK );
}
catch( Exception ex )
{
//log error
return Request.CreateResponse( HttpStatusCode.BadRequest );
}
}
Service:
service.saveAssignment = function (assignment) {
var serviceurl = baseURL + "api/Assignments/" + (assignment.ID || 0);
return $http({
method: "POST",
data: angular.toJson(assignment),
dataType: "json",
headers: { "Content-Type": "application/json; charset=UTF-8;" },
url: serviceurl
});
};
Request:
POST http://localhost:31415/api/Assignments/0 HTTP/1.1
Host: localhost:31415
Connection: keep-alive
Content-Length: 43
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://localhost:31415
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
Content-Type: application/json; charset=UTF-8;
DNT: 1
Referer: http://localhost:31415/Settings
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
{"SemesterID":3,"CourseID":1,"FacultyID":1}
Response:
{"Message":"The request contains an entity body but no Content-Type header.
The inferred media type 'application/octet-stream' is not supported for this resource.", "ExceptionMessage":"No MediaTypeFormatter is available to read an object of type 'Assignment' from content with media type 'application/octet-stream'.", "ExceptionType":"System.Net.Http.UnsupportedMediaTypeException",
"StackTrace":" at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable'1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable'1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)"}

PostAsJsonAsync POST variables don't arrive at Flight PHP REST server

I have a Flight PHP REST server set up.
At 1 end point it expects POST data and based on one of the POST data it retrieves some data from the database and returns it as JSON.
When I use the Postman REST extension in Chrome I see the correct result. But when I do the call using my C# application the returned json is null because the $_POST seems empty.
This is my Flight index.php:
Flight::route('POST /getText', function(){
// Create a new report class:
$reportText = new ReportText;
$theText = $reportText->ParsePost($_POST);
if ($theText == null)
{
echo null;
}
else
{
echo json_encode($theText);
}
});
This is my ParsePost:
public function ParsePost($PostDictionary)
{
$textArray = null;
foreach ($PostDictionary as $key => $value)
{
if (!empty($value))
{
list($tmp, $id) = explode("_", $key);
$text = $this->geFooWithText($id);
$textArray[$key] = "bar";
}
}
return $textArray;
}
This is my C# part:
private static async Task RunAsyncPost(string requestUri)
{
using (var client = new HttpClient())
{
// Send HTTP requests
client.BaseAddress = new Uri("myUrl");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// HTTP POST
var response = await client.PostAsJsonAsync(requestUri, new { question_8 = "foo", question_9 = "bar" });
response.EnsureSuccessStatusCode(); // Throw if not a success code.
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
if (string.IsNullOrEmpty(json))
{
throw new ArgumentNullException("json", #"Response from the server is null");
}
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
foreach (var kvp in dictionary)
{
Debug.WriteLine("Key: {0}, Value: {1}", kvp.Key, kvp.Value);
}
}
}
catch (HttpRequestException e)
{
// Handle exception.
Debug.WriteLine(e.ToString());
throw;
}
}
}
This is the response from Postman:
{
"question_8": "foo",
"question_9": "bar"
}
It seems I'm missing something in my call using C#.
[Update]
In this post (Unable to do a HTTP POST to a REST service passing json through C#) the same problem seems to appear.
Using Fiddler was suggested.
Using Postman and x-www-form-urlencoded:
POST http://myHost/api/getText HTTP/1.1
Host: myHost
Connection: keep-alive
Content-Length: 29
Cache-Control: no-cache
Origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip,deflate
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
question_8=foo&question_9=bar
Using Postman and form-data:
POST http://myHost/api/getText HTTP/1.1
Host: myHost
Connection: keep-alive
Content-Length: 244
Cache-Control: no-cache
Origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvb4wmaP4KooT6TFu
Accept: */*
Accept-Encoding: gzip,deflate
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
------WebKitFormBoundaryvb4wmaP4KooT6TFu
Content-Disposition: form-data; name="question_8"
foo
------WebKitFormBoundaryvb4wmaP4KooT6TFu
Content-Disposition: form-data; name="question_9"
bar
------WebKitFormBoundaryvb4wmaP4KooT6TFu--
Using my C#-application:
POST http://myHost/api/getText/ HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-8
Host: myHost
Content-Length: 50
Expect: 100-continue
Connection: Keep-Alive
{"question_8":"foo","question_9":"bar"}
The C# application is sending it clearly in a different way.
I've found the problem.
Because I use client.PostAsJsonAsync() the POST data is send as json, as you can see in Fiddler.
PHP doesn't expects the POST data to be in json format.
To read that data I need to use $data = file_get_contents('php://input'); in my PHP file.
Now I have my keys and values and can I continue. It looks like PHP needs a $_JSON variable ;)

HttpWebRequest Http Headers

I'm using HttpWebRequest component and trying to POST data to server.
When I use browser I can trace that it sends this request
POST https://plus.google.com/_/socialgraph/mutate/modifymemberships/?_reqid=1950158&rt=j HTTP/1.1
Host: plus.google.com
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
X-Same-Domain: 1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Referer: https://plus.google.com/_/apps-static/_/js/home/b,s/rt=h/ver=OeD97kiQfn8.en./sv=1/am=!iPoVWvyH1UcKPT9bc1pNSZLcSj8oHAelto24gJorhwk/d=1/
Content-Length: 216
Cookie: PREF=ID=c42cff62752fc3e8:U=dae37ffa177e0689:FF=0:TB=2:LD=en:CR=2:TM=1244434765:LM=1311323210:DV=0SJoub_nzRUL:GM=1:S=EuE8opfqNl8PGGHI; NID=54=enDovqVn7CSHrPtZ2ZSPAt4PrE0ZZE-rWJawva2NiUWC1TzreG-sVdiSnRp7kolqcvMCGCIKt7agHKT6Hi2JZkV5qYmY_fUkxFjk6PUc7TrdNRAT7_9mRnvwOxeBOcng; rememberme=false; __utma=1.340991765.1324442547.1324723420.1324806933.8; __utmz=1.1324723420.7.7.utmcsr=google.com|utmccn=(referral)|utmcmd=referral|utmcct=/accounts/Logout2; OTZ=1044056_4_4_133320_8_385320; S=analytics-realtime-frontend=h23QCGj_I9O7FLG9cqDjkA:awfe=SnIt_U1wxuihQ1myCwuiZA:awfe-efe=lCXLSEuiUzX3HyaRuXVuRg:adwords-optimization=yCZeLrx1FD0uGQFYb07LTQ:adwords-common-ui=WfNukVX7rVpTuVtMlZ6IbA; S_awfe=tyb6VRVQyBHkv8nbfMNWRg; GMAIL_RTT=571; __utmc=1; HSID=AtaMO-oLk9-OMZkiv; SSID=AGt3gDSdd3Q98pA81; APISID=7xRgosYs7uOXzd0Y/AI4OXaHRTViR8oE8s; SAPISID=0HNI_ffNupNL-UfT/Ao6YbG5vkEashPdOM; ULS=EgYKBBICZW4Yy-Xb9wQ; SID=DQAAALMAAADk5OelxcPoQKO8FrSoOfOGoTHX4HeVfeJJQhtd19k07mJMUhJkiehF1FTzb7jNt34c80UGpyXEJT5FML373p6RR_5EQ3etVYjUXmgqHsdO7G-XuP_k_m798MDvd4AWkDX2vKVtqc5zA_olxB9UkJBLU_g2IM2vZ3Scp-eThZj8C3uZuzdN_DCpQeVjrU6a1kiIdQRsz9rUtxzoC0E22Ux4ba0QneaWBT73Ns14wh7fqZtYB-DRB2zcWkXXoNnV67U; FBS_VI_1324806859_0=ot_00Qg-hkQV7uhIEb0dTMT0_DD6aAI
Pragma: no-cache
Cache-Control: no-cache
a=%5B%5B%5B%225947b6d78a8231f3%22%5D%5D%5D&m=%5B%5B%5B%5Bnull%2Cnull%2C%22113690702042497323038%22%5D%2C%22Stephanie%20Parker%22%2C%5B%5D%5D%5D%5D&r=%5B%5B%5D%5D&at=AObGSAg06IXl5iYSceecKRc64xHVAB_GDw%3A1324806859000&
And when I use HttpWebRequester is sends following data which results in Code 400 rather then Code 200
POST https://plus.google.com/_/socialgraph/mutate/modifymemberships/?_reqid=1950158&rt=j HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
Accept-Language: en-gb,en;q=0.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
X-Same-Domain: 1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Referer: https://plus.google.com/_/apps-static/_/js/home/b,s/rt=h/ver=OeD97kiQfn8.en./sv=1/am=!iPoVWvyH1UcKPT9bc1pNSZLcSj8oHAelto24gJorhwk/d=1/
Pragma: no-cache
Cache-Control: no-cache
Host: plus.google.com
Cookie: ULS=EgYKBBICZW4Yp_7k9wQ; SID=DQAAALYAAAAZuUVe6hDQbW__dA1Itrcz8thm2Ncxk5YFMfpeiKyr6Pps1Pu0ajmReczMDHKGnDpk3yrx7WFy-5QMOf0Fu4WiPVdUWcU_cLNfD7FhKtqmSmOgFiffTkyj8dg0bsTeahhrKR7j75rjU_eXqGnQI2qcJHOyk1cLEkWNaWyLRGeYDrsfAh6uzx4AI-1GtKbwwrE7UHsn_sUFG1DuwI_Ct_g9C2llFVVyQruvFnlmRE1xDE_ORwvnBYCrGQYjyt1blg8; HSID=AbkExs5EzrPodpoKx; SSID=A2y_-xD7iOhW9Y2HF; APISID=73YQ7BugDgjmMSdd/AgFF1ClZc0z-fpPGM; SAPISID=mT6qzvCACzlvDrg-/AN1ajSgZCB0R9xOmX
Content-Length: 216
Connection: Keep-Alive
a=%5b%5b%5b%225947b6d78a8231f3%22%5d%5d%5d&m=%5b%5b%5b%5bnull%2cnull%2c%22113690702042497323038%22%5d%2c%22Stephanie%20Parker%22%2c%5b%5d%5d%5d%5d&r=%5b%5b%5d%5d&at=AObGSAg06IXl5iYSceecKRc64xHVAB_GDw%3a1324806859000&
So any idea why this to similar requests have 2 different server response?
BTW I did check cookies and they are fine. I'm just puzzled on why my request would not work.
UPDATE Request Code added
webRequest_ = (HttpWebRequest)HttpWebRequest.Create(Params.URL);
webRequest_.Method = "POST";
//webRequest_.Proxy = new WebProxy("http://plus.google.com", false);
webRequest_.UserAgent = Params.UserAgent;
webRequest_.Headers.Add("Accept-Language", "en-gb,en;q=0.5");
webRequest_.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
webRequest_.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
webRequest_.KeepAlive = true;
webRequest_.Headers.Add("X-Same-Domain", "1");
webRequest_.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
webRequest_.Referer = "https://plus.google.com/_/apps-static/_/js/home/b,s/rt=h/ver=OeD97kiQfn8.en./sv=1/am=!iPoVWvyH1UcKPT9bc1pNSZLcSj8oHAelto24gJorhwk/d=1/";
webRequest_.CookieContainer = Params.Cookie;
webRequest_.Headers.Add("Pragma", "no-cache");
webRequest_.Headers.Add("Cache-Control", "no-cache");
var sp = webRequest_.ServicePoint;
var prop = sp.GetType().GetProperty("HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic);
prop.SetValue(sp, (byte)0, null);
var parameters = new StringBuilder();
foreach (var key in Params.Params)
{
parameters.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(key.ToString()),
HttpUtility.UrlEncode(Params.Params[key.ToString()]).Replace("+","%20"));
}
using (var writer = new StreamWriter(webRequest_.GetRequestStream()))
{
writer.Write(parameters.ToString());
}
After extensive testing I have figured out that problem is not in a header but rather in the data that gets posted, particularly in "at" parameter which is stands for session Id. After successfully generation session id it did work like a charm.

Categories