DownloadStrinAsync error during parsing in Windows Phone - windows

i've an issue... I would create an app that scraping the result of a google search.. but when I try to use downloadstringasync the debug return me an error "Impossible to assign 'void' to a local variable ..."
You say how I can resolve it?
This is the code
public class SearchResult
{
public string url;
public string title;
public string content;
public FindingEngine engine;
public enum FindingEngine { google, bing, google_and_bing };
public SearchResult(string url, string title, string content, FindingEngine engine)
{
this.url = url;
this.title = title;
this.content = content;
this.engine = engine;
}
}
public static List<SearchResult> GoogleSearch(string search_expression,
Dictionary<string, object> stats_dict)
{
var url_template = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=large&safe=active&q={0}&start={1}";
Uri search_url;
var results_list = new List<SearchResult>();
int[] offsets = { 0, 8, 16, 24, 32, 40, 48 };
foreach (var offset in offsets)
{
var searchUrl = new Uri(string.Format(url_template, search_expression, offset));
var page = new WebClient().DownloadStringAsync(searchUrl);
var o = (JObject)JsonConvert.DeserializeObject(page);
var results_query =
from result in o["responseData"]["results"].Children()
select new SearchResult(
url: result.Value<string>("url").ToString(),
title: result.Value<string>("title").ToString(),
content: result.Value<string>("content").ToString(),
engine: SearchResult.FindingEngine.google
);
foreach (var result in results_query)
results_list.Add(result);
}
return results_list;
}
Thanks!

DownloadStringAsync doesn't return anything i.e. a void so you cannot simply assign a variable to it.
You need to add an event handler to DownloadStringCompleted which will be fired when DownloadStringAsync completes.
var client = new WebClient();
client.DownloadStringCompleted += client_DownloadStringCompleted;
client.DownloadStringAsync(searchUrl);
static void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) {
// e.Result will contain the returned JSON. Move the code that parse the result to here.
}

Related

File upload example for grapevine

I am new to Web API and REST services and looking to build a simple REST server which accepts file uploads. I found out grapevine which is simple and easy to understand. I couldn't find any file upload example?
This is an example using System.Web.Http
var streamProvider = new MultipartFormDataStreamProvider(ServerUploadFolder);
await Request.Content.ReadAsMultipartAsync(streamProvider);
but the grapevine Request property does not have any method to do that. Can someone point me to an example?
If you are trying to upload a file as a binary payload, see this question/answer on GitHub.
If you are trying to upload a file from a form submission, that will be a little bit trickier, as the multi-part payload parsers haven't been added yet, but it is still possible.
The following code sample is complete untested, and I just wrote this off the top of my head, so it might not be the best solution, but it's a starting point:
public static class RequestExtensions
{
public static IDictionary<string, string> ParseFormUrlEncoded(this IHttpRequest request)
{
var data = new Dictionary<string, string>();
foreach (var tuple in request.Payload.Split('='))
{
var parts = tuple.Split('&');
var key = Uri.UnescapeDataString(parts[0]);
var val = Uri.UnescapeDataString(parts[1]);
if (!data.ContainsKey(key)) data.Add(key, val);
}
return data;
}
public static IDictionary<string, FormElement> ParseFormData(this IHttpRequest request)
{
var data = new Dictionary<string, FormElement>();
var boundary = GetBoundary(request.Headers.Get("Content-Type"));
if (boundary == null) return data;
foreach (var part in request.Payload.Split(new[] { boundary }, StringSplitOptions.RemoveEmptyEntries))
{
var element = new FormElement(part);
if (!data.ContainsKey(element.Name)) data.Add(element.Name, element);
}
return data;
}
private static string GetBoundary(string contenttype)
{
if (string.IsNullOrWhiteSpace(contenttype)) return null;
return (from part in contenttype.Split(';', ',')
select part.TrimStart().TrimEnd().Split('=')
into parts
where parts[0].Equals("boundary", StringComparison.CurrentCultureIgnoreCase)
select parts[1]).FirstOrDefault();
}
}
public class FormElement
{
public string Name => _dispositionParams["name"];
public string FileName => _dispositionParams["filename"];
public Dictionary<string, string> Headers { get; private set; }
public string Value { get; }
private Dictionary<string, string> _dispositionParams;
public FormElement(string data)
{
var parts = data.Split(new [] { "\r\n\r\n", "\n\n" }, StringSplitOptions.None);
Value = parts[1];
ParseHeaders(parts[0]);
ParseParams(Headers["Content-Disposition"]);
}
private void ParseHeaders(string data)
{
Headers = data.TrimStart().TrimEnd().Split(new[] {"\r\n", "\n"}, StringSplitOptions.RemoveEmptyEntries).Select(header => header.Split(new[] {':'})).ToDictionary(parts => parts[0].TrimStart().TrimEnd(), parts => parts[1].TrimStart().TrimEnd());
}
private void ParseParams(string data)
{
_dispositionParams = new Dictionary<string, string>();
foreach (var part in data.Split(new[] {';'}))
{
if (part.IndexOf("=") == -1) continue;
var parts = part.Split(new[] {'='});
_dispositionParams.Add(parts[0].TrimStart(' '), parts[1].TrimEnd('"').TrimStart('"'));
}
}
}
If you are looking for something async to use immediately, you can try to implement the answer to this stackoverflow question, which has not been tested by me.

