How to type cast in MVC 4?

This is the case I'm facing:

I do have 3 controllers as following: a) MetricController b) CategoryController c) NavController

Before I go further, I better to share that I have a simple layout on View (HTML page) which consists of a column (on left) representing categories and on right portion of page I have to show a set of information. The information has to change base on selected category (report type) on left column.

MetricController is responsible to retrieve some information from a table (Metrics table) and it is something:



   public class Metric  {   //just a class for IIS log
        public int Id { get; set; }
        public string date { get; set; }
        public string time { get; set; }
        public string c_ip { get; set; }
        public string cs_username { get; set; }
        public string s_sitename { get; set; }
        public string s_computername { get; set; }
        public string s_ip { get; set; }
        AND MORE...

    }

Open in new window



 
public class MetricController : Controller {
        private IMetricRepository repository;

        public MetricController(IMetricRepository metricRepository) {
            this.repository = metricRepository;
        }

        public ViewResult List() {

            MetricsListViewModel model = new MetricsListViewModel {
                Metrics = repository.Metrics
                .OrderBy(p => p.Id)   //just few columns for now
            };

            return View(model);
        }
    }

Open in new window



NavController is responsible for navigation and showing categories (retrieved from its table) in left column as following:

public class NavController : Controller  {

        private ICategoryRepository repository;
        public NavController(ICategoryRepository repo) {
            repository = repo;
        }

        public PartialViewResult Menu() {
            IEnumerable<string> categories = repository.Categories
                                                .Where(x => x.Visible == "1" /*|| x.Visible == "0"*/)
                                                .Select(x => x.CategoryName)
                                                .Distinct()
                                                .OrderBy(x => x);

            return PartialView(categories);
        }

Open in new window


Now, I have an HTML page which shows off a left column populated with categories (or let's say report names in the left column) and need to setup and run a query every time user clicks on one of a report/category name.

One thing I know (feel free to correct me if I'm wrong) is that I have to work on CategoryController but using a code as following ends up to getting a type casting error:

public class CategoryController : Controller   {
        private IMetricRepository repository;

        public CategoryController(IMetricRepository metricRepository) {
            repository = metricRepository;
        }

        public ViewResult List(string category)
        {

            MetricsListViewModel viewModel = new MetricsListViewModel {
                Metrics = repository.Metrics
                    .Select(p => p.cs_username)  <<<<<<<<  cannot convert 
            };
        }
    }

Open in new window


The error is:

Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)

This is my first MVC application and I feel like I'm missing something. I could use a constant list of report and use

@Html.ActionLink(GenerateReport1, action ,Controllername)
@Html.ActionLink(GenerateReport2, action ,Controllername)
@Html.ActionLink(GenerateReport3, action,Controllername)
but need to load the report names from a table. Any help is appreciated.

Regards,
Amit
akohanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

käµfm³d 👽Commented:
Please provide the definition for the MetricsListViewModel class.
0
akohanAuthor Commented:
Oh sorry! I missed that part ... Thanks for reminding it goes as:


 
   public class MetricsListViewModel  {

        public IEnumerable<Metric> Metrics { get; set; }
        public PagingInfo PagingInfo { get; set; }
        public string CurrentCategory { get; set; }
    }
}

Open in new window

0
käµfm³d 👽Commented:
The cs_username property in your last snippet of the OP is of type string. Your problem is that Select will return IEnumerable<string>, but you are trying to assign that result to a property of type IEnumerable<Metric>. This does not work. You need to modify your Select so that it returns the correct type.
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

akohanAuthor Commented:
OK, so what do you suggest? which part has to be modified to avoid this type cast error?
0
käµfm³d 👽Commented:
I would think that you don't even need the Select:

e.g.

MetricsListViewModel viewModel = new MetricsListViewModel
{
    Metrics = repository.Metrics
};

Open in new window


...but that would depend on how repository.Metrics is defined. You may still need the Select, but with a tweak:

MetricsListViewModel viewModel = new MetricsListViewModel
{
    Metrics = repository.Metrics.Select(p => new Metric() { cs_username =  p.cs_username });
};

Open in new window

0
akohanAuthor Commented:
1)
I guess, something is not right. please see the attached picture.
I am new to MVC but I am expecting this to return a variable from ViewResult type and pass it onto a view.


