Link to home
Start Free TrialLog in
Avatar of Todd Penland
Todd PenlandFlag for United States of America

asked on

How to Modify Existing Controller and View to Incorporate Additional Data (from Stored Procedure)

This is a continuation of the question found at: https://www.experts-exchange.com/questions/28654179/How-to-Display-Table-of-Values-From-Stored-Procedure-in-ASP-NET-MVC5-View-Step-by-Step-Help-Needed.html

The original problem (how to get data from a stored procedure in EF Database First and display it in a view) has been solved (I think), however I now need to incorporate that solution into an already existing Controller and View.

Here's the existing Controller:
        // GET: ClientGroupMembers/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            ClientGroupMember clientGroupMember = db.ClientGroupMembers.Find(id);
            if (clientGroupMember == null)
            {
                return HttpNotFound();
            }
            return View(clientGroupMember);
        }

Open in new window


and here's the proposed solution for making my list of dates available to the View (altered to use the Details view rather than Index):
public ActionResult Details(int id)
{
    var myintparam = new SqlParameter
    {
        ParameterName = "myParam",
        Value = id
    };
    var results = context.Database.SqlQuery<DateTime>("dbo.MyStoredProcedureName @myParam").ToList();
    return View(results);
}

Open in new window


A related question that I still haven't figured out: how do I find out the name of the database context I should use in the preceding code sample?  Sorry, but I'm still confused about that too. ;-)

Now for presentation: Here is my current view:
@model Scheduler.Models.ClientGroupMember
@using Microsoft.AspNet.Identity
@Scripts.Render("~/bundles/jquery");

@{
    ViewBag.Title = "Details";
}

<h2>@Model.SortName</h2>

<div>
    <h4>Details</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.LastName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.LastName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.FirstName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.FirstName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.MidNames)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.MidNames)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Business)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Business)
        </dd>
    </dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
    @Html.ActionLink("Back to List", "Index")
</p>
<div id="rootwizard">
    <ul class="nav nav-pills nav-justified">
        <li role="presentation" class="active"><a href="#contactinfo" data-toggle="tab" class="actve"><span class="glyphicon glyphicon-home"></span>  Contact Info</a></li>
        <li role="presentation"><a href="#schedules" data-toggle="tab"><span class="glyphicon glyphicon-apple"></span>  Schedules</a></li>
    </ul>
    <div class="tab-content">
        <div class="tab-pane active" id="contactinfo">
            <div class="row">
                <p>Coming soon...</p>
            </div>
        </div>
        <div class="tab-pane" id="schedules">
            <div class="row">
                 CODE TO DISPLAY COLUMN HEADING GOES HERE
            </div>
            <div>
                CODE TO DISPLAY LIST OF DATES GOES HERE
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        $('#rootwizard').bootstrapWizard({ 'tabClass': 'nav nav-pills' });
    });
</script>

Open in new window


and finally, the proposed changes to the view:
@model IEnumerable<DateTime>
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<table>
@foreach(var date in model)
{
    <tr>
        <td>@date</td>
    </tr>
}
</table>

Open in new window


I'm pretty sure once I understand how to do THIS a whole new world is going to open up ;-)  Any help resolving this will be much appreciated.  Thanks!
Avatar of Ioannis Paraskevopoulos
Ioannis Paraskevopoulos
Flag of Greece image

Hi,

I will gladly help you out with this one, but i would need a look at your model structure. Can you show how is Scheduler.Models.ClientGroupMember defined? Does it have a list of DateTimes in it? It is possible that you would need to define a derived model. We'll see.

Giannis
Avatar of Todd Penland

ASKER

