Passing post parameters to action methods in asp.net mvc? - c#

I'm new to asp.net mvc. I'm having some trouble getting the values of parameters in my Action methods.
I have the following code:
[HttpPost]
public ActionResult ToggleRecommend(string mode)
{
byte[] requestContent = new byte[Request.ContentLength];
Request.InputStream.Read(requestContent, 0, Request.ContentLength);
string content = Encoding.ASCII.GetString(requestContent);
return EmptyResult();
}
I access this method using an Ajax request. The request has these headers:
Accept application/json
Accept-Encoding gzip, deflate
Accept-Language en-gb,en;q=0.5
Connection keep-alive
Content-Length 8
Content-Type text/plain; charset=UTF-8
Host localhost:62718
Referer http://localhost:62718/microsite
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1
X-Request JSON
X-Requested-With XMLHttpRequest
and this body:
mode=off
My problem is that the mode parameter of ToggleRecommend is not being populated with the value from the request - instead, it is null.
The request is reaching my server correctly: the variable content in the method has the value mode=off and Request.ContentLength is 8 as expected. Also, Request.RequestType is "POST", as is intended. However, Request.Form is empty: it has no keys or values. (I don't know if that is relevant).
What is going wrong here? How do I get the value of my mode parameter to go into my action method?
The problem must be to do with post: If I remove the HttpPost attribute and do a request to the Url localhost:62718/microsite/toggleRecommend/?mode=off the mode parameter gets the value off as is intended.
Edit:
The request is being made with javascript using the Mootools library. I've included that part of the code below:
var req = new Request.JSON({ method: "post",
url: "/microsite/toggleRecommend/" ,
autoCancel: true, urlEncoded: false, secure: false,
onFailure: recommendFail, onException: recommendFail,
onSuccess: recommendSuccess
});
req.send({ data: { mode: 'on'} });
Using firebug, I can see the exact format of the request (and that looks fine) so hopefully the specifics of the javascript code doesn't matter.

Your ajax call content/type is text/html, you need to specify to your controller that you are sending application/json information, otherwise he receives the info, but doesn't know how to distribute it to it's params

Related

[FromBody]JToken param is null when ContentType: application/json or it's bad serialized when Contenttype: application/x-www-form-urlencoded [Fiddler]

As the topic says, I've faced with a problem while trying to call an endpoint (POST) with a Request Body via Fiddler.
There is a http api method:
[HttpPost]
[Route("books")]
public IHttpActionResult GetBooks([FromBody]JToken filterRequest)
{...}
In Fiddler I make a POST call with request header:
User-Agent: Fiddler
Host: localhost
Content-Length: 21
Content-Type: application/json
And the Request Body looks like: { "title" : "Harry Potter"}. While debugging it, I get null filterRequest parameter.
But when I use Content-Type: application/x-www-form-urlencoded, parameter filterRequest parameter is not null but unfortunately contains incorrect syntax like:
{{"{ \"title\" : \"Harry Potter\"}": ""}}
And it's wrong serialized by:
var columnsFilter = new JavaScriptSerializer().Deserialize<Dictionary<string, string>>(filter);
I have no idea what I am doing wrong here. Maybe do you have met with similar problem and could help?
It turned out that the whole problem was based on wrong quotes. I had to use just ' and the posted request body was correct with Content-Type: application/json.

Difference between RestSharp methods AddParameter and AddQueryParameter using HttpGET

I'm using RestSharp to call an external API.
This works:
var client = new RestClient(apiUrl);
var request = new RestRequest(myurl, Method.GET);
foreach (var param in parameters)
{
request.AddQueryParameter(param.Key, param.Value);
}
var response = client.Execute(request);
This doesn't:
var client = new RestClient(apiUrl);
var request = new RestRequest(myurl, Method.GET);
foreach (var param in parameters)
{
request.AddParameter(param.Key, param.Value);
}
var response = client.Execute(request);
Resulting in:
System.Exception: API Call MyWebAPIMethod GET: Failed with status code
0 - Unable to connect to the remote server
What's the difference between AddParameter and AddQueryParameter?
According to the documentation they should function the same when using HttpGET and according to Fiddler they seem to generate the same URL as well.
To answer your question
AddQueryParameter adds a parameter in the query string as ParameterType.QueryString whereas AddParameter(string, object) adds the parameter as ParameterType.GetOrPost
For more details on each parameter type, see:
GetOrPost: https://github.com/restsharp/RestSharp/wiki/ParameterTypes-for-RestRequest#getorpost
QueryString: https://github.com/restsharp/RestSharp/wiki/ParameterTypes-for-RestRequest#querystring
To solve your problem
It seems it is unrelated to the type of parameter, because the exception thrown seems to indicate you aren't even connecting to the remote server.
make sure you pass the same apiUrl / myUrl in both cases.
To answer the OP and anyone else who might have trouble with the concept.
It took me awhile to get around to the concept.
You probably need to visualise the RESTful standard of how to construct a GET request message in a url against constructing for a POST request message.
You will notice that for GET , the parameter(s) are attached to the URL header
whereas for the POST , the parameter(s) are placed in the body of the message.
RestSharp 's method AddQueryParameter() will only add the (Query) parameters in the header of the message, whereas the AddParameter() will only add the parameters to the mesasge body. As demonstrated below the GET has one query parameter with a value of "Flavours" . For the POST , the parameters contact_name and company_name are located in the bottom of the message body.
Eg:
GET message format :
GET http://www.consumerdiarydemo.cbrnetwork.test.au/api/ConsumerDiary/getSizesOrFlavours/Flavours HTTP/1.1
Host: www.consumerdiarydemo.cbrnetwork.test.au
Connection: keep-alive
Accept: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Referer: http://www.consumerdiarydemo.cbrnetwork.test.au/ConsumerDiaryPage2template
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
POST message format :
POST
http://localhost:1234567/api/customers HTTP/1.1
Accept: application/json, text/javascript, /; q=0.01
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
{"contact_name":"value_data1","company_name":"value_data2"}
AddParameter / Get or Post
GetOrPost behaves differently based on the method. If you execute a GET call, RestSharp will append the parameters to the Url in the form url?name1=value1&name2=value2.
On a POST or PUT Requests, it depends on whether you have files attached to a Request. If not, the Parameters will be sent as the body of the request in the form name1=value1&name2=value2.
Ref: https://restsharp.dev/usage.html#get-or-post
AddQueryParameter / Query String
QueryString works like GetOrPost, except that it always appends the parameters to the url in the form url?name1=value1&name2=value2, regardless of the request method.
Ref: https://restsharp.dev/usage.html#query-string

How to get RestSharp to properly deflate compressed HTTP response?

I'm using RestSharp to make a call to REST service. My call looks something like this:
var request = new RestRequest("/foo", Method.POST);
request.JsonSerializer.ContentType = "application/json; charset=utf-8";
request.AddJsonBody(new string[] { "param1", "param2" });
var response = this._client.Execute<Foo>(request);
For most other calls this works fine. I'm running into issues when the response is compressed. The headers in the response look (mostly) like this:
HTTP/1.1 200 OK
Uncompressed-Size: 35000
Content-Length: 3019
Content-Encoding: deflate
Content-Type: application/json
The issue is when I call this method with RestSharp I keep getting the error:
Error: Block length does not match with its complement.
I've tried setting the Accept-Encoding header in the request but it still produces the error. I also tried using a custom deserializer but the error is occurring before deserialization. From what I can tell, RestSharp should automatically handle deflation if the Content-Encoding header says deflate (which it does).
How can I get RestSharp to handle the deflation properly?
UPDATE
In the end I was able to have the service changed to look for an Accept-Encoding header in the request with a value of identity. If found, the service was changed to return the data uncompressed.
This is unfortunately not really a solution to the original issue but it does resolve the problem for me. If a better solution is posted I will try it.
According to this post, you should be able to handle it if you won't pass charset=utf-8 in content type.
Please refer to this:
RestSharp compress request while making rest call to server

ASP.NET WebAPI - Issues with [FromBody]

I'm looking to implement a new API but rather than going down my usual route of PHP I've opted for C#.
I've had a little play with the 'MVC 4 API' example, but so far I can't seem to get my requests working.
I've created a controller called 'Values' and have the following method:
[HttpPost]
public void Post([FromBody]string value)
{
string body = value;
}
I've then sent the following POST request via fiddler to said API:
User-Agent: Fiddler
Host: localhost:56501
Content-Length: 10
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
value=test
After running this, it looks as though the method is being called, but when attempting to get the 'value' sent through the body, it doesn't seem to pick up on it and instead gives me a null.
I can't seem to make it work for Content-Type: application/x-www-form-urlencoded, but this should work meanwhile :)
User-Agent: Fiddler
Host: localhost:56501
Content-Length: 6
Content-Type: application/json; charset=UTF-8
"test"
So I found out that if you need to make it work with application/x-www-form-urlencoded then you only need to pass =value as the body of your request. Definitely weird, but I guess this is not MVC, it's WebApi, so you shouldn't be passing application/x-www-form-urlencoded anyway ;)

