I have a web api method which is as follows,
[Route("api/Nltk")]
[HttpPost]
public string Create([FromBody]string text)
{
string result = "Error";
//Assign result here
return result;
}
When I make a POST request I get 404 - File or directory not found. error. While other methods (which are all GET methods) in the same api work just fine. For further detail http://ozgurakpinar.net/api/Nltk is the complete url.
The following is one of the methods I've tried, so far.
var values = new Dictionary<string, string> {
{ "text", "This is a relatively short sentence." },
};
HttpClient client = new HttpClient();
var content = new FormUrlEncodedContent(values);
var result = client.PostAsync("http://ozgurakpinar.net/api/Nltk", content).Result;
Edit: After I added the FromBody attribute the method is finally called, but the value of text is null.
First, I think you may have a typo. It should be [FromBody] not [FormBody].
Secondly, you need to append an "=" before your content string.
ie:
client.PostAsync("http://ozgurakpinar.net/api/Nltk", "=" + content)
When you are giving a name to your value then actually you are looking for a class with that member. In your case you are posting to a method which accept a class having a text member of string type.
If you need to post to a method having a string parameter then no need to give it a name. Below is working code.
var values = new Dictionary<string, string> {{ "", "This is a relatively short sentence." }};
var content = new FormUrlEncodedContent(values);
var client = new HttpClient();
var result = client.PostAsync("http://localhost:49923/api/Nltk", content).Result;
Console.Write(result);
Related
I've got a working Java method that uses java.net.HttpURLConnection that I should re-implement in C# using the .NET HttpClient.
Java method:
public static String getMyThingAPIToken() throws IOException{
URL apiURL = new URL("https://myThingAPI/token");
HttpURLConnection apiConnection = (HttpURLConnection) apiURL.openConnection();
apiConnection.setRequestMethod("POST");
apiConnection.setDoOutput(true);
String apiBodyString = "myThingAPI login id and secret key";
byte[] apiBody = apiBodyString.getBytes(StandardCharsets.UTF_8);
OutputStream apiBodyStream = apiConnection.getOutputStream();
apiBodyStream.write(apiBody);
StringBuffer apiResponseBuffer;
try (BufferedReader in = new BufferedReader(new InputStreamReader(apiConnection.getInputStream()))){
String inputline;
apiResponseBuffer = new StringBuffer();
while((inputline = in.readLine()) != null) {
apiResponseBuffer.append(inputline);
}
}
}
So far, my C# looks like below, and you'll notice that this early form of my implementation does not interpret the response. Nor does it have a string return type required for the token string.
This is because when I test it, the response has:
StatusCode: 400
ReasonPhrase: 'Bad Request'
So something in my apiBody byte array or use of PostAsync must be different to what the Java method does, but I cannot work out what it could be.
public async static Task<HttpResponseMessage> getMyThingAPIToken(HttpClient client)
{
var apiURI = new Uri("https://myThingAPI/token");
string apiBodystring = "myThingAPI login id and secret key";
byte[] apiBody = System.Text.Encoding.UTF8.GetBytes(apiBodystring);
var response = await client.PostAsync(apiURI, new ByteArrayContent(apiBody));
return response;
}
The Java code doesn't specify a type which means that by default the request uses application/x-www-form-urlencoded. This is used for FORM POST requests.
The default content type for ByteArrayContent on the other hand is application/octet-stream while for StringContent it's text/plain.
FORM content is used through the FormUrlEncoodedContent class which can accept any Dictionary<string,string> as payload.
The input in the question is not in a x-www-form-urlencoded form so either it's not the real content or the API is misusing content types.
Assuming the API accepts proper x-www-form-urlencoded content, the following should work:
var data=new Dictionary<string,string>{
["login"]=....,
["secret"]=.....,
["someOtherField"]=....
};
var content= new FormUrlEncodedContent(data);
var response=await client.PostAsync(apiURI,content);
To send any text using application/x-www-form-urlencoded, we need to specify the content type in StringContent's constructor:
var contentType="application/x-www-form-urlencoded";
var content= new StringContent(apiBodyString, Encoding.UTF8,contentType);
var response=await client.PostAsync(apiURI,content);
Can you try using following code:
client.BaseAddress = new Uri("https://myThingAPI/");
var message = new HttpRequestMessage(HttpMethod.Post, "/token");
// Add your login id and secret key here with the format you want to send
message.Content = new StringContent(string.Format("userName={0}&password={1}", UserName, Password));
var result = await client.SendAsync(message);
return result;
I have the following .Net Core 2.2 controller method, which is always receiving a null value:
public class ValuesController : Controller
{
[HttpPost]
public async Task<IActionResult> AddValue(string value)
{
var newValue = await DoSomethingWithValue(value); // value is null here
// Other code
return Ok();
}
}
The calling code is as follows:
string newValue = Guid.NewGuid();
//var stringContent = new StringContent(newValue);
var result = await httpClient.PostAsync(uri + newValue, null);
if (!result.IsSuccessStatusCode)
The controller method is called successfully, but whether I try to pass the value as HttpContent, or as a query parameter (e.g. myuri/AddValue/123) it still comes through as null. What could I be doing wrong here?
First, that's not a query param; that's a route segment. If you want to receive it that way, you need to specify a route param:
[HttpPost("AddValue/{value}")]
Otherwise, you need to send it as an actual query param, i.e. myuri/AddValue?value=123.
As for the post, the default binding is FromForm, which is expecting an x-www-form-urlencoded or multipart/form-data encoded body, which is not what you're sending. You would need to do:
var stringContent = new StringContent($"value={newValue}", Encoding.UTF8, "application/x-www-form-urlencoded");
Or you can actually use FormUrlEncodedContent:
var values = new Dictionary<string, string>
{
["value"] = Guid.NewGuid().ToString()
};
var formUrlEncodedContent = new FormUrlEncodedContent(values);
Trying to send a rather long string to a REST web api (youtrack). I get the following exception:
Invalid URI: The Uri string is too long.
My code:
var encodedMessage = HttpUtility.UrlEncode(message);
var requestUri = string.Format("{0}{1}issue/{2}/execute?comment={3}", url, YoutrackRestUrl, issue.Id, encodedMessage);
var response = await httpClient.PostAsync(requestUri, null).ConfigureAwait(false);
So I took my chances with a FormUrlEncodedContent
var requestUri = string.Format("{0}{1}issue/{2}/execute", url, YoutrackRestUrl, issue.Id);
var postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("comment", message));
var content = new FormUrlEncodedContent(postData);
var response = await httpClient.PostAsync(requestUri, content).ConfigureAwait(false);
Which results in the exact same issue.
The string (comment) I am sending, is the changed file set of a commit into SVN. Which can be really long, so I don't really have a way to get around that. Is there a way to post content without the string length restriction?
Read the following topics, but didn't find an answer there:
.NET HttpClient. How to POST string value?
How do I set up HttpContent for my HttpClient PostAsync second parameter?
https://psycodedeveloper.wordpress.com/2014/06/30/how-to-call-httpclient-postasync-with-a-query-string/
http://forums.asp.net/t/2057125.aspx?Invalid+URI+The+Uri+string+is+too+long+HttpClient
Well the short answer to it - just put it into the Body, instead of trying to push all the data via the URL
But as the work on the ticket showed - the answer was here How to set large string inside HttpContent when using HttpClient?
The actual problem beeing in the FormUrlEncodedContent
Try this..Will be helpful for uwp..
Uri uri = new Uri("your uri string");
Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient();
var value1 = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string,string>>
{
// your key value pairs
};
var response = await client.PostAsync(uri,new HttpFormUrlEncodedContent(value1));
var result = await response.Content.ReadAsStringAsync();
I am writing a small application that sends data to a server through REST API as simple URL calls. I use the RestSharp library to do this. My problem is, that some data strings I am sending include the / character.
I can't leave the character as it is, since the called URL would then be invalid. But when I replace it with %2F (which is then translated back on the server side), the RestSharp replaces the % character again, giving %252F. The Rest call than fails since server is missing the backslash.
I have searched the web but found no working solution to this problem. Do you have any idea how to solve it, without using different library and rewriting it myself? Also, not using the backslash is NOT an option.
My code is here:
using RestSharp; //Version 104
private string RestRequest(string URL, RestSharp.Method Method)
{
var Client = new RestClient();
Client.Authenticator = new HttpBasicAuthenticator(ID, Password);
var Request = new RestRequest(URL, Method);
IRestResponse Response = Client.Execute(Request);
return Response.Content;
}
Sample URL that is passed to the function:
htp://localhost:8080/api/jsonws/knowledge-base-portlet.kbarticle/add-kb-article/portlet-id/1_WAR_knowledgebaseportlet/parent-resource-class-name-id/20704/parent-resource-prim-key/20200/title/SomeTitle/url-title/%2FTitle/content/SomeContent
After snooping around Resharper's Github issues, like this one, it seems you have to use RestRequest.AddURLSegment(). Tested with RestSharp v. 104.0.0
var url = "http://localhost:4422/api/jsonws/knowledge-base-portlet.kbarticle/add-kb-article/portlet-id/1_WAR_knowledgebaseportlet/parent-resource-class-name-id/20704/parent-resource-prim-key/20200/title/SomeTitle/url-title/{segment}/content/SomeContent";
var Client = new RestClient();
var Request = new RestRequest(url,Method.GET);
Request.AddUrlSegment("segment", "%2Ftitle");
I don't know if it's possible for you to pass multiple arguments. If you cannot, the simplest scenario would be splitting by %2F and concatenate multiple arguemnts. Something like this:
private string RestRequest(string URL, RestSharp.Method Method)
{
var Client = new RestClient();
string requestUrl;
bool hasBackslashArgument = ParseEncodedBackSlash(URL, out requestUrl);
RestRequest request;
if (hasBackslashArgument)
{
request = new RestRequest(requestUrl, Method);
request.AddUrlSegment("segment", "%2F");
}
else
{
request = new RestRequest(URL, Method);
}
IRestResponse response = Client.Execute(request);
return response.Content;
}
private bool ParseEncodedBackSlash(string url, out string preformattedString)
{
preformattedString = null;
var urlSegments = url.Split(new string[] { "%2F" }, StringSplitOptions.None);
if (urlSegments.Length == 0) return false;
preformattedString = string.Join("{segment}", urlSegments);
return true;
}
I am having issues passing data parameters from a classic asp application to a .NET Web API. It seems that no matter what I do I cannot access the parameter inside the .NET web API. I have included the code I am using below:
The Classic ASP code:
Public Function GetResponse (HTTPMethod, ReqURL, QueryParamsOrArgs)
Set XMLHTTP = Server.CreateObject("MSXML2.ServerXMLHTTP")
If HTTPMethod = "GET" Then
ReqURL = ReqURL & "?" & QueryParamsOrArgs
QueryParamsOrArgs = ""
End If
XMLHTTP.open HTTPMethod , ReqURL, false
XMLHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
XMLHTTP.setRequestHeader "AuthToken", ServiceUrl_AuthToken
XMLHTTP.send(QueryParamsOrArgs)
If XMLHTTP.Status = 200 Then
GetResponse = XMLHTTP.responseText
Else
GetResponse = ""
End If
End Function
Public Function TestPOST(url)
mydata = "value1=1&value2=2&value3=3"
TestPOST = GetResponse("POST", url, mydata)
End Function
In the calling ASP page:
dim oDataUtils : Set oDataUtils = (New DataUtils)
myResponse = oDataUtils.TestPost(ServiceUrl_Base & "EventData/Post")
The .NET Web API Action Method:
[HttpPost]
public HttpResponseMessage Post([FromBody]string value)
{
StringContent sc = new StringContent(value);
sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage resp = new HttpResponseMessage();
resp.Content = sc;
return resp;
}
No matter what I send, the value of the parameter "value" inside the api method is always null. Ultimately I would love to be able to send an entire dictionary or parameters to this method, but cannot even get the most simple component (a string) to pass in. What am I missing here?
My ultimate goal would be for something like this to work:
[HttpPost]
public HttpResponseMessage Post(Dictionary<string, object> data)
{
// Do something with the dictionary and then return a response...
StringContent sc = new StringContent("test");
sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage resp = new HttpResponseMessage();
resp.Content = sc;
return resp;
}
but I will take either option at this point...
The "issue" is: [FromBody]
public HttpResponseMessage Post([FromBody]string value)
It is for "simple" type, and translated means, just one value. Additionally, the format the API expects using FromBody is =value (notice the missing "key").
e.g.
foo=bar //this will fail "null"
=bar //this is good (no key)
This will explain it in detail even if the topic is about jquery, it will give you insight to the behavior of FromBody.
Use FormDataCollection...
Hth....
It might work if you pass proper json instead of just string ,
form you json like
mydata="{'value':'value1=1&value2=2&value3=3'}"
You can also pass dictionary of like
var data={};
data.Value1="1";
data.Value2="2";
data.Value3="3";
Remember the name of param in action method and name of json key must be same,here 'values
mydata={values:data};
[HttpPost]
public HttpResponseMessage Post(Dictionary<string, string> values)