type cast error
0
akohanAuthor Commented:
One question to add here: if there is no need to use a SELECT or no linq involved then how can I retrieve the data from table?
0
käµfm³d 👽Commented:
1. Change the ending semi-colon ( ; ) to a comma ( , )
2. It looks like you are using Entity Framework. Without going into too much detail, the repository.Metrics effectively is your table. When ASP.NET gets to a point in the page life cycle where it actually needs to spit out the data, then it will make the appropriate calls out to the database just by virtue of having set the code up as I mentioned above.

Having said that, I seem to recall that you cannot pass the "table" back to the view in the fashion I outlined above. If you run into any issues with the above code, then try adding in a ToList call at the end.

e.g.

Metrics = repository.Metrics.Select(p => new Metric() { cs_username =  p.cs_username }).ToList();

Open in new window

0
akohanAuthor Commented:
Thanks. yes, I'm using EF 5.0 in MVC 4. I followed the steps and it runs but then in runtime I get this error

The entity or complex type 'NameSpace.Domain.Concrete.Metric' cannot be constructed in a LINQ to Entities query.
0
akohanAuthor Commented:
just to have it reviewed by you. I'm getting error on this line 26:

Line 24:         {
Line 25:
Line 26:             MetricsListViewModel viewModel = new MetricsListViewModel
Line 27:             {
Line 28:                 Metrics = repository.Metrics.Select(p => new Metric() { cs_username = p.cs_username}).ToList(),
0
käµfm³d 👽Commented:
OK, my fault. (We don't get to use EF at work, so I've only played with it a handful of times.) From what I see on the web, you cannot create instances of entities that exist for the purpose of modeling your database. You would need to create an additional class that has the same structure, and then Select into that. This means you would have to change your view model to use the new class as well.

Let me see if I can get someone with a little bit more EF experience to pop in.
0
akohanAuthor Commented:
Thank you so much! I'm new to EF and also to MVC so have to confess totally feel hopeless.
However, just to make sure I am following you right: so I have to make a new class and replace the View Model? or should I change Metric class instead?

I truly appreciate your concern and help OK I will wait for your inputs.

Regards.
Amit
0
käµfm³d 👽Commented:
I sent a message to a guy who I know is knowledgeable about EF stuff. I'm not sure when he'll see it, but I'm sure he'll drop buy when he gets it  = )
0
akohanAuthor Commented:
Thank you Kaufmed!
0
Fernando SotoRetiredCommented:
Hi akohan;

If I understand what is going on here in this line of code,

Metrics = repository.Metrics.Select(p => new Metric() { cs_username =  p.cs_username }).ToList();

Open in new window

Metric() is a class that was created by Entity Framework to map to the database table Metrics. Entity Framework will not allow you to create new instance objects of the same object type that it is returning from the query. You can return the complete object or create a Data Transfer Object, DTO, and fill only those fields that are needed. There is a third way and that is to return an Anonymous type from the query but in a case like this I would not suggest that. The DTO class does not need to have all the same fields as the Metric class only those fields that are needed or you can have all if you want that. And as Kaufmed has stated, "you would have to change your view model to use the new class as well."
0
akohanAuthor Commented:
Hello Fernando,

I truly appreciate you and Kaufmed for the care and time you both took to address this issue! OK, now let me bug you with this. This is the MetricsListViewModel class that you both said it should be changed:

public class MetricsListViewModel  {

        public IEnumerable<Metric> Metrics { get; set; }
        public string CurrentCategory { get; set; }
    }

Open in new window


As you see, I have IEnumerable<Metric> defined in there. Also, my model is Metric as following:
  public class Metric  { // information from IIS log - FYI
        public int Id { get; set; }
        public string date { get; set; }
        public string time { get; set; }
        public string c_ip { get; set; }
        public string cs_username { get; set; }
        public string s_sitename { get; set; }
        public string s_computername { get; set; }
        public string s_ip { get; set; }

Open in new window



I'm assuming from "changing" you mean I have to get rid of IEnumerable<Metric>. Right? if so, what it should be changed to?

In existing code in linq,  compiler is trying to type case IEnumerable<string> to IEnumerable<Metric>. Right?

Thank you,
Amit
0
Fernando SotoRetiredCommented:
Hi Amit;

In the Model when you/EDMX designer created the classes to map to the database, for the table Metrics the designer created a class called Metric and I am assuming that the class you posted in your last post is that same class Metric. If I am wrong about that please let me know because the following information is based on that assumption. The reason you were getting the following error, "The entity or complex type 'NameSpace.Domain.Concrete.Metric' cannot be constructed in a LINQ to Entities query.", is that EF was returning a Metric object and you in your query were asking it to create an object of the same type Metric and assign to one of its field the value from the Metric the query had already created. This is not allowed.

So let me ask the question what do you want this query to have accomplished for you?:
Metrics = repository.Metrics.Select(p => new Metric() { cs_username =  p.cs_username }).ToList();

Open in new window


To your question in your last post, "I'm assuming from "changing" you mean I have to get rid of IEnumerable<Metric>. Right?", yes. And to this part of the question, "if so, what it should be changed to?", It should become a collection of object created by the query. But to give a more complete answer I need to understand what the query is returning.
0
akohanAuthor Commented:
Thank you again!

As you advised let me share few things to make sure we both are on the same page:

I did not use EDMX designer, I manually created a Metric class and after getting to  "Server Explorer" in VS 2012, I was able to see the table structure table which was made/generated by  EF 5.0.0.0

In response to your question I should Yes, the class is Metric.cs I already posted it here.

Now, regarding Linq code that you addressed here: that was given to me by Kaufmed as he was helping me with the problem.

What am I trying to do? it is simple.

I have two tables one called Metric which contains few columns (imported from IIS log file e.g. client IP address, Server IP Address and etc) and one is called Category which in fact is a list of Report names in it e.g.  as following:

    public class Category {
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }  // in fact, it should be ReportName
        public string Visible { get; set; }  // to hide/visible a report
    }

Open in new window


When user clicks on a category (or report name ), I need to run a specific query or linq script to generate a report so I did make a controller as:

public class CategoryController : Controller   {

        private IMetricRepository repository;

        public CategoryController(IMetricRepository metricRepository) {
            repository = metricRepository;
        }

        public ViewResult List(string category)   {
             
            IF category is "TOP 10 VISITED PAGES" THEN RUN ITS QUERY OR LINQ CODE
            IF category is "LIST OF UNIQUE VISITORS" THEN RUN ITS QUERY OR LINQ CODE

        }
}

As you notice, it is a simple application and I just need to have code choose and call a query base on selected item or report item from a menu (left column menu on page).  Yes, I can create a static menu in View as:


@Html.ActionLink("New vs Returning", "GetNewVsRetruningUsers", "Metric")
@Html.ActionLink("Total Visits", "GetTop10Page", "Metric")
@Html.ActionLink("Browser", "GetBrowserTypeUsed", "Metric")

Open in new window


but like to be more flexible and also I'm still learning MVC. Please ask me more questions if it is not clear.
Once again I appreciate your help.

Thanks
AK
0
Fernando SotoRetiredCommented:
Is it possible for you to zip up the complete project with a test database so I can run and test on my system?
0
akohanAuthor Commented:
Sure, why not?!!
That's so nice of you. How may I send it over?
0
Fernando SotoRetiredCommented:
Hi akohan;

Well you can't sent it through EE email messaging I got 24 emails with the same message but no files. The first way is to zip the complete project and test database into one zip file and use the attach file link below the "Post a Comment" text box as shown in the image below. The next way if for some reason it does not allow you is to use the EE-Stuff web site which has  the same username and password as here. Once you login to EE-Stuff click on Expert Area Tab at the top left of the page. Then on the next page click on the "Upload a new file" link and follow the instructions on the page. If all else fails you can post to a web site such as Microsoft OneDrive but only if all else fails. For the second and third options please post the link to the downloads so we can download them.
0
akohanAuthor Commented:
Hello Fernando,

I hope all is well. I'm kinda surprised that how you have received 24 emails from me!!! I sent you one to share my email.
No idea why this happened!

OK sure, I will email you the zip file just one question. Where does the database is made by EF? it is not in under the project folder.


Any idea?

Thanks,
Akohan
0
Fernando SotoRetiredCommented:
OK, if your using localdb for development then look here, On my system I found them at the following location.

C:\Users\<USER NAME>\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\Projects

If you can not find them there look in the web.config file under the connectionstring node look at the property AttachDbFileName = " PATH TO LOCATION OF DB ", It could also be in the  App_Data directory.

If you are not using localdb please tell me which SQL Server you are using.
0
akohanAuthor Commented:
Thank you so much! I'll be by my computer tonight and will follow the instructions.

Regards,
Akohan
0
akohanAuthor Commented:
Hello,

No it is not under the path you addressed but also I looked at web.config yet I don't see the property "AttachDbFileName ".  

[i] <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="EFDbContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=Analytics;Integrated Security=True" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <appSettings>[/i]

Open in new window


Any advice? meanwhile, I will be looking for more information on how to find the DB. This EF doesn't make me feel so comfortable first , I'm new to it and when things get automated nobody exactly knows what is happening in the background.




Thanks.
0
akohanAuthor Commented:
Ok found it! it was hidden.
0
Fernando SotoRetiredCommented:
Hi akohan;

Try this path to see if the database file Analytics is there.

C:\Program Files\Microsoft SQL Server\110\LocalDB\Binn

If it is note and you have a 64 bit machine then also try this location.

C:\Program Files (x86)\Microsoft SQL Server\110\LocalDB\Binn

If that also gives no joy try a file system search for the file Analytics.*
0
Fernando SotoRetiredCommented:
Were did you find it so I will know in the future.
0
akohanAuthor Commented:
No, you are right but I guess it is a networking thing.
My username is akohan but I had to look at akohan.companyName folder instead.

I did a search for the DB name and set the Windows Explorer to show hidden files and it was under C:\Users\MyUsernameDot.CompnayName

So nothing new. I had to pay more attention!

I'm uploading them on server then will email it to your EE contact email.

Would that be OK?
0
Fernando SotoRetiredCommented:
I have explained in this post ID: 40280074 how to up load. I do not think EE mail will do it.
0
akohanAuthor Commented:
I read the other day and today Monday forgot about it!
Here is the URL

please let me know if it works or not.

Regards,
Ak
0
Fernando SotoRetiredCommented:
Hi Akohan;

Have downloaded the two zip files and will be looking at them soon.
0
akohanAuthor Commented:
Thank you!!!
0
Fernando SotoRetiredCommented:
The afa.zip file seems to be corrupted with an unknown error. Can you re-zip the project and try again. The DB.zip file came down with no errors and I unzip'ed it without issue.
0
akohanAuthor Commented:
Sure, this is the URL for new zip file, not sure why my upload is super slow!
URL

URL
0
Fernando SotoRetiredCommented:
I get it and was able to un-zip it fine.
0
akohanAuthor Commented:
Great!

Thanks for confirm it.
0
Fernando SotoRetiredCommented:
OK, so lets get on the same page now that I have something to look at.

I see that you have comment out the original EF query we were working on. So what is the current issue you need help with?
0
akohanAuthor Commented:
OK, let's us forget to the statement we had and commented out.
my question is:

How can I click on one of report names on left column and run a specific query?

And see the result on page?

Thanks
0
akohanAuthor Commented:
In fact, I am thinking of something like case statement so that each case will contain or run a unique query to get specific results per report.
0
Fernando SotoRetiredCommented:
When kaufmed asked me to take a look at that this question it was for the Entity Framework part. As I told him I do not know MVC well enough to help with that. I sent him a email to have him help with this part.
0
akohanAuthor Commented:
That is fine I appreciate your concern and help.
The problem is that I'm new to both MVC and EF :)

See, as I said I was trying to invoke a specific linq query base on selected report (listed on left column) which get both MVC and EF involved. OK, I will wait for Kaufmed but if you don't mind I might ask questions related to EF if your time allows.

Once again, I appreciate all your help!

Regards,
ak
0
Fernando SotoRetiredCommented:
Hi akohan;

In you original question you were trying to display cs_username on the page. Here is a way that can be done. Once those changes are made you can click on Unique Users on the left of the screen and the middle should change.

// In this class CategoryController change this method as shown below.

public ViewResult List(string category)
{
    List<String> viewModel = new List<String>();
    viewModel.AddRange(repository.Metrics.Select(u => u.cs_username).ToList<String>());
    
    return( viewModel );
}


// In the view for the above method found in the View folder for Category in List.cshtml make these chanages.

@model List<String>           

<h2>List of Reports</h2>

@{
    ViewBag.Title = "Airforce Tracer";
}

@foreach (var p in Model) { 
    <div id="item">
        <h3>@p</h3>
    </div>
}

Open in new window

0
Fernando SotoRetiredCommented:
I will stick around until the end to help in any way I can. I will also be learning somethings with this question.
0
akohanAuthor Commented:
Thanks. yes, it looks a right way of doing but here is the situation:

This left menu is populated by a controller called NavController so my assumption is we have to call in there, however, when I do so it doesn't like it and throws error as:

The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[System.String]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Afa.Domain.Entities.Category]'.

