I have some strange problem. I am using Microsoft.AspNet.WebApi.Client.5.2.3 for simple .NET client for API. I want to post some data to API. I am using PostAsJsonAsync method for it.
using (var client = new HttpClient())
{
var adress = new Uri("http://localhost:28906/v1/things?access_token=SOMETOKEN");
var result = await client.PostAsJsonAsync(adress, new ThingModel() { Name = "test"});
}
When I am sending request, my uri is transformed from "http://localhost:28906/v1/things?access_token=SOMETOKEN" to "http://localhost:28906/v1/things/?access_token=SOMETOKEN" ( '/' is inserted before '?'). And request becomes wrong. How can I overcome this? In fact, how can I pass query string and json body?
Related
I have created API-1 which reads data from a remote database. How to create an API-2 which will read the data from API-1 & display it?
You have given very limited information. Based on that I tried to give you answer. You just add another web API controller API2. As you said your API1 reading information which have httpget. So when you added API2 let see you implement httpGet in API as well and just use HttpClient service class to call API1. Below is code to in API2
using (var client = new HttpClient())
{
client.BaseAddress = new
Uri("http://localhost:XXXXX/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
//GET Method
var responseTask = client.GetAsync("api/API1");
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var readTask =
result.Content.ReadAsAsync<string[]>();
}
else
{
Console.WriteLine("Internal server Error");
}
}
This is just example.
I am unable to post data to a ASP.NET WebAPI server.
I can get data from the WEBAPI server. However, I am unable to post.
The following code fails to post:
response = await client.PostAsync("api/Cars", content);
Error:
StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1
Client:
[TestClass]
public class UnitTest1
{
// http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
[TestMethod]
public async Task TestMethod1()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:48213/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
var response = await client.GetAsync("api/Cars");
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
}
// HTTP POST
using (var content = new StringContent(#"some_value"))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
response = await client.PostAsync("api/Cars", content);
if (response.IsSuccessStatusCode)
{
Debug.WriteLine("Post was successful.");
}
}
}
WebAPI:
namespace FSharpWebAPI.Controllers
open System.Web.Http
open FSharpWebAPI.Models
type CarsController() =
inherit ApiController()
let values = [| { Make = "Ford"; Model = "Mustang" }; { Make = "Nissan"; Model = "Titan" } |]
member x.Get() = values
member x.Post(data) =
ignore
What updates do I need to make just to make a simple post?
As #Fyodor Soikin has pointed out, the Post method is generic ('a -> 'b -> unit), and ASP.NET Web API refuses to wire up such methods.
ASP.NET Web API uses convention over configuration in order to figure out how to route and handle incoming requests. If an HTTP POST arrives, it'll go hunting for a method (partially) named Post, and attempt to call it. While you could argue that if a generic method could handle the input, it'd be possible for Web API to still call it, it doesn't do that.
You'll need to add a type annotation - for example:
member x.Post(data : Car) =
ignore
That's probably still not going to be enough, because the type of that version of Post is Car -> 'a -> unit, so the return value is a generic function. I'd be surprised if Web API knows what to do with that.
The reason is that ignore is a function, and since Post doesn't invoke the function, the return value is the function itself.
If you want to ignore the input and return unit, you can simply do this:
member x.Post(data : Car) = ()
This version has the type Car -> unit, which I expect Web API will find acceptable.
I'm struggling with this issue for several hours, and I can't find any solution.
Does someone used ServiceStack to upload multiple files with one POST request?
I was trying to use PostFile:
FileInfo fi = new FileInfo("ExampleData\\XmlAPI.xml");
var client = new XmlServiceClient("http://localhost:1337");
client.PostFile<DefaultResponse>("/test", fi, "application/xml");
But here I am able to add only one file to the request.
My second shot was to use LocalHttpWebRequestFilter but inside there is only a extension method which also allows to post only one file.
Multiple File Upload APIs have been added to all .NET Service Clients in v4.0.54 that allow you to easily upload multiple streams within a single HTTP request. It supports populating Request DTO with any combination of QueryString and
POST'ed FormData in addition to multiple file upload data streams:
using (var stream1 = uploadFile1.OpenRead())
using (var stream2 = uploadFile2.OpenRead())
{
var client = new JsonServiceClient(baseUrl);
var response = client.PostFilesWithRequest<MultipleFileUploadResponse>(
"/multi-fileuploads?CustomerId=123",
new MultipleFileUpload { CustomerName = "Foo,Bar" },
new[] {
new UploadFile("upload1.png", stream1),
new UploadFile("upload2.png", stream2),
});
}
Or using only a Typed Request DTO. The JsonHttpClient also includes async equivalents for each of the new
PostFilesWithRequest APIs:
using (var stream1 = uploadFile1.OpenRead())
using (var stream2 = uploadFile2.OpenRead())
{
var client = new JsonHttpClient(baseUrl);
var response = await client.PostFilesWithRequestAsync<MultipleFileUploadResponse>(
new MultipleFileUpload { CustomerId = 123, CustomerName = "Foo,Bar" },
new[] {
new UploadFile("upload1.png", stream1),
new UploadFile("upload2.png", stream2),
});
}
This is a follow-up to this post: New at MVC 4 Web API Confused about HTTPRequestMessage
Here is a summary of what I am trying to do: There is a web site that I want to interface with via MVC 4 Web API. At the site, users can log in with a user name and password, then go to a link called ‘Raw Data’ to query data from the site.
On the ‘Raw Data’ page, there is a dropdown list for ‘Device’, a text box for ‘From’ date, and a text box for ‘To’ date. Given these three parameters, the user can click the ‘Get Data’ button, and return a table of data to the page. What I have to do, is host a service on Azure that will programmatically provide values for these three parameters to the site, and return a CSV file from the site to Azure storage.
The company that hosts the site has provided documentation to programmatically interface with the site to retrieve this raw data. The document describes how requests are to be made against their cloud service. Requests must be authenticated using a custom HTTP authentication scheme. Here is how the authentication scheme works:
Calculate an MD5 hash from the user password.
Append the request line to the end of the value from step one.
Append the date header to the end of the value in step two.
Append the message body (if any) to the end of the value in step 3.
Calculate MD5 hash over the resulting value from step 4.
Append the value from step 5 to the user email using the “:” character as a delimiter.
Calculate Base64 over the value from step 6.
The code that I am going to list was done in Visual Studio 2012, C#, .NET Framework 4.5. All of the code in this post is in my 'FileDownloadController.cs' Controller class. The ‘getMd5Hash’ function takes a string, and returns an MD5 hash:
//Create MD5 Hash: Hash an input string and return the hash as a 32 character hexadecimal string.
static string getMd5Hash(string input)
{
// Create a new instance of the MD5CryptoServiceProvider object.
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
This function takes a string, and returns BASE64:
//Convert to Base64
static string EncodeTo64(string input)
{
byte[] str1Byte = System.Text.Encoding.ASCII.GetBytes(input);
String plaintext = Convert.ToBase64String(str1Byte);
return plaintext;
}
The next function creates an HTTPClient, makes an HTTPRequestMessage, and returns the authorization. Note: The following is the URI that was returned from Fiddler when data was returned from the ‘Raw Data’ page: GET /rawdata/exportRawDataFromAPI/?devid=3188&fromDate=01-24-2013&toDate=01-25-2013 HTTP/1.1
Let me first walk through what is happening with this function:
The ‘WebSiteAuthorization’ function takes a ‘deviceID’, a ‘fromDate’, a ‘toDate’ and a ‘password’.
Next, I have three variables declared. I’m not clear on whether or not I need a ‘message body’, but I have a generic version of this set up. The other two variables hold the beginning and end of the URI.
I have a variable named ‘dateHeader’, which holds the data header.
Next, I attempt to create an HTTPClient, assign the URI with parameters to it, and then assign ‘application/json’ as the media type. I’m still not very clear on how this should be structured.
In the next step, the authorization is created, per the requirements of the API documentation, and then the result is returned.
public static string WebSiteAuthorization(Int32 deviceid, string fromDate, string toDate, string email, string password)
{
var messagebody = "messagebody"; // TODO: ??????????? Message body
var uriAddress = "GET/rawdata/exportRawDataFromAPI/?devid=";
var uriAddressSuffix = "HTTP/1.1";
//create a date header
DateTime dateHeader = DateTime.Today;
dateHeader.ToUniversalTime();
//create the HttpClient, and its BaseAddress
HttpClient ServiceHttpClient = new HttpClient();
ServiceHttpClient.BaseAddress = new Uri(uriAddress + deviceid.ToString() + " fromDate" + fromDate.ToString() + " toDate" + toDate.ToString() + uriAddressSuffix);
ServiceHttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//create the authorization string
string authorizationString = getMd5Hash(password);
authorizationString = authorizationString + ServiceHttpClient + dateHeader + messagebody;
authorizationString = email + getMd5Hash(authorizationString);
authorizationString = EncodeTo64(authorizationString);
return authorizationString;
}
I haven’t tested this on Azure yet. I haven't completed the code that gets the file. One thing I know I need to do is to determine the correct way to create an HttpRequestMessage and use HttpClient to send it. In the documentation that I've read, and the examples that I've looked at, the following code fragments appear to be possible approaches to this:
Var serverAddress = http://my.website.com/;
//Create the http client, and give it the ‘serverAddress’:
Using(var httpClient = new HttpClient()
{BaseAddress = new Uri(serverAddress)))
Var requestMessage = new HttpRequestMessage();
Var objectcontent = requestMessage.CreateContent(base64Message, MediaTypeHeaderValue.Parse (“application/json”)
or----
var formatters = new MediaTypeFormatter[] { new jsonMediaTypeFormatter() };
HttpRequestMessage<string> request = new HttpRequestMessage<string>
("something", HttpMethod.Post, new Uri("http://my.website.com/"), formatters);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var httpClient = new HttpClient();
var response = httpClient.SendAsync(request);
or------
Client = new HttpClient();
var request = new HttpRequestMessage
{
RequestUri = "http://my.website.com/",
Method = HttpMethod.Post,
Content = new StringContent("ur message")
};
I'm not sure which approach to take with this part of the code.
Thank you for your help.
Read this step by step tutorial to understand the basic.
I just started playing around with RestSharp and WebApi and I've run into a little bit of an issue.
I'm not sure if this is best practice or even possible, but I'll demonstrate through code (this isn't my exact code but it's the exact same concept)
[HttpPost]
public HttpResponseMessage CreateEmployee(Employee emp, int employeeType)
{
// CREATE EMPLOYEE
return Request.CreateResponse(HttpStatusCode.Created, emp.id);
}
I've created a console app to test this using RestSharp. Here's what I have:
var client = new RestClient();
client.BaseUrl = #"http://localhost:15507";
var employee = new Employee();
//populate employee model
postrequest.Method = Method.POST;
postrequest.Resource = "api/Employee/CreateEmployee";
postrequest.AddHeader("Accept", "application/json");
postrequest.AddHeader("Content-Type", "application/json");
postrequest.RequestFormat = DataFormat.Json;
postrequest.AddBody(new { emp = employee, listId = 2 });
var res = client.Execute(postrequest);
The error that I get is that employeeType parameter comes in as null. Am I formatting this properly? Is this something that's even possible to do?
When i remove the employeeType parameter from the WebApi action method and modify the request to:
postrequest.AddBody(employee);
everything works fine.
any ideas? Thanks
if you are expecting employeetype from uri and if its not part of defined route, you can send it as query string parameter...Ex:
api/Employee/CreateEmployee?employeeType=