Passing lists to the view .Net Core - asp.net

Im looping through all the results from the SQL query in a .Net Core project. here is Model
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; }
public List<int> MessagesSendersid { get; set; }
public List<string> MessagesSenders { get; set; }
public List<string> MessagesTitles { get; set; }
public List<string> MessagesInformation { get; set; }
public List<string> MessagesStatus { get; set; }
}
I loop through the users messages in my controller then i pass that model to the view
sqlcon.Open();
int? userid = HttpContext.Session.GetInt32("UserID");
SqlCommand sqlcom = new SqlCommand("select * from messages where Messagereceiver=" +userid , sqlcon);
SqlDataReader reader = sqlcom.ExecuteReader();
if(reader.HasRows)
{
int index = 0;
while(reader.Read())
{
string s;
s = reader[0].ToString();
Mymessages.MessagesIDs.Add(int.Parse(s));
Mymessages.MessagesSendersid.Add(int.Parse(reader[1].ToString()));
Mymessages.MessagesTitles.Add(reader[3].ToString());
Mymessages.MessagesInformation.Add(reader[4].ToString());
Mymessages.MessagesStatus.Add(reader[5].ToString());
index++;
}
Mymessages.MyMessagesCount = index;
}
the very first line Mymessages.MessagesIDs.Add(int.Parse(s)); it throws an exception saying System.NullReferenceException: 'Object reference not set to an instance of an object
i wanted to make sure that reader was holding the results so i added int s and checked on it and it was holding the value it was supposed to.
whats going wrong here? is this how we are supposed to pass list-like data to the view?

You need to initlize MessagesIDs in entity Mymessages, like this:
var Mymessages = new Mymessagesinfo()
{
MessagesIDs = new List<int>()
};
Mymessages.MessagesIDs.Add(id);
Or just define the class like this,
public class Mymessagesinfo
{
public int MyMessagesCount { get; set; }
public List<int> MessagesIDs { get; set; } = new List<int>();
public List<int> MessagesSendersid { get; set; } = new List<int>();
public List<string> MessagesSenders { get; set; } = new List<string>();
public List<string> MessagesTitles { get; set; } = new List<string>();
public List<string> MessagesInformation { get; set; } = new List<string>();
public List<string> MessagesStatus { get; set; } = new List<string>();
}

Here is how I would restructure what you have to make it work.
First, your model class:
public class Mymessagesinfo
{
public List<MessageInfo> Messages { get; set; } = new List<MessageInfo>();
}
public class MessageInfo
{
public int ID { get; set; }
public int Senderid { get; set; }
public string Sender { get; set; }
public string Title { get; set; }
public string Information { get; set; }
public string Status { get; set; }
}
With this approach you have a list of message objects, instead of a bunch of lists containing property data.
Here is how I would suggest you load it from SQL Server:
var data = new Mymessagesinfo();
int? userid = HttpContext.Session.GetInt32("UserID");
var messagesTable = new System.Data.DataTable("messages");
using (var sqlcom = sqlcon.CreateCommand())
{
sqlcom.CommandText = $"select * from messages where Messagereceiver='{userid}'";
using (var adapter = new SqlDataAdapter(sqcom))
{
adapter.Fill(messagesTable);
}
}
// we are now done with SQL and have the data in memory...
foreach(DataRow row in messagesTable.Rows)
{
data.Messages.Add( new MessageInfo {
ID = row.Field<int>(0),
Senderid = row.Field<int>(1),
Sender = row.Field<string>(2),
Title = row.Field<string>(3),
Information = row.Field<string>(4),
Status = row.Field<string>(5),
});
}
return View(data);
This is a lot cleaner and by using a DataAdapter and DataTable you minimize the amount of time that the connection to the database is connected.
Here is how you would use this model in an MVC View:
#Model Mymessagesinfo
<div>
<!-- This is where you can display the properties of the message. //-->
<ul>
#foreach(var message in Model.Messages)
{
<li> #message.Title - #message.Id </li>
}
<ul>
<div>

Related

Adding a list of objects to SQL Server - ASP.NET Web API