How to convert image to base64 string in Windows Phone?

I am developing a windows phone application in which I have to convert image to base64 string and I have to pass that string through Web Service. So I tried many Ways, but I cant able to send it as everytime I am getting error as "Target Invocation error". With this code I can choose the image from library but I cant send through web service.
I used the following code to covert the image:
private void photoChooserTask_Completed(object sender, PhotoResult e)
{
BitmapImage image = new BitmapImage();
image.SetSource(e.ChosenPhoto);
this.imageTribute.Source = image;
byte[] bytearray = null;
using (MemoryStream ms = new MemoryStream())
{
if (imageTribute.Source == null)
{
}
else
{
WriteableBitmap wbitmp = new WriteableBitmap((BitmapImage)imageTribute.Source);
wbitmp.SaveJpeg(ms, 40, 40, 0, 82);
bytearray = ms.ToArray();
}
}
strimage = Convert.ToBase64String(bytearray);
}
So please if anyone knows about that, help me out. Thanx in advance.
EDIT
void uploadphoto()
{
WebClient webClient1 = new WebClient();
webClient1.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient1_DownloadStringCompleted);
webClient1.DownloadStringAsync(new Uri("Web Service"));
}
void webClient1_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var rootobject1 = JsonConvert.DeserializeObject<RootObject1>(e.Result);
int error = rootobject1.response.errorFlag;
string message = rootobject1.response.msg;
if (error == 0)
{
MessageBox.Show(message);
}
else
{
MessageBox.Show(message);
}
}
public class Response1
{
public int errorFlag { get; set; }
public string msg { get; set; }
public List<string> uploadedImageNames { get; set; }
}
public class RootObject1
{
public Response1 response { get; set; }
}
private void ImageUpload(object sender, RoutedEventArgs e)
{
//MessageBoxResult mb = MessageBox.Show("Select the mode of uploading the picture", "", MessageBoxButton.OKCancel);
Popup popup = new Popup();
photoSelection photo = new photoSelection();
popup.Child = photo;
popup.IsOpen = true;
photo.camera.Click += (s, args) =>
{
photoCameraCapture.Show();
popup.IsOpen = false;
};
photo.library.Click += (s, args) =>
{
photoChooserTask.Show();
popup.IsOpen = false;
};
}
EDIT
Here I uploaded the stack trace of my error. So please check and reply me.
A Target Invocation Exception error tells you that the application crashed while invoking a method which could be many things. The real error is in the InnerException.
Look at the InnerException property of the TargetInvocationException object. This will show you the stack trace and the actual error thrown.
Get your file into stream either from resource or from isolatedStorage
//getting file from resource
var resource = Application.GetResourceStream(new Uri("image.jpg", UriKind.Relative));
//get Stream Data
StreamReader streamReader = new StreamReader(resource.Stream);
//initializing bytearray to stream length
byte[] imageData = new byte[streamReader.Length];
//wriing from stream to imagdata
streamReader.Read(imageData, 0, imageData.Length);
streamReader.Close();
Use isolatedStorageFile to read from isolated storage
now you have your image data in imageData and to convert it into base64 use:
var baseString = Convert.ToBase64String(imageData);

Don't show dropdown in Autocompletebox in windows phone

