0

I'm an intern working on some quality-of-life improvements for a site. Nothing essential, but since this is actually going to be deployed I want to keep things tidy.

I need to pull a table from a database, and display it in in a shared header on a site. I already have the database set up, the model getting data from the database, and a test view just to see if it's displaying correctly. However, the model is being passed by the page controller through the viewbag, which I've been told not to do.

So, how can I have my page print out my model data without passing it through a viewbag?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
UIDAlexD
  • 218
  • 2
  • 12
  • 4
    [Use a strongly typed view model to transfer data between your action method and view](http://stackoverflow.com/questions/11262034/mvc-viewbag-best-practice/11262118#11262118) – Shyju Jul 08 '16 at 18:43
  • Pass it through the view bag if that is how it was setup. Who cares. The model is stored in the view bag too! Make it work and move on. – Travis J Jul 08 '16 at 18:53

3 Answers3

2

You can do that using this format

    public ActionResult Index(YourModelHere model)
    {
        return View(model);
    }

In your view, add this

@model yournamespacehere.Models.YourModelHere

UPDATE

Create a new controller for partial view data

//partial view call
public ActionResult GetHeaderPartial()
{
   var model = new DataModel();
   model.data1 = "Menu 1";
   model.data2 = "Menu 2";

   return PartialView("_HeaderPartial", model);
}

Create the Partial View for the shared header. In this example, i've named it as "_HeaderPartial"

@model yournamespace.Models.DataModel

<li><a href="#">@Model.data1</a></li>
<li><a href="#">@Model.data2</a></li>

In your shared header layout, add @Html.Action("GetHeaderPartial","ControllerHere")

<header>
    <div class="content-wrapper">
        <div class="float-left">
            <p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>
        </div>
        <div class="float-right">
            <section id="login">
                @Html.Partial("_LoginPartial")
            </section>
            <nav>
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                    @Html.Action("GetHeaderPartial","Sample")
            </nav>
        </div>
    </div>
</header>
iamrico
  • 161
  • 5
  • If I do this it fails as soon as I change pages, giving me `System.NullReferenceException: Object reference not set to an instance of an object.` It's in a shared header that'll be on every page of the site. ActionResult Index doesn't look like it'll cut it. – UIDAlexD Jul 08 '16 at 19:11
  • You can add @model yournamespacehere.Models.YourModelHere in the shared header – iamrico Jul 08 '16 at 19:14
  • Already done. The pages don't use the same controller. Without ActionResult passing it to the view it's not working. – UIDAlexD Jul 08 '16 at 19:17
  • Try creating a new actionresult that will return a partial view, then load that partial view in your shared header. – iamrico Jul 08 '16 at 19:27
  • @iamrico Your code doesn't make much sense to me. You would rather declare your model inside the body of your method instead of model binding a complex type (in a get method I assume) which will cause difficulties in the model binding process. – hbulens Jul 08 '16 at 19:41
  • @hbulens I know that you can declare the model as a new object, I just thought that he just needs a simple controller action (nothing complex) that's why I used that example. – iamrico Jul 08 '16 at 20:02
0

Here's a good place to start. As the article states, there are basically three ways to pass data to the view:

  • ViewBag
  • Dynamic objects
  • Strongly Typed objects

With the latter approach (generally a good idea), you just have to pass the model instance to the ActionResult you're returning (in your case, that would be a ViewResult instance).

So instead of this....

public ActionResult Index() 
{ 
   ViewBag.Foo= new Foo();
   return View();
}

you do this...

 public ActionResult Index() 
 {
    return View(new Foo());
 }

Make sure your model in the Index view has the following line:

@model Foo

Now you can use Razor or whatever syntax you're using to do what you need to do in your view.

hbulens
  • 1,872
  • 3
  • 24
  • 45
  • Is there any way I can do this without the @model in my view? It's my understanding that you can only have one per view, and there's going to be other data involved. – UIDAlexD Jul 08 '16 at 18:54
  • I don't think so, but there's such thing as ViewModels (a concept familiar in SilverLight and WPF). This is just a regular class that groups all other objects you want to use in your view. See http://www.asp.net/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-3 for more information about view models. – hbulens Jul 08 '16 at 19:22
  • It's a good idea to use ViewModels anyway. That way your view accesses only what it needs, and not everything that the database returns. – Ellesedil Jul 08 '16 at 20:57
0

Setup a view model that is created in the controller and passed to the view. This link will help you!

Steven
  • 150
  • 10