Thus project works fine in .Net Framework but now I'm trying to do it in .Net Core 3 but its not working properly.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string ImageURL { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
public class BasketLine
{
public int Id { get; set; }
public string BasketId { get; set; }
public int ProductId { get; set; }
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public Product Product { get; set; }
}
So what happens is iI can add to the BasketLine table and calculate the total of all Products, however when I load the Cart page I get a NullReferenceException
On the Cart Page if I comment out #Model.BasketLines[i].Product.Name or any navigation properties, the Cart Page works
This is the addBasket method
public void AddToBasket(int productId, int quantity)
{
var basketLine = db.BasketLines.FirstOrDefault(b => b.BasketId == BasketId &&
b.ProductId == productId);
if (basketLine == null)
{
basketLine = new BasketLine
{
ProductId = productId,
BasketId = BasketId,
Quantity = quantity,
DateCreated = DateTime.Now
};
db.BasketLines.Add(basketLine);
}
else
{
basketLine.Quantity += quantity;
}
db.SaveChanges();
}
Am I missing something because I have no clue what I'm doing wrong here
Added Include didn't change a thing, then a strange thing happened, I changed this
<a asp-area="Customer"
asp-controller="Shop"
asp-action="Details"
asp-route-id="#Model.BasketLines[i].ProductId">
#Model.BasketLines[i].Product.Name
</a>
to this
#Html.ActionLink(Model.BasketLines[i].Product.Name, "Details", "Products", new { id = Model.BasketLines[i].ProductId }, null)<br />
then the everything worked for a few tries then I got the same error all over again
AspNetCore.Areas_Customer_Views_Basket_Index.<ExecuteAsync>b__15_0() in Index.cshtml
+
#Html.ActionLink(Model.BasketLines[i].Product.Name, "Details", "Products", new { id = Model.BasketLines[i].ProductId }, null)<br />
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
Microsoft.AspNetCore.Mvc.TagHelpers.RenderAtEndOfFormTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count)
AspNetCore.Areas_Customer_Views_Basket_Index.ExecuteAsync() in Index.cshtml
+
{
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, Nullable<int> statusCode)
Have you tried Include? You can use the Include method to specify related data to be included in query results.
var basketLine = db.BasketLines
.Include(b => b.Product)
.FirstOrDefault(b => b.BasketId == BasketId && b.ProductId == productId);
[Source]
Related
I have this code -
var add = (from h in db.Hotels
where h.Address.Contains(hotels.Address)
select h).Take(2);
ViewBag.Related = add;
Now, in the View, I want to display the images, so I'm using this code -
<img src="~/img/#item.FirstOrDefault().Image" />
This is giving me this error -
'System.Data.Entity.DynamicProxies.Hotels_D1EE6FD2E11BD1D9436F26FEA6336CFE76F33C59111E2ABC7C1BBE456FF61C23' does not contain a definition for 'FirstOrDefault'
I've tried using 'joins' also but same error occurs. Please help me out in this! :(
My Hotels class -
public class Hotels
{
[ScaffoldColumn(false)]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Address { get; set; }
[StringLength(8)]
public string PinCode { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string FilledBy { get; set; }
public DateTime DateAdded { get; set; }
//public int ImageId { get; set; }
public int TotalRooms { get; set; }
public bool Available { get; set; }
public virtual ICollection <Rooms> Rooms { get; set; }
public virtual ICollection <Images> Images { get; set; }
public virtual ICollection<Ameneties> Ameneties { get; set; }
public virtual ICollection <Bookings> Bookings { get; set; }
public virtual ICollection<NearByLocations> Nearby { get; set; }
public virtual ICollection<Ratings> Ratings { get; set; }
public virtual ICollection<RoomType> RoomTypes { get; set; }
public virtual ICollection<CustomerReviews> Reviews { get; set; }
public virtual ICollection<HotelRules> HotelRules { get; set; }
}
My Images class -
public class Images
{
[ScaffoldColumn(false)]
public int id { get; set; }
public string Image { get; set; }
public int? HotelId { get; set; }
public virtual Hotels Hotels { get; set; }
//public ICollection<Hotels> Hotels { get; set; }
}
I have used this type of collections...
This is my Details View Controller code -
public ActionResult Details(int? id)
{
IEnumerable<Images> galleries = (from gallery in db.Images
where gallery.Hotels.Id == id
select gallery);
ViewBag.Images = galleries;
ViewBag.ImgCount = galleries.Count();
IEnumerable<Ameneties> ameneties = (from a in db.Ameneties
where a.Hotels.Id == id
select a);
ViewBag.Ameneties = ameneties;
IQueryable<Rooms> rooms = (from room in db.Rooms
where room.Hotels.Id == id
select room);
var ratings = (from rating in db.Ratings
where rating.Hotels.Id == id
select rating.Points);
ViewBag.Ratings = ratings;
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Hotels hotels = db.Hotels.Find(id);
if (hotels == null)
{
return HttpNotFound();
}
var add = db.Hotels.Include("Images").Where(h => h.Address.Contains(hotels.Address))
.Select(h => h)
.Take(2)
.ToList();
var model = new MyViewModel { Hotels = add };
ViewBag.Reviews = hotels.Reviews;
ViewBag.Ratings = hotels.Ratings;
ViewBag.NearBy = hotels.Nearby;
ViewBag.RoomTypes = hotels.RoomTypes;
ViewBag.Rules = hotels.HotelRules;
return View(hotels);
}
Could you add ToList() at the end of the query?
var add = (from h in db.Hotels
where h.Address.Contains(hotels.Address)
select h).Take(2)
.ToList();
ViewBag.Related = add;
Then you could call item.Images.FirstOrDefault()?.Image.
#foreach (var item in ViewBag.Related)
{
<img src="~/img/#item.Images.FirstOrDefault().Image" />
}
If it still doesn't work, you will need to explicitly load Image when you query Hotel. For example,
public IActionResult Index()
{
var add = db.Hotels
.Include("Images")
.Where(h => h.Address.Contains(hotels.Address))
.Select(h => h)
.Take(2)
.ToList();
var model = new MyViewModel { Hotels = add };
return View(model);
}
View
#model YourNameSpace.Models.MyViewModel
#foreach (var item in Model.Hotels)
{
<img src="~/img/#item.Images.FirstOrDefault().Image" />
}
Model
public class MyViewModel
{
public List<Hotels> Hotels { get; set; }
}
I'm working at my first project in .Net Core 2.0. It is a simple blog system. I want to add search functionality based on post title and tags.
My entities:
public class Post
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Body { get; set; }
public int CategoryID { get; set; }
public DateTime ReleaseDate { get; set; }
public string ImageName { get; set; }
public Category Category { get; set; }
public ICollection<PostTag> PostTags { get; } = new List<PostTag>();
}
public class PostTag
{
public int PostID { get; set; }
public int TagID { get; set; }
public Post Post { get; set; }
public Tag Tag { get; set; }
}
public class Tag
{
public int TagID { get; set; }
public string Name { get; set; }
public int Counter { get; set; }
public ICollection<PostTag> PostTags { get; } = new List<PostTag>();
public Tag()
{
Counter = 1;
}
So far I have come up with something like that. I joined the Tag table to be able to view all the tags for each post in IndexView.
public async Task<IActionResult> Index(int? page, string searchString)
{
IQueryable<Post> posts = _context.Posts
.OrderByDescending(post => post.ReleaseDate)
.Include(post => post.Category)
.Include(post => post.PostTags)
.ThenInclude(pt => pt.Tag);
//SEARCH
if (!String.IsNullOrEmpty(searchString))
{
posts = posts.Where(post => post.PostTags.Any(pt => pt.Tag.Name.Contains(searchString)) || post.Title.Contains(searchString));
//POPULARITY INCREESE
var tag = _context.Tags.SingleOrDefault(t => t.Name == searchString);
if (tag != null)
{
tag.Counter += 1;
_context.Update(tag);
_context.SaveChanges();
}
}
int pageSize = 4;
return View("Index", await PaginatedList<Post>.CreateAsync(posts.AsNoTracking(), page ?? 1, pageSize));
}
It's wroking but I would like to know if there is a simpler or better way.
And will .Where function work when i dont include related tables?
First of all the answer to your last question: As long as you didn´t send any request to the database, you don´t need Include() for filtering.
If you want to populate a list of entities, and you want to access Navigation-Properties e.g. while iterating over the list, you need to use Include().
If you want to avoid using Include(), you should select the values you need. This will avoid unexpected behaviour with NavigationProperties or something like this too. I would do something like this:
IQueryable<Post> posts = _context.Posts.OrderByDescending(post => post.ReleaseDate);
//SEARCH
if (!String.IsNullOrEmpty(searchString))
{
posts = posts.Where(post => post.PostTags.Any(pt => pt.Tag.Name.Contains(searchString)) || post.Title.Contains(searchString));
//POPULARITY INCREESE
var tag = _context.Tags.SingleOrDefault(t => t.Name == searchString);
if (tag != null)
{
tag.Counter += 1;
_context.Update(tag);
_context.SaveChanges();
}
}
int pageSize = 4;
return View("Index", await PaginatedList<Post>.CreateAsync(posts.AsNoTracking().Select(e=> new YourDisplayObject { DiplayValue = e.DbValue, DisplayNavProp = e.NavProp }, page ?? 1, pageSize));
I'm using Entity Framework Core to build a simple web app. For this app, I've created a model called Company that includes basic business info + a list of contacts (sales reps).
Here's my model:
public class Company
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Promo { get; set; }
public virtual List<Contact> Contacts { get; set; }
}
public class Contact
{
[Key]
public int ContactID { get; set; }
[ForeignKey("Company")]
public int CompanyID { get; set; }
public virtual Company Company { get; set; }
public string ContactName { get; set; }
public string ContactNumber { get; set; }
}
Here's the controller's index() method:
// GET: Companies
public async Task<IActionResult> Index()
{
List<Company> viewModelData = await _context.Companies
.Include(c => c.Contacts)
.ToListAsync();
return View(viewModelData);
}
Edit method:
// GET: Companies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var company = await _context.Companies
.Include(v => v.Contacts)
.FirstOrDefaultAsync(m => m.ID == id);
if (company == null)
{
return NotFound();
}
return View(company);
}
// POST: Companies/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int? id, [Bind("ID,Name,Promo,Contacts")] Company company)
{
if (id == null)
{
return NotFound();
}
var companyToUpdate = await _context.Companies
.Include(v => v.Contacts)
.FirstOrDefaultAsync(m => m.ID == id);
if (await TryUpdateModelAsync<Company>(
companyToUpdate,
"",
i => i.Name, i => i.Promo, i => i.Contacts
)) {
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
return RedirectToAction("Index");
}
return View(companyToUpdate);
}
This is not correct since the code only allows me to edit Company info. How do I modify the code so that I can edit both Company & its contacts on the same edit view?
If you're purely looking to update values, then you can explicitly update them like so. A View Model is also recommended but this comes down to good vs bad practice. This omits the exception handling and serves only as an example of how to map these values, you'll have to modify the remainder of your controller to work directly with the CompanyEditViewModel
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int? id, [Bind("ID,Name,Promo,Contacts")] CompanyEditViewModel company)
{
if (!ModelState.IsValid)
return RedirectToAction("Index");
var companyToUpdate = await _context.Companies
.Include(v => v.Contacts)
.FirstOrDefaultAsync(m => m.ID == id);
// Assign the new values
companyToUpdate.Name = company.Name;
companyToUpdate.Promo = company.Promo;
companyToUpdate.Contacts = company.Contacts?.ToList();
// Update and save
_context.Companies.Update(companyToUpdate);
await _context.SaveChangesAsync();
return View(companyToUpdate);
}
public class Company
{
public int ID { get; set; }
public string Name { get; set; }
public string Promo { get; set; } // Yes or No field
public List<Contact> Contacts { get; set; }
public class Contact
{
[Key]
public int ContactID { get; set; }
public int CompanyID { get; set; }
public string ContactName { get; set; }
public string ContactNumber { get; set; }
}
}
// The View Model contains the Company details which were modified
// The first Edit method will have to be updated to bind this View Model to the view
public class CompanyEditViewModel
{
public int ID { get; set; }
public string Name { get; set; }
public string Promo { get; set; }
public IList<Company.Contact> Contacts { get; set; }
}
The following code below:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Car model, HttpPostedFileBase file)
{
var currentUser = UserManager.FindById(User.Identity.GetUserId());
var user = this.db.Users.Where(u => u.Id == currentUser.Id).FirstOrDefault();
if(ModelState.IsValid)
{
if (file != null && file.ContentLength > 0)
{
var photo = new FilePath
{
FileName = Guid.NewGuid().ToString() + System.IO.Path.GetExtension(file.FileName),
FileType = FileType.Photo
};
model.FilePaths = new List<FilePath>();
model.FilePaths.Add(photo);
file.SaveAs(Path.Combine(Server.MapPath("~/Images/"), photo.FileName));
}
user.Cars.Add(model);
db.SaveChanges();
return RedirectToAction("Default", "Home");
}
SetCategoryViewBag(model.Category.CategoryId);
return View(model);
}
Won't let me to store any images to the database. The image table doesn't store any information at all. However, the cars table is ok, but images is still showing as null.
What have I done wrong here?
Edit:
Car model:
public class Car
{
[Key]
public int CarId { get; set; }
public string Title { get; set; }
public int Price { get; set; }
public virtual Category Category { get; set; }
public int CategoryId { get; set; }
public virtual ICollection<FilePath> FilePaths { get; set; }
}
FilePath model:
public class FilePath
{
public int FilePathId { get; set; }
[StringLength(255)]
public string FileName { get; set; }
public FileType FileType { get; set; }
public int CarId { get; set; }
public virtual Car Cars { get; set; }
}
I have been trying to get data from the table I have joined to the main user table, the second table is to hold images. My current code posted below, only return the ImageID from the table when I want to be retrieving the ImagePath field, just to note this is a separate table as the user can add many images.
These are the models:
[Table("accountInfo")] // Table name
public class accountInfo
{
[Key]
public int AccountID { get; set; }
public int UserId { get; set; }
public int UserIdent { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public virtual ICollection<UserImages > UserImages { get; set; }
}
[Table("UserImages")] // Table name
public class UserImages
{
[Key]
public int ImageID { get; set; }
public int AccountID { get; set; }
public string ImagePath { get; set; }
public string ImageDesc { get; set; }
public int ProfileImage { get; set; }
}
Controller:
public ActionResult Index()
{
int id = (int)WebSecurity.CurrentUserId;
var users = db.AccountInformation.Include(c => c.UserImages).Where(c => c.UserId == id);
return View(users.ToList());
}
I am assuming I have gone wrong in the models set up. Can anyone help?
var a = db.AccountInformation.Include(c => c.UserImages.Select(x => x.AccountId)).Where(c => c.UserId == id);