Sure thing.  Here's the model:

    public partial class ClientGroupMember
    {
        public ClientGroupMember()
        {
            this.ClientGroupMemberAddresses = new HashSet<ClientGroupMemberAddress>();
            this.ClientGroupMemberEmails = new HashSet<ClientGroupMemberEmail>();
            this.ClientGroupMemberPhones = new HashSet<ClientGroupMemberPhone>();
            this.ClientGroupMembersDatesNotAvailables = new HashSet<ClientGroupMembersDatesNotAvailable>();
            this.Schedules = new HashSet<Schedule>();
        }
    
        public int Id { get; set; }
        public int GroupID { get; set; }
        public Nullable<int> Title { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string MidNames { get; set; }

        [NotMapped]
        [Display(Name = "Sort Name")]
        public string SortName
        {
            get { return LastName + ", " + FirstName + " " + MidNames; }
        }
        
        public Nullable<int> Suffix { get; set; }
        public string Business { get; set; }
        public System.DateTime DateCreated { get; set; }
        public string CreatedBy { get; set; }
        public Nullable<System.DateTime> StartDate { get; set; }
        public Nullable<System.DateTime> DueDate { get; set; }
        public Nullable<System.DateTime> InactiveDate { get; set; }
        public Nullable<bool> Unavailable { get; set; }
        public Nullable<bool> Assigned { get; set; }
        public Nullable<int> SinceLastTeamed { get; set; }
        public Nullable<int> SinceLastWildcard { get; set; }
        public Nullable<int> LegacyID { get; set; }
    
        public virtual ICollection<ClientGroupMemberAddress> ClientGroupMemberAddresses { get; set; }
        public virtual ICollection<ClientGroupMemberEmail> ClientGroupMemberEmails { get; set; }
        public virtual ICollection<ClientGroupMemberPhone> ClientGroupMemberPhones { get; set; }
        public virtual ClientGroup ClientGroup { get; set; }
        public virtual NameSuffix NameSuffix { get; set; }
        public virtual Title Title1 { get; set; }
        public virtual ICollection<ClientGroupMembersDatesNotAvailable> ClientGroupMembersDatesNotAvailables { get; set; }
        public virtual ICollection<Schedule> Schedules { get; set; }
    }

Open in new window

And which is the property that should hold the results of the SP? Is there such a property? Is it the Schedules ?
Now we're into parts of EF that I don't fully understand yet but I'll try to answer as best I can.

This line represents the one to many relationship in the database between the ClientGroupMembers table and the Schedule table.  Here is the model for Schedule (if that helps):

    public partial class Schedule
    {
        public int Id { get; set; }
        public System.DateTime IntervalStartDate { get; set; }
        public int TeamNumber { get; set; }
        public int Participant { get; set; }
    
        public virtual ClientGroupMember ClientGroupMember { get; set; }
    }

Open in new window


(Participant in this model is the foreign key "Id" from ClientGroupMembers.)

Does this help?
Yes but i think you would not need the SP part. EF should have this filled already. I have to go out be back with suggestions in a while.
Ok,

First of all i think that the Schedules are already there due to EF lazy loading. So i would suggest to first take the following steps that will be the less intrusive to what you currently have.

1. Create a template.

Browse to your \Views\Shared folder and create a new Folder named "DisplayTemplates".
In that folder add a new item (cshtml) named "Schedules.cshtml"
In that View add the following code:
@model IEnumerable<Schedule>
@foreach(var schedule in Model)
{
<div class="row">
    @schedule.IntervalStartDate 
</div>
}

Open in new window


You will use that in your main View.

2. Use the template.

In your View as it is defined now you will need to change the following part (lines 67 to 69):
            <div>
                CODE TO DISPLAY LIST OF DATES GOES HERE
            </div>

Open in new window

to :
@Html.DisplayFor(m=>m.Schedules,"Schedules")

Open in new window


Lets try this. I can see that there may be some issues but i would like you to first try this and if it does not work i will give further instructions. The issue you might have is an exception saying that :


The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

but judging from your controller's code, you may not experience that.

Giannis
Done.  I got an entirely different result though.  This is what is displayed in my view where the list of dates should be:

System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12

Open in new window

Lets go a step further then.

In your controller change the following line:

            ClientGroupMember clientGroupMember = db.ClientGroupMembers.Find(id);

Open in new window


to:

            ClientGroupMember clientGroupMember = db.ClientGroupMembers.Include("Schedules").Where(x=> x.Id == id).FirstOrDefault();

Open in new window


Giannis
Done.  That produces this exception though:

Error      1      Cannot implicitly convert type 'System.Linq.IQueryable<Scheduler.Models.ClientGroupMember>' to 'Scheduler.Models.ClientGroupMember'. An explicit conversion exists (are you missing a cast?)      projectPath\ClientGroupMembersController.cs      33      51      Scheduler
yes i noticed that a bit late and updated my post. Can you add the FirstOrDefault() ?
Yes.  I added it.  (I have to admit that, at this point I'm just following your lead...not really sure what I'm doing exactly.)

Changed the line in the controller to:
ClientGroupMember clientGroupMember = db.ClientGroupMembers.Include("Schedules").Where(x => x.Id == id).FirstOrDefault();
            

Open in new window


When I view the page I'm still getting this result though:

System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12

Open in new window


I should have pointed out that I had to slightly change the model directive in the shared view from:

@model IEnumerable<Schedule>

to:

@model IEnumerable<Scheduler.Models.Schedule>

I doubt that makes any difference but wanted to point it out just in case.
No, it is ok what you did. I am not on a pc to do any test so lets try two things:

1. Change IEnumerable to IQueryable.

If that does not work :

2. Add ToList() on the DisplayFor as
@Html.DisplayFor(m=>m.Schedules.ToList(),"Schedules")

Open in new window


Hopefully this will help it to enumerate the values.

Just as info, dynamic proxy is the way of EF to enumerate dependencies. You select from a table and EF will use DynamicProxy to lazy load related tables (like Schedules in our case).

Giannis
I changed IEnumerable to IQueryable but got exactly the same result.  I changed it back to IEnumerable and added ToList() to the view.  When I ran it I got this exception:

System.InvalidOperationException was unhandled by user code
  HResult=-2146233079
  Message=Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
  Source=System.Web.Mvc
  StackTrace:
       at System.Web.Mvc.ModelMetadata.FromLambdaExpression[TParameter,TValue](Expression`1 expression, ViewDataDictionary`1 viewData, ModelMetadataProvider metadataProvider)
       at System.Web.Mvc.ModelMetadata.FromLambdaExpression[TParameter,TValue](Expression`1 expression, ViewDataDictionary`1 viewData)
       at System.Web.Mvc.Html.TemplateHelpers.TemplateFor[TContainer,TValue](HtmlHelper`1 html, Expression`1 expression, String templateName, String htmlFieldName, DataBoundControlMode mode, Object additionalViewData, TemplateHelperDelegate templateHelper)
       at System.Web.Mvc.Html.TemplateHelpers.TemplateFor[TContainer,TValue](HtmlHelper`1 html, Expression`1 expression, String templateName, String htmlFieldName, DataBoundControlMode mode, Object additionalViewData)
       at System.Web.Mvc.Html.DisplayExtensions.DisplayFor[TModel,TValue](HtmlHelper`1 html, Expression`1 expression, String templateName)
       at ASP._Page_Views_ClientGroupMembers_Details_cshtml.Execute() in c:\Users\MichaelTodd\Documents\Visual Studio 2013\Projects\Scheduler\Scheduler\Views\ClientGroupMembers\Details.cshtml:line 69
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
       at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
       at System.Web.WebPages.StartPage.RunPage()
       at System.Web.WebPages.StartPage.ExecutePageHierarchy()
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
       at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
       at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
       at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
  InnerException: 

Open in new window

Here's where we are now by the way (for anyone else who may be following this later):

Controller:
        // GET: ClientGroupMembers/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            
            ClientGroupMember clientGroupMember = db.ClientGroupMembers.Include("Schedules").Where(x => x.Id == id).FirstOrDefault();
            if (clientGroupMember == null)
            {
                return HttpNotFound();
            }
            return View(clientGroupMember);
        }

