Could somebody please provide an example of how to combine two models within one view?
Currently I have a page called RecordCard which contains:
#model IEnumerable<WebApplication1.Models.Weight>
This is provided by the following code in the AccountController:
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
return View(weightModel);
}
The RecordCard page also contains a form which is bound to the following class:
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
However, these are two individual models with different purposes, so how do I combine to a single model that contains an IEnumerable list and set of form elements that will ultimately post to the AccountController correctly to add a record to the database using the following code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(Weight Model)
{
if (ModelState.IsValid)
{
using (WebApplication1Entities db = new WebApplication1Entities())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return View(Model);
}
I have included the Weight class below:
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
Also here is the WebApplication1Entities class which declares the Weight table as Weights:
public partial class WebApplication1Entities : DbContext
{
public WebApplication1Entities()
: base("name=WebApplication1Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Weight> Weights { get; set; }
}
Please explain what needs to be modified and how, no matter what I try to read, follow and implement, I seem to be missing something.
Any help would be much appreciated :-)
I would say this is good example of using ViewModel here. I would suggest something like -
Create ViewModel with the composition of the two classes
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
....
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
.....
public class WeightViewModel
{
public IList<AddWeightModel> AddWeightModel { get; set; }
public Weight Weight { get; set; }
}
Then change your view to accept the view models -
#model WeightViewModel
Finally modify your controller to cope with the change -
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
var viewModel = new WeightViewModel
{
Weight = weightModel,
AddWeightModel = new List<AddWeightModel>(){}
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(WeightViewModel viewModel)
{
Weight Model = viewModel.Weight;
if (ModelState.IsValid)
{
using (WebApplication1Entities db = new WebApplication1Entities())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return RedirectToAction("RecordCard");
}
I've tackled this before, can came to an elegant solution.
First, you'd want to setup your main classes to send, as well as a 'holder' class to store them to eventually send to a view.
As you probably found out, this is because a view can't have multiple models sent to it.
public class WebsiteTheme
{
public string Color { get;set; }
public string Title { get;set; }
public WebsiteTheme() {
Color = "blue";
Title = "test website";
}
}
public class User
{
public string Name { get;set; }
public string Gender { get;set; }
public User() {
Name = "Anonymous";
Gender = "Unspecified";
}
}
public class ToPage
{
public WebsiteTheme WebsiteTheme{ get; set; }
public User User { get; set; }
public ToPage() {
websiteTheme = new WebsiteTheme();
user = new User();
}
}
This will allow you to send any amount of classes to your page.
Then, in your controller, you'd want to populate those classes. Make sure to initialise them all first, then set the populated classes to your holder class.
WebsiteTheme websiteTheme = new WebsiteTheme();
websiteTheme.Color = "orange";
User user = new User();
user.Name = "Darren";
ToPage toPage = new ToPage();
toPage.User = user;
toPage.WebsiteTheme = websiteTheme;
return View(toPage);
In your view, you'd call them in any way you want to. But make sure to use HolderModel.SpecifiedModel in every case.
#model WebApplication1.Models.ToPage
#Html.DisplayFor(model => model.User.Name)
I did a compound model like this:
public class CompoundModel
{
public SearchModel SearchModel { get; set; }
public QueryResultRow ResultModel { get; set; }
}
public class QueryResultRow
{
[DisplayName("Id")]
public long id { get; set; }
[DisplayName("Importdatum")]
public System.DateTime importdate { get; set; }
[DisplayName("Mandant")]
public int indexBMClient { get; set; }
}
public class SearchModel
{
[Required]
[DataType(DataType.Date)]
[Display(Name = "Zeitraum von")]
public DateTime dateFrom { get; set; }
[Display(Name = "Terminal-ID")]
public string tid { get; set; }
[Display(Name = "Belegnummer")]
public string receiptnumber { get; set; }
}
In the view header:
#model MyProject_aspmvc.Models.CompoundModel
And get data access from the SearchModel, for example:
model => model.SearchModel.tid
and data access from the ResultModel, for example:
model => model.ResultModel.importdate
Related
I have a model class
namespace myapp.Models
{
public class SubjectModels
{
[Key]
public int SubjectId { get; set; }
[Required]
public int SubjectType { get; set; }
[Required]
[MinLength(5)]
public string SubjectName { get; set; }
}
}
Here, SubjectType = 1 for Optional and SubjectType = 2 for Compulsory
Now in another class I have to create a drop down for this class,
namespace myapp.Models
{
public class SelectionModels
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int SelectionId { get; set; }
[Required]
[MinLength(5)]
public string SelectionDate { get; set; }
[ForeignKey("SubjectId")]
public SubjectModels Subject { get; set; }
public int SubjectId { get; set; }
}
}
When I genereted controller and create.cshtml via scaffolding, my create controller method:
public ActionResult Create()
{
ViewBag.SubjectId = new SelectList(db.Subjects, "SubjectId", "SubjectName");
return View();
}
But I have to create a drop down concatenating the fields "SubjectName" and "SubjectType". Also, display for SubjectType should be Optional and Compulsory not integer.
for example,
"Optional - ResearchMethodology"
"Compulsory - BioChemistry"
How shall I do this? I googled but could not found suitable solutions. Please help!!!
I would create an extra property in the SubjectModels class.
class SubjectModels
{
public int SubjectId { get; set; }
public int SubjectType { get; set; }
public string SubjectName { get; set; }
public string SubjectNameAndType
{
get
{
return string.Format("{0} - {1}", SubjectName, SubjectType);
}
}
}
Then in the Controller you can use that property to fill the SelectList
var list = new List<SubjectModels>()
{
new SubjectModels()
{
SubjectType = 1,
SubjectName = "Name 1"
},
new SubjectModels()
{
SubjectType = 2,
SubjectName = "Name 2"
}
};
ViewBag.SubjectId = new SelectList(list, "SubjectId", "SubjectNameAndType");
Now you will see the correct values in the DropDownList.
#Html.DropDownListFor(m => m.MyValue, (SelectList)ViewBag.SubjectId, "Select...")
I have code in controller that write data from View to table
Here is code
[HttpGet]
public ActionResult WelcomeScreen()
{
// Формируем список команд для передачи в представление
SelectList teams = new SelectList(db.Vacancy, "VacancyId", "VacancyName");
ViewBag.Teams = teams;
SelectList teams2 = new SelectList(db.Companies, "CompanyID", "CompanyName");
ViewBag.Teams2 = teams2;
return View();
}
[HttpPost]
public ActionResult WelcomeScreen(Interview interview)
{
db.Interview.Add(interview);
db.SaveChanges();
int id = interview.Interview_Id;
return RedirectToAction("Index", "Questions");
}
Here is model
[Key]
public int Interview_Id { get; set; }
public string Greeting { get; set; }
public string Detail { get; set; }
public Nullable<int> VacancyId { get; set; }
public virtual Vacancy Vacancy { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Interwier> Interwiers { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<InvitationMail> InvitationMails { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<MassLink> MassLinks { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<QuestionBlock> QuestionBlocks { get; set; }
}
I need to have Interview_Id
I try to make it like this, but it not works int id = interview.Interview_Id;
How I can write id to variable?
If I understood your question right. You might have something like this.
public DbSet<Interview> Interviews {get; set;}
Rename Interview_Id to simply Id or InterviewId (no underscore).
public class Interview
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int InterviewId { get; set;}
// other properties
}
DAL Method.
public int Add(Interview inteview)
{
using(DbContext entities = new DbContext()
{
entities.Interviews.Add(interview);
entities.SaveChanges();
var id = interview.InterviewId;
return id;
}
}
From your Controller.
[HttpPost]
public ActionResult WelcomeScreen(Interview interview)
{
Dal dalObj = new Dal();
var inteviewId = dal.Add(interview);
//use this id
}
Hope this helps.
You can try this.
[HttpPost]
public ActionResult WelcomeScreen(Interview interview)
{
db.Interview.Add(interview);
db.SaveChanges();
int id = db.Interview.Max(x=>x.Interview_Id);
return RedirectToAction("Index", "Questions");
}
check you dbml
make sure you have this attribute set correctly
AutoSync=AutoSync.OnInsert
the full attribute usually like this
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true, UpdateCheck=UpdateCheck.Never)]
This is an ASP.NET MVC4 project with Entity Framework.
I need to use 2 tables in single view
I have 2 tables in my database (Budgets and Products).
My Models
Budget.cs
public class Budget
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Product> Products { get; set; }
}
Product.cs
public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public decimal Value { get; set; }
public int BudgetId { get; set; }
}
BpDb
public class BpDb:DbContext
{
public DbSet<Budget> Budgets { get; set; }
public DbSet<Product> Products { get; set; }
}
MasterBP
public class MasterBP
{
public int Id { get; set; }
public string Title { get; set; }
public List<Product> ProdName { get; set; }
public int CountOfValues { get; set; }
}
I need something about Controller to get ProdName (Title from table products)
public class HomeController : Controller
{
BpDb _db = new BpDb();
public ActionResult Index()
{
var model=_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).ToList(),
CountOfValues = r.Products.Count()
});
return View(model);
}
}
I need a way to get a list of products Title when the BudgetId = ID (1 Budget can have more than 1 Products)
And my Index is like:
#model IEnumerable<MvcGg.Models.MasterBP>
#foreach (var item in Model)
{
<div>
<h4>#item.Title</h4>
#foreach (var product in item.ProdName)
{
#(product.Title.ToString());
}
Values:#item.CountOfValues
</div>
}
It sounds like (correct me if I am wrong) you want to access two sets of entities in your view model?
Then something along these lines will do:
public class BudgetsViewModel
{
public IEnumerable<MasterBP> MasterBps { get;set; }
public IEnumerable<Product> Products { get;set;}
}
And then you just retrieve all the data and populate the viewmodel and pass it down.
...
var budgets =_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).ToList(),
CountOfValues = r.Products.Count()
});
var model = new BudgetsViewModel()
{
MasterBps = budgets
//Products here
}
return View(model);
...
However it would be better if you made some form of service layer to handle the retrieving on entities and the mapping to view models instead of having all this logic in your controller.
finally this solve my problem,
Model:
MasterBP
public class MasterBP
{
public int Id { get; set; }
public string Title { get; set; }
public IEnumerable<Product> ProdName { get; set; }
public int CountOfValues { get; set; }
}
I replaced List<> with IEnumerable<>
Controller:
public ActionResult Index()
{
var model=_db.Budgets
.Select(r=>new MasterBP
{
Id = r.Id,
Title = r.Title,
ProdName = r.Products.Where(s => s.BudgetId == r.Id).AsEnumerable(),
CountOfValues = r.Products.Count()
});
return View(model);
}
In addition i have change ToList() in AsEnumerable() and now i can see my result using this
View:
Index
#foreach (var item in Model)
{
<div>
#item.Title
<ul>
#foreach (var prod in item.ProdName)
{
<li>#prod.Title</li>
}
</ul>
<hr />
</div>
}
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;
}
I am trying to understand why my Html.ListBoxFor() is not highlighting current selected items when the view loads.
I have a database model:
public class Issue
{
[Key]
public int IssueId { get; set; }
public int Number { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
public virtual ICollection<Creator> Creators { get; set; }
}
public class Creator
{
[Key]
public int CreatorId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Issue> Issues { get; set; }
}
public class Icbd : DbContext
{
public DbSet<Issue> Issues { get; set; }
public DbSet<Creator> Creators { get; set; }
}
I then have an editing model:
public class IssueEditModel
{
public Issue Issue { get; set; }
public IEnumerable<Creator> Creators { get; set; }
public IEnumerable<Creator> SelectedCreators { get {return Issue.Creators;} }
}
Then, in my controller I populate IssueEditModel:
public ActionResult EditIssue( int id = 0 )
{
IssueEditModel issueEdit = new IssueEditModel{
Creators = db.Creators.ToList(),
Issue = new Issue{ Creators = new List<Creator>()},
};
if (id > 0)
{
issueEdit.Issue = db.Issues.Include("Creators").Where(x => x.IssueId == id).Single();
}
return View(issueEdit);
}
This populates all objects correctly (as far as I can tell, anyway.) In my View, I am writing a listbox like this:
<%: Html.ListBoxFor(
x => x.SelectedCreators,
new SelectList(
Model.Creators,
"CreatorId",
"LastName"
)
)%>
This lists all the options correctly, but I cannot get the currently select items to highlight. I almost want to write my own Html Helper because this is such a simple operation, I don't understand why this is being so difficult.
Why wont the Html Helper highlight the current items?
You need a list of scalar types as first argument to the ListBoxFor helper which will map to the creator ids that you want preselected:
public class IssueEditModel
{
public IEnumerable<Creator> Creators { get; set; }
public IEnumerable<int> SelectedCreatorIds { get; set; }
}
and then:
IssueEditModel issueEdit = new IssueEditModel
{
Creators = db.Creators,
SelectedCreatorIds = db.Creators.Select(x => x.CreatorId)
};
and in the view:
<%: Html.ListBoxFor(
x => x.SelectedCreatorIds,
new SelectList(
Model.Creators,
"CreatorId",
"LastName"
)
) %>
The example submitted by Darin is ALMOST correct, but there is a slight error. Presently, his example will preselect ALL creators! However, the desired result is to only preselect the creators associated with a particular instance of Issue.
So this:
IssueEditModel issueEdit = new IssueEditModel
{
Creators = db.Creators,
SelectedCreatorIds = db.Creators.Select(x => x.CreatorId)
};
Should be this:
IssueEditModel issueEdit = new IssueEditModel
{
Creators = db.Creators,
SelectedCreatorIds = CurrentIssue.Creators.Select(x => x.CreatorId)
};
Where CurrentIssue is an instantiation of the Issue class (presumably previously populated from the datastore).