Xamarin MVVM Fill Model with a Model Property - xamarin

How do work with a model with a model property inside of it?
I am pulling info from an api successfully but it does not work after I try to change my model from int to model like below:
public class TypeModel
{
[PrimaryKey]
public int pType { get; set; }
public DepartmentModel fDepartment { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Comments { get; set; }
public string Version { get; set; }
}
Here is the department model
public class DepartmentModel
{
public int pDepartment { get; set; }
public string Name { get; set; }
}
My ViewModel had this code and was working. Been trying to make changes as I think I need to change it in here somehow.
Types.Clear();
IEnumerable<TypesModel> types = await DataSource.GetTypesAsync(typeinfo.pType, true);
foreach (var column in types)
{
Types.Add(column);
}
Here is the deserialization from the api.
IEnumerable<TypeModel> TypeEnumerator;
public async Task<IEnumerable<TypeModel>> GetTypesAsync(bool r = false)
{
if (r)
{
var j = await HttpConstructor.GetStringAsync($"api/gettypes");
return await Task.Run(() => JsonConvert.DeserializeObject<IEnumerable<TypeModel>>(j));
}
return TypeEnumerator; ;
}
Here is the json information being produced from the api for types
{
"pType": 10,
"fDepartment": 1,
"title": "Bigwig",
"description": "For the bigwigs",
"comments": "high priority",
"version": "1.2.3"
},
{
"pType": 11,
"fDepartment": 1,
"title": "Frontdesk",
"description": "front end people",
"comments": "none",
"version": "1.2.4"
}

this is what I would do. There are undoubtedly other ways to approach it
public class TypeModel
{
[PrimaryKey]
public int pType { get; set; }
public int fDepartment { get; set; }
public DepartmentModel Department { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Comments { get; set; }
public string Version { get; set; }
}
List<TypesModel> types = await DataSource.GetTypesAsync(typeinfo.pType, true);
foreach (var type in types)
{
type.Department = new DepartmentModel
{
pDepartment = type.fDeparment,
Name = "???"
};
}

Got a solution going by using a Dictionary collection and avoided adjusting the model and mess up the business logic throughout the app.
I kept the original model and created a new one called TypesModel to use for list views.
public class TypesModel
{
[PrimaryKey]
public int pType { get; set; }
public Dictionary<int, string> fDepartment { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Comments { get; set; }
public string Version { get; set; }
}
Then I used Linq join to combine the information and also fill in the dictionary values.
var query = from t in types
join d in departments
on t.fDeparment equals d.pDepartment
select new TypesModel
{
pType = t.pType,
fDepartment = new Dictionary<int, string>()
{
{ d.pDepartment, d.Name }
},
Title = t.Title,
Description = t.Description
};

Related

Xamarin Picker Binding from nested classes

I am calling an API that returns nested classes (example below) and I am struggling to bind these to a Picker.
Is it possible to bind them nested classes to a picker as is? or do I need to somehow add them to a IList?
<Picker Title="Select a Currency" ItemsSource="{Binding CurrencyClass}" ItemDisplayBinding="{Binding currencyName}"/>
class MainPageViewModel : INotifyPropertyChanged
{
private Currencies _CurrencyClass;
public Currencies CurrencyClass
{
get { return _CurrencyClass; }
set
{
_CurrencyClass = value;
OnPropertyChanged();
}
}
}
This is a cut of the class they get desterilized too
public class Currencies
{
public class Rootobject
{
public Results results { get; set; }
}
public class Results
{
public XCD XCD { get; set; }
public EUR EUR { get; set; }
}
public class XCD
{
public string currencyName { get; set; }
public string currencySymbol { get; set; }
public string id { get; set; }
}
public class EUR
{
public string currencyName { get; set; }
public string currencySymbol { get; set; }
public string id { get; set; }
}
}
And this a cut of the json I am receiving.
{
"results": {
"XCD": {
"currencyName": "East Caribbean Dollar",
"currencySymbol": "$",
"id": "XCD"
},
"EUR": {
"currencyName": "Euro",
"currencySymbol": "€",
"id": "EUR"
}
}
}
So I figured out a work around for what I was aiming to achieve, this may not be a direct answer to my question but it is a solution for my issue.
I ended up just deserializing the JSON differently into a list of a Currency and then binding easily like you normally would.
class Currency
{
public string currencyName { get; set; }
public string currencySymbol { get; set; }
public string id { get; set; }
}
and how I deserialized it to fit in that class here, I parsed the JSON into a JObject and then for each child of each child I deserialize it into my Currency class.
List<Currency> cList = new List<Currency>();
HttpResponseMessage response = await client.GetAsync(urlAPI);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
JObject jo = JObject.Parse(responseBody);
var children = jo.SelectToken("results").Children();
foreach(var child in children)
{
var childrenOfChild = child.Children();
foreach(var c in childrenOfChild)
{
cList.Add(JsonConvert.DeserializeObject<Currency>(JsonConvert.SerializeObject(c)));
}
}

Can't get object with ReadAsAsync<T>

I have a Product class, which looks like this:
Public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Barcode { get; set; }
public string InnerCode { get; set; }
public virtual ProductUnit ProductUnit { get; set; }
public int? ProductUnitID { get; set; }
public virtual ProductType ProductType { get; set; }
public int? ProductTypeID { get; set; }
}
In ASP.NET Core Web API Service I have a put method which returns OK(product).
The response in postman looks like this:
{
"result": {
"id": 22,
"name": "Bread",
"productType": {
"id": 4,
"name": "Food",
"remarks": null,
"products": []
},
"productTypeID": 4,
"code": "566",
"barcode": "855",
"innerCode": "145522",
"productUnit": {
"id": 4,
"name": "Box",
"remarks": null,
"products": []
},
"productUnitID": 4
},
"id": 592, ---> //probably this
"exception": null,
"status": 5,
"isCanceled": false,
"isCompleted": true,
"isCompletedSuccessfully": true,
"creationOptions": 0,
"asyncState": null,
"isFaulted": false
}
I am trying to get Product object as shown below:
var data = await httpResponseMessage.Content.ReadAsAsync<Product>();
But As a result, I get the product object with null properties, except the ID, which is random number and which as I think is the id above the exception in the json response.
What mistake do I have?
So, I believe you are trying to parse result which is the inner object in your case.
In order to parse the whole result you have to create a type for mentioned json, which you can create using https://app.quicktype.io/#l=cs&r=json2csharp.
Classes will be as follows :
public partial class ProductResult
{
[JsonProperty("result")]
public Result Result { get; set; }
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("exception")]
public object Exception { get; set; }
[JsonProperty("status")]
public long Status { get; set; }
[JsonProperty("isCanceled")]
public bool IsCanceled { get; set; }
[JsonProperty("isCompleted")]
public bool IsCompleted { get; set; }
[JsonProperty("isCompletedSuccessfully")]
public bool IsCompletedSuccessfully { get; set; }
[JsonProperty("creationOptions")]
public long CreationOptions { get; set; }
[JsonProperty("asyncState")]
public object AsyncState { get; set; }
[JsonProperty("isFaulted")]
public bool IsFaulted { get; set; }
}
public partial class Result
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("productType")]
public Product ProductType { get; set; }
[JsonProperty("productTypeID")]
public long ProductTypeId { get; set; }
[JsonProperty("code")]
[JsonConverter(typeof(ParseStringConverter))]
public long Code { get; set; }
[JsonProperty("barcode")]
[JsonConverter(typeof(ParseStringConverter))]
public long Barcode { get; set; }
[JsonProperty("innerCode")]
[JsonConverter(typeof(ParseStringConverter))]
public long InnerCode { get; set; }
[JsonProperty("productUnit")]
public Product ProductUnit { get; set; }
[JsonProperty("productUnitID")]
public long ProductUnitId { get; set; }
}
public partial class Product
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("remarks")]
public object Remarks { get; set; }
[JsonProperty("products")]
public List<object> Products { get; set; }
}
now you can use ProductResult as
var data = await httpResponseMessage.Content.ReadAsAsync<ProductResult>();
Update
Another solution is, instead of creating type (class) for full JSON data you can use JObject class and using jsonpath you can select any property or object as follows :
string result = await httpResponseMessage.Content.ReadAsStringAsync();
Product product = JObject.Parse(result).SelectToken("$.result").ToObject<Product>()