Either I have to change the design/structure of the application or there is a way to do so.

Just as reminder:

MetricController handles the data item
CategoryController handles the name of categories or reports.
NavController handles the navigation so maybe I have to get rid of it?

Thanks.
0
käµfm³d 👽Commented:
Is the project still available? The link doesn't show anything for me.
0
akohanAuthor Commented:
oh sure I will enable it again.
give me few minutes

Thanks.
0
akohanAuthor Commented:
Hi again Kaufmed

Please try this URL

Please confirm it it working for you and when you are done downloading.
0
käµfm³d 👽Commented:
I grabbed it.
0
akohanAuthor Commented:
Great! thanks to you both for helping!!!
0
käµfm³d 👽Commented:
OK, so here's an example that takes into account what we've discussed. I've started with an action that you haven't implemented yet:  UniqueVisitors (I renamed it a bit, but that's a bit of a stylistic change; you can leave it as "GetUniqueVisitors" if you like...after all, it's your app!). So we create a new view model class to represent what gets put into the view from the database:

using System.Collections.Generic;

namespace Airforcea.WebUI.Models
{
    public class UniqueVisitorsViewModel
    {
        public IEnumerable<string> Usernames { get; set; }
    }
}

Open in new window


It's very simple:  there's only one property. Notice that I've named the view model the same as the view it correlates to. Again, this is stylistic, but it helps clarify what the view the view model applies to. (There could certainly be situations where you share view models between views, but I tend to start simple, and then adjust as necessary.) So, now that I have a view model for my view, what might the view look like?

