MVC, Entity Framework Select data from multiple models - asp.net

In a ASP.NET MVC3 Razor project I have 2 Models
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Contents { get; set; }
public int Author { get; set; }
}
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
Post.Author field links to Author.Id field
In a view, I need to display list of
Post.Title
Post.Contents
Author.Name
How to display the information joining (from) both models?
Note : I guess I need to use a ViewModel and bind the view with IEnumerable List, but I have no idea how to select the data from both models

You can create a viewmodel which will have ONLY properties which u want to be displayed on view
public class PostViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Contents { get; set; }
public string AuthorName { get; set; }
}
You populate this viewmodel with your data in your controller action taking necessary joins
public ActionResult GetAuthorInfor()
{
var query = //context.Post join with context.Author
Select new PostViewModel()
{
Id = post.id,
Title = post.title,
Contents = post.contents,
AuthorName = author.authorname
}
return view(query.Single());
}
and create a typed view to render this model.

Model Post.cs:
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Contents { get; set; }
public int AuthorID { get; set; }
public virtual Author Author { get; set; }
}
Model Author.cs :
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
DBContext Class:
public class SampleDB : DbContext
{
public DbSet<Author> Authors{ get; set; }
public DbSet<Post> Posts{ get; set; }
}
I.Way(using direkt view)
you can use on View like this :
Samp.Models.SampleDB dbPosts = new Samp.Models.SampleDB();
foreach (var post in dbPosts.Posts.ToList())
{
string post_Title = post.title;
string post_Contents = post.Contents;
string author_Name = post.Author.Name;
}
II.Way (Using via Controller) -Recommended-
you can use on Controller like this :
Samp.Models.SampleDB db = new Samp.Models.SampleDB();
public ActionResult Index()
{
return View(db.Posts.ToList());
}
Using this on View:
#model IEnumerable<Samp.Models.Post>
foreach (var post in Model.Posts.ToList())
{
string post_Title = post.title;
string post_Contents = post.Contents;
string author_Name = post.Author.Name;
}

Related

Why navigation property in one to many relationship in model makes ModelState Invalid

