Binding Odata Xamarin Xaml - xaml

I'm having trouble with binding a ListView from Odata, when I was working with local Db I was able to do the data binding returning a list in my ModelView class into my list variable through the get method, but with the Odata the method is Async, so I'am not able to return the list, and some how if i fill the variable in the method, it doesn't work, and at this point I cant find the solution, if someone could help me, I will really appreciate it, here is my code so far:
ViewModel class:
public class Page1ViewModel
{
public string Nombre { set; get; }
public string Direccion { set; get; }
public string Descripcion { set; get; }
public string Logo { set; get; }
public List<Restaurant> RestaurantDb { get; set; }
public async void GetRestaurant()
{
String str = "";
try
{
var x = ODataDynamic.Expression;
var client = new ODataClient("http://192.168.0.9/WSTestDev/WSTestDev.svc/");
var packages = await client.FindEntriesAsync("Restaurant");
foreach (var package in packages)
{
var rt = new Restaurant
{
Nombre = package["Nombre"].ToString(),
Direccion = package["Direccion"].ToString(),
Descripcion = package["Descripcion"].ToString(),
Logo = package["Logo"].ToString()
};
RestaurantDb.Add(rt);
}
}
catch (Exception err)
{
str = err.ToString();
}
}
}
View Class:
public partial class Page1 : ContentPage
{
public Page1ViewModel vm;
public Page1()
{
vm = new Page1ViewModel();
vm.GetRestaurant();
BindingContext = vm;
InitializeComponent();
}

Instead of List<Restaurant>, use ObservableCollection<Restaurant>. It behaves similarly to List, but will notify the UI of any changes to it's contents so that the UI can update.
Alternately, you could await vm.GetRestaurant(), but that will require more restructuring of your code.

Related

Core WebAPI not returning all values/parameters

I am upgrading a .NET 4.5 solution to .Net 5. In the process of this i have found some code that works in 4.5 but does not seem to work in Core.
It is a rather simple WebAPI call, a simplified example as follows;
Model:
public class UJ
{
public interface IJComponent
{
string Type { get; set; }
}
public class JComponentRte : IJComponent
{
public string? Type { get; set; }
public string Text { get; set; }
}
}
Controller:
private List<IJComponent> GetJComponents(...)
{
var sComponents = new List<IJComponent>();
foreach (var component in components)
{
sComponents.Add(
new JComponentRte {
Type = "My type",
Text = "My text"
});
break;
}
}
The issues is that it always just returns the Type, not the Text. The Text is not just empty, is is not included in the return value at all - like it is only looking at IJComponent as the Model and not the JComponentRte? WHat am I missing?
Am not sure why it would have worked in earlier version but problem appears to be that your interface does not include the Text property, so when the result is being serialised using interface IJComponent, there is no Text property to serialise.
Either add the Text property to the interface:
public interface IJComponent
{
string Type { get; set; }
string Text { get; set; }
}
Or return a list of JComponent:
private List<JComponent> GetJComponents(...)
{
var sComponents = new List<JComponent>();
foreach (var component in components)
{
sComponents.Add(
new JComponentRte {
Type = "My type",
Text = "My text"
});
break;
}
}

Retrieve values from SQL database - EF

I'm trying to figure out how to pull values from a SQL database and display this in a razor view.
I have the following class using Entity Framework (I believe)
public class EventLog
{
[Key]
public int Id { get; set; }
public int EventId { get; set; }
public int MaxDelegates { get; set; }
public string Code { get; set; }
public DateTime End { get; set; }
public string Title { get; set; }
}
And I want to map title to DBTitle in the following model:
public class CourseDetailVM : CourseDetailSummaryVM
{
public EventLog DBTitle { get; set; }
}
I then want to see this in the following view:
#using TSW.Web.Helpers
#model TSW.Web.ViewModels.CourseDetailVM
#{
Layout = "~/Views/_Master.cshtml";
}
#Model.DBTitle.Title;
I have the following controller already in place (sorry for the length I plan to reduce this down):
public class CourseDetailController : BaseRenderController<CourseDetailPageDT>
{
private readonly ISitePageFactory _pageFactory = null;
private readonly IEventService _eventService = null;
public CourseDetailController(IEventService eventService, ISitePageFactory pageFactory)
{
_pageFactory = pageFactory;
_eventService = eventService;
}
public async Task<ActionResult> CourseDetail()
{
var homepage = _pageFactory.GetCurrentHomepage();
var model = Mapper.Map<CourseDetailVM>(CurrentContent);
model.Email = homepage.ContactEmail;
model.PhoneNumber = homepage.HeaderPhoneNumber;
model.InnerPageHeader.ShowHeading = true;
model.InnerPageHeader.Title = model.PageTitle;
if (model.Categories.Count == 1)
{
var categoryTagId = model.Categories.First().Id;
var contentTypeAlias = DocumentTypeHelper.GetDocumentTypeAlias<CourseListingPageDT>();
var courseCategoryPage = Umbraco.TypedContentAtXPath($"//{contentTypeAlias}")
.FirstOrDefault(x => x.GetPropertyValue<int>(Constants.DocumentTypes.CourseListingPage.Category) == categoryTagId);
if (courseCategoryPage != null)
{
model.InnerPageHeader.BackLink = Mapper.Map<LinkItem>(courseCategoryPage.Id);
}
}
try
{
model.Events = await _eventService.GetEventsForCourse(CurrentContent.AdministrateId);
}
catch (Exception ex)
{
model.Events = new StaticPagedList<Event>(Enumerable.Empty<Event>(), 1, 1, 0);
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
if (CurrentContent.Graphic != 0)
{
model.InnerPageHeader.Graphic = Mapper.Map<CtaItem>(CurrentContent.Graphic);
}
return View(model);
}
}
I've tried every suggestion I can google to add the mapping in the controlling but can't get my head around this simple function of pulling the value from a SQL database into the razor view.
Could anyone help me out?

Using ReadAsAsync<T>() to deserialize complex Json object

I want to use ReadAsAsync() in my mvc project with .net 4.0. The result comes as null.
If I enter the uri to address bar, the result in chrome as(tag names are changed):
<ns2:MyListResponse xmlns:ns2="blablabla">
<customerSessionId>xxcustomerSessionIdxx</customerSessionId>
<numberOfRecordsRequested>0</numberOfRecordsRequested>
<moreResultsAvailable>false</moreResultsAvailable>
<MyList size="1" activePropertyCount="1">
<MySummary order="0">
<id>1234</id>
<name>...</name>
.
.
</MySummary>
</MyList>
</ns2:MyListResponse>
If I use the statement in code :
using (var client = new HttpClient())
{
var response = client.GetAsync(apiUri).Result;
var message = response.Content.ReadAsStringAsync().Result;
var result1 = JsonConvert.DeserializeObject<MyListResponse>(message);
var result2 = response.Content.ReadAsAsync<MyListResponse>().Result;
}
the message comes in string format as "{\"MyListResponse\":{\"customerSessionId\"...}" which corresponds to a json object as:
{"MyListResponse":
{"customerSessionId":"xxcustomerSessionIdxx",
"numberOfRecordsRequested":0,
"moreResultsAvailable":false,
"MyList":
{"#size":"1",
"#activePropertyCount":"1",
"MySummary":
{"#order":"0",
"id":1234,
"name":"...",
.
.
}
}
}
}
and the properties of result1 and result2 came as null or default values. Class definitions are below. I want to read the content as an object but I couldn't. What do you advice to solve this? What am I doing wrong? Thanks in advance.
public class MySummary
{
public int #Order { get; set; }
public string Id { get; set; }
public string Name { get; set; }
.
.
}
public class MyList
{
public int #Size { get; set; }
public int #ActivePropertyCount { get; set; }
public MySummary MySummary{ get; set; }
}
public class MyListResponse
{
public string CustomerSessionId { get; set; }
public int NumberOfRecordsRequested { get; set; }
public bool MoreResultsAvailable { get; set; }
public MyList MyList { get; set; }
}
I defined a new class as:
public class ResponseWrapper
{
public MyListResponse MyListResponse { get; set; }
}
then I used this wrapper with,
var result1 = JsonConvert.DeserializeObject<ResponseWrapper>(message);
var result2 = response.Content.ReadAsAsync<ResponseWrapper>().Result;
then it worked. I need only MySummary object but I should write more classes to make it work.
After reading your solution I came up with one that doesn't need an extra class:
private static async Task<U> Execute<U>(HttpClient client, string path)
{
U output = default(U);
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
var jsonAsString = await response.Content.ReadAsStringAsync();
output = JsonConvert.DeserializeObject<U>(jsonAsString);
}
else
{
throw new ApplicationException(string.Format("Response message is not OK. Issues in action: {0}", path));
}
return output;
}
For the sake of future readers, I think the correct approach is using ReadAsAsync overload that takes IEnumerable<MediaTypeFormatter> and provide a formatter with the same settings used on the server for serialization. That should fix it.
It is possible to use at client ReadAsAsync with MyListResponse directly (in consequence without ResponseWrapper). To do this, you can define "BodyStyle = WebMessageBodyStyle.Bare" in the operation contract of "apiuri" in stead of "BodyStyle = WebMessageBodyStyle.Wrapped" (server side, i.e. service contract).