I'm trying to add a list of objects to a SQL Server database via Entity Framework but I get an error with Add
[HttpPost]
public void Post(List<Row> rows)
{
try
{
using (DbModel dbModel = new DbModel())
{
foreach (var el in rows)
{
dbModel.Provider_Status.Add(el);
}
dbModel.SaveChanges();
}
}
catch { }
}
Row class:
public class Row
{
public string FileName { get; set; }
public string FileTitle { get; set; }
public string ProviderID { get; set; }
public string ServiceID { get; set; }
public string PublishDate { get; set; }
public string ExpiryDate { get; set; }
}
Database Model DbModel:
public partial class Provider_Status
{
public int Id { get; set; }
public string FileName { get; set; }
public string FileTitle { get; set; }
public string ProviderID { get; set; }
public string ServiceID { get; set; }
public string PublishDate { get; set; }
public string ExpiryDate { get; set; }
}
Error Message:
CS1503 Argument 1: cannot convert from 'File_Upload.Models.Row' to 'File_Upload.Models.Provider_Status
Your DbModel defines a data set of type Provider_Status - so if you want to add data to this data set, you need to provide Provider_Status objects - not Row objects (as you do now).
You need to convert those Row object to Provider_Status - try something like this:
[HttpPost]
public void Post(List<Row> rows)
{
try
{
using (DbModel dbModel = new DbModel())
{
foreach (var el in rows)
{
// create a new "Provider_Status" object, based on the
// "Row" values being passed in
Provider_Status status = new Provider_Status
{
FileName = el.FileName
FileTitle = el.FileTitle
ProviderID = el.ProviderID
ServiceID = el.ServiceID
PublishDate = el.PublishDate
ExpiryDate = el.ExpiryDate
};
// add that new Provider_Status object to your dbModel
dbModel.Provider_Status.Add(status);
}
dbModel.SaveChanges();
}
}
catch { }
}

Null exception when try to display data from viewmodel in view ASP.NET MVC

