1

I'm learning asp.net MVC and I'm trying to build an application but i can't have data displayed in my view. I've search here but wasn't able to find an answer to this issue. I have a model structure with Person which is my base class and two other classes that inherited from Person - Professor and Student. What i want is when i click the Students tab in my application it displays only students data and when i click Professors it displays only professors data with their common data and specific for each type. Right now i have only one table "Person" with students and professors attributes. Thanks in advance!!

Here is my base class Person and subclasses Professor and Student

public abstract class Person
{
    public virtual int PersonID { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string Email { get; set; }
    public virtual string Login { get; set; }
    public virtual string Senha { get; set; }
    public virtual string Address { get; set; } 
}
public class Professor : Person
{
    public string CREF { get; set; }
    public string Education { get; set; }
    public virtual ICollection<Session> Sessions { get; set; }
} 
public class Student : Person
{
    public DateTime SessionStart { get; set; }
    public DateTime SessionEnd { get; set; }
    public virtual ICollection<TSession> Sessions { get; set; }
}

and here is my StudentController

public class StudentController : Controller
{
    private SessionContext db = new SessionContext();

    public ActionResult Index()
    {
        return View(db.People.ToList());
    }
}

Here is my Index studentView

....

<table class="table">
    <tr>
        <th>@Html.DisplayNameFor(model => model.FirstName)</th>
        <th>@Html.DisplayNameFor(model => model.LastName)</th>
         ....
    </tr>
    @foreach (var item in Model) {
        <tr>
            <td>@Html.DisplayFor(modelItem => item.FirstName)</td>
            <td>@Html.DisplayFor(modelItem => item.LastName)</td>
            ....
        </tr>
    }
</table>
  • If you have one table, then you need a property to identify whether a person is a `Professor` or `Student` s that you can filter the results based on that property –  Apr 28 '16 at 23:21
  • 1
    Please also refer [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) - 99% of this code has nothing to do with the question. –  Apr 28 '16 at 23:23
  • You posted `AccountController`, not `StudentController`. That's a bunch of code for authentication that I assume is not relevant. – Paul Abbott Apr 28 '16 at 23:24
  • I think you pasted in your AccountController not your StudentController. – Skiltz Apr 28 '16 at 23:24
  • Sorry i didn't notice that. – Victor Gabriel Bucar Freitas Apr 29 '16 at 00:18
  • That's exactly what i have in my DB one table "Person" that holds all attributes. how would i filter the results based on the property ? – Victor Gabriel Bucar Freitas Apr 29 '16 at 00:36
  • Which of those properties in you table identifies if a `Person` is a `Professor` or a `Student`? (SO is an English only site) –  Apr 29 '16 at 01:13
  • The ones that are not in Person, if is a Professor i has CREF and Formacao. But if is a Student it has the DateTime attributes. The other properties are commom to both of then. – Victor Gabriel Bucar Freitas Apr 29 '16 at 01:25
  • I believe that should be "this stackoverflow site is in English, with a meta to direct users who do not seem to be able to communicate in English to their native-language resources": [is English required?](http://meta.stackexchange.com/questions/13676/do-posts-have-to-be-in-english-on-stack-exchange)... I don't see how that applies here because Victor seems quite able to communicate in English...(edit: I'm not trying to be snarky, just welcoming...) – Chaim Eliyah Apr 29 '16 at 01:30
  • @ChaimEliyah, The comment was relating to the fact the the property names are not in `English`. The model requires a property that identifies if `Person` is a `Professor` or a `Student` - for example `public bool IsProfessor { get; set; }` (or perhaps and enum) - We cannot tell if one of those properties is in fact that property :) –  Apr 29 '16 at 01:49
  • Gotcha, that makes sense. I saw your edit, I think that makes it pretty clear. :) – Chaim Eliyah Apr 29 '16 at 01:56
  • There is no property that differs a student and a professor besides the one i've already made changes to. CREF is just an acronymous in portuguese that every Physical Education Teacher has. So i don't have any especific type of property to do this identification. – Victor Gabriel Bucar Freitas Apr 29 '16 at 02:04
  • @VictorGabrielBucarFreitas, If your table contains a property `CREF` which has a value if its a `Professor` and is `null` if its a `Student`, then you could get the students using `var students = db.Pessoas.AsEnumerable().Where(x => x.CREF == null);` but all this suggests problems with your database design –  Apr 29 '16 at 02:06
  • @VictorGabrielBucarFreitas I updated my answer below, hopefully it's more useful than the last one. – Chaim Eliyah Apr 29 '16 at 05:12

3 Answers3

1

I have saved my original answer in a gist as it didn't really answer the OP's question. Ironically the source I was using was designed to solve the opposite problem, where two tables needed to be combined into a single page.

Here the OP is saying that there is a database table Persons from which we'd like to extrapolate two Views, Professor and Student, and display them on different pages.

Such that--

//StudentController.cs
public class StudentController : Controller
{
    private SessionContext db = new SessionContext();

    public ActionResult Index()
    {
        var result = db.People.Where(x => !string.IsNullOrEmpty(x.Education));
        return View(result.ToList());
    }
}

and...

//ProfessorController.cs
//...
    var result = db.People.Where(x => string.IsNullOrEmpty(x.Education));
//...

...could be one way of separating the views.