I get response from server, it is Json where are data about street names. Then I parse response string to Json, and add street names to list. I want that this list show like dropdown in Autocompletebox, when text length equals two(I press second character in Autocompletebox).
Also I use Json.Net library.
I use this code:
Here is class(JsonWorker) I use:
class JsonWorker
{
public async Task<HttpWebResponse> send(string requestUrl, JObject jsonObjesct)
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(requestUrl);
request.ContentType = "text/plain; charset=utf-8";
request.Method = "POST";
byte[] jsonAsBytes = Encoding.UTF8.GetBytes(jsonObjesct.ToString());
Stream x = await request.GetRequestStreamAsync();
await x.WriteAsync(jsonAsBytes, 0, jsonAsBytes.Length);
x.Close();
HttpWebResponse response = (HttpWebResponse) (await request.GetResponseAsync());
return response;
}
public async Task<string> get(
HttpWebResponse response)
{
var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
string str_responsefromjson = await sr.ReadToEndAsync();
sr.Close();
stream.Close();
return str_responsefromjson;
}
Here is method(GetSteets):
private async Task<List<string>> GetStreets()
{
JObject jo = new JObject();
jo.Add("chars", AutoCompleteBox_Streets.Text);
jo.Add("city_id", "1");
JsonWorker jWorker = new JsonWorker();
var response = await jWorker.send("website", jo);
string str_responseformjson = await jWorker.get(response);
jo = JObject.Parse(str_responseformjson);
JArray ja = (JArray)jo["street"];
List<string> list_Streets = new List<string>();
foreach (var elem in ja)
{
list_Streets.Add(elem["title"].ToString());
}
return list_Streets;
}
Here is when I call the method above:
private async void AutoCompleteBox_Streets_TextChanged(object sender, RoutedEventArgs e)
{
if (AutoCompleteBox_Streets.Text.Length.Equals(2))
{
AutoCompleteBox_Streets.ItemsSource = await GetStreets();
//On the string of code above in debug, ItemSource contains list of streets
}
}
And when I enter the second character in Autocompletebox, it don't show dropdownlist. Please help.
Edit
After understanding your use case then what you need is use the Populating event. This event is fired when you want to populate the drop-down with possible matches. To make this called once 2 characters or more have been typed you will also need to set MinimumPrefixLength to 2.
Moreover, change your GetStreets method to take a string param containing the chars in the textbox.
// Your page Loaded event. Bind this event in your xaml.
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) {
AutoCompleteBox_Streets.MinimumPrefixLength = 2;
AutoCompleteBox_Streets.Populating += AutoComplete_Populating;
}
private async void AutoComplete_Populating(object sender, PopulatingEventArgs e) {
// e.Parameter will contain the chars in your textbox.
AutoCompleteBox_Streets.ItemsSource =
await GetStreets(HttpUtility.UrlEncode(e.Parameter));
AutoCompleteBox_Streets.PopulateComplete();
}
private async Task<List<string>> GetStreets(string chars) {
JObject jo = new JObject();
jo.Add("chars", chars);
// Rest of your method code
// ...
}
What you need is setting MinimumPrefixLength property to 2.
Also move your bindings to the constructor and remove the TextChanged event.
// Your constructor
public MyPage() {
InitializeComponent();
BindStreetNames();
}
private async void BindStreetNames() {
AutoCompleteBox_Streets.ItemsSource = await GetStreets();
AutoCompleteBox_Streets.MinimumPrefixLength = 2;
}
private async void AutoCompleteBox_Streets_TextChanged(object sender, RoutedEventArgs e) {
/* Remove this handler */
}

uploading photo to a webservice with mvvmcross and mono touch