Open in new window


Shared View:
@model IEnumerable<Scheduler.Models.Schedule>

@foreach (var schedule in Model)
{
    <div class="row">
        @schedule.IntervalStartDate
    </div>
}

Open in new window


View:
@model Scheduler.Models.ClientGroupMember
@using Microsoft.AspNet.Identity
@Scripts.Render("~/bundles/jquery");

@{
    ViewBag.Title = "Details";
}

<h2>@Model.SortName</h2>

<div>
    <h4>Details</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.LastName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.LastName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.FirstName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.FirstName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.MidNames)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.MidNames)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Business)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Business)
        </dd>
    </dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
    @Html.ActionLink("Back to List", "Index")
</p>
<div id="rootwizard">
    <ul class="nav nav-pills nav-justified">
        <li role="presentation" class="active"><a href="#contactinfo" data-toggle="tab" class="actve"><span class="glyphicon glyphicon-home"></span>  Contact Info</a></li>
        <li role="presentation"><a href="#schedules" data-toggle="tab"><span class="glyphicon glyphicon-apple"></span>  Schedules</a></li>
    </ul>
    <div class="tab-content">
        <div class="tab-pane active" id="contactinfo">
            <div class="row">
                <p>Coming soon...</p>
            </div>
        </div>
        <div class="tab-pane" id="schedules">
            <div class="row">
                <div><strong>Schedule</strong></div>
                <hr />
            </div>
            <div>
                @Html.DisplayFor(m => m.Schedules.ToList(), "Schedules")
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        $('#rootwizard').bootstrapWizard({ 'tabClass': 'nav nav-pills' });
    });