First of all I should say my code was working fine before transferring DataAccess (Db Context & Entity classes) to class library but after transfer The value of ModelState.Isvalid return's false because the navigation property (Category) in The Review model is null.
The problem will solved by adding an nullable annotation to Category property but my question is why this problem has arisen after using class library for DataAccess.
This is my Review Model :
public class Review
{
public int Id { get; set; }
public string Author { get; set; }
[MaxLength(500)]
public string Body { get; set; }
public int Rating { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
And this is my Category Model :
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Description { get; set; }
public List<Review> Review { get; set; }
}
This is my action :
public async Task<IActionResult> AddReview(Review review)
{
if (!ModelState.IsValid) return BadRequest("Enter required fields");
await _uReviewService.AddReview(review);
TempData["message"] = "success";
return RedirectToAction("Comments");
}

generate a list of products of a category

I am developing a shop application and I need to show products of each category. The problem is each product is created from a product template which is stored in a table and each template is related to a category. here is the product model:
namespace fardashahr.Models
{
[Table("Product")]
public class ProductModel
{
public ProductModel()
{
if (Specs == null)
{
Specs = new Dictionary<string, SpecItemsModel>();
}
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public int ProductTemplateId { get; set; }
[Required]
public bool IsPublished { get; set; }
[Required]
public bool InStock { get; set; }
[Range(95, 110)]
public float SyncRate { get; set; }
public DateTime? ProductionDate { get; set; }
[Required]
public DateTime RegisterationDate { get; set; }
public string ImageName { get; set; }
public IEnumerable<string> GalleryImages { get; set; }
[NotMapped]
public Dictionary<string, SpecItemsModel> Specs { get; set; }
[ForeignKey("ProductTemplateId")]
public virtual ProductTemplateModel ProductTemplate { get; set; }
[ForeignKey("ManufacturerId")]
public virtual CodingItemModel Manufacturer { get; set; }
[ForeignKey("BrandId")]
public virtual CodingItemModel Brand { get; set; }
[ForeignKey("ModelId")]
public virtual CodingItemModel Model { get; set; }
[ForeignKey("SeriesId")]
public virtual CodingItemModel Series { get; set; }
}
}
and here is the the ProductTemplate:
namespace fardashahr.Models
{
[Table("ProductTemplate")]
public class ProductTemplateModel
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[StringLength(500)]
public string Name { get; set; }
[Required]
public int CategoryId { get; set; }
[StringLength(500)]
public string Description { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryModel Category{ get; set; }
}
}
and the controller is:
namespace fardashahr.Controllers
{
public class ProductsController : Controller
{
// GET: Products
public ActionResult Index()
{
return RedirectToAction("Index", "Home");
}
public ActionResult Category(string name)
{
//declare a list of products
List<ProductModel> productList;
using(MainModel db = new MainModel())
{
//get category id
CategoryModel category = db.Categories.Where(x => x.CategorytUrl == name).FirstOrDefault();
int catId = category.Id;
//initialize the list
productList = db.Products.Where(x => x. == catId).ToList();
}
}
}
}
finaly, what I want to know is how to initialize a list of products.
In your models, you added virtual keyword which indicates that navigation property will be automatically loaded without the need of LINQ lambda .include() expression.
Hence you can immediately access the navigation property and load the list like this;
productList = db.Products.Where(x => x.ProductTemplate.CategoryId == catId).ToList();
string categoryNameOfFirstProduct = productList.FirstOrDefault().ProductTemplate.Category.Name;
string categoryNameOfFirstProduct = productList.FirstOrDefault().ProductTemplate.Category.CategorytUrl;

ServiceStack AutoQuery join use

After reading the documentation, I am not sure but I have come to the conclusion that when creating QueryDb, you cannot choose the columns to join by? And I am under the impression, you must have DTO object to copy to? You cannot copy to a regular object or a dynamic object?
public class SampleAutoQueryDb : QueryDb<MailResponseDetailOrm, object>, ILeftJoin<MailResponseDetailOrm, MailResponseOrm> { }
Can anyone provide any insight on joining my MailResponseOrm to MailResponseDetailOrm. MailResponseDetailOrm has 5 fields namely the Email address. And I would like MailResponseOrm to be joined to it by Email as well. I also, for good measure do not want to alter either columnname. Would I have to create a custom implementation or a service to do this?
UPDATE
Here is my code as posted below:
[Alias("MailReportsDetail")]
public class MailResponseDetailOrm
{
public string Email { get; set; }
public int ID { get; set; }
[Alias("RespDate")]
public DateTime? AddedDateTime { get; set; }
[Alias("DLReport")]
public string Action { get; set; }
public string ActionDetail { get; set; }
public string IP { get; set; }
public string UserAgent { get; set; }
public string EmailReferrer { get; set; }
}
[Alias("MailReports")]
public class MailResponseOrm
{
public int ID { get; set; }
public string Email { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string Company { get; set; }
public string Contact { get; set; }
public string Country { get; set; }
[Alias("LastMail")]
public DateTime? ModifiedDateTime { get; set; }
[Alias("LastReport")]
public string Action { get; set; }
public DateTime? OptOut { get; set; }
public string Part { get; set; }
public string Phone { get; set; }
public string PostalCode { get; set; }
public string Source { get; set; }
public string State { get; set; }
public string Title { get; set; }
#region Obsolete
[Obsolete]
public string Class { get; set; }
[Obsolete]
public string IP { get; set; }
#endregion
}
public class SampleAutoQueryDb : QueryDb<MailResponseDetailOrm> { }
public class MyQueryServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
// Override with custom implementation
public object Any(SampleAutoQueryDb query)
{
var q = AutoQuery.CreateQuery(query, base.Request);
q.Join<MailResponseDetailOrm, MailResponseOrm>((x, y) => x.Email == y.Email)
// .Select<MailResponseDetailOrm, MailResponseOrm>((x, y) => new { x.ID, y.Email })
;
return AutoQuery.Execute(query, q);
}
}
Joins in AutoQuery needs to use OrmLite's Joins Reference conventions and all AutoQuery Services results are returned in a Typed DTO, which by default is the table being queried or you can use the QueryDb<From,Into> base class to return a custom result of columns from multiple joined tables.
You would need to use a Custom AutoQuery Implementation or your own Service implementation if you need customizations beyond this, e.g:
public class SampleAutoQueryDb : QueryDb<MailResponseDetailOrm> { }
public class MyQueryServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
// Override with custom implementation
public object Any(SampleAutoQueryDb query)
{
var q = AutoQuery.CreateQuery(query, base.Request);
q.Join<MailResponseDetailOrm,MailResponseOrm>((x, y) => x.Email == y.Email);
return AutoQuery.Execute(query, q);
}
}
// The query to join 2 objects on field names not specifically set in the class.
var q = Db.From<MailResponseDetailOrm>().Join<MailResponseDetailOrm>(x,y) => x.Email = y.Email);
// Run the query
var results = Db.Select(q);

How to make single view using viewmodel in asp.net mvc 4?

