Reputation: 359
I am trying to learn MVC and came up with a little project to figure it out. I have two models:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace reqcoll.Models
{
public class Project
{
[Key]
public int ProjectID { get; set; }
[Required]
[DataType(DataType.Text)]
[MaxLength(150, ErrorMessage = "The project name cannot be longer than 150 characters!")]
[Display(Name = "Project name:")]
public string projectName { get; set; }
[Required]
[Display(Name = "Project type:")]
public ProjectType projectType { get; set; }
public int RequirementID { get; set; }
public virtual List<Requirement> Requirements { get; set; }
}
}
and
using System.ComponentModel.DataAnnotations;
namespace reqcoll.Models
{
public class Requirement
{
[Key]
public int requirementID { get; set; }
[DataType(DataType.Text)]
[MaxLength(150, ErrorMessage = "This is a short description, it cannot be longer than 150 characters.")]
[Required]
public string shortDesc { get; set; }
[DataType(DataType.Text)]
[MaxLength(3999, ErrorMessage = "This is a short description, it cannot be longer than 150 characters.")]
[Required]
public string longDesc { get; set; }
[Required]
public int priorityCode { get; set; }
[Required]
public int OrderID { get; set; }
public int projectID { get; set; }
}
}
And I have one view:
@using reqcoll.Models;
@model Tuple<Project, IEnumerable<Requirement> >
@{
ViewBag.Title = "ReqColl - project";
}
<div class="top-spacing col-md-12 col-lg-12 col-sm-12">
<div class=" well">
@Html.ValidationSummary(true)
<div class="row">
@Html.LabelFor(tuple => tuple.Item1.projectName, htmlAttributes: new { @class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
@Html.TextBoxFor(tuple => tuple.Item1.projectName, htmlAttributes: new { @class = "ProjectNameInput" })
@Html.ValidationMessageFor(tuple => tuple.Item1.projectName)
</div>
</div>
@Html.ValidationSummary(true)
<div class="row row-spacing">
@Html.LabelFor(tuple => tuple.Item1.projectType, htmlAttributes: new { @class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
@Html.DropDownListFor(tuple => tuple.Item1.projectType, new SelectList(
new List<Object>{
new { value = 0 , text = "...Select..." },
new { value = 1 , text = "Windows application" },
new { value = 2 , text = "Web application" },
new { value = 3 , text = "Device application"}
},
"value",
"text",
0), htmlAttributes: new { @class = "DropDownList" })
@Html.ValidationMessageFor(tuple => tuple.Item1.projectType)
</div>
</div>
</div>
</div>
<div class="top-spacing col-md-6 col-lg-6 col-sm-12">
<div class=" well">
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(tuple => tuple.Item2.shortDesc)
</th>
<th></th>
</tr>
@foreach (Requirement item in (IEnumerable<Requirement>)Model.Item2)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.shortDesc)
</td>
<td>
@Html.ActionLink("E", "Edit", new { id = item.requirementID }) |
@Html.ActionLink("D", "Delete", new { id = item.requirementID })
</td>
</tr>
}
</table>
</div>
</div>
<div class="top-spacing col-md-6 col-lg-6 col-sm-12">
<div class=" well">
</div>
</div>
When I run the website, I get an error:
CS1061: 'IEnumerable' does not contain a definition for 'shortDesc' and no extension method 'shortDesc' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)
The error is in the view on the line "@Html.DisplayNameFor(tuple => tuple.Item2.shortDesc)"
For some reason it doesn't see the property "shortDesc" in Item2. I can't figure out why not.
Any help is appreciated.
Upvotes: 0
Views: 409
Reputation: 309
The problem you are facing is that tuple.Item2 is a collection, so there is no tuple.Item2.shortDesc as you declared.
You need to do something like:
@Html.DisplayFor(tuple => tuple.Item2)
Then you will need a Display Template that will know what to render with that collection passed in.
This question has been asked before, this will lead you to the right path:
ASP.net MVC - Display Template for a collection
Upvotes: 1
Reputation: 26
The Item2
property points to IEnumerable<Requirement>
as indicated in the model
@model Tuple<Project, IEnumerable<Requirement>>
I can see that you already enumerate Item2
in this code
@foreach (Requirement item in (IEnumerable<Requirement>)Model.Item2)
and you already make a call to item.shortDesc. Is this a duplicate call?
Upvotes: 0