Reportviewer not displaying data from object - c#

I have read several questions and answers on this topic, it seems to be a fairly common topic, but none have so far been able to help me.
I am using Visual Studio 2013 and entity framework and trying to create a local report from an object and display it in the reportviewer.
When I run it the report headers show but no data despite the fact that my GetConstraints() method is called and runs without a problem.
The model for the data has been kept fairly simple:
public class ConstraintDataModel
{
public string name { get; set; }
public int interval { get; set; }
public string complianceEntity { get; set; }
public string inspectionEntity { get; set; }
public string nominalValue { get; set; }
public int taskID { get; set; }
public string installations { get; set; }
public int groupTask { get; set; }
public string lastInspectionDate { get; set; }
public string nextInspectionDate { get; set; }
public int missed { get; set; }
public string rating { get; set; }
}
As has the method for returning it:
public static List<ConstraintDataModel> GetConstraints()
{
List<ConstraintDataModel> constraintList = new List<ConstraintDataModel>();
List<ICMConstraint> constraints = (List<ICMConstraint>)ctx.ICMConstraints.Where(cust => cust.CustomerID.Equals(1001)).ToList();
foreach (ICMConstraint constraint in constraints)
{
ConstraintDataModel constraintsModel = new ConstraintDataModel();
constraintsModel.taskID = constraint.ConstraintID;
constraintsModel.name = constraint.Name;
constraintsModel.complianceEntity = GetEntityName(constraint.ComplianceEntityID);
constraintsModel.inspectionEntity = GetEntityName(constraint.InspectionEntityID);
constraintsModel.installations = GetInstallations(constraint.ConstraintID);
constraintsModel.interval = constraint.Interval;
constraintsModel.nextInspectionDate = constraint.NextInspectionDate.ToShortDateString();
constraintsModel.missed = constraint.MissedInspections;
constraintsModel.nominalValue = constraint.NominalValue;
constraintsModel.rating = GetConstraintRating(constraint.ConstraintID);
}
return constraintList;
}
I have followed a few tutorials and haven't deviated from them. I have also tried explicitly binding the data on Page_Load but that doesn't help.
I am not sure what other code to post so if anything else is need just say.

Don't you need to add the object to the list you are returning:
}
return constraintList;
to this:
constraintList.Add(constraintsModel);
}
return constraintList;

Related

How to initialize an array in a property's sub-class? (Object reference not set.... error)

