Silverlight - How to get Webresponse string from WebClient.UploadStringAsync - silverlight

public void Register(string email, string name, string hash)
{
string registerData = "{\"email\":\"" + email + "\",\"name\":\"" + name + "\",\"hash\":\"" + hash + "\"}";
WebClient webClient = new WebClient();
webClient.Headers["Content-Type"] = "application/json";
webClient.UploadStringCompleted += new UploadStringCompletedEventHandler(HandleRegisterAsyncResult);
webClient.UploadStringAsync(new Uri(registerUrl), registerData);
}
void HandleRegisterAsyncResult(object sender, UploadStringCompletedEventArgs e)
{
}
I'm basically trying to call a webservice with a https:// post command that takes a data string. It works well, except when I get an error I can't seem to find the actual WebResponse content. If I cast the e.Error that was returned to a WebException there's a class called Response that's a BrowserHttpWebResponse but the ContentLength is 0 (eventhough I can see the content lenght is not 0 in fiddler)
Is there a way to get the response content with this method? And if not is there another way to do a Post command that does allow me to get the response content?

Related

Sending a List of Byte Array as response

I am using SpringBoot for my restful web service and for one of the end points I am sending a ByteArray as response which works perfectly as it uses ByteArrayHttpMessageConverter.
But now I want to send List of ByteArray in response but it fails as it is not able to find suitable Message converter.
Any ideas on how this can be achieved.
Below is snippet of code for End Point. If I return just byte array instead of list then it works but when I try to return list of byte array then it fails as it cannot find Message converter:
#RequestMapping(value = "/payloadList", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<List<byte[]>> loadPayload(#RequestParam(value = "tradeIds", required = false) List<String> tradeIds,
#RequestParam(value = "clientName", required = false) String clientName) throws SQLException, IOException {
LOG.info(String.format("Fetching generic trade details for client : {%s} and trade id : {%s}", clientName, Arrays.toString(tradeIds.toArray())));
tradeIds.forEach(tradeId->validateRequestParams(tradeId, clientName));
List<byte[]> payload = tradeLoadService.loadPayload(clientName,tradeIds);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<List<byte[]>> (payload, headers, HttpStatus.OK);
}

How do I get a mixed multipart in a RESTEasy response?

