Error while accessing the Navigation Property in EF Code First - asp.net-mvc

I am having a simple ViewModel which have something like this...
ViewModel
public class UserPostCommentViewModel
{
public virtual List<Comment> Comment { get; set; }
public virtual User User { get; set; }
public virtual Post Post { get; set; }
}
so that i can return a view which has 1 Post with the details 1 User details and Many Comments submitted by users....
POST
[Key]
[ScaffoldColumn(true)]
public int PostID { get; set; }
[Required(ErrorMessage="Required")]
[StringLength(250)]
public string Title { get; set; }
[Required(ErrorMessage="Required")]
[DataType(DataType.MultilineText)]
public string Body { get; set; }
[DataType(DataType.Date)]
public DateTime DateCreated { get; set; }
[DataType(DataType.Date)]
public DateTime DateModified { get; set; }
[ScaffoldColumn(false)]
public int UserID { get; set; }
[ScaffoldColumn(false)]
public int? TagID { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual User Users { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
Comment
[Key]
[ScaffoldColumn(true)]
public int CommentID { get; set; }
[DisplayName("Your Comment")]
[DataType(DataType.MultilineText)]
public string Body { get; set; }
[DataType(DataType.Date)]
[ScaffoldColumn(true)]
public DateTime DateCreated { get; set; }
[ScaffoldColumn(true)]
public int PostID { get; set; }
[ScaffoldColumn(true)]
public int UserID { get; set; }
public User User { get; set; }
public Post Posts { get; set; }
USer
[ScaffoldColumn(true)]
[Key]
public int UserID { get; set; }
[StringLength(15)]
[DisplayName("First Name")]
[Required(ErrorMessage="First Name is Required")]
public string FirstName { get; set; }
[StringLength(15)]
[DisplayName("Last Name")]
[Required(ErrorMessage = "Last Name is Required")]
public string LastName { get; set; }
[DataType(DataType.EmailAddress,ErrorMessage="please enter valid email")]
[DisplayName("Email Address")]
[Required(ErrorMessage = "Email is Required")]
[Remote("CheckUniqueEmail","User",ErrorMessage="An account with this email address already exists.")]
public string Email { get; set; }
[DataType(DataType.Password)]
[Required(ErrorMessage = "Password is Required")]
public string Password { get; set; }
[DataType(DataType.Date)]
[ScaffoldColumn(true)]
public DateTime JoiningDate { get; set; }
[DataType(DataType.Date)]
[ScaffoldColumn(true)]
public DateTime? LastActivityDate { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
i have a StronglyTyped View with the ViewModel so that i can return all the three model properties in one view...
BUT :( i want to show the userName instead of userID in front of the each comment for that particular post. so i am using ICollection comments in the viewmodel so that i can return collection of the comments. and when i try to access the userName property like this #Model.Comments.User.LastName // OR Email // OR FirstName .. i am getting the compilation error. and i cant use like this because its a collection type ...
how can i retrieve the userName from the comments entity using the userID which is available in comments..
please help...
Got it all working by adding in the partial view..
_Comments Partial View..
in my partial view i have added like this...
========================
#{
ContextRepository db = new ContextRepository();
var userID = Model.UserID;
var userName = db.EUser.Find(userID).FirstName;
}

You can create a partial view to display the comment and call that inside a loop in the main view.
Post Details view
#model UserPostCommentViewModel
#{
ViewBag.Title = "Post";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#foreach (Comment comment in Model.Comments)
{
#Html.Partial("_Comment", comment);
}
_Comment partial view
#model Comment
<div class="comment">
<div class="desc">#Model.Body</div>
<div class="submitted-by">#Model.User.LastName</div>
</div>
Model issues
You need to make the navigational properties virtual to be lazy loaded.
public class Comment
{
//other properties
public virtual User User { get; set; }
public virtual Post Posts { get; set; }
}
If you are going to access these navigational properties then you need to eager load them. Otherwise you will run into Select n+1 problem. Use the Include method to eager load properties
var post = db.Posts.Include(p => Comments)
.Include(p => p.Comments.Select(c => c.User))
.Where(p => p.PostID == 1).Single();

Related

Rendering partial view ASP MVC

I want to render a partial view within the main view.
This is what I have done so far, but non of the code not loading the partial view.
Can anyone help me with this? Thanks in advance.
This is my main model
public class AppRequest
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name = "Request Type")]
public int ReqType { get; set; }
[Required]
[Display(Name = "Requesting By")]
public int Req_By { get; set; }
[Required]
[Display(Name = "Requesting Date")]
public DateTime Req_Date { get; set; } = DateTime.Now;
[Required]
[Display(Name = "Request Location")]
public int Req_Location { get; set; }
[Required]
[Display(Name = "Request Heading")]
public string Req_Heading { get; set; }
[Display(Name = "Cover Note")]
public string Req_CoverNote { get; set; }
[Required]
[Display(Name = "Company Name")]
public int Company_Id { get; set; }
public virtual IList<Purchase> Purchase { get; set; }
public virtual IList<General> General { get; set; }
[NotMapped]
public Purchase PurchaseItem { get; set; }
}
#region Purchase
public class Purchase
{
[Key]
public int Id { get; set; }
[Required]
[ForeignKey("AppRequest")]
public int Req_Id { get; set; }
public virtual AppRequest AppRequest { get; set; }
public virtual IList<PurchasingEmpl> PurchasingEmpl { get; set; }
public virtual IList<PurchasingItems> PurchasingItems { get; set; }
}
public class PurchasingEmpl
{
[Key]
public int Id { get; set; }
[Required]
[ForeignKey("Purchase")]
public int Purchase_Id { get; set; }
public virtual Purchase Purchase { get; set; }
public int Emp_Id { get; set; }
public bool Status { get; set; }
}
public class PurchasingItems
{
[Key]
public int Id { get; set; }
[Required]
[ForeignKey("Purchase")]
public int Purchase_Id { get; set; }
public virtual Purchase Purchase { get; set; }
public int Supp_Id { get; set; }
public int Itm_Description_Id { get; set; }
public decimal Unit_Amount { get; set; }
public byte[] Attachment { get; set; }
public decimal Qty { get; set; }
public string Recomandation { get; set; }
public bool Status { get; set; }
public bool Settled { get; set; } = false;
public string PoNo { get; set; }
}
#endregion
And this is the View. My partial view name is "_Purchasing". So under this _Purchasing partial view, I have added another 2 partial views. So I need to load this main partial view to show the other details.
#model Asp_PASMVC.Models.AppRequest
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>AppRequest</h4>
<hr />
<div id="PurchseReq">
#Html.Partial("_Purchasing");
</div>
</div>
}
you can use #RenderPartial and #Partial
#RenderPartial vs #Partial
As mentioned, you can incorporate a partial view in a Razor view by using either of two methods: #RenderPartial or #Partial. The difference between the two methods may look small and harmless, but it may bite at you if you don’t know how to handle it.
The key difference between the two methods is that Partial returns a HTML-encoded string while #RenderPartial is a void method that writes directly to the response output stream. The usage of the two methods is slightly different:
#Html.Partial("_yourPartialView")
#Html.RenderPartial("_yourPartialView")