@model Airforcea.WebUI.Models.UniqueVisitorsViewModel

@{
    ViewBag.Title = "UniqueVisitors";
}

<h2>UniqueVisitors</h2>
@if (Model.Usernames.Any())
{
    <ul>
        @foreach (var username in Model.Usernames)
        {
            <li>@username</li>
        }
    </ul>
}
else
{
    <text>No users found.</text>
}

Open in new window


Again, rather simple. This particular view just checks to see if there are any usernames contained within the model. If there are, then we spit them out as a part of a <ul> element. Otherwise, we simply print out a message that there were no users found. Note the use of the <text></text> tags. These are special tags in Razor. Whenever you use an @ symbol you are introducing server-side code that runs as a part of building the actual HTML that gets returned to the browser. When you have braces (e.g. @{ } ), then you introduce an entire block that is effectively server-side code. While you can include HTML as a part of your server side code, sometimes the Razor parser gets confused, and you have to explicitly tell it that what you just typed is not server-side code but raw text. That is what those special tags do.

Now, we've created a view model as well as a view to display that model. But how do we populate that view model? We obviously have to query the database to fill the view model. So in the controller we might do:

public ViewResult UniqueVisitors()
{
    UniqueVisitorsViewModel viewModel = new UniqueVisitorsViewModel();

    viewModel.Usernames = this.repository.Metrics.Select(metric => metric.cs_username)
                                                    .Distinct()
                                                    .ToList();

    return View(viewModel);
}