JQuery ajax call executes error on 200 [duplicate]

This question already has answers here:
Ajax request returns 200 OK, but an error event is fired instead of success
(14 answers)
Closed 7 years ago.
My c#/WebApi server code looks like:
[HttpPost]
public HttpResponseMessage Logout()
{
// do some stuff here ...
return Request.CreateResponse(HttpStatusCode.OK);
}
In the client I do an ajax call using jquery 2.0.3
ADDED: Jquery code (typescript)...
var ajaxSettings: JQueryAjaxSettings = {};
ajaxSettings.type = 'POST';
ajaxSettings.data = null;
ajaxSettings.contentType = "application/json; charset=utf-8";
ajaxSettings.dataType = "json";
ajaxSettings.processData = false;
ajaxSettings.success = (data: any, textStatus: string, jqXHR: JQueryXHR) => {
console.log("Success: textStatus:" + textStatus + ", status= " + jqXHR.status);
};
ajaxSettings.error = (jqXHR: JQueryXHR, textStatus: string, errorThrow: string) => {
console.log("Error: textStatus:" + textStatus + ", errorThrow = " + errorThrow);
};
$.ajax("http://apidev.someurl.com/v1/users/logout", ajaxSettings);
ADDED 2: Request headers resulting from the above code:
POST http://apidev.someurl.com/v1/users/logout HTTP/1.1
Host: apidev.someurl.com
Connection: keep-alive
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Origin: http://apidev.someurl.com
Authorization: SimpleToken 74D06A21-540A-4F31-A9D4-8F2387313998
X-Requested-With: XMLHttpRequest
Content-Type: application/json; charset=utf-8
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Referer: http://apidev.someurl.com/test/runner/apitest/index.html?
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
The response is 200, yet the error handler from the ajax call is fired instead of the success handler. Reason: parseerror, unexpected end of input.
One solution is to change serverside code to:
return Request.CreateResponse<String>(HttpStatusCode.OK, "Logout ok");
I understand that an empty response is not valid JSON, but the response message is intentionally empty. The 200 says it all.
The response headers look like:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://apidev.someurl.com
Access-Control-Allow-Credentials: true
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 05 Jan 2014 01:20:30 GMT
Content-Length: 0
Is this a bug in jquery? Or should the Request.CreateResponse(OK) never be used that way? Should I fix this with some workaround in the client? AFAIK the server is not doing it wrong here ... any thoughts?
EDIT:
Thanks to feedback of kevin, nick and John this issue has become clear. The solution I choose is to return a NoContent
return Request.CreateResponse(HttpStatusCode.NoContent);
Serverside this seems for this case the correct code. Clientside this is handled perfectly by JQuery (the succes handler is called). Thanx all for clearing this up!
(I don't know who to give credit for the answer ... since nick and kevin gave their valuable feedback in comments, johns feedback also added a better understanding) ... if no other suggestions are given ... i'll later mark the only 'answer' as the Answer)
Thanks all!
From MSDN, HttpStatusCode.OK is defined as follows (emphasis mine):
Equivalent to HTTP status 200. OK indicates that the request succeeded and that the requested information is in the response. This is the most common status code to receive.
Because a 200 implies some content is sent with the response (even an empty JSON object literal would be fine), you can run into problems if jQuery's Ajax implementation assumes a non-zero length response but does not receive it, especially if it tries parsing JSON (and possibly XML) from it. This is why John S makes the suggestion of changing the dataType to text; doing so would allow you to take specific action when receving an empty response.
On the other hand, HttpStatusCode.NoContent is defined as (emphasis mine):
Equivalent to HTTP status 204. NoContent indicates that the request has been successfully processed and that the response is intentionally blank.
In your particular situation, it may make more sense to set the status code to HttpStatusCode.NoContent to ensure that jQuery Ajax understands that it does not need to attempt any parsing/processing of the response.
This is how jQuery works.
JQuery will assume the response is JSON if either:
You specify dataType: 'json' in the ajax call, or
You do not include the dataType setting but jQuery detects the response is JSON because of a response header.
And when jQuery assumes the response is JSON, it automatically tries to parse the response into objects before it calls the success handler. If the parse fails, the error handler is called instead.
From the jQuery documentation:
As of jQuery 1.9, an empty response is also rejected; the server
should return a response of null or {} instead.
I don't know why jQuery couldn't make an exception for an empty response and treat it the same as null, or even as undefined, but if you cannot (or won't) change the response, a work-around would be to specify dataType: 'text' and then parse the response yourself.
$.ajax(url, {
type: 'post',
dataType: 'text',
data: params,
success: function(text) {
if (text) {
var data = jQuery.parseJSON(text);
// ...
}
}
});

Categories

Resources