I am trying to display data in my view using a ViewModel however I am getting null exceptions when doing so and I am not sure what the issue is. Basically I have a user, who's data I wish to display in a profile layout in my view, as well as data from different tables all in the same profile view.
ViewModel Code:
public int DonatorID { get; set; }
public string DonatorName { get; set; }
public string DonatorSurname { get; set; }
public string DonatorEmail { get; set; }
public int ContactNo { get; set; }
public int UserID { get; set; }
public string DonatorRank { get; set; }
public string RankIcon { get; set; }
public int XpAmount { get; set; }
public int TokenBalance { get; set; }
public int PaymentID { get; set; }
public string CardNo { get; set; }
public int ExpirationMonth { get; set; }
public int ExpirationYear { get; set; }
public int CVV { get; set; }
public int Zip { get; set; }
public string CardType { get; set; }
public int PaymentDonatorID { get; set; }
public int NpoID { get; set; }
public string NpoName { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
Controller Code:
id = 1;
//Disable lazy loading
db.Configuration.ProxyCreationEnabled = false;
//Add data to the dynamic object
var DynamicProfileDetail = db.tblDonator.Where(zz => zz.user_id == id).Include(yy => yy.tblUser).Include(xx => xx.tblDonator_Rank).FirstOrDefault();
DonatorUserViewModel ProfileDetails = new DonatorUserViewModel();
//Set profile details values
ProfileDetails.DonatorName = DynamicProfileDetail.donator_name;
ProfileDetails.DonatorSurname = DynamicProfileDetail.donator_surname;
ProfileDetails.DonatorEmail = DynamicProfileDetail.tblUser.email;
ProfileDetails.ContactNo = Convert.ToInt32(DynamicProfileDetail.donator_contact_no);
//Set other information
ProfileDetails.XpAmount = DynamicProfileDetail.xp_amount;
ProfileDetails.DonatorRank = DynamicProfileDetail.tblDonator_Rank.description;
ProfileDetails.RankIcon = DynamicProfileDetail.tblDonator_Rank.rank_icon;
ProfileDetails.TokenBalance = DynamicProfileDetail.donator_token_balance;
//Payment details section
int DonatorID = DynamicProfileDetail.donator_id;
var DynamicPaymentDetails = db.tblDonator_Payment_Details.Where(gg => gg.donator_id == DonatorID).Include(ff => ff.tblCard_Type).FirstOrDefault();
DonatorUserViewModel PaymentDetails = new DonatorUserViewModel();
//Set payment detail values
PaymentDetails.CardNo = DynamicPaymentDetails.donator_card_no;
PaymentDetails.ExpirationMonth = DynamicPaymentDetails.expiration_month;
PaymentDetails.ExpirationYear = DynamicPaymentDetails.expiration_year;
PaymentDetails.CVV = DynamicPaymentDetails.cvv;
PaymentDetails.Zip = DynamicPaymentDetails.zip_code;
PaymentDetails.CardType = DynamicPaymentDetails.tblCard_Type.description;
//Map marker section
var DynamicMapMarkers = db.tblNpo;
DonatorUserViewModel MapMarkers = new DonatorUserViewModel();
//Set map marker values
foreach (var item in DynamicMapMarkers)
{
MapMarkers.NpoID = item.npo_id;
MapMarkers.NpoName = item.npo_name;
MapMarkers.Longitude = Convert.ToDouble(item.longitude);
MapMarkers.Latitude = Convert.ToDouble(item.latitude);
MapMarkerList.Add(MapMarkers);
}
//ViewBags to display the relevant info
ViewBag.MapMarkerList = MapMarkerList;
return View();
My logic in the code above is that I am setting the values from my database to the objects in the ViewModel and then would be able to display it in my view.
View Code:
#model MyProject.ViewModels.DonatorUserViewModel
<h2>View/Edit your Details:</h2>
<ul>
<li>First Name: #Model.DonatorName</li>
<li>Surname: #Model.DonatorSurname</li>
<li>Contact Number: #Model.ContactNo</li>
<li>Email Address: #Model.DonatorEmail</li>
</ul>
Sorry for the amount of code in the question (particulary the viewmodel and controller sections) I just need to show that there are a lot of different objects from different database tables.
Now back to my issue, I am getting a null exception in my view for <li>First Name: #Model.DonatorName</li> and I'm assuming for the rest of them as well. I have a feeling there is something wrong with the way I am trying to use my viewmodel, as I am used to doing it using lists and then looping through that list in the view, however I am not sure how to do it now that I am only displaying essentially one line from the database tables instead of all the lines. Anyway any help would be much appreciated.

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ConsoleUserInfoes_dbo.ConsolesCheckBoxes_consoleId"

I'm getting this error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ConsoleUserInfoes_dbo.ConsolesCheckBoxes_consoleId". The conflict occurred in database "aspnet-ForePlay-20180525122039", table "dbo.ConsolesCheckBoxes", column 'ConsoleId'.
I'm using Entity Framework and ASP.NET MVC 5 and IdentityUser and try to insert data form checkListBox to table into my database.
This is happening on the register view, when user need to register and fill the form.
public class ConsoleUserInfo
{
[Key]
public int identity { get; set; }
[Required]
[StringLength(255)]
[ForeignKey("User")]
public string userid { get; set; }
[Required]
[ForeignKey("consolesCheckBox")]
public int consoleId { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ConsolesCheckBox consolesCheckBox { get; set; }
}
This is the table that need to get a user id (form applictionUser) and consoleId
(form ConsolesCheckBox )
This is the ApplicationUserUser model class:
public class ApplicationUser : IdentityUser
{
[Required]
[StringLength(255)]
override
public string UserName { get; set; }
[Required]
[StringLength(50)]
public string Phone { get; set; }
public byte[] UserPhoto { get; set; }
public virtual UserAddress Address { get; set; }
public virtual ICollection<ConsolesCheckBox> consoleCheckBox { get; set; }
}
and this is the checkBoxList table:
public class ConsolesCheckBox
{
[Key]
public int ConsoleId { get; set; }
public string ConsoleName { get; set; }
public bool IsChecked { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
This is my account controller, all in the register get and post
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register()
{
//using database
using (ApplicationDbContext dbo = new ApplicationDbContext())
{
//data will save list of the consoleCheckBoxItem
var data = dbo.consolesCheckBox.ToList();
// because the view is request a common model, we will create new one
CommenModel a = new CommenModel();
a.ConsolesCheckBoxList = data;
// we will need to return common model, that way we will return a
return View(a);
}
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register([Bind(Exclude = "UserPhoto")]CommenModel model)
{
if (ModelState.IsValid)
{
// To convert the user uploaded Photo as Byte Array before save to DB
byte[] imageData = null;
if (Request.Files.Count > 0)
{
HttpPostedFileBase poImgFile = Request.Files["UserPhoto"];
using (var binary = new BinaryReader(poImgFile.InputStream))
{
imageData = binary.ReadBytes(poImgFile.ContentLength);
}
}
var user = new ApplicationUser
{
UserName = model.registerViewModel.Email,
Email = model.registerViewModel.Email,
Phone = model.registerViewModel.Phone
};
user.UserPhoto = imageData;
var result = await UserManager.CreateAsync(user, model.registerViewModel.Password);
//after the user create, we will use the id and add the id to the userAddress table include
// Address, longitude and latitude.
using (ApplicationDbContext dbo = new ApplicationDbContext())
{
var currentUserId = user.Id;
var pasinfo = dbo.userAddress.FirstOrDefault(d => d.Userid == currentUserId);
if (pasinfo == null)
{
pasinfo = dbo.userAddress.Create();
pasinfo.Userid = currentUserId;
dbo.userAddress.Add(pasinfo);
}
pasinfo.Address = model.useraddress.Address;
pasinfo.latitude = model.useraddress.latitude;
pasinfo.longitude = model.useraddress.longitude;
dbo.SaveChanges();
foreach (var item in model.ConsolesCheckBoxList.Where(x => x.IsChecked).Select(x => x.ConsoleId))
{
var consoleUserInfo = new ConsoleUserInfo
{
userid = currentUserId,
consoleId = item
};
dbo.consoleUserInfo.Add(consoleUserInfo);
}
dbo.SaveChanges();
}
}
}
In the register GET I have a common model, because I used 3 models in the view
this is the common model:
public class CommonModel
{
public UserAddress useraddress { get; set; }
public RegisterViewModel registerViewModel { get; set; }
public List<ConsolesCheckBox> ConsolesCheckBoxList { get; set; }
}
I need your help here, I've been trying to fix this all day.

using DataContractJsonSerializer when Json object propety is named with "#" symbol

When using DataContractJsonSerializer to parse a json response, I've come across a json object with a property name of #id and I can't seem to populate this field. All of the other fields are populated without a problem. I can even get this field populated using Fiddler, but not using DataContractJsonSerializer. My code is as follows...
public IEnumerable<Vehicle> vehicles { get; set; }
public async Task GetVehicleList(string access_token)
{
vehicles = await GetVehicleListInfo(access_token);
}
private async Task<IEnumerable<Vehicle>> GetVehicleListInfo(string access_token)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://www.example.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.example.api-v1+json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer" + access_token);
HttpResponseMessage response = await client.GetAsync("vehicles");
//IEnumerable<Vehicle> vehicles = new IEnumerable<Vehicle>();
Vehicle vehicle = new Vehicle();
PagedVehicleResult pvr = new PagedVehicleResult();
Stream dataStream = null;
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(pvr.GetType());
pvr = (PagedVehicleResult)serializer.ReadObject(dataStream);
}
vehicles = pvr.vehicle;
return vehicles;
}
}
}
/// <summary>
/// parent object returned by json. contains list of vehicle objects
/// </summary>
public class PagedVehicleResult
{
public int count { get; set; }
public int index { get; set; }
public int limit { get; set; }
public int total { get; set; }
public string type { get; set; }
public IEnumerable<Vehicle> vehicle { get; set; }
}
public class Vehicle
{
public int id { get; set; } //This is the property in question.
//When it comes back in fiddler it looks like "#id", and it does get populated.
//when it comes back in my console application it is 0 if int and null if string.
public string vin { get; set; }
public string label { get; set; }
public string color { get; set; }
public string make { get; set; }
public string model { get; set; }
public string deviceSerialNumber { get; set; }
public int year { get; set; } //consider making date? unknown repercussions
public CreateTimestamp createdTimestamp { get; set; }
public ModifiedTimestamp modifiedTimestamp { get; set; }
}
public class CreateTimestamp
{
public string readOnly { get; set; }
public string value { get; set; } //had to cast as string.. can convert to datetime before database insert
}
public class ModifiedTimestamp
{
public string readOnly { get; set; }
public string value { get; set; }
}
How can I map that json #id field to my Vehicle class id property?
Okay, I figured this out on my own from reading various different post on the subject.
All I had to do was parse it into a json string first, then call a .replace() on the string to change the id. Then I used the JavaScriptSerializer on that and it worked.
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
string content;
using (StreamReader reader = new StreamReader(dataStream, true))
{
content = reader.ReadToEnd();
content = content.Replace("#id", "id");
JavaScriptSerializer js = new JavaScriptSerializer();
pvr = js.Deserialize<PagedVehicleResult>(content);
}
}
vehicles = pvr.vehicle;
return vehicles;
Now, when i try, my object id is correctly inserted.