Open in new window


Notice above that I create a new instance of my view model class, and then right after I craft the query that goes out to the database. The Select allows me to only pull the cs_username field, and the subsequent Distinct ensures that I only deal in unique values. The ToList is required to force the query to actually execute--neither of the previously-mentioned method will cause query execution. If you don't include the ToList, then you will encounter strange errors pertaining to your context no longer being valid.

So we take the result of the query and assign it to the Usernames property of the view model. Then, we push the view model to the view by passing it to the View call.

So what do we end up seeing? With the current state of the data:

Screenshot
If we modify the data a touch--since your database has NULL for every username at present:

Screenshot
You see a blank in the first spot because I left some of the rows as NULL. You could account for this in your query, of course.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
akohanAuthor Commented:
Thank you dear Kaufmed,

One question only ... the controller you were talking about in your example, is it a new one or you used an existing one?
if existing one then which one?

Regards,
ak
0
käµfm³d 👽Commented:
The Metric controller. You can tell in the URL:

Screenshot
0
akohanAuthor Commented:
oh yes!!! got it this time.
0
akohanAuthor Commented:
One question to add here. Currently you have one column displayed in the report or query and its object name is usernames right?
now if I want to have multiple columns to show on report, I think I don't need to modify the Model. Just have to access to all other columns using the same usernames.ColumnName.

