david
david

Reputation: 33

MVC5 MVCGRID Linq multiples tables

Im working with ASPNET MVC5 and i just Followed this tutorial : http://www.c-sharpcorner.com/UploadFile/4d9083/creating-simple-grid-in-mvc-using-grid-mvc/ and it works fine. I now want to update my HomeController with 2 tables (Users & Roles), Note : My Datacontext contains 2 tables (Users & Roles)

HomeController.cs

 public ActionResult Details()
        {
            DataClassesUserDataContext db = new DataClassesUserDataContext();
            var SchemeList = from d in db.AspNetUsers
                             join i in db.AspNetUserRoles
                               on d.Id equals i.UserId
                             select new { AspNetUsers = d, AspNetUserRole = i };
            return View(SchemeList);
        }

I return good my results

Now in my View :

My Details.cshtml Is the probleme here ? can i call shanuMVCUserRoles.DB.AspNetUser & AspNetUserRoles ???

@model IEnumerable <shanuMVCUserRoles.DB.AspNetUser>
// possible to add other models here ? @model IEnumerable <shanuMVCUserRoles.DB.AspNetUserRole >


  >  <div
    > class="code-cut">
    >     @Html.Grid(Model).Columns(columns => {
    >     columns.Add(c => c.UserName).Titled("UserName").Filterable(true);
    >     columns.Add(c => c.Id).Titled("ID").Filterable(true);
    >     columns.Add(c => c.PasswordHash).Titled("PasswordHash").Filterable(true);
    >     columns.Add(c => c.Email).Titled("Email").Filterable(true);
    >     columns.Add(c => c.AccessFailedCount).Titled("AccessFailedCount").Filterable(true);
    >     columns.Add(c => c.PhoneNumber).Titled("PhoneNumber").Filterable(true);
    >     columns.Add()
    >     .Encoded(false)
    >     .Sanitized(false)
    >     .SetWidth(30)
    >     .RenderValueAs(o => Html.ActionLink("Edit", "Edit", new { id = o.Id })); }).WithPaging(10).Sortable(true) </div>

i have the following error : The model item passed into the dictionary is of type 'System.Data.Linq.DataQuery1[<>f__AnonymousType42[shanuMVCUserRoles.DB.AspNetUser,shanuMVCUserRoles.DB.AspNetUserRole]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[shanuMVCUserRoles.DB.AspNetUser]'.

Upvotes: 0

Views: 315

Answers (2)

PSkalka
PSkalka

Reputation: 147

I have edited my previous answer with some information about how the Controller could be implemented. The NullReferenceException happens because returning

return View();

provides a null model to the View, so Model.Users and Model.Roles cause the NullReferenceException in your View. Please note that I am returning

return View(model);

in my HomeController.

Just let me add that I avoid using DbContexts in my controllers. I prefer implementing the Repository pattern. You can find a nice example here: http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application It is a better approach because it allows you to create a Test project and to test your controllers by providing mock repository implementations.

Upvotes: 0

PSkalka
PSkalka

Reputation: 147

you could workaround the problem by putting your AspNetUserRoles collection into ViewBag. This link shows this solution among others: http://www.codeproject.com/Articles/687061/Multiple-Models-in-a-View-in-ASP-NET-MVC-MVC

Personally, I consider the Model as a kind of contract between my Controller and my View, so I do not like putting business information outside the Model. For example, it would be ok to store a string to format DateTimes into the ViewBag. But if I want a Controller and a View to manage Users and Roles, I want it to be clear for me and for anybody else reading the code, which can happen today, tomorrow or in ten years.

So in this case I would create a Model class:

namespace WebApplication1.Models
{
    public class UsersAndRolesModel
    {
        public IList<shanuMVCUserRoles.DB.AspNetUser> Users { get; set; }
        public IList<shanuMVCUserRoles.DB.AspNetRole> Roles { get; set; }
    }
}

I would create it and populate it in my Controller. Then in my View I would declare:

@model WebApplication1.Models.UsersAndRolesModel

and finally my grids:

@Html.Grid(Model.Users).Columns(columns => { // and so on...

@Html.Grid(Model.Roles).Columns(columns => { // and so on...

I hope this helps.

Editing: Hi David, it depends on what you actually want to do: do you want a View showing two tables, one for all the users and one for all the roles? In this case, a first implementation could (but should not) be:

    public ActionResult Details()
    {
        UsersAndRolesModel model = new UsersAndRolesModel();
        DataClassesUserDataContext db = new DataClassesUserDataContext();
        model.Users = db.AspNetUsers.ToList();
        model.Roles = db.AspNetUserRoles.ToList();
        return View(model);
    }

I wrote should not be because DataClassesUserDataContext must be disposed after usage. So what you really should do is:

public class HomeController : Controller
{
    private DataClassesUserDataContext db = new DataClassesUserDataContext();

    public ActionResult Details()
    {
        UsersAndRolesModel model = new UsersAndRolesModel();
        model.Users = db.AspNetUsers.ToList();
        model.Roles = db.AspNetUserRoles.ToList();
        return View(model);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }

}

Upvotes: 0

Related Questions