11

I currently have a controller with a LINQ statement that i am passing data from to my view. I am trying to find a more efficient and better coding method to do this. My home controller statement is as follows.

Var Melt
  Furnace1 =
           (from item in db.tbl_dppITHr
           where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
           select item).Sum(x => x.Furnace1Total),

ViewData["Furnace1Total"] = Melt.Furnace1;

In my view i then reference the ViewData To show this. Using

 @model dynamic

Now i have quite alot of linq statements inside the Index method. And for each one i am doing the ViewData[]

I am hoping that someone can show how i pass more than one var from a controller across to a view without the ViewData or ViewBag methods. And how i would get access to this within my view.

Darren
  • 68,902
  • 24
  • 138
  • 144
Inkey
  • 2,189
  • 9
  • 39
  • 64

5 Answers5

11

You should create a ViewModel with all of your data needed and then pass that down to the view.

public class ViewModel 
{
   public List<int> Melt1 { get; set; }

   public void LoadMeltProperties() 
   {

       if (Melt1 == null) 
       {
          Melt1 = new List<int>();
       }

       Melt1 = (from item in db.tbl_dppITHr
       where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
       select item).Sum(x => x.Furnace1Total).ToList();
   }

   public ViewModel Load()
   {
       LoadMeltProperties();
       return this;
   }
}

public ActionResult YourControllerAction() 
{
      var vm = new ViewModel().Load();
      return View("ViewName", vm);
}

Then in your View you can use a strongly typed model rather than dynamic

@model ViewModel

You can then iterate over your ViewModel properties via:

foreach(var melt in Model.Melt1) {
     // do what you require
}
Darren
  • 68,902
  • 24
  • 138
  • 144
  • don't you missed the `Model.` in `foreach(var melt in Melt1)`? – sasjaq Sep 04 '13 at 08:26
  • I have a model created so is best practice for me to do my LINQ code inside the model in a new method and call that from the controller to pass to view? – Inkey Sep 04 '13 at 08:37
  • @Inkey - yes. I have created a `Load` method for you. You can put each of your LINQ code in new methods and then invoke these methods in the `Load` definition, then your Model will automatically pick up the new properties/methods. – Darren Sep 04 '13 at 08:41
  • One last query i have sorry. I am using Entity FrameWork and have the Model Class generated for me so all the get; set; properties created for the melt table. Do i need to create a new model class or just code inside the model class created from Entity Framework – Inkey Sep 04 '13 at 08:47
  • 1
    @Inkey - you can extend the existing class if that's easier for you. However I'd personally keep the EF entities in a separate file (kinda like DTO objects and then a new ViewModel that accesses the EF created objects). That way you have a pure data access layer, business logic layer and then the View which is the presentation layer, much more `n tier` architecture. – Darren Sep 04 '13 at 08:50
  • Some of my data types are nullable this is affecting the var vm = new ViewModel().Load(); with the following error Cannot assign void to an implicitly-typed local variable – Inkey Sep 04 '13 at 10:15
  • `Load` is a void, my bad. I have updated the code to return an instance of `ViewModel`. – Darren Sep 04 '13 at 10:20
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/36779/discussion-between-inkey-and-darren-davies) – Inkey Sep 04 '13 at 11:32
  • I get namespace "ViewModel" could not be found. – Demodave Jan 21 '15 at 17:48
6

IMHO, you should create a ViewModel an pass data using it.

Create a class

public class MyViewModel
{
    public <MeltFurnace1Type> MeltFurnace1{get;set;}
}

In Action Method

public ActionResult Action() 
{
      MyViewModel vm = new MyViewModel();
      vm.MeltFurnace1 = something;
      return View("YourViewName", vm);
}

In View

@model MyViewModel

//You can access your property using
Model.MeltFurnace1
Satpal
  • 132,252
  • 13
  • 159
  • 168
2

If you need to pass data actually from the controller and its data is depend on internal state or input controller parameters or has other properties of "business data" you should use Model part from MVC pattern:

Model objects are the parts of the application that implement the logic for the application's data domain. Often, model objects retrieve and store model state in a database. For example, a Product object might retrieve information from a database, operate on it, and then write updated information back to a Products table in a SQL Server database.

You can see details here or look to the Models and Validation in ASP.NET MVC part of Microsoft tutorial.

  1. Add model class:

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string City { get; set; }
    }
    
  2. Pass model object to the view:

    public ActionResult Index()
    {
        var model = GetModel();
        return View(model);
    }
    
  3. Add strongly typed View via define model type:

    @model Person
    
  4. Use Model variable in your view:

    @Model.City
    
Community
  • 1
  • 1
Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
1

Use models instead

var Melt
 Furnace1 =
       (from item in db.tbl_dppITHr
       where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
       select item).Sum(x => x.Furnace1Total),
return View("SomeVIew",MeltFurnace1)

In view@model "TypeOfMeltFurnace1"

You can reference model in view by property Model

vborutenko
  • 4,323
  • 5
  • 28
  • 48
0

If someone is still looking for options…

You also can pass object from Controller to View, if you don’t use any particular Model for the View. To pass just a single (or maybe few) parameter from the Controller to the View, you can do it inside View() Method. In the Controller:

public async Task<IActionResult> Update(int id)
{           
    return View(new { Id = id });            
}

Then in the View you can access your parameter like this (assuming you don’t use any other Model inside your View):

<div>
    @Html.ActionLink("Link name", "ControllerMethod", "ControllerName", new { id = (int)Model.Id })   
</div>

Otherwise, like already mentioned, pass your model inside View() Method.

b_scored
  • 11
  • 1