However, as suggested in comments, if your design requires these objects to be displayed and treated separately in the application, you may just want to have multiple tables. One example in TSQL:

CREATE TABLE dbo.Person (
    Id int NOT NULL PRIMARY KEY,
    Name nvarchar(200) NOT NULL --unicode
);
CREATE TABLE dbo.Professor (
    Id int NOT NULL PRIMARY KEY,
    Education nvarchar(50) NOT NULL,
    PersonId int FOREIGN KEY REFERENCES Person.Id
);
--etc

But since I'm not a DBA and you're using ASP.NET you can use Entity Framework's Code First table generation, which I think is what you're hinting at above:

public class Person
{
    public int PersonId { get; set; }
    [Required] // == NOT NULL
    public string Name { get; set; }
    // demais... (the rest)
}

public class Professor // no inheritance!
{
    public int ProfessorId { get; set; }
    [Required]
    public string Education { get; set; }
    [ForeignKey("PersonId")]
    public Person Person { get; set; }
}

Note that this is a 1-1 relationship, and honestly I haven't validated this. Julie Lerman has many posts on Microsoft's Data Developer Center website, such as this one that goes into these relationships. (That's my best Quick Googling (tm) and points to Entity Framework 4.1, so I'm sure you can find something newer. But the principles should still hold.)

Whew!

Chaim Eliyah
  • 2,743
  • 4
  • 24
  • 37
  • I don't think this is really addressing OP's issue - which is to filter the results so that one tab displays a collection of `Professor` and the other tab a collection `Student` - e.g. - `var students = db.Pessoas.Where(x => x.SomeProperty == someValue);` and `var professors = db.Pessoas.Where(x => x.SomeProperty == anotherValue);` –  Apr 29 '16 at 02:00
  • Ah. I thought he rather had that part down, I guess I assumed that the code he posted would go in the EditorTemplate, like so... https://github.com/chaim1221/Machete/blob/master/Machete.Web/Views/Shared/EditorTemplates/Person.cshtml – Chaim Eliyah Apr 29 '16 at 02:03
  • In other words, if he uses this template pattern he can create separate Views and Controllers for Professors, Students, etc., which are activated by the different tabs. – Chaim Eliyah Apr 29 '16 at 02:04
  • The problem with what you have shown is the the model in the template is `@model MyApp.Person` which means it could only ever display the base properties. If the solution involved using an `EditorTemplate`, then 2 would be required (one for `Professor` and one for `Student`) –  Apr 29 '16 at 02:09
  • That makes sense. Probably also better for this example to use DisplayTemplate. I'll make the edits. – Chaim Eliyah Apr 29 '16 at 02:10
  • Let me know if that looks any better. I didn't actually draw out the Student controller, but hopefully the comment I added will give readers the idea. – Chaim Eliyah Apr 29 '16 at 02:24
  • There's nothing wrong with your code, but it does not really answer OP's question :) –  Apr 29 '16 at 02:25
  • @StephenMuecke Oh crud. I get it now. :facepalm: – Chaim Eliyah Apr 29 '16 at 04:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110588/discussion-between-chaim-eliyah-and-stephen-muecke). – Chaim Eliyah Apr 29 '16 at 04:20
1

This question has 2 parts, namely, displaying data on a view and getting the data from a database via some method like Entity Framework. And because this is an ASP.NET MVC question I am only going to answer the displaying of data on the view. How you get your data back is up to you.

I personally would have 2 tables in the database for this, one for students and one for professors. This is debatable but this is how I would do it.

You professor and student classes look correct to me.

You will need to create a view model for this. View models contain data that you pass to the view. I gave a detailed answer on what view models are. Please read it:

What is ViewModel in MVC?

First go and create your view model that you will send to the view. You will probably display other data on the screen, but I am only going to display a list of students and a list of professors. So for each you will have a property to contain the data:

public class ViewModel
{
     public List<Student> Students { get; set; }

     public List<Professor> Professors { get; set; }
}

In your Index action method you will create an instance of this view model, populate it with student and professor data and then send it through to the view:

public ActionResult Index()
{
     // Please make use of a repository to handle this
     // You need to set up your data layer to handle students and professors
     SessionContext db = new SessionContext();

     ViewModel model = new ViewModel();

     // Get all the students
     model.Students = db.Students.ToList();
     // Get all the professors
     model.Professors = db.Professors.ToList()

     return View(model);
}

Now you have your view model populated with student and professor data. You send it through to the view and the view will display it. You will need 2 HTML tables and have your tabs display the correct table when needed:

@model Project.Models.ViewModel

<table>
     @foreach (var student in Model.Students)
     {
          <tr>
               <td>@student.FirstName</td>
               <td>@student.FirstName</td>
          </tr>
     }
</table>

<table>
     @foreach (var professor in Model.Professors)
     {
          <tr>
               <td>@professor.FirstName</td>
               <td>@professor.FirstName</td>
          </tr>
     }
</table>

This is a simplistic approach and might not be what you are looking for but it will guide you on the correct path and give you ideas of what can be done.

Community
  • 1
  • 1
Brendan Vogt
  • 25,678
  • 37
  • 146
  • 234
1

Thank you everyone who gave your time trying to help me solve this problem, i was enable to extract the specific properties from the inherited classes and display it in different views so, i decided to create two tables Student and Professor and it solved my problem.