Right?
0
käµfm³d 👽Commented:
I'll expand the example when I get home this afternoon. The short answer is no.
0
akohanAuthor Commented:
Thank you! please take your time.
0
käµfm³d 👽Commented:
My apologies for the delay. I hit the pillow when I got home, and apparently went in to hibernation mode  = )

So, let's extend the example to add in additional information. Recall above that we said we would have a 2nd class that basically mimics the EF entity. We have that above, but now we need to add in the additional columns that we care about. Let's add in IP address and site name. Previously, I made the Usernames property very simple:  it only contains a "list" of strings that represent the usernames of people in the system. But we now want to add in more information about each user. At this point, though, we wouldn't want to just add in more properties to the view model. Rather, we want to modify the Usernames property to reflect that we have additional user information, not just usernames. (I'll explain why in at the end.) So, let's add an additional class that represents user information:

namespace Airforcea.WebUI.Models
{
    public class VisitorModel
    {
        public string Username { get; set; }
        public string IpAddress { get; set; }
        public string SiteName { get; set; }
    }
}

Open in new window


This class captures all of the "user" information for an individual user. Then, since our view model will contain information about all users that have visited us, we tweak that class:

using System.Collections.Generic;

namespace Airforcea.WebUI.Models
{
    public class UniqueVisitorsViewModel
    {
        public IEnumerable<VisitorModel> Visitors { get; set; }
    }
}