Rasa NLU:Entity Synonyms detection inconsistency

Me and my team have been using Rasa NLU as a replacement for MS LUIS for over 2 months now, and it has worked out pretty well for us so far. Now we have around 900 entries as Entity Synonyms(as we were using List entity in LUIS).
And only for some utterances, the entity is detected as synonyms and for the majority of utterances, it is unable to detect Entity Synonyms. In order to detect synonyms, I have to create another simple entity which again we are manually training with all the synonym values, once the intents are trained with this simple Entity Rasa seems to detect entity for this intent as both simple and synonyms.
And another quick question, Is the Entity Synonyms in Rasa designed to return only one matched entity(unlike LUIS which used to return all the matched entities values)?
Is there any alternative to list entity from LUIS here in Rasa?
Entity Synonyms in Rasa can lead to some confusion. The actual functionality that they provide is very simple. For each entity that is parsed by the model the value of that entity is checked against the list of entity synonyms. If the value matches an entity synonym then it is replaced with the synonym value.
The big catch in the above statement is that the the entity has to be identified by the model before it can be replaced with a synonym.
So take this as a simplified example. Here is my entity synonym definition:
{
"value": "New York City",
"synonyms": ["NYC", "nyc", "the big apple"]
}
If my training data only provides this example:
{
"text": "in the center of NYC",
"intent": "search",
"entities": [
{
"start": 17,
"end": 20,
"value": "New York City",
"entity": "city"
}
]
}
It is very unlikely that my model will be able to detect an entity in a sentence like In the center of the big apple. As I said above if the big apple isn't parsed as an entity by the model it cannot be replaced by the entity synonyms to read New York City.
For this reason you should include more examples in the actual common_examples of the training data with the entities labeled. Once all of the variations of the entity are being classified correctly then add those values to the entity synonym and they will be replaced.
[
{
"text": "in the center of NYC",
"intent": "search",
"entities": [
{
"start": 17,
"end": 20,
"value": "New York City",
"entity": "city"
}
]
},
{
"text": "in the centre of New York City",
"intent": "search",
"entities": [
{
"start": 17,
"end": 30,
"value": "New York City",
"entity": "city"
}
]
}
]
I've opened a pull request into the Rasa docs page to add a note to this effect.
Firstly, I have downloaded some LUIS model JSON for doing this, as shown in the following screenshot:
Next, I have written a sample C# console app for converting LUIS Model Schema into RASA.
Here is the LUISModel model class.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace JSONConversion.Models
{
public class LuisSchema
{
public string luis_schema_version { get; set; }
public string versionId { get; set; }
public string name { get; set; }
public string desc { get; set; }
public string culture { get; set; }
public List<Intent> intents { get; set; }
public List<entity> entities { get; set; }
public object[] composites { get; set; }
public List<Closedlist> closedLists { get; set; }
public List<string> bing_entities { get; set; }
public object[] actions { get; set; }
public List<Model_Features> model_features { get; set; }
public List<regex_Features> regex_features { get; set; }
public List<Utterance> utterances { get; set; }
}
public class regex_Features
{
public string name { get; set; }
public string pattern { get; set; }
public bool activated { get; set; }
}
public class Intent
{
public string name { get; set; }
}
public class entity
{
public string name { get; set; }
}
public class Closedlist
{
public string name { get; set; }
public List<Sublist> subLists { get; set; }
}
public class Sublist
{
public string canonicalForm { get; set; }
public List<string> list { get; set; }
}
public class Model_Features
{
public string name { get; set; }
public bool mode { get; set; }
public string words { get; set; }
public bool activated { get; set; }
}
public class Utterance
{
public string text { get; set; }
public string intent { get; set; }
[JsonProperty("entities")]
public List<Entities> Entities { get; set; }
}
public class Entities
{
[JsonProperty("entity")]
public string Entity { get; set; }
public int startPos { get; set; }
public int endPos { get; set; }
}
}
Here is the RASAModel model class:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace JSONConversion.Models
{
public class RASASchema
{
public Rasa_Nlu_Data rasa_nlu_data { get; set; }
}
public class Rasa_Nlu_Data
{
public List<Entity_Synonyms> entity_synonyms { get; set; }
public List<Regex_Features> regex_features { get; set; }
public List<Common_Examples> common_examples { get; set; }
}
public class Entity_Synonyms
{
public string value { get; set; }
public List<string> synonyms { get; set; }
}
public class Common_Examples
{
public string text { get; set; }
public string intent { get; set; }
public List<Entity> entities { get; set; }
}
public class Entity
{
public string entity { get; set; }
public string value { get; set; }
public int start { get; set; }
public int end { get; set; }
}
public class Regex_Features
{
public string name { get; set; }
public string pattern { get; set; }
}
}
And I have written 2 methods which parse the LUISModel model class for synonyms from the phraselist section and adds them in the common_examples object in RASA_NLU training object.
using JSONConversion.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace JSONConversion.Services
{
public static class JSONHelper
{
public static Task<string> ReadFromFile(string FilePath)
{
try
{
Task<string> readFromFileTask = Task.Run<string>(() =>
{
return File.ReadAllText(FilePath);
});
return readFromFileTask;
}
catch(Exception ex)
{
throw;
}
}
public static RASASchema ConvertLUISJSON(string StringifiedLUISJson)
{
try
{
LuisSchema luisSchema = JsonConvert.DeserializeObject<LuisSchema>(StringifiedLUISJson);
RASASchema rasaSchema = new RASASchema();
rasaSchema.rasa_nlu_data = new Rasa_Nlu_Data();
rasaSchema.rasa_nlu_data.common_examples = new List<Common_Examples>();
rasaSchema.rasa_nlu_data.entity_synonyms = new List<Entity_Synonyms>();
rasaSchema.rasa_nlu_data.regex_features = new List<Regex_Features>();
luisSchema.closedLists.ForEach(x =>
{
x.subLists.ForEach(y =>
{
rasaSchema.rasa_nlu_data.entity_synonyms.Add(new Entity_Synonyms()
{
value = y.canonicalForm,
synonyms = y.list
});
});
});
luisSchema.model_features.ForEach(x =>
{
rasaSchema.rasa_nlu_data.entity_synonyms.Add(new Entity_Synonyms()
{
value = x.name,
synonyms = x.words.Split(',').ToList()
});
});
luisSchema.regex_features.ForEach(x =>
{
rasaSchema.rasa_nlu_data.regex_features.Add(new Regex_Features()
{
name = x.name,
pattern = x.pattern
});
});
luisSchema.utterances.ForEach(x =>
{
Common_Examples rasaUtterances = new Common_Examples();
rasaUtterances.text = x.text;
rasaUtterances.intent = x.intent;
List<Entity> listOfRASAEntity = new List<Entity>();
x.Entities.ForEach(y =>
{
listOfRASAEntity.Add(new Entity()
{
start = y.startPos,
end = y.endPos,
entity = y.Entity,
value = x.text.Substring(y.startPos, (y.endPos - y.startPos) + 1)
});
});
rasaUtterances.entities = listOfRASAEntity;
rasaSchema.rasa_nlu_data.common_examples.Add(rasaUtterances);
});
return rasaSchema;
}
catch (Exception ex)
{
throw;
}
}
}
}
And just called those JSON conversion methods to convert LUIS Models into RASA models.
using System.Text;
using JSONConversion.Services;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace JSONConversion
{
class Program
{
static void Main(string[] args)
{
string json = JsonConvert.SerializeObject(JSONConversion.Services.JSONHelper.ConvertLUISJSON(JSONHelper.ReadFromFile(#"C:\Users\xyz\Documents\luis.json").Result), new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Formatting = Formatting.Indented
});
File.WriteAllText(#"C:\Users\xyz\Desktop\RASA\data\examples\RasaFormat.json", json, Encoding.UTF8);
}
}
}
After getting the RASA model, you can just simply train RASA for synonyms.

Convert query expression to lambda in LINQPad4

While coding I had came across a LINQ query that I was able to accomplish in query syntax but not in lamda syntax. While this works fine in the application, I wanted to learn the query syntax for what I was trying to do.
Essentially, I have a database with views, CO_Leather_V and CO_LeatherSizeColor_V. I also have two classes, CuttingOrder and CuttingOrderDetail. CuttingOrderDetail contains entirely string,int and float properties. The CuttingOrder Class contains 2 string properties and a List of CuttingOrderDetails.
public class CuttingOrder
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public List<CuttingOrderDetail> details { get; set; }
}
public class CuttingOrderDetail
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public string itemCode { get; set; }
public string material { get; set; }
public string color { get; set; }
public string size { get; set; }
public int qty { get; set; }
public float squareFeet { get; set; }
public float squareFeetUsed { get; set; }
}
The query expression I used to get a list of all CuttingOrders with a given SalesOrder was
cos = (from l in db.CO_Leather_Vs
where l.orderNo == Globals.orderNo
select new Globals.CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = (
from d in db.CO_LeatherSizeColor_Vs
select new Globals.CuttingOrderDetail
{
cuttingOrderNo = d.orderNo
}
).ToList()
}).ToList();
I converted this to work in LINQPad with the following query, but I can't get anything to show on the lambda pane.
void Main()
{
var p = (from l in CO_Leather_V
select new CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = (
from d in CO_LeatherSizeColor_V
select new CuttingOrderDetail
{
cuttingOrderNo = d.OrderNo
}
).ToList()
}).ToList();
p.Dump();
}
// Define other methods and classes here
public class CuttingOrder
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public List<CuttingOrderDetail> details { get; set; }
}
public class CuttingOrderDetail
{
public string cuttingOrderNo { get; set; }
public string reserveSalesOrderNo { get; set; }
public string itemCode { get; set; }
public string material { get; set; }
public string color { get; set; }
public string size { get; set; }
public int qty { get; set; }
public float squareFeet { get; set; }
public float squareFeetUsed { get; set; }
}
If anyone knows how to perform the linq query in lambda form or knows why LINQPad is unable to generate the lamda form it would be greatly appreciated.
This should work:
var p = CO_Leather_V.Select(l=> new CuttingOrder
{
cuttingOrderNo = "NOT SET",
reserveSalesOrderNo = "FAKE_SO_NO",
details = CO_LeatherSizeColor_V.Select(d=>new CuttingOrderDetail {cuttingOrderNo = d.OrderNo}).ToList()
}).ToList();
However, CO_LeatherSizeColor_V does not reference l, so you're going to get everything in that table, every time. You might want something like:
details = l.LeatherSizeColor.Select(d=>new CuttingOrderDetail {cuttingOrderNo = d.OrderNo}).ToList()
for that line instead.