First of all, please stick to how I accomplish this with the current setup, and not in trying to redesign how it is structured. I have to build an app/web service to receive a JSON query. The JSON is generated by a widget that we can not customize. I used Visual Studio to create the class structure from a JSON example.
I want to test my service, and I'm getting errors in SOAPUI, so I need something where I can debug, so I'm hard-coding the JSON input object for my Service Reference.
Here are the classes, as they reside on the web service -
[DataContract]
public class QuoterIn
{
[DataMember]
public Quoterinput quoterinput { get; set; }
}
public class Quoterinput
{
public string agent_id { get; set; }
public string key { get; set; }
public string auto_assign { get; set; }
public Consumer consumer { get; set; }
public string viaEmail { get; set; }
}
public class Consumer
{
public string brand_id { get; set; }
public string full_name { get; set; }
public Addresses_Attributes[] addresses_attributes { get; set; }
public string birth_or_trust_date { get; set; }
public string gender { get; set; }
public Emails_Attributes[] emails_attributes { get; set; }
public Phones_Attributes[] phones_attributes { get; set; }
public Cases_Attributes[] cases_attributes { get; set; }
}
public class Addresses_Attributes
{
public string zip { get; set; }
}
public class Emails_Attributes
{
public string value { get; set; }
}
public class Phones_Attributes
{
public string value { get; set; }
}
public class Cases_Attributes
{
public Quoting_Details_Attributes[] quoting_details_attributes { get; set; }
}
public class Quoting_Details_Attributes
{
public string carrier_id { get; set; }
public string duration_id { get; set; }
public string policy_type_id { get; set; }
public string plan_name { get; set; }
public string product_type_name { get; set; }
public string face_amount { get; set; }
public string carrier_health_class { get; set; }
public string planned_modal_premium { get; set; }
public string premium_mode_id { get; set; }
public string health_class_id { get; set; }
}
Looking at the sub-class of Consumer, there are several sub-classes that are arrays - address_attributes, phone_attributes, and email_attributes.
I'm able to initialize the main JSON input/inquiry container, and then I can initialize the main class and the sub-class of "Consumer." I can enter data for the main fields, and then fields in the sub-class of Consumer, but I can't initialize the arrays.
Here's the code up until this point for populating that input container -
protected void btnRun_Click(object sender, EventArgs e)
{
QuoterIn req = new QuoterIn();
req.quoterinput = new Quoterinput();
req.quoterinput.consumer = new Consumer();
req.quoterinput.agent_id = "1938";
req.quoterinput.key = "afasdfasdfasdfasdfasd";
req.quoterinput.auto_assign="true";
req.quoterinput.consumer.brand_id = "21264";
req.quoterinput.consumer.full_name = "Fred Smith";
req.quoterinput.consumer.addresses_attributes[0].zip = "53704";
.................(more code like this, but this last line is where the program fails)
Since we aren't going to take in multiple email addresses or phone numbers, I'd be fine with not having it be an array, but I'm worried that the incoming JSON with all the grouping and bracketing will fail if it's not set up like an array. I've tried to initialize instance zero like this -
req.quoterinput.consumer.addresses_attributes[0] = new Addresses_Attributes();
.... and Visual Studio likes the code syntax-wise, but it doesn't initialize an instance when it runs, and then I get the "Object reference not set to an instance of an object." error when it runs. It hasn't allowed me to initialize the array using more generic methods since it has to map to this specific property we've already declared.
I have no doubt it's probably straightforward, but I'm not all that experienced in manipulating arrays and lists like this, and I haven't been able to find examples of arrays of sub-classes within subclasses of properties.
Just instantiate / assign the address at the same time. Something like this should work:
req.quoterinput.consumer.addresses_attributes = new []
{
new Addresses_Attributes
{
zip = "53704"
}
};
Another way (since the property toy are trying to set is an Array), is to create a dynamic sized list, add to it, then convert it back during declaration.
var addresses = new List<Addresses_Attributes>
{
new Addresses_Attributes {zip = "53704"}
};
req.quoterinput.consumer.addresses_attributes = addresses.ToArray();
Or, you can assign it an array of size 1, and then set it up from there:
req.quoterinput.consumer.addresses_attributes = new Addresses_Attributes[1];
req.quoterinput.consumer.addresses_attributes[0] = new Addresses_Attributes { zip = "666" };

Invoking child nodes Entity Framework Core

I'm new into this sort of object programming, do you mind helping me?
I have to invoke the child nodes, but specific fields, but I can't figure out how to do that. I have already looked into a huge number of places, but it doesn't seem to work.
For example, I want just the FirstName in the RepunicAccount, and all the other info from RepunicAccountType, or anything like it.
My DbContext:
public class RepunicContext : DbContext
{
public virtual DbSet<RepunicAccount> RepunicAccount { get; set; }
public virtual DbSet<RepunicAccountType> RepunicAccountType { get; set; }
protected override void OnConfiguring (DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer ("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Repunic;Data Source=DESKTOP- 6I8LD45\\SQLEXPRESS_ERICH");
}
public RepunicContext (DbContextOptions<RepunicContext> options) :base (options)
{ }
public RepunicContext () { }
}
My model class:
public class RepunicAccount
{
public int ID { get; set; }
public string Email { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[ForeignKey ("ID_Type")]
public int? ID_Type { get; set; }
public ICollection<RepunicAccountType> TipoConta { get; set; }
public DateTime? DataCadastro { get; set; } = DateTime.Now;
public DateTime? DataAlteracao { get; set; } = DateTime.Now;
}
My child node class:
public class RepunicAccountType
{
[Key]
public int ID_Type { get; set; }
public string Descricao { get; set; }
public DateTime DataCadastro { get; set; } = DateTime.Now;
public DateTime DataAlteracao { get; set; } = DateTime.Now;
}
I have a repository, that is where I do my coding, before putting into the controller, it's pretty much the same in every place, but I'm going to show the example that I'm trying to use in both places.
public IEnumerable<RepunicAccount> GetAllByIDType ()
{
var data = db.RepunicAccount.Where (a => a.ID_Type != null)
.Include (p => p.types);
var type = db.RepunicAccountType.OrderBy (b => b.Descricao);
return data.ToList();
}
The problem is: I dont know how to invoke specific items nor make anything else other thanToList();`
So, what should I do? If there is any more info that I can send, just ask me.
I would love to comment however, I do not have the required reputation to do so.
Since you are new to the subject please be sure to follow the documentation.
EF Core Documentation
I also have created a youtube video for getting started that I would suggest you take a few minutes to view.
Video on EF Core
in short, you need a DBContext and your Models. You then can start a query for data and returning in the format you wish. Like so:
using (var context = new RepunicContext())
{
var accounts = context.RepunicAccounts.ToList();
}
accounts will then have a list of every account that you can iterate through. Hope this helps.

Web api skips all objects but first in List<T> when returning to client

I have a web api that returns a complex object that looks like this:
public class CanDeleteRumsaAttributeResponse
{
public CanDeleteRumsaAttributeResponse()
{
}
public CanDeleteRumsaAttributeResponse(int attributeId)
{
RumsaAttributeId = attributeId;
}
public int RumsaAttributeId { get; set; }
public bool AttributeFound { get; set; }
public List<RumsaRoom> AffectedRumsaRooms { get; set; } = new List<RumsaRoom>();
public List<RumsaAttribute> AffectedLinkedRumsaAttributes { get; set; } = new List<RumsaAttribute>();
[JsonIgnore]
public bool CanDelete
{
get
{
return AffectedRumsaRooms.Count == 0&&AttributeFound&&AffectedLinkedRumsaAttributes.Count==0;
}
}
}
When I debug it I can see that the controller return that object and that the list AffectedLinkedRumsaAttributes has several objects in the list
When the client receives the list all but the first object are null.
I've tried returning the object as Ok(CanDeleteRumsaAttributeResponse) and I've tried serializing it like this:
RoomAttributesUtils utils = new RoomAttributesUtils(db);
string json = JsonConvert.SerializeObject(utils.GetCanDeleteColor(id));
var response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
In the second case I can search the json string and find the missing data.
So its being serialized in the second case.
I've checked fiddler to see what is being sent and I can see that something is not right in the json-data.
The missing objects gets values like $ref: "4" and so on, but nothing else.
Here is the json-string I'm afraid I dont know how to format it properly for Stackoverflow, but I think that the information is there as well, but when I look at it using a viewer, its not and it sure doesnt deserialize to the correct objects.
The other list in the object can have any number of objects and they all return fine. Also, other endpoints are returning lists of the same type perfectly fine.
The three objects have unique values on the Code property and they are V30, V31 and V12 (if you want to identify them in the json string).
Any ideas?
Here is the json string
{"RumsaAttributeId":4797,"AttributeFound":true,"AffectedRumsaRooms":[{"$id":"1","RoomName":"STÄD","RoomNumber":"U12102-1150","Building":"U1","PartOfBuilding":"21","Plan":"02","Number":"1150","RoomDescriptions":[],"IsDeleted":false,"PMs":[],"IDNR":"175D_40","Exclude":false,"Department":"VN40 Lokalvård","Comments":"","Area":"23.19","HygeneClass":null,"CeilingHeight":"","UniqueRoomId":"d00e5325-7918-4d01-b273-813a770b46ca-010591d3","SolviegHasOpenedThis":true,"LastSynchedFromRevit":"1900-01-01T00:00:00","LastUpdatedFromRevit":"1900-01-01T00:00:00","Id":25772}],"AffectedLinkedRumsaAttributes":[{"$id":"2","AMACode":"KBC.3211","Malning":"56-03510","AvaliableColors":[{"$id":"3","AvaliableMaterials":[{"$ref":"2"},{"$id":"4","AMACode":"MBE.221","Malning":"-","AvaliableColors":[{"$ref":"3"}],"RoomDescriptions":[],"Code":"V30","ShortDescription":"Kakel, vattenavvisande beklädnad","LongDescription":"-","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1438},{"$id":"5","AMACode":"MBE.222","Malning":"-","AvaliableColors":[{"$ref":"3"}],"RoomDescriptions":[],"Code":"V31","ShortDescription":"Kakel, vattentät beklädnad","LongDescription":"-","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1439}],"RoomDescriptions":[],"Code":"V31_01","ShortDescription":"Kakel, vattentät beklädnad","LongDescription":"Marazzi SistemC Arch ME83, kulör Bianco(vit)200x200x5 mm. Fog Mapei Ultracolor Plus kulör 111 Silver Grey","Comment":"På 1 fondvägg","PartOfRoom":null,"PartOfRoomId":960,"Id":4797}],"RoomDescriptions":[],"Code":"V12","ShortDescription":"Gipsskivor, hygienklass 2","LongDescription":"Hög standard, hygienklass 2\n","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1425},{"$ref":"4"},{"$ref":"5"}]}
I had a similar situation in which I found that due to circular references, the serialization was not completed.
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogForeignKey { get; set; }
[ForeignKey("BlogForeignKey")]
public Blog Blog {get;set;}
}
I just deleted the child to parent relationship and included the foreingkey anotation to the entity set.
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
[ForeignKey("BlogForeignKey")]
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogForeignKey { get; set; }
}
Also consider LoopReferenceHandling

Entity Framework objects being duplicated in the database

I am working with Entity Framework (code first) for the first time and I have a little problem.
I have a class called Taxi & one called Driver
Taxi has a reference to the Driver, you can see both classed below
public partial class Taxi
{
public Taxi()
{
}
public int TaxiId { get; set; }
public Driver Driver { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Color Colour { get; set; }
public string NumPlate { get; set; }
public int MaxPassengers { get; set; }
}
public partial class Driver
{
public Driver()
{
}
public int DriverId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string HomePhone { get; set; }
public string MobilePhone { get; set; }
public DateTime JoinedFirm { get; set; }
}
And I am saving the changed Taxi like this:
using (var db = new DataModel())
{
db.Configuration.ProxyCreationEnabled = false;
db.Taxis
.Where(x => x.TaxiId == CurrenltySelectedTaxi.TaxiId)
.ToList()
.ForEach(x =>
{
x.Make = CurrenltySelectedTaxi.Make;
x.Model = CurrenltySelectedTaxi.Model;
x.NumPlate = CurrenltySelectedTaxi.NumPlate;
x.Colour = CurrenltySelectedTaxi.Colour;
x.MaxPassengers = CurrenltySelectedTaxi.MaxPassengers;
x.Driver = CurrenltySelectedTaxi.Driver;
});
db.SaveChanges();
}
My problem is that the Driver gets duplicated the in database every time I save a taxi.
You can see the database here:
Can someone point me in the right direction,
Thanks
EDIT:
The drivers are in a combo box and are selected like this
private void cmbTaxiDriver_SelectedIndexChanged(object sender, EventArgs e)
{
using (var db = new DataModel())
{
db.Configuration.ProxyCreationEnabled = false;
Driver listSelected = (Driver) cmbTaxiDriver.SelectedItem;
CurrenltySelectedTaxi.Driver = db.Drivers.Where(x => x.DriverId == listSelected.DriverId).ToArray()[0];
}
}
And the combo box is populated like this:
listDrivers.Items.AddRange(db.Drivers.ToArray());
The only thing that I can possibly find based on the content you have provided is that CurrenltySelectedTaxi.Driver is a detached or new driver. Be careful to ensure that the object pointed to by CurrenltySelectedTaxi.Driver is an attached driver record.
An option you can do to help determine the status of that record is to put a breakpoint on that line and then look at the DbEntry record status.
Your design doesn't create a relationship between Taxi and Driver that's going to translate to a database. Try something like this:
public partial class Taxi
{
public Taxi()
{
}
public int TaxiId { get; set; }
public int DriverId {get; set; }
public virtual Driver Driver { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Color Colour { get; set; }
public string NumPlate { get; set; }
public int MaxPassengers { get; set; }
}
You may also want to add the following to the Driver object:
public virtual IEnumerable<Taxi> Taxis { get; set; }
So it turns out my issue is because i followed the tutorial on MSDN that says to recreate your context EVERYTIME you use it. Although this 'may' be good practice, in this instance it caused the problem.
If I make one context for the entire class it works as expected/

Updating List<T> in DbContext

I have a Model like this
public class Challenge
{
public int ID { get; set; }
public string Name { get; set; }
public string Blurb { get; set; }
public int Points { get; set; }
public string Category { get; set; }
public string Flag { get; set; }
public List<string> SolvedBy { get; set; }
}
public class ChallengeDBContext : DbContext
{
public DbSet<Challenge> Challenges { get; set; }
}
and then Controller like this. But I cannot update the List "SolvedBy", the next time I step through with the debugger, the list is still empty.
[HttpPost]
public string Index(string flag = "", int id=0)
{
Challenge challenge = db.Challenges.Find(id);
if (flag == challenge.Flag)
{
var chall = db.Challenges.Find(id);
if (chall.SolvedBy == null)
{
chall.SolvedBy = new List<string>();
}
chall.SolvedBy.Add(User.Identity.Name);
db.Entry(chall).State = EntityState.Modified;
db.SaveChanges();
//congrats, you solved the puzzle
return "got it";
}
else
{
return "fail";
}
}
is there any way around it to make a list of strings kept in the database?
EF don't know how to store an array in database table so it just ignore it. You can create another table/entity or use XML/JSON to store the list. You can serialize the list before saving and deserialize it after loading from database
A List<T> in a model would normally map to a second table, but in your DbContext you only have a single table. Try adding a second table.
public class ChallengeDBContext : DbContext
{
public DbSet<Challenge> Challenges { get; set; }
public DbSet<Solution> Solutions {get; set;}
}
public class Challenge
{
public int ID { get; set; }
public string Name { get; set; }
public string Blurb { get; set; }
public int Points { get; set; }
public string Category { get; set; }
public string Flag { get; set; }
public List<Solution> SolvedBy { get; set; }
}
public class Solution
{
public int ID { get; set; }
public string Name { get; set; }
}
Then your controller can use code along the lines of...
var chall = db.Challenges.Find(id);
if (chall.SolvedBy == null)
{
chall.SolvedBy = new List<Solution>();
}
chall.SolvedBy.Add(new Solution {Name=User.Identity.Name});
None of the above has been tested and I may have made some mistakes there, but the general principle I want to illustrate is the fact that you need another table. The List<T> represents a JOIN in SQL.

Categories

Resources