How do you do lookup tables via code first

I've been searching this without any luck on how to resolve. I have a list of available departments that can be used within my stores. Since stores vary, some departments may not exist and I want to keep track of how much shelving space each department has for each store. What's the best way to create this?
Here's my model:
public class Store
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; } //StoreNumber
public virtual List<StoreDepartment> StoreDepartments { get; set; }
}
public class StoreDepartment
{
[Key]
public int ID { get; set; }
public int StoreID { get; set; }
public Department Department { get; set; }
public int ShelvingLinealFT { get; set; }
}
public class Department
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; } //DepartmentNumber
public string Name { get; set; }
public bool InActive { get; set; }
}
I've already populated my Department tables, but when I attempt to save a StoreDepartment object, I get an error stating that it can't insert a row since its trying to create a duplicate key. It's like it's trying to create a new record.
Any help would be appreciated.
Here's the code for my DbContext:
public class StoresRepository:DbContext
{
public DbSet<Store> Stores { get; set; }
public DbSet<StoreDepartment> StoreDepartments { get; set; }
public DbSet<Department> Departments { get; set; }
}
Here is my Save method:
/// <summary>
/// Saves a StoreDepartment Object to the store("dept.storeid")
/// Adds a new record if ID is 0
/// </summary>
/// <param name="dept"></param>
/// <returns></returns>
public bool Save(StoreDepartment dept)
{
bool retval = false;
try
{
using (var db = new StoresRepository())
{
if (dept.ID.Equals(0))
{
//Add Store Department
db.StoreDepartments.Add(dept);
}
else
{
//this is an update
StoreDepartment department = db.StoreDepartments.Where(p => p.ID.Equals(dept.ID)).FirstOrDefault();
department.Department = dept.Department;
department.ShelvingLinealFT = dept.ShelvingLinealFT;
}
int rowsupdated = db.SaveChanges();
retval = true;
}
}
catch (Exception ex)
{
Utils.Trace(string.Format("StoresContext.cs: StoreDepartments.Save(). ID:{1}. Exception: {0}", ex, dept.ID), Utils.ErrorTypes.Error);
}
return retval;
}
You probably change the state of the Department to added when you add the StoreDepartment object. Something like this:
using(var db = new MyContext())
{
var storeDepartment = new StoreDepartment();
storeDepartment.StoreId = storeId;
storeDeparemtent.Department = department;
db.StoreDepartments.Add(storeDepartment); // also marks Department as added
db.SaveChanges();
}
The solution is to move up the line where you add the object:
using(var db = new MyContext())
{
var storeDepartment = new StoreDepartment();
db.StoreDepartments.Add(storeDepartment);
storeDepartment.StoreId = storeId;
....
}
You can also add a DepartmentId to the StoreDepartment class and set its value, as you do with StoreId. Together with the Department property this is called a foreign key association.
I figured it out.
Here are the correct models:
public class StoreDepartment
{
[Key]
public int ID { get; set; }
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
public int ShelvingFootage { get; set; }
}
public class Department
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
public virtual ICollection<StoreDepartment> StoreDepartments { get; set; }
}
Using Affluent API, I setup my relationships as follows:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<StoreDepartment>().HasRequired(d => d.Department);
modelBuilder.Entity<Department>().HasMany(d => d.StoreDepartments);
}
Once I had this setup, one of the main issues I had was with populating the object.
Normally, you would do the following:
StoreDepartment sd = new StoreDepartment();
sd.Department = new Department(){
ID = 302,
Name = "Deli"
};
sd.ShelvingFootage = 100;
However when trying to save this object, Entity would attempt to add a new record in the Department table which of course would throw an exception due to a violation in the primary key.
The trick was to not update this directly and to build my StoreDepartment object as follows:
StoreDepartment sd = new StoreDepartment();
sd.DepartmentID = 302;
sd.ShelvingFootage = 100;
By doing this, you are only updating the foreign key for the StoreDepartment.Department object.

Resources