I am trying to use resteasy. While I am able to do send a mixed multipart as a request to a webservice, I am unable to do get a mixed multipart in the response.
For eg: Requesting for a file (byte[] or stream) and the file name in a single Response.
Following is what I have tested:
Service code:
#Path("/myfiles")
public class MyMultiPartWebService {
#POST
#Path("/filedetail")
#Consumes("multipart/form-data")
#Produces("multipart/mixed")
public MultipartOutput fileDetail(MultipartFormDataInput input) throws IOException {
MultipartOutput multipartOutput = new MultipartOutput();
//some logic based on input to locate a file(s)
File myFile = new File("samplefile.pdf");
multipartOutput.addPart("fileName:"+ myFile.getName(), MediaType.TEXT_PLAIN_TYPE);
multipartOutput.addPart(file, MediaType.APPLICATION_OCTET_STREAM_TYPE);
return multipartOutput;
}
}
Client code:
public void getFileDetails(/*input params*/){
HttpClient client = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("urlString");
MultipartEntity multiPartEntity = new MultipartEntity();
//prepare the request details
postRequest.setEntity(multiPartEntity);
HttpResponse response = client.execute(postRequest);
HttpEntity returnEntity = response.getEntity();
//extracting data from the response
Header header = returnEntity.getContentType();
InputStream is = returnEntity.getContent();
if (is != null) {
byte[] bytes = IOUtils.toByteArray(is);
//Can we see the 2 parts that were added?
//Able to get a single InputStream only, and hence unable to differentiate two objects in the response
//Trying to see the contents - printing as string
System.out.println("Output from Response :: " + new String(bytes));
}
}
The output is as follows - able to see 2 different objects with different content types, but unable to extract them separately.
Output from Response ::
--af481055-4e4f-4860-9c0b-bb636d86d639
Content-Type: text/plain
fileName: samplefile.pdf
--af481055-4e4f-4860-9c0b-bb636d86d639
Content-Length: 1928
Content-Type: application/octet-stream
%PDF-1.4
<<pdf content printed as junk chars>>
How can I extract the 2 objects from the response?
UPDATE:
Tried the following approach to extract the different parts - use the 'boundary' to break the MultipartStream; use the content type string to extract approp object.
private void getResponeObject(HttpResponse response) throws IllegalStateException, IOException {
HttpEntity returnEntity = response.getEntity();
Header header = returnEntity.getContentType();
String boundary = header.getValue();
boundary = boundary.substring("multipart/mixed; boundary=".length(), boundary.length());
System.out.println("Boundary" + boundary); // --af481055-4e4f-4860-9c0b-bb636d86d639
InputStream is = returnEntity.getContent();
splitter(is, boundary);
}
//extract subsets from the input stream based on content type
private void splitter(InputStream is, String boundary) throws IOException {
ByteArrayOutputStream boas = null;
FileOutputStream fos = null;
MultipartStream multipartStream = new MultipartStream(is, boundary.getBytes());
boolean nextPart = multipartStream.skipPreamble();
System.out.println("NEXT PART :: " + nextPart);
while (nextPart) {
String header = multipartStream.readHeaders();
if (header.contains("Content-Type: "+MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
fos = new FileOutputStream(new File("myfilename.pdf"));
multipartStream.readBodyData(fos);
} else if (header.contains("Content-Type: "+MediaType.TEXT_PLAIN_TYPE)) {
boas = new ByteArrayOutputStream();
multipartStream.readBodyData(boas);
String newString = new String( boas.toByteArray());
} else if (header.contains("Content-Type: "+ MediaType.APPLICATION_JSON_TYPE)) {
//extract string and create JSONObject from it
} else if (header.contains("Content-Type: "+MediaType.APPLICATION_XML_TYPE)) {
//extract string and create XML object from it
}
nextPart = multipartStream.readBoundary();
}
}
Is this the right approach?
UPDATE 2:
The logic above seems to work. But got another block, when receiving the RESPONSE from the webservice. I could not find any references to handle such issues in the Response.
The logic assumes that there is ONE part for a part type. If there are, say, 2 JSON parts in the response, it would be difficult to identify which part is what. In other words, though we can add the part with a key name while creating the response, we are unable to extract the key names int he client side.
Any clues?
You can try the following approach...
At the server side...
Create a wrapper object that can encapsulate all types. For eg., it could have a Map for TEXT and another Map for Binary data.
Convert the TEXT content to bytes (octet stream).
Create a MetaData which contains references to the Key names and their type. Eg., STR_MYKEY1, BYTES_MYKEY2. This metadata can also be converted into octet stream.
Add the metadata and the wrapped entity as parts to the multipart response.
At the Client side...
Read the MetaData to get the key names.
Use the key name to interpret each part. Since the Keyname from the metadata tells if the original data is a TEXT or BINARY, you should be able to extract the actual content with appropriate logic.
The same approach can be used for upstream, from client to service.
On top of this, you can compress the TEXT data which will help in reducing the content size...

Excel doc contents to webservice

I have a wpf staff creation window in which I can create basic information like first name, last name etc this creates the staff in my REST web service. An example:
Client side:
private void CreateStaffMember_Click(object sender, RoutedEventArgs e)
{
string uri = "http://localhost:8001/Service/Staff";
StringBuilder sb = new StringBuilder();
sb.Append("<Staff>");
sb.AppendLine("<FirstName>" + this.textBox1.Text + "</FirstName>");
sb.AppendLine("<LastName>" + this.textBox2.Text + "</LastName>");
sb.AppendLine("<Password>" + this.passwordBox1.Password + "</Password>");
sb.AppendLine("</Staff>");
string NewStudent = sb.ToString();
byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "application/xml";
req.ContentLength = arr.Length;
Stream reqStrm = req.GetRequestStream();
reqStrm.Write(arr, 0, arr.Length);
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
MessageBox.Show("Staff Creation: Status " + resp.StatusDescription);
reqStrm.Close();
resp.Close();
}
Web Service side:
#region POST
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Staff")]
void AddStaff(Staff staff);
#endregion
public void AddStaff(Staff staff)
{
staff.StaffID = (++eCount).ToString();
staff.Salt = GenerateSalt();
byte[] passwordHash = Hash(staff.Password, staff.Salt);
staff.Password = Convert.ToBase64String(passwordHash);
staffmembers.Add(staff);
}
All fine on that side, but Im looking to "import" the staff details from an excel spreadsheet, not sure if import is the correct word but I want to take the first names and last names contained in such n such spreadsheet and add them to the web service from the client side wpf application.
How would I go about it? I have my open file dialog:
private void Import_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
}
}
So I open my excel spread sheet then how would I go about taking the inner contents and sending it to the web service? Really stuck on the code or how to go about it :/
Just looking for an automated way of adding staff members rather than manually typing the names, but seeing as the staff excel doc could be named anything I wanted the open file dialog box. The structure inside will always be the same first name then last name.
First, here is my test Excel file that contains the Staff you want to import:
(Column 'A' if first name, column 'B' is last name and column 'C' is the password...)
Ok, so assuming that your code calling your web service works, here is my version of the Import_Click method (and a generic method to save new staff):
private void Import_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
Microsoft.Office.Interop.Excel.Application vExcelObj = new Microsoft.Office.Interop.Excel.Application();
try
{
Workbook theWorkbook = vExcelObj.Workbooks.Open(filename, Type.Missing, true);
Worksheet sheet = theWorkbook.Worksheets[1]; // This is assuming that the list of staff is in the first worksheet
string vFirstName = "temp";
string vLastName = "temp";
string vPassword = "temp";
int vIndex = 1;
while (vFirstName != "")
{
// Change the letters of the appropriate columns here!
// In my example, 'A' is first name, 'B' is last name and 'C' is the password
vFirstName = sheet.get_Range("A" + vIndex.ToString()).Value.ToString();
vLastName = sheet.get_Range("B" + vIndex.ToString()).Value.ToString();
vPassword = sheet.get_Range("C" + vIndex.ToString()).Value.ToString();
this.SaveNewStaff(vFirstName, vLastName, vPassword);
vIndex++;
}
}
catch (Exception ex)
{
MessageBox.Show("Error processing excel file : " + ex.Message);
}
finally {
vExcelObj.Quit();
}
}
}
private void SaveNewStaff(string firstName, string lastName, string password) {
string uri = "http://localhost:8001/Service/Staff";
StringBuilder sb = new StringBuilder();
sb.Append("<Staff>");
sb.AppendLine("<FirstName>" + firstName + "</FirstName>");
sb.AppendLine("<LastName>" + lastName + "</LastName>");
sb.AppendLine("<Password>" + password + "</Password>");
sb.AppendLine("</Staff>");
string NewStudent = sb.ToString();
byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "application/xml";
req.ContentLength = arr.Length;
Stream reqStrm = req.GetRequestStream();
reqStrm.Write(arr, 0, arr.Length);
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
//MessageBox.Show("Staff Creation: Status " + resp.StatusDescription);
reqStrm.Close();
resp.Close();
}
Note: I have REMed out the MessageBox in the call to the web service to make sure you are not annoyed by it if the list is long, but you are free to "unREM" it if you need confirmation for every staff creation. In the same line of taught, there is not validation that the creation has occurred successfully. I would need more details to create a decent validation process.
Also VERY important, this does not validate if the staff you are saving already exists in the list. If you re-run this import procedure multiple times, it may (and probably will) create duplicate entries.
Cheers