</script>

Open in new window

Hmm, can we try something else?

Rename the template to "Schedule" ( remove the last s)

Change the model to Schedule instead of IEnumerable<Schedule>.

Change the DisplayFor as
@Html.DisplayFor(m=>m.Schedules)

Sorry but i am not on a pc to actually test.

Giannis
No worries...I'm just grateful for the help! ;-)

These changes produced the same result we got earlier:
System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12

Open in new window


Controller (no change from before)

Shared View (renamed Schedule.cshtml from Schedules.cshtml):
@model Scheduler.Models.Schedule

@foreach (var schedule in Model)
{
    <div class="row">
        @schedule.IntervalStartDate
    </div>
}

Open in new window


View:
@model Scheduler.Models.ClientGroupMember
@using Microsoft.AspNet.Identity
@Scripts.Render("~/bundles/jquery");

@{
    ViewBag.Title = "Details";
}

<h2>@Model.SortName</h2>

<div>
    <h4>Details</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.LastName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.LastName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.FirstName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.FirstName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.MidNames)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.MidNames)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Business)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Business)
        </dd>
    </dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
    @Html.ActionLink("Back to List", "Index")
</p>
<div id="rootwizard">
    <ul class="nav nav-pills nav-justified">
        <li role="presentation" class="active"><a href="#contactinfo" data-toggle="tab" class="actve"><span class="glyphicon glyphicon-home"></span>  Contact Info</a></li>
        <li role="presentation"><a href="#schedules" data-toggle="tab"><span class="glyphicon glyphicon-apple"></span>  Schedules</a></li>
    </ul>
    <div class="tab-content">
        <div class="tab-pane active" id="contactinfo">
            <div class="row">
                <p>Coming soon...</p>
            </div>
        </div>
        <div class="tab-pane" id="schedules">
            <div class="row">
                <div><strong>Schedule</strong></div>
                <hr />
            </div>
            <div>
                @Html.DisplayFor(m => m.Schedules)
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        $('#rootwizard').bootstrapWizard({ 'tabClass': 'nav nav-pills' });
    });
</script>

Open in new window

Also this change to the template

@model Scheduler.Models.Schedule

    <div class="row">
        @Model.IntervalStartDate
    </div>

Open in new window

Done.  Same result though:

System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12System.Data.Entity.DynamicProxies.ClientGroupMember_1CE87C82519B5BC54E8BB9142812F0A78322A167CB434675C6A862954D88CF12

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Ioannis Paraskevopoulos
Ioannis Paraskevopoulos
Flag of Greece 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
That appears to have done the job. :-D

User generated image
To be honest i knew it would, but i really wanted the template to work, as it feels more MVC appropriate. And more reusable.

Maybe tomorrow i will create a little project to see where i was wrong...

Glad i could help.

Giannis
Can't tell  you how much I appreciate the help with this.  If you do find the more MVC appropriate and reusable solution I'd love to see that too.  Thank you!!!
You just made me an ASP.NET Guru, so that's the list i can do.... ;-)
WINNING!!! :-D
Ok, i couldn't wait, so i created a project from scratch. I only referenced a dll which handles my database models etc.

I have a model called "villas" and each villa has a collection of Photos, as your ClientGroupMembers model has a collection of schedules. I followed the following steps exactly (from the standard MVC template in VS 2013):

1. I added a folder DisplayTemplates under \Views\Shared.

User generated image

2. Added the following code:

@model MyNamespace.Photos
<tr><td>@Model.Image</td></tr>

Open in new window

3. Changed the \Views\Home\Index.cshtml

@model MyNamespace.villas

@Model.property_description
<table>
@Html.DisplayFor(m => m.Photos)
</table>

Open in new window

4. Modified HomeController

        public ActionResult Index()
        {
            using(Data data = new Data())
            {
                var model = data.villas.Include("Photos").Where(x => x.ID == 17050).FirstOrDefault();
                return View(model);
            }
        }

Open in new window


"Data" in the controller is my dll that handles the database, but that doesn't make any difference.

The result is the following:
User generated image
As you can see as defined on the view, there is the description and also a list of strings defining the Photos.

As i said it should have worked. And this way i could reuse that template to other places.

Do you see any difference with what you had?

Giannis
@model Scheduler.Models.Schedule