What I want to do is simply to upload a photo to a webservice using mono touch/mono droid and mvvmcross, hopefully in a way so I only have to write the code once for both android and IOS :)
My initial idea is to let the user pick an image (in android using an intent) get the path for the image. Then use MvxResourceLoader resourceLoader to open an stream from the path and then use restsharp for creating a post request with the stream.
However I already hit a wall, when the user picks an image the path is e.g. "/external/images/media/13". this path results in a file not found exception when using the MvxResourceLoader resourceLoader.
Any ideas to why I get the exception or is there an better way to achieve my goal?
This is how I ended up doinging it - thank you stuart and to all the links :)
public class PhotoService :IPhotoService, IMvxServiceConsumer<IMvxPictureChooserTask>,IMvxServiceConsumer<IAppSettings>
{
private const int MaxPixelDimension = 300;
private const int DefaultJpegQuality = 64;
public void ChoosePhotoForEventItem(string EventGalleryId, string ItemId)
{
this.GetService<IMvxPictureChooserTask>().ChoosePictureFromLibrary(
MaxPixelDimension,
DefaultJpegQuality,
delegate(Stream stream) { UploadImage(stream,EventGalleryId,ItemId); },
() => { /* cancel is ignored */ });
}
private void UploadImage(Stream stream, string EventGalleryId, string ItemId)
{
var settings = this.GetService<IAppSettings>();
string url = string.Format("{0}/EventGallery/image/{1}/{2}", settings.ServiceUrl, EventGalleryId, ItemId);
var uploadImageController = new UploadImageController(url);
uploadImageController.OnPhotoAvailableFromWebservice +=PhotoAvailableFromWebservice;
uploadImageController.UploadImage(stream,ItemId);
}
}
public class PhotoStreamEventArgs : EventArgs
{
public Stream PictureStream { get; set; }
public Action<string> OnSucessGettingPhotoFileName { get; set; }
public string URL { get; set; }
}
public class UploadImageController : BaseController, IMvxServiceConsumer<IMvxResourceLoader>, IMvxServiceConsumer<IErrorReporter>, IMvxServiceConsumer<IMvxSimpleFileStoreService>
{
public UploadImageController(string uri)
: base(uri)
{
}
public event EventHandler<PhotoStreamEventArgs> OnPhotoAvailableFromWebservice;
public void UploadImage(Stream stream, string name)
{
UploadImageStream(stream, name);
}
private void UploadImageStream(Stream obj, string name)
{
var request = new RestRequest(base.Uri, Method.POST);
request.AddFile("photo", ReadToEnd(obj), name + ".jpg", "image/pjpeg");
//calling server with restClient
var restClient = new RestClient();
try
{
this.ReportError("Billedet overføres", ErrorEventType.Warning);
restClient.ExecuteAsync(request, (response) =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
//upload successfull
this.ReportError("Billedet blev overført", ErrorEventType.Warning);
if (OnPhotoAvailableFromWebservice != null)
{
this.OnPhotoAvailableFromWebservice(this, new PhotoStreamEventArgs() { URL = base.Uri });
}
}
else
{
//error ocured during upload
this.ReportError("Billedet kunne ikke overføres \n" + response.StatusDescription, ErrorEventType.Warning);
}
});
}
catch (Exception e)
{
this.ReportError("Upload completed succesfully...", ErrorEventType.Warning);
if (OnPhotoAvailableFromWebservice != null)
{
this.OnPhotoAvailableFromWebservice(this, new PhotoStreamEventArgs() { URL = url });
}
}
}
//method for converting stream to byte[]
public byte[] ReadToEnd(System.IO.Stream stream)
{
long originalPosition = stream.Position;
stream.Position = 0;
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
stream.Position = originalPosition;
}
}
}
Try:
Issues taking images and showing them with MvvmCross on WP
Need an example of take a Picture with MonoDroid and MVVMCross
https://github.com/Redth/WshLst/ - uses Xam.Mobile for it's picture taking

Unauthorizedaccessexception{"Invalid cross-thread access."}...is occur

i want to short my url with bitly but an exception is occur when i want to set out string to my text block
private void button1_Click(object sender, RoutedEventArgs e)
{
ShortenUrl(textBox1.Text);
}
enum Format
{
XML,
JSON,
TXT
}
enum Domain
{
BITLY,
JMP
}
void ShortenUrl(string longURL)
{
Format format = Format.XML;
Domain domain = Domain.BITLY;
string _domain;
//string output;
// Build the domain string depending on the selected domain type
if (domain == Domain.BITLY)
_domain = "bit.ly";
else
_domain = "j.mp";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
string.Format(#"http://api.bit.ly/v3/shorten?login={0}&apiKey={1}&longUrl={2}&format={3}&domain={4}",
"username", "appkey", HttpUtility.UrlEncode(longURL), format.ToString().ToLower(), _domain));
request.BeginGetResponse(new AsyncCallback(GetResponse), request);
}
void GetResponse(IAsyncResult result)
{
XDocument doc;
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string responseString = reader.ReadToEnd();
doc = XDocument.Load(reader.BaseStream);
}
//// var x = from c in doc.Root.Element("data").Elements()
// where c.Name == "url"
// select c;
//XElement n = ((IEnumerable<XElement>)x).ElementAt(0);
// textBox2.Text = ((IEnumerable<String>)x).ElementAt(0);
lista = (from Born_rich in doc.Descendants("url")
select new a()
{
shrtenurl = Born_rich.Value
}).ToList();
output = lista.ElementAt(0).shrtenurl;
textBox2.Text = output;
//
//
// textBox2.Text = s;
}
List<a> lista = new List<a>();
String output;
}
public class a
{
public String shrtenurl { set; get; }
}
The calback from HttpWebRequest occurs on a non-UI thread. If you want to change soemthing in the UI you must do it on the UI thread. Fortunatley there is an easy way to do this. You simply use the dispatcher to invoke the code in question on the UI.
Dispatcher.BeginInvoke(() => textBox2.Text = output);

Resources