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)
Related
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);
I'm currently trying to post an angular model to a web API inside .NET Core MVC. The model on the Angular side is populated correctly before the point at which is Posts to the web API. When it reaches the API, however, the model looks like {"urlEndpoint":null,"token":null}.
I have tried changing the header Content-Type, I have tried adding [FromBody], I have also tried changing the controller from HttpResponseMessage to IHttpActionResult - pretty much every solution on stack overflow to similar problems actually. However, the interesting thing is, that this same code works in an older project on standard .NET.
Any help with this would be massively appreciated... it's driving me nuts!
Angular component:
getPdfData() {
let token = this.httpService.getToken("token");
this.urlAndTokenModel = new UrlAndTokenModel();
this.urlAndTokenModel.Token = token;
this.urlAndTokenModel.UrlEndpoint = this.apiEndpoint;
this.httpService.postPdfBytes('/blahblah/api/pleaseworkthistime', this.urlAndTokenModel, this.successCallback.bind(this),
this.failureCallback.bind(this));
}
Angular http.service
postPdfBytes(url: string, data: UrlAndTokenModel, successCallback, errorCallback) {
return this.http.post(url, data,
{
headers: new HttpHeaders().set('Content-Type', 'application/json'),
responseType: 'blob'
}
).subscribe(
resp => successCallback(resp),
error => errorCallback(error)
);
}
Web API:
public class TestController : BaseController
{
public TestController(ICacheHelper cacheHelper) :
base(cacheHelper)
{
}
[Route("api/pleaseworkthistime")]
[HttpPost]
public HttpResponseMessage GetDocument(UrlAndTokenModel data)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", data.Token);
var responseTask = client.GetAsync(data.UrlEndpoint);
responseTask.Wait();
var result = responseTask.Result;
byte[] finalResult = null;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsByteArrayAsync();
readTask.Wait();
finalResult = readTask.Result;
}
var httpRequestMessage = new HttpRequestMessage();
var httpResponseMessage = httpRequestMessage.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new ByteArrayContent(finalResult);
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = "mytestpdf.pdf";
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponseMessage;
}
}
Then obviously there is the angular URLAndTokenModel with a URLEndpoint and a Token - the same is mirrored in the C# model.
Finally solved it! I hope this helps anyone else going through the same issue.
When it posts to the .NET API, it firstly needs to be JSON.Stringify
this.httpService.postPdfBytes('/blahblah/api/pleaseworkthistime', JSON.stringify(this.urlAndTokenModel), this.successCallback.bind(this),
this.failureCallback.bind(this));
The angular http.service also needs to be updated therefore to a string instead of a model.
postPdfBytes(url: string, data: string, successCallback, errorCallback)
at this point it still wasn't having it, and then a simple add of [FromBody] to the Controller and walahh!
public HttpResponseMessage GetDocument([FromBody] UrlAndTokenModel data)
So I have built an REST API that in itself also consumes another API. Now I could just call the other api, create objects from that call and then make a new request and send it on it's way but that would use up a bit of performance.
I tried just sending the second request again but the problem is that Content serializes it again so I get alot of backslashes. This is my code that does this:
[Route("")]
public IHttpActionResult GetAllDevices()
{
var request = new RestRequest();
request = new RestRequest("devices", Method.GET);
IRestResponse response = client.Execute(request);
return Content(HttpStatusCode.OK, response.Content);//response.Content get's serialized again.
}
As I said, I could deserialized the first call and then just put that in Content, but it feels unnecessary.
Here is one way of doing it, remember to set the content-type explicitly to application/json if needed:
[HttpGet]
[Route("test")]
public HttpResponseMessage Test()
{
const string json = "{ \"test\": 123 }"; // from RestClient
var res = Request.CreateResponse();
res.Content = new StringContent(json);
res.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
return res;
}
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);
I want to POST data to WebAPI. Ideally I would just do:
http:www.myawesomesite.com?foo=bar
As a POST. But to my specific question, I am trying to use:
using(var webClient = new WebClient())
{
client.uploadString("http:www.myawesomesite.com", "POST", "foo=bar");
}
But that converts "foo=bar" to a bye array. Okay fine, I'm just trying to get it to work at this point.
My Web API controller looks like this:
[HttpPost]
public void MashPotatos(string foo)
{
potatoMasher.Mash(foo);
}
But I get The remote server returned an error: (404) Not Found. First off, I thought WebAPI would automatically grock that data for me even if it was in the body of the request. But more importantly, I just want to be able to get it to work.
Ideally, I'd like to leave the WebAPI method in a form such that you can still invoke it by using a query string with a POST verb.
you need to configure your web API route to accept a foo parameter.May be this will solve your issue
config.Routes.MapHttpRoute(name: "newont",
routeTemplate: "api/{controller}/{foo}",
defaults: new { controller = "Controllername", foo= "foo"}
);
Well here is a post that might be helpful to some. For me I just had to do:
using(var webClient = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
client.uploadString("http:www.myawesomesite.com", "POST", "foo=bar");
}
and
[HttpPost]
public void MashPotatos([FromBody]string foo)
{
potatoMasher.Mash(foo);
}
I decided against doing a POST with a query string as it seems to go against convention but there is also a [FromUri] attribute
public string GetData(){
string jsonResponse = string.Empty;using (WebClient client = new WebClient()){client.Headers[HttpRequestHeader.ContentType] = "application/json";
jsonResponse = client.UploadString(baseuri, "POST", #"{personId:""1"", startDate:""2018-05-21T14:32:00"",endDate:""2018-05-25T18:32:00""}");
return JsonConvert.DeserializeObject<Model>(jsonResponse);}}
#"{personId:""1"",
startDate:""2018-05-21T14:32:00"",endDate:""2018-05-25T18:32:00""}
It's a JSON custom string, or you can serialize the object here on the API side
HttpPost
public string Metod(Something data)
{
DateTimeOffset sDate = DateTimeOffset.Parse(data.date1);
DateTimeOffset eDate = DateTimeOffset.Parse(data.date2);
return _someService.GetService(data.Id, sDate, eDate);
}
Then we go to the service and get data from DB