1

Hi I'm very new to MVC

Basically what I want in webforms terms is to create a control on the master page that renders on every page associated to it, but in MVC.

So I decided that a view within a view is the best choice because I need a different model and controller than the previous view.

//Model

public class FilterViewModels
    {
        public Int32 CompanyID { get; set; }
        public Int32 ServiceID { get; set; }
        public IEnumerable<SelectListItem> Companies { get; set; }
        public IEnumerable<SelectListItem> Services { get; set; }
    }

//Controller

public ActionResult Filter()
        {
            var query = db.Companies.Select(c => new SelectListItem
            {
                Value = c.CompanyID.ToString(),
                Text = c.Company
                //,Selected = c.CompanyID.Equals(3)
            });

            var query1 = db.Services.Select(c => new SelectListItem
            {
                Value = c.ServiceID.ToString(),
                Text = c.Service
            });

            var model = new FilterViewModels
            {
                Companies = query.AsEnumerable(),
                Services = query1.AsEnumerable()
            };

            return View(model);
        }

//sub view

@model SalesSystem.Models.FilterViewModels

@{
    Layout = null;
}

@using (Html.BeginForm("Filter", "Filter"))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    @Html.DropDownListFor(m => m.CompanyID, Model.Companies)
    @Html.DropDownListFor(m => m.ServiceID, Model.Services)
}

//In Main View

@RenderPage("~/Views/Filter/Filter.cshtml");

But when I run the example I get the error: "Object reference not set to an instance of an object"

The View renders correctly in the actual view but not from the main view because it isn't running the sub views controller.

Is this the wrong way of going about what I'm trying to accomplish?

Anarchy101
  • 315
  • 1
  • 2
  • 8
  • You need to check this link for Basic Asp.Net MVC :https://www.codeproject.com/Articles/866143/Learn-MVC-Project-in-days-Day – Laxman Gite Jun 21 '17 at 12:40
  • Have a look at the MVC layout page. This works like a master page in ASP.NET web forms. – Wheels73 Jun 21 '17 at 12:40
  • @Laxman Gite Thanks I'll have a look at that project – Anarchy101 Jun 21 '17 at 12:42
  • @Wheels73 But the layout doesn't have a controller to pass the populated model class. At least that's how I understand it – Anarchy101 Jun 21 '17 at 12:43
  • @Anarchy101 - You use @{Html.RenderPartial("MyPartialViewControl"); }. This partial view then has whatever links or buttons you need to post to a controller/action. If i've understood your need correctly. :) – Wheels73 Jun 21 '17 at 13:05
  • 2
    @Anarchy101 - You can also use Html.RenderAction("YourAction", "YourController") and have this return a PartialViewResult – Wheels73 Jun 21 '17 at 13:18
  • @Anarchy101 - Have a look at this answer, it might help. https://stackoverflow.com/questions/13225315/pass-data-to-layout-that-are-common-to-all-pages – Wheels73 Jun 21 '17 at 13:20
  • @Wheel73 Thanks the RenderAction was what I needed – Anarchy101 Jun 21 '17 at 13:29
  • @wheel73 If you add it as an answer I will check it – Anarchy101 Jun 21 '17 at 13:46
  • @Anarchy101 you dont have to create new viewmodel for all model or query combinations. You can use dynamic ExpandoObject to achieve your goal – hasan Jun 21 '17 at 17:19

2 Answers2

2

You are trying to combine two query in one viewmodel. I would suggest that using dynamic ExpandoObject to combine two query in one object. This way prevent that creating viewmodel for all query or model combinations.

You can call your partial view with Html.RenderAction("Filter", "YourController") in desired view and You can use this way like following.

//Controller

public ActionResult Filter()
{
   var listCompany = db.Companies.Select(c => new SelectListItem
   {
        Value = c.CompanyID,
        Text = c.Company
   }).ToList();

   var listService = db.Services.Select(c => new SelectListItem
   {
       Value = c.ServiceID,
       Text = c.Service
   }).ToList();

   dynamic yourmodel = new ExpandoObject(); 
   yourmodel.Companies = listCompany;
   yourmodel.Services  = listService;

   return View(yourmodel);


}

// Filter View

@using SalesSystem; // Your Project Name 
@model dynamic

@{
    Layout = null;
}

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    @Html.DropDownListFor(m => m.Value, new SelectList(Model.Companies, "Value", "Text"))
    @Html.DropDownListFor(m => m.Value, new SelectList(Model.Services, "Value", "Text"))
}

// Desired View

@Html.RenderAction("Filter", "YourController")
hasan
  • 3,484
  • 1
  • 16
  • 23
  • Thanks this is very useful but not the answer to my question. Wheels73 gave me the solution – Anarchy101 Jun 22 '17 at 06:41
  • @Anarchy101 your welcome:) and i have updated my answer with Html.RenderAction("Filter", "YourController") – hasan Jun 22 '17 at 06:48
-1

Hi As per my knowledge you are getting this error:"Object reference not set to an instance of an object" because view page is expecting the model but it is not passed. So the solution is change the code like below.

@RenderPage("~/Views/Filter/Filter.cshtml",new {FilterData = Model});

And in the Filter.cshtml,you can access the data using the page property.

Ex:

@Page.FilterData.CompanyID

Useful Link:http://www.dotnetcurry.com/ShowArticle.aspx?ID=646

Additional Info:

You can also call the partial view using the below code:

@Html.Partial("~/Views/Filter/Filter.cshtml", Model)

Or if you want to call an action method from view :

@Html.Action("action", "controller", parameters)

Hope the above information was helpful

Thanks

Karthik

Karthik Elumalai
  • 1,574
  • 1
  • 11
  • 12