RavenDB issue storing object that inherits List<T>

I have a class that inherits from List, this class has some additional properties on it. When I store the parent document in RavenDB, the list items get stored but the additional properties do not.
The failing test below probably explains my issue better:
[TestFixture]
public class RDBIssueTests
{
private DocumentStore _documentStore;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
_documentStore = new EmbeddableDocumentStore
{
RunInMemory = true,
UseEmbeddedHttpServer = true,
DataDirectory = "Data",
};
_documentStore.Initialize();
}
[Test]
public void StoreSimpleDataTest()
{
string id = "people/1";
string laptopName = "MacPro";
string personName = "Joe Bloggs";
string attrOne = "Screen";
string attrTwo = "Keyboard";
var person = new Person()
{
Id = id,
Name = personName,
Laptop = new Possession<string>()
};
person.Laptop.Name = laptopName;
person.Laptop.Add(attrOne);
person.Laptop.Add(attrTwo);
using (var session = _documentStore.OpenSession())
{
session.Store(person);
session.SaveChanges();
}
using (var session = _documentStore.OpenSession())
{
var loadedPerson = session.Load<Person>(id);
Assert.AreEqual(personName, loadedPerson.Name);
Assert.AreEqual(2, loadedPerson.Laptop.Count); // 2 items in the list
Assert.IsTrue(loadedPerson.Laptop.Contains(attrOne));
Assert.IsTrue(loadedPerson.Laptop.Contains(attrTwo));
Assert.AreEqual(laptopName, loadedPerson.Laptop.Name); // fails here - Person.Laptop.Name is not persisted in RBD
}
}
}
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public Possession<string> Laptop { get; set; }
}
public class Possession<TValueType> : PossessionAttribute<TValueType>
{
public string Name { get; set; } // RDB doesn't persist this value
}
public class PossessionAttribute<TValueType> : List<TValueType>
{
}
As you can see from the test, the string property 'Name' on the Possession class does not get saved.
Is there something I need to do to get this property to persist?
Many thanks!
JSON has no way of representing an object that is both a list and has properties.
That is why you cannot do that. You can have an object that contains a list property, which is a more natural way of going about it.

