We want to sent a post request to an external API provider.
we know how to send a GET, and how to parse the JSON response.
We know how to send a JSON payload into the POST.
What we cant find an example of a good way to get request parameters into the body of a POST with jersey.
e.g. to send a really simple get request, we can do this:
private final Client theHttpClient;
ClientConfig clientConfig = new ClientConfig();
JacksonJaxbJsonProvider jacksonProvider = new JacksonJaxbJsonProvider();
jacksonProvider.setMapper(theObjectMapper);
clientConfig.register(jacksonProvider);
clientConfig.register(EncodingFilter.class);
clientConfig.register(GZipEncoder.class);
theHttpClient = ClientBuilder.newClient(clientConfig);
int param1 = 123134
String param2 = "this+is+a+test";
String url = "https://api.some.com?param1=" + param1 + "¶m2=" + param2;
uri = new URI(url);
WebTarget webTarget = theHttpClient.target(uri);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
RESPONSE response = invocationBuilder.get(responseClass);
This code will send the params via get.
How would we get the params into a post request body?
we see there is an invocationBuild.post which looks like this:
#Override
public <T> T post(final Entity<?> entity, final Class<T> responseType)
throws ProcessingException, WebApplicationException {
return method("POST", entity, responseType);
}
What is entity in this case? We assume we could manually create a text body with the params packed in it, but there must be a nicer way to do this, which will ensure no typos etc? E.g. something which takes a map, or even an addParam function?
Related
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?
I have rest url support POST request. its looks like
api/country/{countryId}/state
using to create state resource in a country with given id
but the mapping function of this url is
public HttpResponseMessage Post(int countryId,StateDto state)
{
var country = _countryAppService.AddNewState(state, countryId);
var message = Request.CreateResponse(HttpStatusCode.Created, country);
return message;
}
and expected sample of the given urls is like
api/country/1/state (create a new state in country with id=1)
but here i am not using the url value (1) in the above function instead of here the caller need to pass the corresponding countryId via request body, ie there is no any guarantee to both contryId in url and post request are same. so my doubt is what is the right url pattern to save a state in particular country vai a post request?
If you have the same information in the resource path and the request body, it's duplication of information; the caller should never need to pass you the same information twice in the same request.
You should pick one as the authoritative source and ignore the other. Since you must have the correct resource address to perform the operation, I would suggest you need to take the value from there:
public HttpResponseMessage Post(int countryId,StateDto state)
{
// Compose the DTO from the route parameter.
state.CountryId = countryId;
var country = _countryAppService.AddNewState(state);
var message = Request.CreateResponse(HttpStatusCode.Created, country);
return message;
}
You can pass StateDto object in body also,it will go in body ,id can go in url
public HttpResponseMessage Post([FromUri]int countryId,[FromBody]StateDto state)
{
var country = _countryAppService.AddNewState(state, countryId);
var message = Request.CreateResponse(HttpStatusCode.Created, country);
return message;
}
Only one param can come from body , other have to come from uri, you can read more here:
http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
Passing stateDto in uri is also an option but then you will have to pass all its members in querystring.
How can I post JSON to an ASP.NET MVC controller action?
sample scenario
An external authentication system requires JSON be posted to it. I would like to capture the user's credentials on my site and forward them as JSON to the authentication site. Redirects are not an option.
So we'll use http://www.example.com/ExtAuth/Login as our fictitious external authentication endpoint.
ExtAuth will expect us to post a JSON string representing an object with two properties: User, and Password.
ExtAuth will return a JSON string representing an object with two properties: Status, and Message.
The key to making this whole thing work is the extRequest.ContentType. It MUST be set to application/json.
I'll leave proper error handling as an exercise to the user.
<HttpPost>
<AllowAnonymous>
Public Function Login(ByVal model As LoginModel) As ActionResult
Dim authEndpointUrl As String = "http://www.example.com/ExtAuth/Login"
Dim result As String = String.Empty ' this will hold the JSON returned from ExtAuth
Dim resultModel As LoginResult = Nothing ' The deserialized form of the result JSON
Dim data As String = String.Empty ' the serialized representation of our login data
Dim extRequest As HttpWebRequest = WebRequest.CreateHttp(authEndpointUrl)
extRequest.Method = "POST"
extRequest.ContentType = "application/json"
data = Newtonsoft.Json.JsonConvert.SerializeObject(model)
Using writer As StreamWriter = New StreamWriter(extRequest.GetRequestStream)
writer.Write(data)
End Using
Using extResponse As HttpWebResponse = extRequest.GetResponse
Using reader As StreamReader = New StreamReader(extResponse.GetResponseStream)
result = reader.ReadToEnd
End Using
End Using
resultModel = Newtonsoft.Json.JsonConvert.DeserializeObject(Of LoginResult)(result)
ViewData("Status") = resultModel.Status
ViewData("Message") = resultModel.Message
Return View(model)
End Function
This method should work for MVC 3+.
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.
Having a string containing the following raw Json data (simplified for the sake of the question):
var MyString = "{ 'val': 'apple' }";
How can I create a JsonResult object representing MyString?
I tried to use the Json(object) method. but it handles the raw json data as an string -logically :P-. So the returned HTTP response looks like:
"{ 'val': 'apple' }"
instead of the given raw Json Data:
{ 'val': 'apple' }
this is what I want to achieve:
The Json() method on Controller is actually a helper method that creates a new JsonResult. If we look at the source code for this class*, we can see that it's not really doing that much -- just setting the content type to application/json, serializing your data object using a JavaScriptSerializer, and writing it the resulting string.. You can duplicate this behavior (minus the serialization, since you've already done that) by returning a ContentResult from your controller instead.
public ActionResult JsonData(int id) {
var jsonStringFromSomewhere = "{ 'val': 'apple' }";
// Content() creates a ContentResult just as Json() creates a JsonResult
return Content(jsonStringFromSomewhere, "application/json");
}
* Starting in MVC2, JsonResult also throws an exception if the user is making an HTTP GET request (as opposed to say a POST). Allowing users to retrieve JSON using an HTTP GET has security implications which you should be aware of before you permit this in your own app.
The way I have generated json data from a string is by using JavaScriptResult in the controller:
public JavaScriptResult jsonList( string jsonString)
{
jsonString = "var jsonobject = new Array(" + jsonString + ");";
return JavaScript(jsonString)
}
Then when you request pass the json string to that action in your controller, the result will be a file with javascript headers.
I think you can use the JavaScriptSerializer class for this
var js = new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonObject = js.Deserialize("{ 'val': 'apple' }", typeof(object));