@Model.IntervalStartDate<br />

Open in new window


I've adapted your solution to mine and it's working perfectly with one exception: the column name for the schedule dates.  In your example you are using this as the column name (I think):

@Model.property_description

However I can't figure out how to change that so that it will read the Display Name I've given this column in my model:

        [Display(Name="Schedule Date")]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
        public System.DateTime IntervalStartDate { get; set; }

Open in new window

(remember that IntervalStartDate is in a different model (Schedule) than the one the rest of the page is derived from (ClientGroupMember)).

In my View I entered this:
        <div class="tab-pane" id="schedules">
            <div class="row">
                <div><strong>@Html.DisplayNameFor(m => m.Schedules)</strong></div>
                <hr />
            </div>
            <div>
                @Html.DisplayFor(m => m.Schedules)
            </div>
        </div>

Open in new window


Instead of getting the column name "Schedule Date" (from the model), I'm getting the name of the model "Schedule".  I also notice that the date format I specified in the model's annotations is not being applied:

User generated image
Any idea what I'm doing wrong?
Hi,

Good to know it finally worked.

I think you need to use @Html.LabelFor.

In my example i just added another property of my model. Property_description is a field in my table.

In order to apply the format you need to go to your template and use @Html.DisplayFor(m=>m.IntervalStartDate)

This will cause it to get the declared format.

Giannis
Sorry, you also need to apply @Html.DisplayName on your template instead of the main view.
Thank you again.  I think I'm just about there.  I moved everything from the view to the view template:

@model Scheduler.Models.Schedule

<div class="row">
    <div><strong>@Html.DisplayNameFor(m => m.IntervalStartDate)</strong></div>
    <hr />
</div>
<div>
    <a href="..\..\Schedules\Details\@Model.TeamNumber\@Model.IntervalStartDate">@Model.IntervalStartDate</a><br />
</div>

Open in new window


so that the view now looks like this:

        <div class="tab-pane" id="schedules">
            @Html.DisplayFor(m => m.Schedules)
        </div>

Open in new window


That does the trick as far as the Display Name is concerned, however as you can see it now repeats with every entry (not the desired outcome) rather than just appearing once at the top of the column:

User generated image
It is supposed to be that way. Remember that your template is for a single object and not for a collection or similar. So, DisplayFor will apply that template for every item in the collection. If you add the header in the template, it will be applied to each item.

I would have the DisplayName in the main view. But since in the main view you are dealing with the collection i would also add the attribute on the collection.

So, in the Schedule model, instead of:

        [Display(Name="Schedule Date")]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
        public System.DateTime IntervalStartDate { get; set; }

Open in new window

i would just have the Format and then in the ClientGroupMembers model i would add to the Schedules property:

        [Display(Name="Schedule Dates")]
        public ICollection<Schedule> Schedules{ get; set; }

Open in new window


One thing i do not know is if it can go to the EF model.. I think not because it is autogenerated. I usually create my own derived classes for the Models in mvc.

I am not sure if what i said helps at all...

Giannis
Success!!!
User generated image
I do have a derived class (in Metadata.cs) for each of my models so that my annotations aren't overwritten during database updates, so I was able to put the suggested annotation there.  It worked perfectly.

So here's what I ended up with (just in case it might help someone else with a similar problem):

ClientGroupMembers Model (Derived)
        [Display(Name = "Schedule Date")]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
        public ICollection<Schedule> Schedules { get; set; }

Open in new window


Controller
        // GET: ClientGroupMembers/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Session["_SessionGroupMember"] = id;            
            ClientGroupMember clientGroupMember = db.ClientGroupMembers.Include("Schedules").Where(x => x.Id == id).FirstOrDefault();
            if (clientGroupMember == null)
            {
                return HttpNotFound();
            }
            return View(clientGroupMember);
        }

Open in new window


View Template
@model Scheduler.Models.Schedule


<a href="..\..\Schedules\Details\@Model.TeamNumber\@Model.IntervalStartDate">@Html.DisplayFor(m => m.IntervalStartDate)</a><br />

Open in new window


View
        <div class="tab-pane" id="schedules">
            <div class="row">
                <div><strong>@Html.DisplayNameFor(m => m.Schedules)</strong></div>
                <hr />
            </div>
            <div>
                @Html.DisplayFor(m => m.Schedules)
            </div>
        </div>

Open in new window


I wish I could give you another bunch of points for the extra help on this!  Thank you very much!!!