How can Xamarin.Forms read json from WCF? - c#

I'm trying to create my first Xamarin.Forms mobile app with a map and pins, so please bear with me.
I'm trying to add pins to the map. I use this code to add one pin:
map = new Map {
IsShowingUser = true,
HeightRequest = 100,
WidthRequest = 960,
VerticalOptions = LayoutOptions.FillAndExpand
};
map.MoveToRegion (MapSpan.FromCenterAndRadius (
new Position (36.9628066,-122.0194722), Distance.FromMiles (3)));
var position = new Position(36.9628066,-122.0194722);
var pin = new Pin {
Type = PinType.Place,
Position = position,
Label = "Santa Cruz",
Address = "custom detail info"
};
map.Pins.Add(pin);
Now, instead of adding just one pin, I'd like to add several pins from a tsql table.
So I created a WCF service that returns a list of coordinates. One returns a json and the other returns a datatable:
public DataTable ToEraseGetCoordinates()
{
string sqlQuery = "select lat,lon from MyStores";
string connString = GetConnString();
SqlDatabase sqlDatabase = new SqlDatabase(connString);
DataSet result = sqlDatabase.ExecuteDataSet(CommandType.Text, sqlQuery);
return result.Tables[0];
}
public System.IO.Stream ToEraseGetCoordinatesJson()
{
string sqlQuery = "select lat,lon from MyStores";
string connString = GetConnString();
SqlDatabase sqlDatabase = new SqlDatabase(connString);
DataSet result = sqlDatabase.ExecuteDataSet(CommandType.Text, sqlQuery);
return ConvertToJson(result.Tables[0]);
}
I invoke the WCF like so: http://80.102.51.381:101/Service1.svc/ToEraseGetCoordinates (for an xml representation of the datatable)
For the JSON: http://80.102.51.381:101/Service1.svc/ToEraseGetCoordinatesJson, which returns this:
{"lat":25.7616,"lon":-80.1917},{"lat": 28.5383,"lon":-81.3792}
My question is: what do I next so that my Xamarin.Form reads this?
Regardless of the return type, I don't know how Xamarin will consume the WCF and draw the pins.

