A quick update, So it turns out somewhere during my troubleshooting process this started working if I do the post from my application, but if I take the exact same data and try to post it via fiddler the oject is null. It was so much "easier" to try after changes in fiddler that I stuck to it but it looks like it burned me and wasted hours. I also tried posting this data via chromes rest client and it doesnt work. I wish I knew why because if I cant get this to work via fiddler or chrome its really going to increase my troublshooting time in the future.
Thank you for trying to help.
I am trying to post data from a winforms app to Web API. I had this problem initially but setting content type to application/json fixed it but now I am having the same behavior. I dont remember changing anything but I must have. This occurs even when I post the data from fiddler. I removed everything from my viemodel but 1 string key value to try to eliminate format issues in the data itself but at the controller side the viewmodel is still null. Not the values but the viewmodel itself. The controller is being reached but like I said the object is null
The controller looks like this
[HttpPost]
public HttpResponseMessage LogValidation([FromBody]ValidationViewModel validationviewmodel)
{
//Do something
}
The Model
public class ValidationViewModel
{
public string AssetName { get; set; }
}
The data being posted
{
\"AssetName\":\"testname\"
}
In the interest of providing as much info as possible when I do the post from the client I am doing the following. This is also how I generated the test data to use in fiddler
`public Task SubmitValidation()
{
ReportValidaton reportvalidation = new ReportValidaton();
var serializedReportValidation = JsonConvert.SerializeObject(reportvalidation);
var client = new HttpClient();
client.BaseAddress = new Uri("MyURI");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeader("application/json"));
MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
HttpContent content = new ObjectContent<ReportValidaton>(reportvalidation, jsonFormatter);
HttpResponseMessage response = client.PostAsync("api/LogValidation/", content).Result;
}`
When posting from fiddler, ensure:
that the Content-Type header is set to application/json
that the data doesn't contain escaped strings: {"AssetName":"testname"} and NOT {\"AssetName\":\"testname\"}
that the method is set to POST
Related
I'm new to writing .net APIs and I'm working in Visual Studio 2017. I've been working on this for a couple of days and I'm completely stumped. I'm trying to create a simple web API that a Post call sends a cXML string passed into it via the Post Body. I then take the incoming cXML string and simply save it to a text file on a network drive. That is all I need to do, I don't need to de-serialize the xml, read any of the fields or extract any data out of the XML, I just need to grab the entire input xml string and save it to a text file. The problem I'm having is no matter what I've tried the incoming body always seems to be null. My code is simple:
[HttpPost]
[Route("api/Pass_XML_to_File")]
public HttpResponseMessage Post([FromBody] dynamic IncomingXML)
{
//do work here: take Incoming xml string and save it to a file which should be simple...
}
Unfortunately my IncomingXML variable is always null, so I have no data to save into a text file. I've been testing this from Postman and no matter what I've tried the variable is always null.
I've tried many other ways such as
Post([FromBody] XmlDocument IncomingXML)
Post([FromBody] string IncomingXML), etc.
I've tried changing in Content-Type header in Postman from application/xml, text/xml, text and a few others without any success. The funny thing is if I pass a JSON string in the body (changing the Content-Type to text/JSON) the data comes in perfectly without issue. Just when I pass xml the incoming body is always null.
Does anyone know how I can get the body xml to come in as a string so I can simply save it to a text file for later processing on a separate system? Thank you all in advance for your assistance.
Can you post the form you sent on the client side?
[HttpPost]
[Route("api/Pass_XML_to_File")]
public HttpResponseMessage Post([FromBody] dynamic IncomingXML)
{
// data is coming in correctly.
return null;
}
Postman Client Send :
{
"IncomingXML":"<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don'tforgetmethisweekend!</body></note>"
}
data comes to variable successfully.
if you want to accept a xml format request, you should do the below steps:
Startup.ConfigureServices edit:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddXmlSerializerFormatters();
}
Apply the Consumes attribute to controller classes or action methods that should expect XML in the request body.
[HttpPost]
[Route("api/Pass_XML_to_File")]
[Consumes("application/xml")]
public HttpResponseMessage Post([FromBody] dynamic IncomingXML)
{
// data is coming in correctly.
return null;
}
Note: Install the Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet package.
I am trying to build a web api that returns true but when i send my response through a HttpResponseMessage, Postman reads it as the structure of the HttpResponseMessage. Instead of sending the result in a string with the word true it returns the entire structure of the HttpResponseMessage. I have used the exact same method with other APIs that I have created So I don´t know why it is suddenly returning the wrong answer in postman.
I´ve tried switching methods to the Request method, I´ve also tried returning Mediatypeformater but that haven´t helped. Anyone have any ideas?
The code:
[HttpGet]
public HttpResponseMessage Exportreport(string imei) //tristis est, valet doctrina
{
try
{
//bunches of code
return new HttpResponseMessage((HttpStatusCode)200)
{
Content = new ObjectContent(typeof(bool), true, new JsonMediaTypeFormatter())
};
}
Response in postman:
First of all, my English is not so good, I hope you understand what I am trying to say.
I'm new with WebApi's. I created one and all seems good. In my function I return a string, but when I test the web api with Postman it returns a status code 204 no content.
I looked for this status and apparently my request was succeded, but when I look at my database nothing happend. (my function saves some data in my database and returns a string when it is succeded or not).
So, my question is, Why am I receiving this status code when my function must to return a string? Or why when I test the Web Api with Postman it returns a 204 No Content code (that means my request was succeded) when is not true (because nothing was saved in my database)?
Here is my function in my web api:
[HttpPost]
public string IncomingPO(string request)
{
//do some stuff
return "response as a string";
}
My parameter "string request" is a string that cointains a xml. I read the string as a xml and do some stuff with it. (save some nodes from the xml in a database, for example).
If all the function is succeded or not I expect the output of my string, but I'm no receiving anything. Only the status code 204 No Content. (when content should really be returned).
Any suggestion is welcome.
It can solve my problem.
The only thing I had to do was specify the route with which my Api website will be invoked.
In addition I also had to modify the data type of my parameter and my function.
Something like this:
[HttpPost]
[Route("api/Controller/IncomingPO")]
public HttpResponseMessage IncomingPO(HttpRequestMessage request)
{
//do some stuff
return new HttpResponseMessage()
{
Content = new StringContent("My response string", System.Text.Encoding.UTF8, "application/xml"),
StatusCode = HttpStatusCode.OK
};
}
I am currently working on a OAuth2 implementation. However I am stuck on an Error 401. It seems like there is something wrong with my post request that is supposed to retrieve the access token from the Company the User logged in to. This is my code:
internal void RequestAccessToken(string code)
{
string requestBody = "grant_type="+ WebUtility.UrlEncode(GRANTTYPE)+ "&code=" + WebUtility.UrlEncode(code)+"&redirect_uri="+ WebUtility.UrlEncode(REDIRECT_URI);
WebClient client = new WebClient();
client.Headers.Add("Authorization",HeaderBase64Encode(CLIENT_ID, SECRETKEY));
var response = client.UploadString("https://thewebsiteiamcallingto.com/some/api", requestBody);
var responseString = client.OpenRead("https://thewebsiteiamcallingto.com/some/api");
}
My Questions are:
Is there anything wrong with the way I try to make the POST request ?
Is there a way to retrieve the whole string that is posted to the URI using UploadString?
P.S. I have seen this post regarding the POST creation. However I find the async part to be too complicated for my case.
Since we dont know the api documentation, I would suggest you to make a postman request and view the actual request sent and response received, and secondly make a request using your method and capture using a utility like wireshark and compare the difference.
I've created a .NET API, but when I try to use it I'm getting strange results.
If I go to the URL of an API call in Chrome I get the result I would expect, in XML format, but if I try it in IE it downloads a file and when I open it it just says {} or sometimes [{},{},{},{}] if I try a call that returns an array.
I've also tried using a webclient.
WebClient web = new WebClient();
var data = web.DownloadString("http://myAPI.example.com/api/MyAPI/APIMethod?parameter1=hiImAParameter");
This also returns empty {}.
I've tried searching online, but I don't see any mentions of this problem anywhere. I'm sure I must be missing something somewhere, but I've tried looking over how I set up my API, and it all looks fine to me.
Edit:
Here's the response I get in Chrome.
<ArrayOfRoute xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TimePointModel">
<Route>
<RouteId>11235</RouteId>
<RouteName>Fibonacci</RouteName>
<Status i:nil="true"/>
<Width>0</Width>
</Route>
</ArrayOfRoute>
It returns XML on Chrome because of Chrome's accept headers. It's supposed to return JSON on IE, but for some reason the JSON is empty.
This is in my api controller:
[AcceptVerbs("GET")]
public IEnumerable<Route> APIMethod(double parameter)
{
return new Manager(parameter).GetRoutes();
}
This is in my Global.asax.cs:
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHttpRoute(
name: "APIMethod",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = "APIMethod", id = System.Web.Http.RouteParameter.Optional }
);
}
Edit:
This works great when I do an API call which doesn't require parameters.
WebClient web = new WebClient();
var data = web.DownloadString("http://myAPI.example.com/api/MyAPI/SimpleAPIMethod");
I've been doing research, and I tried adding parameters like this:
NameValueCollection myQueryStringCollection = new NameValueCollection();
string myParameter = "hiImAParameter";
myQueryStringCollection.Add("parameter1", myParameter);
web.QueryString = myQueryStringCollection;
var data = web.DownloadString("http://myAPI.example.com/api/MyAPI/APIMethod");
I've noticed that the number of empty {} in my array matches the number of items in the array if I put the full url with the querystring into chrome. It just empties them out for my webclient.
I also tried adding
web.Headers[HttpRequestHeader.ContentType] = "application/json";
before making the call, but there's still no change in the result.
And I tried to follow that tutorial, but it's written for a console application and they're using HttpClient. I can't do that because I can't do Asynchronous calls. This is to be used by a website. That's why I'm using WebClient. I also tried using StreamReader with HttpWebRequest and HttpWebResponse, but it had the same problem as I've been encountered with WebClient.
Without more information, it's a bit hard to diagnose your issue. However, I would say that it is likely your web API is interpreting the expected response type and providing an empty result as it does not support responses of that type, such as happens with ASP .NET Web API websites.
In that sense, the DownloadString is indicating it is expecting a text/html response. You should probably download the Microsoft ASP .NET Web API Client Libraries with NuGet. This library will give you HttpClient which has support for making the queries you want to make with responses such as application/json and application/xml.
You can view a tutorial on how to do the calls right here.
If you want it to work from your web browser, you need to ensure the Accept header field is correct, as you mentioned. Ensure it is being communicated with IE by using something like Fiddler.
I figured out what the problem was. I needed to add [DataMember] attributes to the attributes of the items in the list. I didn't realize it was left out of the return type of that call.