Link to home
Start Free TrialLog in
Avatar of wdarnellg
wdarnellgFlag for United States of America

asked on

MVC-5: Show Full Names

I would like to show a FullName from a computed property at the top of a view. I can see the FullName property when I look at the Autos log. But the lambda expression used in the Html helper only shows the property name, not the data. Is there any way to display the data that the log seems to show to be available?

The View:
            <div class="container">

                
                @using (Html.BeginForm("Index", "Attendances", FormMethod.Get))
                {
                    
                    <div class="row">
                        <div class="col-md-4">
                            <p>
                                <h3>Attendances for player: @Html.DisplayNameFor(model => model.FullName) </h3>
                            </p>
                        </div>
                        <div class="col-md-4">
                            <p>
                                <h4>Attendances Recorded: @Model.Count() </h4>
                            </p>
                            </div>
                            
                        </div>
                }

            </div>

Open in new window


The controller:
        public ActionResult Index(int? Id )
        {
            //Get the rosters and their attendance records
            IQueryable<Attendances> attendances = db.Attendances
                .Where(a => a.Enrollments_Attendance == Id)
                .Include(e => e.Enrollments.Individuals)
                .OrderByDescending(a => a.AttendanceDate);

            ViewBag.EnrollmentId = Id;
            
            var sql = attendances.ToString();
            return View(attendances.ToList());
        } 

Open in new window


The debugger's Auto Log:
User generated image
The browser view:
User generated image
Avatar of Miguel Oz
Miguel Oz
Flag of Australia image

Can you post the model definition in the view (@model)?
Your controller is returning a list. The list itself does not seem to contain FullName property, thus this property value can not be displayed,
Note: Assuming that the model is a list then you should access the first element full name by providing an index  as shown below:
@Html.DisplayNameFor(ml => m[0].FullName)

Open in new window

Avatar of wdarnellg

ASKER

