Suppose I have the following web method using C# and .NET:
[WebInvoke(UriTemplage="/users", Method="POST")]
[OperationContract]
public User AddNewUser(User u);
It is expected that when you implement POST web method you will accept a request body as part of the incoming HTTP request message. The parameter u is expected to be deserialized from the incoming HTTP message body.
My question is: how do we set this request body on the client side ? It's got to be set somewhere. It really confuses me.
Besides if I added "ResponseFormat = WebMessageFormat.Json" to WebInvoke, how can I deserialize from the returned json string into the User object ?
Thanks.
Your question doesn't reveal what you have tried. If you are using .net on the client then you can use the DataContractSerializer to get the serialized data.
You can then use an HttpWebRequest with the method set to POST.
Add the serialized data to the web request and use the GetResponse() method.
Alternatively you could use Fiddlr to test your web service using requests that you create. It gives you a concise view of exactly what is going up to the server.
To perform a POST request to your WCF Rest method:
private string UseHttpWebApproach<T>(string serviceUrl, string resourceUrl, string method, T requestBody)
{
string responseMessage = null;
var request = WebRequest.Create(string.Concat(serviceUrl, resourceUrl)) as HttpWebRequest;
if (request != null)
{
request.ContentType = "application/json";
request.Method = method;
}
if(method == "POST" && requestBody != null)
{
byte[] requestBodyBytes = ToByteArrayUsingJsonContractSer(requestBody);
request.ContentLength = requestBodyBytes.Length;
using (Stream postStream = request.GetRequestStream())
postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);
}
if (request != null)
{
var response = request.GetResponse() as HttpWebResponse;
if(response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
if (responseStream != null)
{
var reader = new StreamReader(responseStream);
responseMessage = reader.ReadToEnd();
}
}
else
{
responseMessage = response.StatusDescription;
}
}
return responseMessage;
}
private static byte[] ToByteArrayUsingJsonContractSer<T> (T requestBody)
{
byte[] bytes = null;
var serializer1 = new DataContractJsonSerializer(typeof(T));
var ms1 = new MemoryStream();
serializer1.WriteObject(ms1, requestBody);
ms1.Position = 0;
var reader = new StreamReader(ms1);
bytes = ms1.ToArray();
return bytes;
}
Now Assuming your User object as shown below:
Public Class User
{
Public int UserId {get;set;}
Public string UserName {get;set;}
Public string Password {get;set;}
}
The to call the above method i do:
User objUser = new objUser();
objUser.Username = "Test";
objUser.Password = "Test";
UseHttpWebApproach<User>(serviceBaseUrl, "users", "POST", objUser);
Related
I have a GET API in which expecting fields from query parameters.
which is look like this
public List<Sms> SendSms([FromQuery] string apiKey, [FromQuery] string accountKey, [FromQuery] string appId,[FromQuery] string userId, [FromQuery] string message, [FromQuery] bool isHighSpeed = false,[FromQuery] List<string> mobile)
{
// do something
}
In this API I am expecting mobile in the list of strings.
when i am calling this api by web request in my other project.
i am adding mobile number but it takes nothing and taking a System.Collections.Generic.List'1[System.String] something like
that.
I don't know how to give list of string in query parameter in the httpweb request.
here is the webrequest :
public virtual bool SendSms(SmsResponse sms)
{
try
{
var message = sms.message;
var mobile = sms.mobile;
var apiKey = Config.GetSection("Sms:apiKey").Value;
var userId = Config.GetSection("Sms:userId").Value;
var accountKey = Config.GetSection("Sms:accountKey").Value;
var appId = Config.GetSection("fusionAuth:Client_Id").Value;
var query = $"apiKey={apiKey}&accountKey={accountKey}&userId={userId}&appId={appId}&message={message}&mobile={mobile}&isHighSpeed={false}";
string createreq = string.Format($"{Config.GetSection("Sms:Url").Get<string>()}SMS/SendSms?{query}");
HttpWebRequest request = WebRequest.Create(createreq) as HttpWebRequest;
request.Method = "GET";
request.ContentType = "application/json";
request.Accept = "application/json; charset=utf-8";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception(String.Format("Server error (HTTP {0}: {1}).", response.StatusCode, response.StatusDescription));
}
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
List<SmsResponse> Data = JsonConvert.DeserializeObject<List<SmsResponse>>(responseFromServer);
if (string.IsNullOrEmpty(Data[0].extMessageId))
{
return false;
}
}
return true;
}
catch (WebException ex)
{
var resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
return false;
}
}
Please check SmsResponse class. Which type of mobile ?
The way you get mobile params is correct.
And you also need to make sure the format of request url.
var query = $"apiKey={apiKey}&accountKey={accountKey}&userId={userId}&appId={appId}&message={message}&mobile={mobile}&isHighSpeed={false}";
1. If the type of mobile is string, you code should like below:
2. If the type of mobile is List<string>, you code should like below:
Dictionary<string, string> data = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
if (data["ReturnValue"].Equals("0"))
{
List<M_Ninushi> m_ninushis = new M_NINUSHI_DAO().GetList(data["LastUpdateDate"]);
string data_m_ninushi = JsonConvert.SerializeObject(m_ninushis);
string sentResponse = Util.FilterData(data_m_ninushi);
Dictionary<string, string> dataResponse = JsonConvert.DeserializeObject<Dictionary<string, string>>(sentResponse);
if (dataResponse["ReturnValue"].Equals("0"))
{
return 0;
}
else
{
return 1;
}
}
this id my code in webservice use asp.net. I use HttpWebRequest send data to symfony2 api
FilterData
XElement xdoc = XElement.Load(configFileName);
var objStringConnection = xdoc.Descendants("URL").Select(e => new { filter_data = e.Descendants("URL_FILTER_DATA").FirstOrDefault().Value }).SingleOrDefault();
string urlAddress = objStringConnection.filter_data;
System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; };
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlAddress);
Dictionary<string, string> json = new Dictionary<string, string>();
json.Add("M_Ninushi", data);
byte[] dataSent = Encoding.ASCII.GetBytes(json.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
//application/x-www-form-urlencoded
request.ContentLength = dataSent.Length;
Stream writer = request.GetRequestStream();
writer.Write(dataSent, 0, dataSent.Length);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = null;
if (response.CharacterSet == null)
readStream = new StreamReader(receiveStream);
else
readStream = new StreamReader(receiveStream, Encoding.GetEncoding(response.CharacterSet));
string dataResponse = readStream.ReadToEnd();
response.Close();
readStream.Close();
return dataResponse;
}
this id my code in webservice use asp.net. I use HttpWebRequest send data to symfony2 api
I know how to send data but I don't know how to get data in symfony2 . someone help me
C# Code Corrections
First, we need to correct the Content-Type sent to the server hosting the Symfony2 application. The data you are sending is not in the proper format for application/x-www-form-urlencoded. Change it to application/json.
Also, JSON data MUST be encoded in Unicode. In PHP, json_decode() only supports UTF-8 encoded strings. Therefore you must use Encoding.UTF8.GetBytes instead of Encoding.ASCII.GetBytes.
Dictionary.toString() does not return a JSON string. Use Json.NET.
Receiving JSON Data in Symfony2
In your Controller, you can use Symfony\Component\HttpFoundation\Request::getContent() to retrieve the form content.
<?php
namespace Company\CodeExampleBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpKernel\Exception\HttpException;
class RestAPIController extends Controller
{
public function doSomethingInterestingAction(Request $request)
{
if($request->headers->get('Content-Type') !== 'application/json') {
throw $this->createBadRequestException();
}
$jsonData = json_decode($request->getContent(), true);
if($jsonData === null) {
throw $this->createBadRequestException();
}
// DO SOMETHING WITH $jsonData
}
protected function createBadRequestException()
{
return new HttpException(400, 'This endpoint expects JSON data in the POST body and requires Content-Type to be set to application/json.');
}
}
I am using the following code to get the json result from the service. It works fine for get methods. But when the method type is POST the request address changes to the previous address.
ie;
on the first call to this method the request.address=XXXXX.com:1234/xxx/oldv1.json (method type is get)
and it returns a json string from which I extract another address:XXXXX.com:1234/xxx/newv1.json
and now I call the makerequest method with this endpoint and method type POST, contenttype="application/x-www-form-urlencoded".
When I put breakpint at using (var response = (HttpWebResponse)request.GetResponse()) and checked the request.address value, it was XXXXX.com:1234/xxx/newv1.json
But after that line is executed, the address changes to XXXXX.com:1234/xxx/oldv1.json and the function returns the same response I got with the first Endpoint(XXXXX.com:1234/xxx/oldv1.json).
Can anybody tell what I am doing wrong here?
Is there any better method to consume the service with POST method?
public string MakeRequest(string EndPoint,string Method, string contentType)
{
var request = (HttpWebRequest)WebRequest.Create(EndPoint);
request.Method = Method;
request.ContentLength = 0;
request.ContentType =contentType;
if ( Method == HttpVerb.POST)
{
var encoding = new UTF8Encoding();
var bytes = Encoding.GetEncoding("iso-8859-1").GetBytes("username=123&password=123");
request.ContentLength = bytes.Length;
using (var writeStream = request.GetRequestStream())
{
writeStream.Write(bytes, 0, bytes.Length);
}
}
using (var response = (HttpWebResponse)request.GetResponse())// request.address changes at this line on "POST" method types
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grab the response
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
EDIT: Yesterday I asked THIS Question about consuming the service at client side and many suggested it needs to be done at server side as the other domain might not allow accessing the json result at client side.
The issue was about cookies. As I forgot to set the cookies, the request was getting redirected. I had to set cookie container by using
request.CookieContainer = new CookieContainer();
I am attempting to replicate the following C# code in Java. This code is a helper class that sends a request containing xml, and reads a response.
internal static String Send(String url, String body)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
try
{
// create the new httpwebrequest with the uri
request.ContentLength = 0;
// set the method to POST
request.Method = "POST";
if (!String.IsNullOrEmpty(body))
{
request.ContentType = "application/xml; charset=utf-8";
byte[] postData = Encoding.Default.GetBytes(body);
request.ContentLength = postData.Length;
using (Stream s = request.GetRequestStream())
{
s.Write(postData, 0, postData.Length);
}
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
String responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
if (response.StatusCode != HttpStatusCode.OK)
{
throw new ResponseException(((int)response.StatusCode),
response.StatusCode.ToString(), request.RequestUri.ToString(),
responseString);
}
return responseString;
}
}
catch (WebException e)
{
using (WebResponse response = e.Response)
{
HttpWebResponse httpResponse = response as HttpWebResponse;
if (httpResponse != null)
{
using (Stream data = response.GetResponseStream())
{
data.Position = 0;
throw new ResponseException(((int)httpResponse.StatusCode),
httpResponse.StatusCode.ToString(), request.RequestUri.ToString(),
new StreamReader(data).ReadToEnd()
);
}
}
else
{
throw;
}
After reading other threads I determined that the Apache HttpComponents library would be my best bet to get the same functionality. After reading the documentation and following the example here:
http://hc.apache.org/httpcomponents-client-ga/quickstart.html
I am unable to figure out how to send the body string as xml. When I attempt to set the entity for the request it requires that I declare a BasicNameValuePair, and I do not understand what this is, or how I would format the body string to meet this specification.
Below is what I have currently done.
protected static String Send(String url, String body)
{
HttpPost request = new HttpPost(url);
try
{
request.setHeader("ContentType", "application/xml; charset=utf=8");
// Encode the body if needed
request.setEntity(new UrlEncodedFormEntity());
//get the response
// if the response code is not valid throw a ResponseException
// else return the response string.
} finally {
request.releaseConnection();
}
return null;
}
EDIT : or should I use a StringEntity and do the following
protected static String SendToJetstream(String url, String body)
{
HttpPost request = new HttpPost(url);
try
{
StringEntity myEntity = new StringEntity(body,
ContentType.create("application/xml", "UTF-8"));
// Encode the body if needed
request.setEntity(myEntity);
//get the response
// if the response code is not valid throw a ResponseException
// else return the response string.
} finally {
request.releaseConnection();
}
return null;
}
Use a FileEntity
File file = new File("somefile.xml");
FileEntity entity = new FileEntity(file, ContentType.create("application/xml", "UTF-8"));
Lots of good examples here: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e165
A friend show me this sample code to implement HTTP POST in C# and did work out in a WINFORM App:
http://www.terminally-incoherent.com/blog/2008/05/05/send-a-https-post-request-with-c/
And implemented in a METRO APP:
// this is what we are sending
string post_data = "user=user#example.com&pass=example123";
// this is where we will send it
string uri = "http://app.proceso.com.mx/win8/login";
// create a request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
// turn our request string into a byte stream
byte[] postBytes = Encoding.UTF8.GetBytes(post_data);
// this is important - make sure you specify type this way
request.ContentType = "application/x-www-form-urlencoded";
Stream requestStream = await request.GetRequestStreamAsync();
// now send it
requestStream.Write(postBytes, 0, postBytes.Length);
// grab te response and print it out to the console along with the status code
WebResponse response = await request.GetResponseAsync();
//var a = new StreamReader(response.GetResponseStream()).ReadToEnd();
StreamReader requestReader = new StreamReader(response.GetResponseStream());
String webResponse = requestReader.ReadToEnd();
I realized, HttpWebRequest does not contain ProtocolVersion and is throwing me this error in this line:
WebResponse response = await request.GetResponseAsync();
// ERROR: The remote server returned an error: (417) Expectation Failed.
I guess the last property is the solution. How can I solve this problem?
Thanks in advance
I recently wrote a small function to handle the posting of trivial data to a server.
private struct HttpPostParam
{
private string _key;
private string _value;
public string Key { get { return HttpUtility.UrlEncode(this._key); } set { this._key = value; } }
public string Value { get { return HttpUtility.UrlEncode(this._value); } set { this._value = value; } }
public HttpPostParam(string key, string value)
{
this._key = key;
this._value = value;
}
};
private static string PostTrivialData(Uri page, HttpPostParam[] parameters)
{
string pageResponse = string.Empty;
try
{
var request = (HttpWebRequest)WebRequest.Create(page); //create the initial request.
request.Method = WebRequestMethods.Http.Post; //set the method
request.AllowAutoRedirect = true; //couple of settings I personally prefer.
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
//create the post data.
byte[] bData = Encoding.UTF8.GetBytes(string.Join("&", Array.ConvertAll(parameters, kvp => string.Format("{0}={1}", kvp.Key, kvp.Value))));
using (var reqStream = request.GetRequestStream())
reqStream.Write(bData, 0, bData.Length); //write the data to the request.
using (var response = (HttpWebResponse)request.GetResponse()) //attempt to get the response.
if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.NotModified) //check for a valid status (should only return 200 if successful)
using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
pageResponse = reader.ReadToEnd();
}
catch (Exception e)
{
/* todo: any error handling, for my use case failing gracefully was all that was needed. */
}
return pageResponse;
}
Essentially it posts the value pairs defined in the "parameters" argument. Will require a reference and import of the System.Web namespace to compile.
I just tested it with your website and got a response back:
HttpPostParam[] httpparams = {
new HttpPostParam("user", "censored#email.com"),
new HttpPostParam("pass", "example123")
};
string response = PostTrivialData(new Uri("http://app.proceso.com.mx/win8/login"), httpparams);
Let me know if there's any issues.