ASP.NET json object doesn't contain custom object - asp.net

When a user gets to a location, he will get a question. As such, I have a class for "Questions" and a class for "Locations". When I retrieve a location, however, the Question parameter is always null.
This seems to be a problem with the whole project, as the same problem repeats itself somewhere else (here, a "Game" has a list of "Teams", but the teams are always empty).
Objects are created when database is initialized:
public static void Initialize(DBContext context)
{
context.Database.EnsureCreated();
if (!context.Games.Any())
{
var teams = new List<Team>();
var team1 = new Team()
{
TeamName = "Kwizmasterz",
TotalPoints = 0,
TotalBoobyTraps = 2
};
var team2 = new Team()
{
TeamName = "Xesennettet",
TotalPoints = 0,
TotalBoobyTraps = 2
};
teams.Add(team1);
teams.Add(team2);
var game = new Game()
{
GameCode = "X35H0",
team = teams
};
context.Games.Add(game);
context.SaveChanges();
}
if (!context.Locations.Any())
{
var que = new Question()
{
QuestionText = "How much is 2 + 2?",
Answer = "4",
IsSolved = false,
Points = 1000000
};
var loc = new Location()
{
LocationName = "LocationName",
Latitude = 50.2299036,
Longitude = 5.4163052,
Question = que,
IsBoobyTrapped = false
};
context.Locations.Add(loc);
context.SaveChanges();
}
}
Location Class:
public class Location
{
public int LocationID { get; set; }
public string LocationName { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public Question Question { get; set; }
public bool IsBoobyTrapped { get; set; }
public int VictorTeamID { get; set; } = -1;
}
Question Class:
public class Question
{
public int QuestionID { get; set; }
public int QuestionType { get; set; } // 1 = Question - Answer
public string QuestionText { get; set; }
public int Points { get; set; }
public bool IsSolved { get; set; }
public string Answer { get; set; }
}
Controller Class:
[Route("api/v1")]
public class GameController : Controller
{
private readonly DBContext context;
public GameController(DBContext context)
{
this.context = context;
}
public IActionResult Index()
{
return View();
}
[Route("location")]
[HttpPost]
public IActionResult postGame([FromBody] Location newLocation)
{
newLocation.LocationID = context.Games.Count();
context.Locations.Add(newLocation);
return Created("", newLocation);
}
[Route("location")]
[HttpGet]
public List<Location> getLocations()
{
return context.Locations.ToList();
}
[Route("location/{id}")]
[HttpGet]
public Location getLocation(int id)
{
int _id = id - 1;
List<Location> loc = context.Locations.ToList();
if (loc[_id] != null)
return loc[_id];
else
return null;
}
[Route("game")]
[HttpPost]
public IActionResult postGame([FromBody] Game newGame)
{
newGame.GameID = context.Games.Count();
context.Games.Add(newGame);
return Created("", newGame);
}
[Route("game")]
[HttpGet]
public List<Game> getGames()
{
return context.Games.ToList();
}
[Route("game/{id}")]
[HttpGet]
public Game getGame(int id)
{
List<Game> game = context.Games.ToList();
if (game[id] != null)
return game[id];
else
return null;
}
}

This is because of lazy loading so objects stored in other tables won't load unless you include them.
Link
You can do this by using Include("Question") so the complete syntax would be:
context.Locations.Include("Question") so you will include the question when retrieving the locations
You can do also multiple includes by chaining them context.Locations.Include("Question").Include("SomethingElse")
Edit as i see in your code getLocation still does not use the include. see below for the correct way to use it
public Location getLocation(int id)
{
int _id = id - 1;
List<Location> loc = context.Locations.Include("Question").ToList();
if (loc[_id] != null)
return loc[_id];
else
return null;
}
2nd edit
Also i would rewrite getLocation because your pulling the whole list first and after getting the single location
public Location getLocation(int id)
{
int _id = id - 1;
//FirstOrDefault will return automatically a null if the id cannot be found.
//This will result in only getting the single Location from context instead the complete list
return context.Locations.Include("Question").FirstOrDefault(x=>x.id == _id);
}

Related

How to get data from list by condition in Xamarin

I have Class Model:
Class ProductInfo
public class ProductInfo
{
public int ID { get; set; }
public int IDProduct { get; set; }
public List<ProductImages> ProductImages { get; set; }
}
Class ProductImages
public class ProductImages
{
public int ID { get; set; }
public int ProductID { get; set; }
public string Images { get; set; }
public Boolean ImgFlag { get; set; }
}
I have data
This is how I get product information
async Task ExecuteLoadProductCommand()
{
IsBusy = true;
try
{
ProductInfos.Clear();
var prodList = await productRepository.GetProductsAsync();
foreach (var prod in prodList)
{
//Get Imgaes by condition
//prod.Images = ProductImages()
ProductInfos.Add(prod);
}
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
The first:
How can I Binding Images with the condition ImgFlag = true in ContentPage Product.axml
The Second:
I have a ContentPage that shows ProductDetails.axml. I show the following information:
"Name": Name Product,... ---> This is fine. However I have an extra CarouselView. I want to show a list of images with the condition that ProductID = ID(ProductInfo)
This is how I pass the ProductDetail data
public DashboardsViewModel()
{
LoadProductCommand = new Command(async () => await ExecuteLoadProductCommand());
ProductInfos = new ObservableCollection<ProductInfo>();
ProductTappedView = new Command<ProductInfo>(OnViewDetailProduct);
}
private async void OnViewDetailProduct(ProductInfo prod)
{
await Navigation.PushAsync(new DetailProduct(prod));
}
Thank you!

How to send object and output param to web api parameters to get or set methods?

I have a web api class in my web api project which has an object parameter and an output parameter
public class ProductsController : ApiController
{
[HttpGet]
public List<Product> GetProducts(out QueryResult queryResult, GlobalInfo globalInfo)
{
var repository = new BusinessRepository();
return repository.GetAllProducts(out queryResult,globalInfo);
}
}
QueryResult and GlobalInfo class is :
class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public decimal Price { get; set; }
}
public class QueryResult
{
private QueryStatus _queryStatus;
public QueryStatus QueryStatus
{
get { return _queryStatus; }
set { _queryStatus = value; }
}
private string _errorCode;
public string ErrorCode
{
get { return _errorCode; }
set { _errorCode = value; }
}
private string _errorText;
public string ErrorText
{
get { return _errorText; }
set { _errorText = value; }
}
}
public enum QueryStatus
{
None,
Error,
RecordFound,
RecordNotFound,
AccessDenied,
Succeded
}
public class GlobalInfo
{
public string UserName { get; set; }
public int UserId { get; set; }
public string IP { get; set; }
}
how to call web api method in console app or asp.net mvc by oject parameter and out object parameter?
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
QueryResult result;
var globalinfo = new GlobalInfo{UserName = "user1",UserId = 12,IP = "98.14.0.1"};
var data = new JavaScriptSerializer().Serialize(globalinfo);
var methodUrl = string.Format("http://localhost/WebApi/api/products/?queryResult={0}&globalInfo={1}",result,data);
var response = client.GetAsync(methodUrl).Result;
response.EnsureSuccessStatusCode();
var content = response.Content.ReadAsAsync<List<Product>>().Result;

Invalid modelstate: how to return to view when I have dropdownlists?

I have a big view with more than 40 fields. Some of these fields are dropdownlists, that I populate with a list of selectlistitems.
I am using the annotations on my viewmodel, to make some of them required.
Now I want to make the ModelState.IsValid check, and return to the original view with errors if there is some errors.
Problem is, if I simply make a return View(model), all my dropdownlists will crash the site, as they need to be populated again to load the page.
So my question is: how do i handle the return when modelstate is invalid.
My controller:
public ActionResult CreateSelling(SellingAdViewModel model)
{
if (ModelState.IsValid)
{
SellingAdvert sellingAdvert = setSellingAd(model);
var stored_advert = sellingAdvertService.Create(sellingAdvert);
if (User != null && User.Identity.IsAuthenticated)
{
if (model.AcceptPartner)
{
notifyPartner(stored_advert);
}
return RedirectToAction("Upgrade", "Ads", new { AdvertID = stored_advert.Id });
}
else
{
return RedirectToAction("ActivateAnonymous", "Ads", new { AdvertID = stored_advert.Id, anonymousId = model.UserId, AdvertType = "selling" });
}
}
return View(model);
}
My viewmodel (I have a SellingAdViewModel that derives from this one and add more properties):
public class BasicAdViewModel
{
public int SectorId { get; set; }
public Guid UserId { get; set; }
public bool IsAnonymousUser { get; set; }
public int AdvertId { get; set; }
[DisplayName("Titel:")]
[Required(ErrorMessage = "Titel skal udfyldes")]
public string Headline { get; set; }
[DisplayName("Beskrivelse:")]
[StringLength(50, ErrorMessage = "Beskrivelsen minimum fylde 50 karakterer")]
public string Description { get; set; }
[DisplayName("Søgeord:")]
public string SearchWords { get; set; }
[DisplayName("Undertitel:")]
public string Subtitle { get; set; }
[DisplayName("Type af drift")]
public List<SelectListItem> OperationTypes { get; set; }
[Required]
public int SelectedOperationTypeId { get; set; }
[Required]
public int SelectedSectorId { get; set; }
public IEnumerable<GroupedSelectListItem> Sectors { get; set; }
}
Setting my dropdownlists in the first place:
My model has the List<SelectListItem> properties, and I fill them by having a couple of helper methods:
SellingAdViewModel model = new SellingAdViewModel()
{
BusinessEntityTypes = ModelListHelpers.GetBusinessEntityTypes(),
FoundedYears = ModelListHelpers.GetFoundedYears(null),
ReasonForSale = ModelListHelpers.GetReasonForSale(),
RevenuePrediction = ModelListHelpers.GetRevenuePrediction(),
RevenueStatus = ModelListHelpers.GetRevenueStatus(),
OperationTypes = ModelListHelpers.GetOperationTypes(),
Region = ModelListHelpers.GetRegions(),
Turnover = ModelListHelpers.Turnovers(),
OperatingIn = ModelListHelpers.OperatingIn(),
AmountOfEmployees = ModelListHelpers.GetAmountOfEmployees()
};
I suggest you this solution put your model in a TempData during your GET action And if the model state is invalid you make an assignment like this
public ActionResult CreateSelling(SellingAdViewModel model)
{
if (ModelState.IsValid)
{
SellingAdvert sellingAdvert = setSellingAd(model);
var stored_advert = sellingAdvertService.Create(sellingAdvert);
if (User != null && User.Identity.IsAuthenticated)
{
if (model.AcceptPartner)
{
notifyPartner(stored_advert);
}
return RedirectToAction("Upgrade", "Ads", new { AdvertID = stored_advert.Id });
}
else
{
return RedirectToAction("ActivateAnonymous", "Ads", new { AdvertID = stored_advert.Id, anonymousId = model.UserId, AdvertType = "selling" });
}
}
model.YourList = TempData.Peek("YourList");
return View(model);
}

Add checking in controller

I have class User in my project and have model UserRow (for showing user in view)
it's UserRow
using System;
namespace Argussite.SupplierServices.ViewModels
{
public class UserRow
{
public Guid Id { get; set; }
public string FullName { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Status { get; set; }
public int Role { get; set; }
public Guid SupplierId { get; set; }
public bool ActionsAllowed { get; set; }
public bool MailResendRequired { get; set; }
}
}
and I need to add in my controller checking if ActionsAllowed
[HttpPost]
public ActionResult Unlock(Guid id)
{
var user = Context.Users.Find(id);
if (user == null)
{
return Json(CommandResult.Failure("User was not found. Please, refresh the grid and try again."));
}
var checkActionsAllowed = Context.Users.AsNoTracking()
.Select(e => new UserRow
{
Id = e.Id,
ActionsAllowed = e.ActionsAllowed
};
if (checkActionsAllowed == true)
{
user.Status = UserStatus.Active;
return Json(CommandResult.Success(string.Format("User {0} has been unlocked.", user.FullName)));
}
else return;
}
but I got error with ActionsAllowed = e.ActionsAllowed and
in else return;
Help me please to solve this problem.
You have two problems:
Context.Users.AsNoTracking()
.Select(e => new UserRow
{
ActionsAllowed = e.ActionsAllowed
};
returns a list of objects, not a single object.
You have queried the user above, so i guess you can write simply:
if (user.ActionsAllowed) {
user.Status = UserStatus.Active;
return Json(CommandResult.Success...);
}
The second problem is the return; statement.
Your method returns an action result, so you have to return something.
For example
return Json(CommandResult.Failure(
"ActionsAllowed = false"));
First error sounds like you User class doesn't provide a ActionsAllowed Boolean property, while the second error happens because you need to return something from the method that can be interpreted as an ActionResult.
EDIT:
Hmm, I didn't notice this the first time, but this:
var checkActionsAllowed = Context.Users.AsNoTracking()
.Select(e => new UserRow
{
Id = e.Id,
ActionsAllowed = e.ActionsAllowed
};
followed by this:
if (checkActionsAllowed == true)
makes no sense - you're not returning a boolean result from a Select method, but rather an IEnumerable. Perhaps you should add your User schema to your question so that it's more obvious what you're trying to accomplish.

JSON dont return assignments that is related to a person (Visual studio 2012, MVC)

Hi im trying to return JSON with a person and the skills that are related to this person.
I have a class person
public class Person
{
[Key]
public int personID { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public int age { get; set; }
public string role { get; set; }
public virtual ICollection<Skill> Skills { get; set; }
}
And a class Skill
public class Skill
{
[Key]
public int skillID { get; set; }
public int personID { get; set; }
public string title { get; set; }
public virtual Person Person { get; set; }
}
DB context
public class ConsultantContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Skill> Skill { get; set; }
}
And i fill upp with some data.
public class PersonInit : DropCreateDatabaseIfModelChanges
{
protected override void Seed(ConsultantContext context)
{
var skills = new List<Skill>
{
new Skill { skillID = 1, personID = 1, title = "Javascript" },
new Skill { skillID = 2, personID = 1, title = "jQuery" },
new Skill { skillID = 3, personID = 1, title = "ASP.NET" }
};
skills.ForEach(s => context.Skills.Add(s));
context.SaveChanges();
var persons = new List<Person>
{
new Person { personID = 1, firstName = "Name1", lastName = "Lastname1", age = 30, role = "Programmer" },
new Person { personID = 2, firstName = "Name2", lastName = "Lastname2", age = 30, role = "Designer" },
new Person { personID = 3, firstName = "Name3", lastName = "Lastname3", age = 30, role = "Manager" }
};
persons.ForEach(s => context.Persons.Add(s));
context.SaveChanges();
}
}
I have a controller called Person
public class PersonController : ApiController
{
private ConsultantContext db = new ConsultantContext();
// GET api/Person
public IEnumerable<Person> GetPeople()
{
return db.Persons.AsEnumerable();
}
// GET api/Person/5
public Person GetPerson(int id)
{
Person person = db.Persons.Find(id);
if (person == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return person;
}
// PUT api/Person/5
public HttpResponseMessage PutPerson(int id, Person person)
{
if (ModelState.IsValid && id == person.personID)
{
db.Entry(person).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
// POST api/Person
public HttpResponseMessage PostPerson(Person person)
{
if (ModelState.IsValid)
{
db.Persons.Add(person);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, person);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = person.personID }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
// DELETE api/Person/5
public HttpResponseMessage DeletePerson(int id)
{
Person person = db.Persons.Find(id);
if (person == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
db.Persons.Remove(person);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
return Request.CreateResponse(HttpStatusCode.OK, person);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
So now to the problem when i use the http:/localhost/api/Person in fiddler it returns JSON:
it returns an empty [].
Can someone help me get JSON back with the personID, name, lastname, role and skills[belonging to this person].
Regards
Try this
public IEnumerable<Person> GetPeople()
{
var skills = db.Skill;
var people = db.Persons;
people.ForEach(person => person.Skills = skills.FindAll(skill => skill.personID == person.personID));
return people;
}

Resources