ASP.NET MVC3 - Entity Framework: Many-to-many relation (news and categories)

I want to create categories for news. It will be many-to-many relation. How do that properly? I have created two classes:
public class News
{
public News()
{
this.NewsCategories = new List<NewsCategory>();
}
public int ID { get; set; }
public DateTime Date { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public IEnumerable<NewsCategory> NewsCategories { get; set; }
}
public class NewsCategory
{
public NewsCategory()
{
this.News = new List<News>();
}
public int ID { get; set; }
public string Name { get; set; }
public IEnumerable<News> News { get; set; }
}
But EF create just two tables...without Join table. I have created also custom DbInitializer:
public class TouristGuideDBInitializer : DropCreateDatabaseAlways<TouristGuideDB>
{
protected override void Seed(TouristGuideDB context)
{
base.Seed(context);
context.NewsCategories.Add(new NewsCategory { Name = "Default" });
context.NewsCategories.Add(new NewsCategory { Name = "Second" });
context.News.Add(new News { Date = DateTime.Now, Text = "asasdfas fasdfa sdf asf asf", Title = "Hello world" });
context.SaveChanges();
var news = context.News.First();
var cat = context.NewsCategories.Where(r => r.Name == "Default").Single();
news.NewsCategories.ToList().Add(cat);
context.SaveChanges();
}
}
But it just add one news and two categories...without relationships...
How it should be done properly (the relations)?
You need to use ICollection<T> for navigation properties.

Resources