This earthquake map sample does basically what you want (it's a bit old, sadly).
Basically you want to download your Json (eg in this class)
// your http://80.102.51.381:101/Service1.svc/ToEraseGetCoordinatesJson would go here
var response = await client.GetAsync("earthquakesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&username=bertt");
var earthquakesJson = response.Content.ReadAsStringAsync().Result;
then you need to convert the Json - but you said you've already done that
var rootobject = JsonConvert.DeserializeObject<Rootobject>(earthquakesJson);
lastly just create and add the pins to the map
var earthquakes = await webSvc.GetEarthquakesAsync();
Xamarin.Forms.Device.BeginInvokeOnMainThread( () => {
Debug.WriteLine("found " + earthquakeString.Length + " earthquakes");
label.Text = earthquakeString.Length + " earthquakes";
foreach (var earthquake in earthquakes)
{
var p = new Pin();
p.Position = new Position(earthquake.lat, earthquake.lng);
p.Label = "Magnitude: " + earthquake.magnitude;
m.Pins.Add(p);
}
});
Originally the pins weren't able to be databound, which is why it loops through to add them. Not sure if the ability to databind pings has been added to Xamarin.Forms since.
You'll probably want to keep track of the lat/longs so you can calculate a new region to set the maps view, to default to showing all the pins you added...
See the Maps docs and maps custom renderers for more info.

Related

Wordcloud Highcharts .NET

I am having an issue with the creation of a Wordcloud with Highcharts 7.1.2 with C# and .NET.
I can create the wordcloud just fine, but I can't set the weight of the words.
The piece of code below is what I currently have, as you can see I am trying to use the Labelrank as a mean to set the weight. I cannot find an example of the wordcloud in c#, but I found some in JS and they always set the weight of each word.
List<Series> seriesList = new List<Series>();
List<WordcloudSeriesData> newWordcloudSeriesDataList = new List<WordcloudSeriesData>();
foreach (var data in datas)
{
newWordcloudSeriesDataList.Add(new WordcloudSeriesData
{
Name = data.Name,
Labelrank = data.Rank
});
}
seriesList.Add(new WordcloudSeries
{
Data = newWordcloudSeriesDataList,
Rotation = new WordcloudSeriesRotation
{
From = 0,
To = 0,
Orientations = 1
}
});
PS: I found a workaround.
When you create the json before sending it to the front, use
chartinfo = chartinfo.Replace("labelrank", "weight");
where chartinfo is the json.

Rally C#: Is it possible to create a new user story along with an attachment? (Avoiding to query for the user-story reference)

Please be patient I have already gone through the example from: How to Add an Attachment to a User Story using Rally REST .NET
However the sample code requires a query to identify the newest user story reference. The sample illustrates how to add an attachment to an existing user story. I would like to accomplish: Creating a new user story along with an attachment.
Here is my method.
public void createUsWithAttachment(string workspace, string project,
string userStoryName, string userStoryDescription){
//Authenticate with Rally
this.EnsureRallyIsAuthenticated();
//UserStory Setup
DynamicJsonObject toCreate = new DynamicJsonObject();
toCreate[RallyField.workSpace] = workspace;
toCreate[RallyField.project] = project;
toCreate[RallyField.name] = userStoryName;
toCreate[RallyField.description] = userStoryDescription;
//get the image reference - assume that this is where the image lives after being downloaded from Outlook
String imageFilePath = "C:\\Users\\secret\\...";
String imageFileName = "file.png";
String fullImageFile = imageFilePath + imageFileName;
Image myImage = Image.FromFile(fullImageFile);
// Convert Image to Base64 format
string imageBase64String = imageToBase64(myImage, System.Drawing.Imaging.ImageFormat.Png);
// Length calculated from Base64String converted back
var imageNumberBytes = Convert.FromBase64String(imageBase64String).Length;
// DynamicJSONObject for AttachmentContent
DynamicJsonObject myAttachmentContent = new DynamicJsonObject();
myAttachmentContent["Content"] = imageBase64String;
try
{
//create user story
CreateResult createUserStory = _api.Create(RallyField.hierarchicalRequirement, toCreate);
//create attachment
CreateResult myAttachmentContentCreateResult = _api.Create("AttachmentContent", myAttachmentContent);
String myAttachmentContentRef = myAttachmentContentCreateResult.Reference;
Console.WriteLine("Created: " + myAttachmentContentRef);
// DynamicJSONObject for Attachment Container
DynamicJsonObject myAttachment = new DynamicJsonObject();
//Note the below commented line
/*myAttachment["Artifact"] = ;*/
myAttachment["Content"] = myAttachmentContentRef;
myAttachment["Name"] = "AttachmentFromREST.png";
myAttachment["Description"] = "Attachment Desc";
myAttachment["ContentType"] = "image/png";
myAttachment["Size"] = imageNumberBytes;
//create attachment
CreateResult myAttachmentCreateResult = _api.Create("Attachment", myAttachment);
}
catch (WebException e)
{
Console.WriteLine(e.Message);
}
}
In the above commented line I need to get a reference to the created user story which I can do, but that would require another method to fetch the user story which I have.
However I am wondering if this can be accomplished a different way similar to how we can create a user story with the dynamicJsonObject staging.
I was thinking something like this would work, but I am having a tough time.
DynamicJsonObject toCreate = new DynamicJsonObject();
toCreate[RallyField.workSpace] = workspace;
toCreate[RallyField.project] = project;
toCreate[RallyField.name] = userStoryName;
toCreate[RallyField.description] = userStoryDescription;
toCreate["Content"] = imageToBase64;
CreateResult createUserStory = _api.Create(RallyField.hierarchicalRequirement, toCreate);
My above assumption is not going as planned and I was wondering if there is a way to create a new user story with an attachment, without having to query for the userstory reference as neatly illustrated in the example from the link provided.
Thanks and credit to the author from the example in the link.
You should already have what you need to associate it from the create result:
myAttachment["Artifact"] = createUserStory.Reference;

How to get data from Parse.com in a list and apply it in listview?

I'm very new to Parse.com and can't seem to get fetching of data working.
I tried an async method which did a foreach but that never seemed to work so then I did a try with a ParseQuery but that didn't work either.
For example:
ParseQuery<ParseObject> query = ParseObject.GetQuery("Horse");
string name = query.Get<string>("Name");
Debug.WriteLine("Horse: " + name);
Ideally I would like to get all records from the model Horse and then loop over it to fill up a listview. I now have a hardcoded sample but since I don't even get all records from the table in a list I have no clue how to continue.
var listView = new ListView
{
RowHeight = 40
};
listView.ItemsSource = new string[]
{
//This should be filled up with the field 'Name' from the model 'Horse' dynamically..
"Buy pears",
"Buy oranges",
"Buy mangos",
"Buy apples",
"Buy bananas"
};
Content = new StackLayout
{
VerticalOptions = LayoutOptions.FillAndExpand,
Children = { listView }
};
Could anybody give me a helping hand here please? I followed the guide from https://parse.com/docs/dotnet_guide#objects-retrieving but those options do not seem to work.
Update:
So far I can fetch all the data thanks to the answer from har07.
Now I get an error when I want to fill up the ListView:
public async void getHorsesFromDb()
{
ParseQuery<ParseObject> query = ParseObject.GetQuery("Horse");
IEnumerable<ParseObject> horses = await query.FindAsync();
var listView = new ListView();
List<string> horseList = null;
foreach (ParseObject horse in horses)
{
string name = horse.Get<string>("Name");
horseList.Add(name);
Debug.WriteLine("Horse: " + name);
}
listView.ItemsSource = horseList;
// Using ItemTapped
listView.ItemTapped += async (sender, e) => {
await DisplayAlert("Tapped", e.Item + " row was tapped", "OK");
Debug.WriteLine("Tapped: " + e.Item);
((ListView)sender).SelectedItem = null; // de-select the row
};
}
Error on my screen:
The current stack frame was not found in a loaded module. Source cannot be shown for this location.
> 0x21 in System.Diagnostics.Debugger.Mono_UnhandledException_internal C#
The link you're following shows how to get single row data (ParseObject) by passing the particular objectId (which value is xWMyZ4YEGZ in that example) to the query.
On the other hand, to get multiple rows from a table follow Queries section of the same. Getting all rows should even be simpler (no need to write any LINQ up to this point) :
ParseQuery<ParseObject> query = ParseObject.GetQuery("Horse");
IEnumerable<ParseObject> horses = await query.FindAsync();
foreach (ParseObject horse in horses)
{
string name = horse.Get<string>("Name");
Debug.WriteLine("Horse: " + name);
}

Object reference not set to instance of object, despite creating a new object

I'm currently working on a basic drawing program. One of the requirements is to be able to save the list of drawn objects and load it back in. So far, I have written a save function that exports all items of the list to an XML format, and I'm currently working on the loading-part.
Whenever the program encounters a "< RechthoekTool >" (Dutch for RectangleTool), it executes the following code:
//Create new tool.
RechthoekTool tool = new RechthoekTool();
//Turn <Startpoint> and <Endpoint> into actual points
var sp = Regex.Replace(xn["Startpunt"].InnerText, #"[\{\}a-zA-Z=]", "").Split(',');
tool.startpunt = new Point(int.Parse(sp[0]), int.Parse(sp[1]));
var ep = Regex.Replace(xn["Eindpunt"].InnerText, #"[\{\}a-zA-Z=]", "").Split(',');
tool.eindpunt = new Point(int.Parse(ep[0]), int.Parse(ep[1]));
//Set colour and width of brush
string kleur = xn["Dikte"].InnerText;
kleur.Replace(#"Color [", "");
kleur.Replace(#"]", "");
Color c = Color.FromName(kleur);
tool.kwastkleur = c;
tool.kwast = new SolidBrush(c);
tool.dikte = int.Parse(xn["Dikte"].InnerText);
//Add to list
s.listItems.Add(tool);
Whenever I run the program, I get the 'NullReferenceException was unhandled' error("Object reference not set to an instance of an object.") at
s.listItems.Add(tool);
I do, however, instantiate the tool right at the beginning, don't I? What could be causing this error? Some Googling told me it might be because I forgot to assign a property, but as far as I can tell I've got them all covered...
Help would be greatly appreciated.
The error is due to s or s.listItems not being instantiated.
Without seeing more code, it's difficult to know which is null, but at a guess you are creating a new object for s, which contains a property/field listItems, but you aren't assigning a list to listItems.
The problem is that you aren't instantiating listItems or s. Not enough information is given to tell you how to instantiate s but you can do the other one like this:
s.listItems = new List<RechthoekTool>();
If you don't instantiate something using the new keyword; it simply won't work.
Using your code, try this:
//Create new tool.
RechthoekTool tool = new RechthoekTool();
//Turn <Startpoint> and <Endpoint> into actual points
var sp = Regex.Replace(xn["Startpunt"].InnerText, #"[\{\}a-zA-Z=]", "").Split(',');
tool.startpunt = new Point(int.Parse(sp[0]), int.Parse(sp[1]));
var ep = Regex.Replace(xn["Eindpunt"].InnerText, #"[\{\}a-zA-Z=]", "").Split(',');
tool.eindpunt = new Point(int.Parse(ep[0]), int.Parse(ep[1]));
//Set colour and width of brush
string kleur = xn["Dikte"].InnerText;
kleur.Replace(#"Color [", "");
kleur.Replace(#"]", "");
Color c = Color.FromName(kleur);
tool.kwastkleur = c;
tool.kwast = new SolidBrush(c);
tool.dikte = int.Parse(xn["Dikte"].InnerText);
List<RechthoekTool> s = new List<RechthoekTool>(); // You can now use your list.
//Add to list
s.listItems.Add(tool);

Amazon Product Advertising API for Asp.net & C#

I want to fetch books using Amazon Product Advertising API with asp.net and C#. All the guides and codes are so confusing as to they don't give you a single method to search the books.
Is there any single stub that can be used to call the service and fetch the books based on the ISBN.
thanks
There's a good sample solution you can download.
http://aws.amazon.com/code/2480?_encoding=UTF8&queryArg=searchQuery&x=0&fromSearch=1&y=0&searchPath=code&searchQuery=Advertising
They give you a class called SignedRequestHelper, then you make a call like this:
public static void Main()
{
SignedRequestHelper helper = new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
/*
* The helper supports two forms of requests - dictionary form and query string form.
*/
String requestUrl;
String title;
/*
* Here is an ItemLookup example where the request is stored as a dictionary.
*/
IDictionary<string, string> r1 = new Dictionary<string, String>();
r1["Service"] = "AWSECommerceService";
r1["Version"] = "2009-03-31";
r1["Operation"] = "ItemLookup";
r1["ItemId"] = ITEM_ID;
r1["ResponseGroup"] = "Small";
/* Random params for testing */
r1["AnUrl"] = "http://www.amazon.com/books";
r1["AnEmailAddress"] = "foobar#nowhere.com";
r1["AUnicodeString"] = "αβγδεٵٶٷٸٹٺチャーハン叉焼";
r1["Latin1Chars"] = "ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJij";
requestUrl = helper.Sign(r1);
title = FetchTitle(requestUrl);
System.Console.WriteLine("Method 1: ItemLookup Dictionary form.");
System.Console.WriteLine("Title is \"" + title + "\"");
System.Console.WriteLine();
}
You need to use the ItemLookup (like the example) but set the IdType to ISBN. Then set the ItemId to the actual ISBN. Here are the details on ItemLookup:
docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?ItemLookup.html
I get this when I use that sample. looks like there has been a change in the API recently.
System.InvalidOperationException: There is an error in the XML document. ---> Sy
stem.InvalidOperationException: <ItemLookupResponse xmlns='http://webservices.am
azon.com/AWSECommerceService/2011-08-01'> was not expected.
To fetch books install this library (Install-Package Nager.AmazonProductAdvertising)
https://www.nuget.org/packages/Nager.AmazonProductAdvertising/
Example:
var authentication = new AmazonAuthentication("accesskey", "secretkey");
var client = new AmazonProductAdvertisingClient(authentication, AmazonEndpoint.UK);
var result = await client.GetItemsAsync("978-0261102385");

Categories