I have different models Image,Page & PageCategories
public class Image
{
public int ImageId { get; set; }
public string ImageTitle { get; set; }
public string ImageURL { get; set; }
}
public class Page
{
public int PageId { get; set; }
public string PageTitle { get; set; }
public string Content { get; set; }
public int PageCategoryId { get; set; }
public virtual PageCategory PageCategory { get; set; }
}
public class PageCategory
{
public int PageCategoryId { get; set; }
public string CategoryName { get; set;
public virtual ICollection<Page> Pages { get; set; }
}
DBContext Class is
class DemoContext:DbContext
{
public DbSet<PageCategory> PageCategories { get; set; }
public DbSet<Page> Pages { get; set; }
public DbSet<Image> Images { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
I am wondering how to get all the model data to the home page using ViewModel.
For Ex.:
How to get image list and Page list in home page from multiple models?
You may want something like this :
viewModel :
//Create a viewModel with all the properties that you need
public class ViewModel
{
public int ImageId { get; set; }
public string ImageTitle { get; set; }
public string ImageURL { get; set; }
public int PageId { get; set; }
public string PageTitle { get; set; }
public string Content { get; set; }
public int PageCategoryId { get; set; }
public string CategoryName { get; set; }
}
Controller :
...
using (DemoContext db = new DemoContext()){
List<ImagePageViewModel> viewData = (from p in db.Page
join pc from db.PageCategory on p.PageCategoryId equals pc.PageCategoryId
select new ViewModel(){
PageTitle=p.PageTitle,
CategoryName = pc.CategoryName
//... set every property you want
})
}
return View(viewData );
note: I didn't add Image to the query because there is no explicit relation
between Image and the others table so i let you do it.
Create another class and define all above three into it. like below
public class MyView
{
public List<Image> Images { get; set; }
public List<Page> Pages { get; set; }
public List<PageCategory> PageCategories { get; set; }
}
Controller Action:-
public ActionResult Index()
{
MyView myView = // Get it using your logic
return View(myView);
}
finally got my answer:
public class ViewModelDemo
{
public IEnumerable<Image> images { get; set; }
public IEnumerable<Pages> pages { get; set; }
public IEnumerable<PageCategory> pagecategories { get; set; }
}
Then in HomeController
private DemoContext db=new DemoContext();
public ActionResult Index()
{
ViewModelDemo vm = new ViewModelDemo();
vm.images = db.Images.ToList();
vm.pages=db.Pagess.ToList();
vm.pagecategories=db.PageCategories.ToList();
return View(vm);
}

How to Update model and database with code first approach in Asp.net MVC

I'm new to mvc. I've creted an MVC app, in which i have used code first approach. Right now i have two tables Deal and Comment. Now i want to add a new table Category in the database and new column categoryId in Deal table.
How i can update database and model?
I'm using Sql Server 2008 R2 for Database.
I've following structure of class:
namespace FBWebApp.Models
{
public class Deal
{
public int ID { get; set; } // ID
public string Title { get; set; } // Titolo del deal
public string Description { get; set; } // Descrizione dell'annuncio
public string FacebookUID { get; set; } // UID facebook dell'utente
public string Visibility { get; set; } // Visibility
public string Category { get; set; }
public int Option1 { get; set; }
public int Option2 { get; set; }
public int Option3 { get; set; }
public int Option4 { get; set; }
public string PhotoURL { get; set; } // URL of the facebook photo profile
public string Name { get; set; } // Name of the user
public string ProfileUrl { get; set; } // URL of the facebook profile
public string Photo1 { get; set; } // URL of the Photo1 (local )
public string Photo2 { get; set; }
public string Photo3 { get; set; }
public string Photo4 { get; set; }
public string Photo5 { get; set; }
}
public class Comment
{
[Key]
public int CommentId { get; set; }
public string CommentText { get; set; }
public int ID { get; set; }
[ForeignKey("ID")]
public Deal DelNav { get; set; }
}
public class DealDBContext : DbContext
{
public DealDBContext() : base("DealDBContext") { }
public DbSet<Deal> Deals { get; set; }
public DbSet<Comment> Comments { get; set; }
}
}
Try using 'update-database -force -verbose' in the Package Manager Console.
If it doesn't work, modify the migration but typing 'add-migration somename' and it will apear in the Migrations folder.
If you are new to MVC and EF, definitely check out this tutorial. It explains all about that and everything else you need to know:
http://pluralsight.com/training/Player?author=scott-allen&name=mvc4-building-m1-intro&mode=live&clip=0&course=mvc4-building
first add your model :
public class Category
{
public int ID { get; set; }
public int cateName { get; set; }
}
in Deal class :
public class Deal
{
//..
[ForeignKey("CatId")]
public virtual Category Category { get; set; }
}
after Enable Migration you should use this command in console manager to update your database :
update-database

Resources