Country and City Dropdown in ASP.NET Core MVC with db-first approach

I know this question might be asked so many times, I tried a lot to find the answer and ultimately I am throwing it here if some one can help me.
I am doing a project in ASP.NET Core MVC with a database-first approach. I have a registration form where I need to populate Country and City dropdowns to fill with data coming in through WeCareConext class.
In my controller I am doing this:
[HttpGet]
public IActionResult Register()
{
CompanyEditViewModel model = new CompanyEditViewModel();
var fromDatabaseEF = new SelectList(_context.Country.ToList(), "CountryId", "NameEn");
ViewData["CompanyRegister"] = fromDatabaseEF;
return View(model);
}
My Country model:
public partial class Country
{
public Country()
{
City = new HashSet<City>();
Currency = new HashSet<Currency>();
HolidayType = new HashSet<HolidayType>();
Holidays = new HashSet<Holidays>();
Province = new HashSet<Province>();
StaffInfo = new HashSet<StaffInfo>();
}
public int CountryId { get; set; }
public string NameAr { get; set; }
public string NameEn { get; set; }
public string NameFr { get; set; }
public string IsoCode2 { get; set; }
public string IsoCode3 { get; set; }
public string RegionAr { get; set; }
public string Region { get; set; }
public byte? PostcodeRequired { get; set; }
public bool? IsActive { get; set; }
public byte? IsAvailable { get; set; }
public string MobileMask { get; set; }
public byte? IsDeleted { get; set; }
public int? BaseCharges { get; set; }
public int? MobileNumberLength { get; set; }
public string CountryCode { get; set; }
public byte[] IconImage { get; set; }
public string PickerListAr { get; set; }
public string PickerListEn { get; set; }
public string PickerListFr { get; set; }
public virtual ICollection<City> City { get; set; }
public virtual ICollection<Currency> Currency { get; set; }
public virtual ICollection<HolidayType> HolidayType { get; set; }
public virtual ICollection<Holidays> Holidays { get; set; }
public virtual ICollection<Province> Province { get; set; }
public virtual ICollection<StaffInfo> StaffInfo { get; set; }
}
My CompanyEditViewModel class:
public class CompanyEditViewModel
{
[Display(Name = "Company Number")]
public string CompanyId { get; set; }
[Required]
[Display(Name = "Company Name")]
[StringLength(75)]
public string Name { get; set; }
[Required]
[Display(Name = "Country")]
public string CountryId { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
[Required]
[Display(Name = "City")]
public string SelectedCityCode { get; set; }
public IEnumerable<SelectListItem> Cities { get; set; }
}
Unfortunately, this returns an error:
System.ArgumentException: 'Format of the initialization string does not conform to specification starting at index 0.'
I am trying different approaches but not solving my issue. Can anyone suggest some code which can help me and I can also select country and then populate city dropdown according to the CountryID without page reload ? Thanks in advance.

Specifying Relationships in Models in ASP.NET MVC4

I'm an ASP.NET MVC4 beginner and I'm trying to create a blog kind of. I have a problem with creating relationships in my models. Background of my issue is that, I have a model (Users.cs) with user information, a model (Posts.cs) containing posts information, and a third model (Comments.cs) containing comments information.
So a user can have many posts but a post can belong to only one user,
a user can have many comments but a comment can belong to only a user,
a post can have many comments but a comment can only belong to a post,
My question is, how do I write the three models? So far I have this:
public class Users
{
public int UserID { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public DateTime DOB { get; set; }
public string Sex { get; set; }
public string Email { get; set; }
public DateTime RegDate { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string PasswordSalt { get; set; }
public virtual List<Posts> Post { get; set; }
public virtual List<Comments> Comment { get; set; }
}
class Posts
{
public int PostID { get; set; }
public string PostTitle { get; set; }
public string PostContent { get; set; }
public DateTime PostDate { get; set; }
public int AuthorID { get; set; }
public int CommentID { get; set; }
public virtual List<Comments> Comment { get; set; }
public virtual Users user { get; set; }
}
public class Comments
{
public int CommentID { get; set; }
public string Comment { get; set; }
public DateTime CommentDate { get; set; }
public int AuthorID { get; set; }
public int PostID { get; set; }
public virtual Posts post { get; set; }
public virtual Users user { get; set; }
}
Please how do I write the three models correctly? Help!!!
You have strongly typed model classes, and you're already using them correctly. You just need to remove the redundant properties pointing to ID's - Comments doesn't need an int AuthorID pointing to the author when it already has Users user.
Remove these properties:
class Posts
{
public int AuthorID { get; set; }
public int CommentID { get; set; }
}
public class Comments
{
public int AuthorID { get; set; }
public int PostID { get; set; }
}

Creating an edit form with partial views MVC

I have data structure for organisation As follows:
public class Organisation
{
public int OrganisationId { get; set; }
[Required]
public string OrganisationCode { get; set; }
[Required]
public string Name { get; set; }
public ICollection<OrganisationSite> Sites { get; set; }
public string TelNo { get; set; }
public int? AddressId { get; set; }
public Address Address { get; set; }
}
An address is stored as its' own entity:
public class Address
{
public int AddressId { get; set; }
[Required]
public string HouseNoName { get; set; }
public string Street { get; set; }
public string Locality { get; set; }
public string TownCity { get; set; }
public string County { get; set; }
[Required]
[RegularExpression("^[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$", ErrorMessage="Postcode must be recognisable UK postal code")]
public string Postcode { get; set; }
[Required]
public int AddressTypeId { get; set; }
public AddressType Type { get; set; }
}
Address will be used in many places thoughout an application so sounds like I need a partial view that I can reuse? In my OrganisationController I am going to make a trip to my OrganisationRepository and include the Address entity(entity framework):
public ActionResult Edit(int id = 1)
{
var organisation = _db.Organisation.Include("Address").Single(og => og.OrganisationId == id);
if (organisation == null)
{
return HttpNotFound();
}
return View(organisation);
}
How do I render a partial address view in my Organisation Edit view? I have had a quick look and seen reference to EditorTemplates, is this the approach I need to take, if so do you know of any decent tutorials as the ones I've seen appear fairly deep?

An error occurred while updating the entries. See the inner exception for details. - Asps.net MVC 3

i am having this exception coming everytime i run and try to create the post..
i am having a simple User,Post,Comment,Tag entity. which has relationship association defined by me. when i am checking the innerException it says "Cannot insert the value NULL into column 'CommentID', table " ... and its pointing to my context where i have a relationship defined..please check my relationship and help me finding this where i have delclared that null is not allowed in Comment ID...
1 user can have many posts, can create many tags, can have many
comments
1 post can have 1 user, many comments, and can have many tags
1 tag can have 1 user, many post
1 comment can have 1 user, 1 post
RelationShip...
modelBuilder.Entity<User>().HasMany(p => p.Posts).WithRequired(u => u.Users).HasForeignKey(P=>P.UserID);
modelBuilder.Entity<User>().HasMany(t => t.Tags).WithRequired(u => u.Users);
modelBuilder.Entity<User>().HasMany(c => c.Comments).WithRequired(u => u.Users);
modelBuilder.Entity<Post>().HasRequired(u => u.Users).WithMany(p=>p.Posts);
modelBuilder.Entity<Post>().HasMany(t => t.Tags).WithMany(p => p.Posts);
modelBuilder.Entity<Post>().HasOptional(c => c.Comments);
modelBuilder.Entity<Comment>().HasRequired(u => u.Users);
modelBuilder.Entity<Comment>().HasRequired(p => p.Posts);
modelBuilder.Entity<Tag>().HasRequired(u => u.Users);
modelBuilder.Entity<Tag>().HasMany(p => p.Posts).WithMany(t => t.Tags);
Model - User
[ScaffoldColumn(true)]
[Key]
public int UserID { get; set; }
[StringLength(15)]
[DisplayName("First Name")]
[Required(ErrorMessage="First Name is Required")]
public string FirstName { get; set; }
[StringLength(15)]
[DisplayName("Last Name")]
[Required(ErrorMessage = "Last Name is Required")]
public string LastName { get; set; }
[DataType(DataType.EmailAddress,ErrorMessage="please enter valid email")]
[DisplayName("Email Address")]
[Required(ErrorMessage = "Email is Required")]
[Remote("CheckUniqueEmail","User",ErrorMessage="An account with this email address already exists.")]
public string Email { get; set; }
[DataType(DataType.Password)]
[Required(ErrorMessage = "Password is Required")]
public string Password { get; set; }
[DataType(DataType.Date)]
[ScaffoldColumn(true)]
public DateTime JoiningDate { get; set; }
[DataType(DataType.Date)]
[ScaffoldColumn(true)]
public DateTime? LastActivityDate { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
Model - Post
[Key]
[ScaffoldColumn(true)]
public int PostID { get; set; }
[Required(ErrorMessage="Required")]
[StringLength(250)]
public string Title { get; set; }
[Required(ErrorMessage="Required")]
[DataType(DataType.MultilineText)]
public string Body { get; set; }
[DataType(DataType.Date)]
public DateTime DateCreated { get; set; }
[DataType(DataType.Date)]
public DateTime DateModified { get; set; }
[ScaffoldColumn(false)]
public int UserID { get; set; }
[ScaffoldColumn(false)]
public int? CommentID { get; set; }
[ScaffoldColumn(false)]
public int? TagID { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual User Users { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
Model = Comment
[Key]
[ScaffoldColumn(true)]
public int CommentID { get; set; }
[DisplayName("Your Comment")]
public string Body { get; set; }
[DataType(DataType.Date)]
[ScaffoldColumn(true)]
public DateTime DateCreated { get; set; }
[ScaffoldColumn(true)]
public int PostID { get; set; }
[ScaffoldColumn(true)]
public int UserID { get; set; }
public User User { get; set; }
public Post Posts { get; set; }
model = Tag
[Key]
[ScaffoldColumn(true)]
public int TagID { get; set; }
[StringLength(15)]
public string Name { get; set; }
[ScaffoldColumn(true)]
public int UserID { get; set; }
public User Users { get; set; }
public ICollection<Post> Posts { get; set; }
You need to post your Models here to go in to more details.But as I can see there are several issues with your model configuration.
As you said,
1 comment can have 1 user, 1 post
so what's the point of keeping colllection of users in Comment
modelBuilder.Entity<Comment>().HasRequired(u => u.Users);
it shoud be like this
modelBuilder.Entity<Comment>().HasRequired(u => u.User);
and this is also applied for Post as well.

Resources