The Attendances model:

    public class Attendances
    {
        public int Id { get; set; }

        [Required]
        [StringLength(15)]
        public string Type { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
        public DateTime AttendanceDate { get; set; }

        [StringLength(255)]
        public string Comments { get; set; }

        [Display(Name="Enrollments")]
        public int Enrollments_Attendance { get; set; }

        public virtual Enrollments Enrollments { get; set; }

        [NotMapped]
        public string FullName
        {
            get
            {
                var player = Enrollments.Individuals.FirstName + " " + Enrollments.Individuals.LastName;
                return player;
            }
        }
    }

Open in new window

Actually I need the complete View (especially the model definition).
Notice that the controller is sending a List of Attendances, need to check how the view is set up.  Thanks.
The complete View:

@model IEnumerable<SlamJammersData.Model.Attendances>

@{
    ViewBag.Title = "Rosters";
}

<div class="container container-fluid">
    <div class="panel panel-info">
        <div class="panel-body">
            <div class="container">

                
                @using (Html.BeginForm("Index", "Attendances", FormMethod.Get))
                {
                    
                    <div class="row">
                        <div class="col-md-4">
                            <p>
                                <h3>Attendances for player: @Html.DisplayNameFor(model => model.FullName) </h3>
                            </p>
                        </div>
                        <div class="col-md-4">
                            <p>
                                <h4>Attendances Recorded: @Model.Count() </h4>
                            </p>
                            </div>
                            
                        </div>
                }

            </div>
        </div>
            </div>
        </div>

        <div class="container">
            <div class="row">
                <div class="col-md-2">
                    <p>
                        @Html.DisplayNameFor(model => model.Type)
                    </p>
                </div>
 
                <div class="col-md-2">
                    <p>
                        @Html.DisplayNameFor(model => model.AttendanceDate)
                    </p>
                </div>
            
                <div class="col-md-2">
                    <p>
                        @Html.DisplayNameFor(model => model.Comments)
                    </p>
                </div>
            </div>
           @foreach (var item in Model)
           {
               <div class="row table-striped">
                   <div class="col-md-2">
                       <p>
                           @Html.DisplayFor(modelItem => item.Type)
                       </p>
                   </div>
 
                   <div class="col-md-2">
                       <p>
                           @Html.DisplayFor(modelItem => item.AttendanceDate)
                       </p>
                   </div>

                   <div class="col-md-2">
                       <p>
                           @Html.DisplayFor(modelItem => item.Comments)
                       </p>
                   </div>

                   <div class="col-md-1">
                       <p>
                           <input class="btn btn-xs btn-info" type="button" value="Details" onclick=" location.href = '@Url.Action("Details", "Attendances", new {id = item.Id}, null)' "/>
                       </p>
                   </div>

                   <div class="col-md-1">
                       <p>
                           <input class="btn btn-xs btn-info" type="button" value="Edit" onclick=" location.href = '@Url.Action("Edit", "Attendances", new {id = item.Id}, null)' "/>
                       </p>
                   </div>
                   <div class="col-md-2">
                       <p>
                           <input class="btn btn-xs btn-success" type="button" value="Add New Attendance" onclick=" location.href = '@Url.Action("Create", "Attendances", new {enrollments_Attendance = item.Enrollments_Attendance}, null)' "/>
                       </p>
                   </div>
                   <div class="col-md-1">
                       <p>
                           <input class="btn btn-xs btn-danger" type="button" value="Delete" onclick=" location.href='@Url.Action("Delete", "Attendances", new {id = item.Id}, null)' " />
                       </p>
                   </div>
               </div>
               

           }
            
        </div>

Open in new window

Thanks for looking.
The complete View:

@model IEnumerable<SlamJammersData.Model.Attendances>

@{
    ViewBag.Title = "Rosters";
}

<div class="container container-fluid">
    <div class="panel panel-info">
        <div class="panel-body">
            <div class="container">

                
                @using (Html.BeginForm("Index", "Attendances", FormMethod.Get))
                {
                    
                    <div class="row">
                        <div class="col-md-4">
                            <p>
                                <h3>Attendances for player: @Html.DisplayNameFor(model => model.FullName) </h3>
                            </p>
                        </div>
                        <div class="col-md-4">
                            <p>
                                <h4>Attendances Recorded: @Model.Count() </h4>
                            </p>
                            </div>
                            
                        </div>
                }

            </div>
        </div>
            </div>
        </div>

        <div class="container">
            <div class="row">
                <div class="col-md-2">
                    <p>
                        @Html.DisplayNameFor(model => model.Type)
                    </p>
                </div>
 
                <div class="col-md-2">
                    <p>
                        @Html.DisplayNameFor(model => model.AttendanceDate)
                    </p>
                </div>
            
                <div class="col-md-2">
                    <p>
                        @Html.DisplayNameFor(model => model.Comments)
                    </p>
                </div>
            </div>
           @foreach (var item in Model)
           {
               <div class="row table-striped">
                   <div class="col-md-2">
                       <p>
                           @Html.DisplayFor(modelItem => item.Type)
                       </p>
                   </div>
 
                   <div class="col-md-2">
                       <p>
                           @Html.DisplayFor(modelItem => item.AttendanceDate)
                       </p>
                   </div>

                   <div class="col-md-2">
                       <p>
                           @Html.DisplayFor(modelItem => item.Comments)
                       </p>
                   </div>

                   <div class="col-md-1">
                       <p>
                           <input class="btn btn-xs btn-info" type="button" value="Details" onclick=" location.href = '@Url.Action("Details", "Attendances", new {id = item.Id}, null)' "/>
                       </p>
                   </div>

                   <div class="col-md-1">
                       <p>
                           <input class="btn btn-xs btn-info" type="button" value="Edit" onclick=" location.href = '@Url.Action("Edit", "Attendances", new {id = item.Id}, null)' "/>
                       </p>
                   </div>
                   <div class="col-md-2">
                       <p>
                           <input class="btn btn-xs btn-success" type="button" value="Add New Attendance" onclick=" location.href = '@Url.Action("Create", "Attendances", new {enrollments_Attendance = item.Enrollments_Attendance}, null)' "/>
                       </p>
                   </div>
                   <div class="col-md-1">
                       <p>
                           <input class="btn btn-xs btn-danger" type="button" value="Delete" onclick=" location.href='@Url.Action("Delete", "Attendances", new {id = item.Id}, null)' " />
                       </p>
                   </div>
               </div>
               

           }
            
        </div>

Open in new window

The view is referring to a list (@model IEnumerable<SlamJammersData.Model.Attendances>).
Thus, this view needs to display the list of "Attendances" instances first with edit/details button in each entry  and then you need to create a another controller actions (Details, Edit) and view to edit/display the selected  "Attendances" instances. You can not display an instance in this view because there is no Id to identify which specific instance of the list you are looking for.

My recommendation will be to let ASP.NET MVC 5 generates the controllers and views for you, just delete your current controller and associated views and follow the example in this MVC5 link that shows how to create the Index view and what is scaffolded by VS2013.  You will see that it creates the index page as well as your edit, details and delete actions and associated views. You can always change the generated code later on to introduce in the Index method a filtering parameter. ( I assume you have a home page that will specify the filtering parameter)

Note: If you need to display a specific item then please change the return action and the view model to target an specific instance. For example
Controller: //Assumption you need to return the first instance.
 return View(attendances[0]);
View:
@model SlamJammersData.Model.Attendances
Hi Miguel.
You can not display an instance in this view because there is no Id to identify which specific instance of the list you are looking for.

The list you are looking at is for a specific student whose id is passed from a roster (enrollments) list. Here's the story as it stands now:
First step is to get a session of locations to view roster attendances from:
User generated image
Then a session is selected and the list of locations are presented:
User generated image
From the locations we select the roster we want in order to get the enrollments:
User generated image
If we look at the details of the enrollment, we can see the Ids of the enrollment instance and its foreign key (player id):
User generated image
If we click on the Attendances link we get the list of attendances for this individual on the attendance index page:
User generated image
When we look at the debugger to see what is being collected we can see the FullName's data.
User generated image
Ok, all attendances are related to just one player.
If that is the case my first post suggestion is correct, just replace:
<h3>Attendances for player: @Html.DisplayNameFor(model => model.FullName) </h3>

Open in new window

with:
<h3>Attendances for player: @Html.DisplayNameFor(model => model[0].FullName) </h3>

Open in new window


Basically you need to access the first element of the list([0]). FullName is not property of the current model.
MVC doesn't seem to like that solution, Miguel.

User generated image
My bad (a typo) the code should be:
<h3>Attendances for player: @Html.DisplayFor(model => model.FullName) </h3>

Open in new window

Note: DisplayNameFor display the property name, not the value.
Yes, I thought that too, but I don't get the list of properties with that method. I don't understand.

User generated image
ASKER CERTIFIED SOLUTION
Avatar of Miguel Oz
Miguel Oz
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for checking into this Miguel. The line of code that works is:
<h3> Attendances for player: @Html.DisplayName(Model.First().FullName) </h3>

User generated image
I've requested that this question be closed as follows:

Accepted answer: 0 points for wdarnellg's comment #a40713239

for the following reason:

I also posted this question on ASP.NET forums and it was suggested to use the First() on the Model. That gave me the list of properties to select the FullName from and the it displayed properly.
Both answers (mine and wdarnellg)  are equivalent, first method returns the first element of the enumeration, thus my answer is correct as well.
I am OK if you decide to delete the question.
Miguel is correct. His solution works the same. As his was posted first, and before I actually tested it, I think he earned the points.
Thank you.
Follow Up...

Not sure if I should ask this as a different question, but I just discovered that if there are no records to get from the database, such as a new player being added to the roster, there is an out of index error thrown for the ElementAt() or a similar error thrown for the First() functions. Is there a way to get the display to just show attendance count as 0? Or do I need to do something like catch the error and show a friendlier message? If the latter, are there any suggestions as to how to show such a message?

User generated image
Uhmm, is there any way you can put the full name in the view bag before calling attendance view? (On the details controller page)
I am assuming that if you have the player id you have access to the full name details, then you put full name in the view bag and display the view bag contents in the attendance view.
I know it is going to change to your initial design, but it will deal with this scenario and this question original scenario.

If you need further info then you need to ask a new question, post the action method that calls attendance view as well as how to get full name form player details.
Thanks. I am going to play with it, and ask a new question if I can't make ViewBag make sense.
Ok, I used the viewbag to display a friendlier message. I put the fullname line in a try catch and it works as expected now.
 
        public ActionResult Index(int? Id)
        {

            //Get the rosters and their attendance records
                        IQueryable<Attendances> attendances = db.Attendances
                            .Where(a => a.Enrollments_Attendance == Id)
                            .Include(e => e.Enrollments.Individuals)
                            .OrderByDescending(a => a.AttendanceDate);

                        ViewBag.EnrollmentId = Id;
            try
            {
                ViewBag.FullName = attendances.First().FullName;        
            
            }
            catch (InvalidOperationException ex)
            {
                ViewBag.Exception = ex;
               ViewBag.FullName = "No Attendances to display for the selected player";
            }
            
            return View(attendances.ToList());
            
        } 

Open in new window

User generated image
Thanks again Miguel!