WCF Service Library

I am new to WCF services. I was asked to manually create a WCF service. I did the following:
Created a new project Console App.
Created a class called Evaluation
Created an interface called IEvaluatorService
Created a class EvaluationService implementing the interface IEvaluatorService
I need to use the following address: http://localhost:8000/Evaluations then test my service via WcfTestClient. I am not sure what to do next. Code below.
Thanks in advance for any help!
namespace Evaluations
{
[ServiceContract]
interface IEvaluatorService
{
[OperationContract(Name="AddEvaluation")]
int Add(string user, string content);
[OperationContract(Name="RemoveEvaluation")]
void Remove([MessageParameter(Name="existingID")] int id);
[OperationContract(Name="GetAllEvaluations")]
Evaluation[] GetAll();
[OperationContract(Name="GetEvaluation")]
Evaluation Get(int id);
[OperationContract(Name="GetAllEvaluationsFrom")]
Evaluation[] GetAll([MessageParameter(Name = "username")] string submitter);
}
}
namespace Evaluations
{
class EvaluationService : IEvaluatorService
{
List<Evaluation> myList = new List<Evaluation>();
static int count = 0;
public int Add(string user, string content)
{
Evaluation eval = new Evaluation()
{
UniqueID = count++,
Submitter = user,
SubmissionTime = DateTime.Now,
Text = content
};
myList.Add(eval);
return eval.UniqueID;
}
public void Remove(int id)
{
myList.RemoveAt(id);
}
public Evaluation[] GetAll()
{
return myList.ToArray<Evaluation>();
}
public Evaluation Get(int id)
{
throw new NotImplementedException();
}
public Evaluation[] GetAll(string submitter)
{
throw new NotImplementedException();
}
}
}
namespace Evaluations
{
[DataContract]
class Evaluation
{
[DataMember]
public string Submitter { get; set; }
[DataMember]
public int UniqueID { get; set; }
[DataMember]
public DateTime SubmissionTime { get; set; }
[DataMember]
public string Text { get; set; }
}
}
The easiest thing to do is...
go into Visual Studio
right click on your project
select Add New
choose WCF Service
See what code Visual Studio added and follow that pattern for your service.