I have created a view that accepts a ProjectsCreatorsVM class. This class has been structured this way:
public class ProjectsCreatorsVM
{
public List<ProjectVM> ProjectsCreators { get; set; }
public ProjectsCreatorsVM(List<ProjectVM> projectsCreators)
{
ProjectsCreators = projectsCreators;
}
}
In addition, the ProjectVM follow this structure:
public class ProjectVM
{
public Project Project { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public ProjectVM(Project pro, ApplicationUser applUser)
{
Project = pro;
ApplicationUser = applUser;
}
}
Lastly, my view tries to go through the ProjectsCreators.Project but it does not seem to be possible.
<div class="card-content-container" >
#foreach (Project obj in #Model.ProjectsCreators.)
{
<div class="card">
<img class="card-img-top" src="#obj.ImgURL" alt ="project image" >
<div class="card-body d-flex flex-column">
<h5 class="card-title">#obj.Title</h5>
<h6 class="card-title">#obj.Title</h6>
<p class="card-text">
#obj.TruncatedDescription
</p>
<div class="mt-auto" style="display: flex; justify-content: space-between; align-items: center;">
View Details
</div>
</div>
</div>
I would appreciate any help. Thanks in advance.
ProjectCreators is a List and when you iterate ProjectCreators you get a ProjectVM object not a Project or ApplicaionUser instance. If you want to access Project instance add Project after #obj like #obj.Project.Title
<div class="card-content-container" >
#foreach (ProjectVM obj in #Model.ProjectsCreators.)
{
<div class="card">
<img class="card-img-top" src="#obj.Project.ImgURL" alt ="project image" >
<div class="card-body d-flex flex-column">
<h5 class="card-title">#obj.Project.Title</h5>
<h6 class="card-title">#obj.Project.Title</h6>
<p class="card-text">
#obj.Project.TruncatedDescription
</p>
<div class="mt-auto" style="display: flex; justify-content: space-between; align-items: center;">
View Details
</div>
</div>
</div>
}
</div>
To achieve what I wanted, I created another class. That looks like this:
public class ProjectAndUserVM
{
public string ProjectTitle { get; set; }
public string ProjectId { get; set; }
public string ProjectImageUrl { get; set; }
public string ProjectDescription { get; set; }
public string ProjectCreatorName { get; set; }
public string ProjectCreatorId { get; set; }
public string ProjectCreatorEmail { get; set; }
public ProjectAndUserVM(string projectTitle, string projectId, string projectImageUrl, string projectDescription, string projectCreatorName, string projectCreatorId, string projectCreatorEmail)
{
ProjectTitle = projectTitle;
ProjectId = projectId;
ProjectImageUrl = projectImageUrl;
ProjectDescription = projectDescription;
ProjectCreatorName = projectCreatorName;
ProjectCreatorId = projectCreatorId;
ProjectCreatorEmail = projectCreatorEmail;
}
}
So, basically my controller is returning that as a list which I convert to an IEnumerable. and I use that list on my view instead.
Related
I´m having an issue where I have three models as show below: Person, Competence with PersonCompetence between them. My current controller method gets an Id from previous page and shows that person with a list of this person's Competence and Level. In this View however I want to have a POST for new Competence. So at the same time you are adding a new one and you can see which ones you already have.
With the controller method I have now I can access the PersonCompetence and Competence when showing the list.
I dont have access to the Competence properties for asp-for="Competence" marked ###### in the View for AddComp.
I need the ID of person for POST to right person
I need the CompetenceType for POST to that property
I need PersonCompetence to show the list of current PersonCompetence.
I get that with the current #model CompetenceRadar.Models.Person I only reach Person properties.
I have looked at having a ViewModel with access to all tables with an IEnumerable for each table, but this breaks my current Controller when I search for the Id of the person showing. I have switched the #model in the View, but then I can't access Person ID/name.
So how do I access the Competence properties , list one person and get a list of PersonCompetences for that Person.
Please tell me if you want me to clarify something.
I don't need working code, just something to point me in the right direction for a solution.
Is it a ViewModel?
Can I POST without the asp-forattribute?
Models
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public ICollection<PersonCompetences> PersonCompetences { get; set; }
}
public class PersonCompetence
{
public int ID { get; set; }
public int PersonID { get; set; } // FK
public int CompetenceID { get; set; } // FK
public int Level { get; set; }
public Competece Competence { get; set; }
public Person Person { get; set; }
}
public class Competence
{
public int ID { get; set; }
public string CompetenceType { get; set; }
public string CompetenceCategory { get; set; }
public ICollection<PersonCompetence> PersonCompetences { get; set; }
}
AddComp Kontroller function
public async Task<IActionResult> AddComp(int? id)
{
var person = await _context.Personer
.Include(pk => pk.PersonCompetences)
.ThenInclude(k => k.Competence)
.FirstOrDefaultAsync(m => m.ID == id);
return View(person);
}
View_AddComp View for AddComp
#model CompetenceRadar.Models.Person
<h1>AddComp</h1>
<div class="row">
<form asp-action="AddComp">
<input type="hidden" asp-for="ID" />
<div class="form-group col-sm-4">
<label asp-for="#############" class="control-label col-sm-4"></label>
<input asp-for="#############" class="form-control col-sm-4" />
<span class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-dark" />
</div>
</form>
</div>
#foreach (var item in Model.PersonCompetences)
{
<div class="row py-2 rounded" style="background-color:lightslategray">
<div class="col-sm-3 pt-2">#item.Competence.CompetenceType</div>
<div class="col-sm-1 pt-2">#item.Niva</div>
<div class="col-sm-3 pt-2">#item.Competence.CompetenceCategory</div>
<div class="col-sm-5 d-flex justify-content-end">
<a class="btn btn-dark mr-1" role="button" asp-area="" asp-controller="Competence" asp-action="UpdateLevel" asp-route-id="#item.ID">Update</a>
<a class="btn btn-dark mr-1" role="button" asp-area="" asp-controller="Competence" asp-action="DeleteComp" asp-route-id="#item.CompetenceID">Remove</a>
</div>
</div>
}
Simple anwser is that I needed a ViewModel with all three Models
public class ExampleViewModel {
public Person person { get; set; }
public PersonCompetence personCompetence { get; set; }
public Competence competence { get; set; }}
This alows me to access the different values for ID, CompetenceType and a List for of the current PersonCompetence.
What is ViewModel in MVC?
As I am new to an ASP.NET Core 2.0 MVC I have a little demo app where I want to add a new entity of Type Lineup which has a ICollection of type Player in its model.
The involved classes are
public class Lineup
{
public int LineupID { get; set; }
public int PlayerID { get; set; }
public ICollection<Player> Attendants { get; set; }
}
and
public class Player
{
public int PlayerID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
My Create Lineup view looks like this
<form asp-action="Create">
<div class="form-horizontal">
<h4>Lineup</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Attendants" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="Attendants" class="form-control"
asp-items="ViewBag.Players" multiple="multiple">
</select>
</div>
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
The ViewBag.Players is part of the LineupsController:
private void PopulatePlayersDropDownList(object selectedPlayer = null)
{
var playersQuery = from p in _context.Player
orderby p.Name
select p;
ViewBag.Players = new SelectList(playersQuery.AsNoTracking(), "PlayerID",
"Name", selectedPlayer);
}
That's how it looks so far:
but inside my Create method
public async Task<IActionResult> Create([Bind("Attendants")] Lineup lineup)
{
if (ModelState.IsValid)
{
_context.Add(lineup);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(lineup);
}
the Attendants count of the Lineup entity is 0 and not 2 as expected from the sample above. What is wrong here? Thanks for any help.
You need to instantiate your property when you create the object. Otherwise, the property is the default, which is null:
public class Lineup
{
public int LineupID { get; set; }
public int PlayerID { get; set; }
public ICollection<Player> Attendants { get; set; } = new List<Player>();
}
ok, these 2 steps solved my problem:
see answer of krillgar
changing the method signature of Create to
public async Task Create(int[] PlayerIDs)
{
...
}
I want to be able to retrieve values from the database from a
specific user, which in this case #Model.user.Xp, it does not work, I
just get 0.
#model TheQuizR.Models.IndexViewModel
#using Microsoft.AspNet.Identity
<div class="row">
<div class="col-sm-6 col-md-6">
<ul class="list-group">
<div class="blue">
#User.Identity.GetUserName()<br />
</div>
<li class="list-group-item">
Title
<span class="badge">#Model.user.Xp</span>
</li>
<li class="list-group-item">
In the IndexViewModel I have this:
public class IndexViewModel
{
public ApplicationUser user = new ApplicationUser();
public bool HasPassword { get; set; }
public IList<UserLoginInfo> Logins { get; set; }
public string PhoneNumber { get; set; }
public bool TwoFactor { get; set; }
public bool BrowserRemembered { get; set; }
}
In the ApplicationUser class I have all the properties:
public class ApplicationUser : IdentityUser
{
[MaxLength(128)]
public string Title { get; set; }
[Range(0, 5000000)]
public int Xp { get; set; }
[Range(0, 100000)]
}
I cant get the id and the username thru Microsoft.AspNet.Identity (the one mark in yellow). I can't get all the other properties.
I would recommend to find the user in controller. Then you can create another model or use Viewbag.
string username = User.Identity.GetUserName();
var user = db.Users.First(u => u.UserAD == username);
ViewBag.userIDconnected = user.ID;
View -
<div class="row">
<div class="col-sm-6 col-md-6">
<ul class="list-group">
<div class="blue">
</div>
<li class="list-group-item">
Title
<span class="badge">#ViewBag.userIDconnected</span>
</li>
<li class="list-group-item">
I was trying to use Html Display For Template for looping through a Model data. Inside my Display template, I wanted to use an EditorFor template that would display a different set of data, In doing so, I was running into issues where my child model was empty. Upon playing around and getting guidance from David, I was able to make this to work. Below, please find my updated working solution.
UPDATE (Correct solution)
public class TargetingAreaViewModel
{
public int DealerId { get; set; }
public int OrderId { get; set; }
public List<TargetingAreaOrderItemViewModel> TargetingAreaOrderItems { get; set; }
public TargetingAreaViewModel()
{
this.TargetingAreaOrderItems = new List<TargetingAreaOrderItemViewModel>();
}
}
public class TargetingAreaOrderItemViewModel
{
public int OrderItemId { get; set; }
public int PackageMediaTypeId { get; set; }
public string PackageMediaTypeHeader { get; set; }
public string MediaTypeDesc { get; set; }
public string TargetingAdditonalInfo { get; set; }
public List<TargetingAreaItemViewModel> TargetingAreaItems { get; set; }
public TargetingAreaOrderItemViewModel()
{
this.TargetingAreaItems = new List<TargetingAreaItemViewModel>();
}
}
public class TargetingAreaItemViewModel
{
public int OrderItemId { get; set; }
public int PackageMediaTargetingFieldId { get; set; }
public string TargetingAreaFieldTitle { get; set; }
public string TargetingValue { get; set; }
public bool IsEnabled { get; set; }
public bool IsRequired { get; set; }
public string Comment { get; set; }
}
Parent View
#model Models.TargetingAreaViewModel
#{
ApplicationContext.Current.PageTitle = "Targeting Info";
Layout = "~/Views/Shared/MainLayout.cshtml";
}
#using (Html.BeginForm("OrderItemTargetingInfo", "Home", FormMethod.Post, new { #class = "form-horizontal" }))
{
#Html.DisplayFor(m => m.TargetingAreaOrderItems)
<div class="col-sm-12">
<div class="pull-right">
<input id="Submit" type="submit" value="Submit" class="btn btn-primary" />
</div>
</div>
}
DisplayFor Template View
#model Models.TargetingAreaOrderItemViewModel
<div class="row">
<div class="col-sm-12">
<div class="col-sm-12 btn-primary" style="margin-bottom: 10px; margin-top: 10px;">
#Html.Label(Model.MediaTypeDesc, new { #style = "font-weight: bold; padding-top: 10px; font-size: 18px;" })
#Html.HiddenFor(m => m.OrderItemId)
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
#Html.Raw(Model.PackageMediaTypeHeader)
</div>
</div>
<br />
<div class="row">
<div class="col-sm-12">
#Html.EditorFor(m => m.TargetingAreaItems)
</div>
</div>
<br />
<div class="row">
<div class="col-md-12">
<div class="form-group">
#Html.Label("Additional Info:", new { #class = "control-label col-md-2" })
<div class="col-md-6">
#Html.TextAreaFor(m => m.TargetingAdditonalInfo, new { #class = "form-control" })
</div>
</div>
</div>
</div>
Now, I am able to display the data, get the data out of my model on Post. Works great!!
In your parent views you are only passing in the TargetingAreaOrderItems of the model but the child view is expecting a TargetingAreaViewModel. Instead you should pass in the entire model:
#Html.DisplayFor(m => m)
I am trying to add datas to two different tables using same view and controller. But I am stuck. I am new at MVC, please let me know what did I wrong.Dto Model, Controller, Facade, Servicei,View and Entity Model as follows.
I get this Error
The model item passed into the dictionary is of type 'LibOrganizerEntity.Entity.OrgProje', but this dictionary requires a model item of type 'LibOrganizerSvc.Dto.ProjeEkleDto'.
Entity Models
[Table("KAR_PROJE")]
public class OrgProje
{
[Key, Required]
[Column("SIRA_NO")]
public int ID { get; set; }
[Column("ACIKLAMA")]
public string Aciklama { get; set; }
[Column("PLANLANAN_BASLANGIC_TARIHI")]
public DateTime? PlanlananBaslangicTarihi { get; set; }
[Column("PLANLANAN_BITIS_TARIHI")]
public DateTime? PlanlananBitisTarihi { get; set; }
[Column("GERCEKLESEN_BASLANGIC_TARIHI")]
public DateTime? GerceklesenBaslangicTarihi { get; set; }
[Column("GERCEKLESEN_BITIS_TARIHI")]
public DateTime? GerceklesenBitisTarihi { get; set; }
[Column("SILINME_TARIHI")]
public DateTime? SilinmeTarihi { get; set; }
[Column("YONETICI_ID")]
public int? YoneticiId { get; set; }
[ForeignKey("YoneticiId")]
public virtual OrgPersonel OrgPersonel { get; set; }
public virtual OrgProjeButce OrgProjeButce { get; set; }
public virtual OrgButce Butce { get; set; }
}
[Table("KAR_PROJE_BUTCE")]
public class OrgProjeButce
{
[Key, Required]
[Column("ID")]
public int ID { get; set; }
[Column("BUTCE_ID")]
public int ButceId { get; set; }
[Column("BUTCE_TUTAR")]
public float ButceTutar { get; set; }
[Column("GERCEKLESEN")]
public float? Gerceklesen { get; set; }
[ForeignKey("ButceId")]
public virtual OrgButce OrgButce { get; set; }
}
Dto Model
public class ProjeEkleDto
{
public string Aciklama { get; set; }
public DateTime? PlanlananBaslangicTarihi { get; set; }
public DateTime? PlanlananBitisTarihi { get; set; }
public DateTime? GerceklesenBaslangicTarihi { get; set; }
public DateTime? GerceklesenBitisTarihi { get; set; }
public DateTime? SilinmeTarihi { get; set; }
public string YoneticiAdi { get; set; }
public string YoneticiSoyadi { get; set; }
public string YoneticiId { get; set; }
public int ButceId { get; set; }
public string ButceAdi { get; set; }
public float ProjeButceTutari { get; set; }
public virtual IEnumerable<OrgPersonel> Proje { get; set; }
public virtual IEnumerable<OrgProjeButce> Butce { get; set; }
}
Controller
public ActionResult ProjeEkle()
{
return View();
}
[HttpPost]
public ActionResult ProjeEkle(OrgProje model)
{
try
{
svc.ProjeEkle(model);
return RedirectToAction("Index", "Home");
}
catch(Exception ex)
{
}
return View(model);
}
Service
public void ProjeEkle(OrgProje proje)
{
var dto = new ProjeFacade(db);
dto.ProjeEkle(proje);
}
Facade
public void ProjeEkle(OrgProje proje)
{
db.OrgProjeler.Add(proje);
db.SaveChanges();
}
View
#model LibOrganizerSvc.Dto.ProjeEkleDto
#{
ViewBag.Title = "ProjeEkle";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
<div class="row">
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Proje Ekle</h4>
</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-6">
<h4 class="heading_a">Proje Detayları</h4>
<div class="form-group" style="width: 47%; float: left">
<label for="reg_input">Proje Adı</label>
<input type="text" id="#Html.IdFor(x => x.Aciklama)" class="form-control">
</div>
<div class="form-group" style="width: 47%; float: right;">
<label for="reg_input">Proje Yöneticisi</label>
<select id="#Html.IdFor(x => x.YoneticiId)" name="chn_country" class="form-control">
#Html.Action("_PersonelleriGetir", "Ortak")
</select>
</div>
<div class="form-group" style="width: 47%; float: right;">
<label for="reg_input">Proje Bütçe Türleri</label>
<select id="#Html.IdFor(x => x.ButceAdi)" name="#Html.IdFor(x => x.ButceAdi)" class="form-control">
#Html.Action("_ButceleriGetir", "Ortak")
</select>
</div>
<div class="col-sm-6" style="padding-left: 0;">
<label for="reg_input">Proje Bütçesi</label>
<input type="text" id="#Html.IdFor(x => x.ProjeButceTutari)" class="form-control" name="#Html.IdFor(x => x.ProjeButceTutari)">
<span class="help-block">2000 ₺</span>
</div>
</div>
<div class="col-sm-6">
<h4 class="heading_a">Proje Zaman Ayarları</h4>
</div>
<div class="col-sm-3">
<label for="reg_input">Planlanan Başlama Tarihi</label>
<div class="input-group date ebro_datepicker" data-date-format="dd-mm-yyyy" data-date-autoclose="true">
<input class="form-control" type="text" id="#Html.IdFor(x => x.PlanlananBaslangicTarihi)">
<span class="input-group-addon"><i class="icon-calendar"></i></span>
</div>
</div>
<div class="col-sm-3">
<label for="reg_input">Planlanan Bitiş Tarihi</label>
<div class="input-group date ebro_datepicker" data-date-format="dd-mm-yyyy" data-date-autoclose="true">
<input class="form-control" type="text" id="#Html.IdFor(x => x.PlanlananBitisTarihi)">
<span class="input-group-addon"><i class="icon-calendar"></i></span>
</div>
</div>
<div class="col-sm-3">
<label for="reg_input" style="margin-top: 15px;">Gerçekleşen Başlama Tarihi</label>
<div class="input-group date ebro_datepicker" data-date-format="dd-mm-yyyy" data-date-autoclose="true">
<input class="form-control" type="text" id="#Html.IdFor(x => x.GerceklesenBaslangicTarihi)">
<span class="input-group-addon"><i class="icon-calendar"></i></span>
</div>
</div>
<div class="col-sm-3">
<label for="reg_input" style="margin-top: 15px;">Gerçekleşen Bitiş Tarihi</label>
<div class="input-group date ebro_datepicker" data-date-format="dd-mm-yyyy" data-date-autoclose="true">
<input class="form-control" type="text" id="#Html.IdFor(x => x.GerceklesenBitisTarihi)">
<span class="input-group-addon"><i class="icon-calendar"></i></span>
</div>
</div>
<div style="float: left; margin-top: 20px; width: 90%; position: relative; left: 15px;">
<input type="submit" class="btn btn-default btn-lg" value="Kaydet" />
</div>
</div>
</div>
</div>
</div>
</div>
}
As the error message indicates, you are passing a class of type OrgProje to a view that requires a view of type ProjeEkleDto.
Your error occurs in this action method:
[HttpPost]
public ActionResult ProjeEkle(OrgProje model)
{
try
{
svc.ProjeEkle(model);
return RedirectToAction("Index", "Home");
}
catch(Exception ex)
{
}
return View(model); // Passing a view model of the wrong type to the view
}
Either pass a view model of type ProjeEkleDto back to the view instead of your model of type OrgProje, or create a different view that accepts a view model of type OrgProje.
In your view Change -
#model LibOrganizerSvc.Dto.ProjeEkleDto
to
#model NameSpace.ProjeEkleDto
I am not sure about which namespace to be used, but you replace NameSpace with appropriate one.