WP7: can't get img from httpget url using webclient.OpenReadAsync

I need to get image from this API on Windows phone7 appplication,
getvmsimg
Description :
API for get variable message sign (VMS) as img
URL:
http://athena.traffy.in.th/apis/apitraffy.php?api=…&id=…[w=...]&[h=...]
Formats:
Image: PNG
HTTP Method:
GET
Requires Authentication :
true
API rate limited :
unlimited
and this is my code
I have to get a session key by another API first(Completely,No problem) and then i have to use the session key as a parameter in httpget url.
my key is correctly 100 percent, i have checked.
but It error at "image.SetSource(e.Result);" line (Unspecified error).
public intsign()
{
InitializeComponent();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("http://api.traffy.in.th/apis/getKey.php?appid="+appid));
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
rd = e.Result;
sessionkey = MD5Core.GetHashString(appid + rd) + MD5Core.GetHashString(hiddenkey + rd);
//MessageBox.Show(sessionkey);
client2.OpenReadCompleted += new OpenReadCompletedEventHandler(client2_OpenReadCompleted);
client2.OpenReadAsync(new Uri("http://athena.traffy.in.th/apis/apitraffy.php?api=getvmsimg&key=" + sessionkey + "&appid=" + appid + "&id=1&h=480&w=480"),client2);
}
void client2_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
BitmapImage image = new BitmapImage();
image.SetSource(e.Result);
intsignimg.Source = image;
}
thx, guy
Did you try to write the entire stream (with a buffer or else) into a MemoryStream and then use that MemoryStream instead of using directly the resulting stream ?

WPF - Web Request being truncated

I'm using the bing api to request some results.. when I run my code the response string is truncated so that its missing the first 10-50 characters.. when I paste the exact same request in the browser it returns the results just fine..
Here is my code.. what am I doing wrong?
string AppId = "My APP ID HERE :O ";
string url = "http://api.search.live.net/xml.aspx?Appid={0}&sources={1}&query={2}";
string completeUri = String.Format(url, AppId, "web", validateforweb(Artist) + "%20" + validateforweb(Song) + "%20" + "Lyrics");
HttpWebRequest webRequest = null;
webRequest = (HttpWebRequest)WebRequest.Create(completeUri);
HttpWebResponse webResponse = null;
webResponse = (HttpWebResponse)webRequest.GetResponse();
XmlReader xmlReader = null;
Stream s = webResponse.GetResponseStream();
xmlReader = XmlReader.Create(s);
StreamReader reader;
reader = new StreamReader(s);
string str = reader.ReadToEnd();
I suspect it's related to the fact you're creating 2 readers on the stream (XmlReader and StreamReader). The XmlReader starts buffering data from the stream as soon as you create it, so when the StreamReader starts reading from the same stream, it misses the part of the data that has been buffered by the XmlReader.
You can't use 2 readers on the same stream, they will conflict with each other.

Resources