Open in new window


We change the Usernames property to a name more fitting, and we change its type from IEnumerable<string> to IEnumerable<VisitorModel>. We next have to change the query to populate this new class. We'll need to modify the Select to create new instances of the VisitorModel class which each contain those bits of information that we care about from the query (i.e. the properties we put into VisitorModel). So:

public ViewResult UniqueVisitors()
{
    UniqueVisitorsViewModel viewModel = new UniqueVisitorsViewModel();

    viewModel.Visitors = this.repository.Metrics.Select(metric => new VisitorModel() { IpAddress = metric.c_ip, SiteName = metric.s_sitename, Username = metric.cs_username })
                                                .Distinct()
                                                .ToList();

    return View(viewModel);
}

Open in new window


Notice that in a LINQ query a Select can basically create anything you like. Here, I create instances of the VisitorModel, whereas previously I was selecting just strings. All of the remaining code in the controller is the same. Now we can modify the view to show this additional information. Previously we had:

@model Airforcea.WebUI.Models.UniqueVisitorsViewModel

@{
    ViewBag.Title = "UniqueVisitors";
}

<h2>UniqueVisitors</h2>
@if (Model.Usernames.Any())
{
    <ul>
        @foreach (var username in Model.Usernames)
        {
            <li>@username</li>
        }
    </ul>
}
else
{
    <text>No users found.</text>
}

Open in new window


...but we no longer have a Usernames property--we now have Visitors. Let's change the view to dump out all of the information that we Selected in the query:

@model Airforcea.WebUI.Models.UniqueVisitorsViewModel

@{
    ViewBag.Title = "UniqueVisitors";
}

<h2>UniqueVisitors</h2>
@if (Model.Visitors.Any())
{
    <ul style="float: left;">
        @foreach (var visitor in Model.Visitors)
        {
            <li>@visitor.Username</li>
        }
    </ul>
    <ul style="float: left;">
        @foreach (var visitor in Model.Visitors)
        {
            <li>@visitor.IpAddress</li>
        }
    </ul>
    <ul style="float: left;">
        @foreach (var visitor in Model.Visitors)
        {
            <li>@visitor.SiteName</li>
        }
    </ul>
}
else
{
    <text>No users found.</text>
}

Open in new window


Here I've added in additional <ul> tags, one for each property of the Visitor that I care about. (I've floated them left just so that each <ul> will be next to each other horizontally rather than vertically.) The results of all of these changes are:

Screenshot
Now, as to why I created an additional class for the visitor information. Your view model class is a class that encompasses all of the data that your view should display. In this simple example, we only had visitor information, but what if we'd also had information about the individual sites that we'd also like displayed? Your view model functions kind of like a container for all of the data items you'd like to show. If each data item has specific elements to it, then it often times makes sense to create a class that represents the data item, and include the specifics in that class. That is what I did with the VisitorModel:  that class captures the specifics about each visitor that I have. Should I want to display site information also, then I would simply create a SiteModel class that represents the specifics about a site. I would then include a Sites property on my view model class to contain all of the sites that I pulled from the database.
0
akohanAuthor Commented:
LOL. I'm glad you did that ... I did the same thing the night before and crashed big time yet my toddler woke me up by 4:30 am and had to entertain him.
Thank you
I will get back to you soon.  I wish I could assign more than 500 score to this thread!
0
akohanAuthor Commented:
Hello Kaufmed,

Sorry for the delay been busy and today I'm getting back to the code again. I just want to thank you for solving the issue and also so much thanks to Fernando for his help and compiling my problem back to you.

I hope I will be in touch with you both and thanks to you both for sharing your knowledge.

Regards,
Ak
0
akohanAuthor Commented:
Cannot thank you enough for solving this!!!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.