Can I pass both the ViewBag AND a Model to a View

2k views Asked by At

Can I use a hybrid approach that passes information in the ViewBag (C#) / ViewData (VB) but also includes a model

For example, I started passing a simple title through an error controller to an error view:

Function NotFound() As ActionResult
    Response.StatusCode = 404
    ViewData.Add("Title", "404 Error")
    Return View("Error")
End Function

This worked fine and the View had access to the property @ViewData("Title")

Then I wanted to include some of the exception information that is automatically routed by Custom Errors in the HandleErrorInfo object like this:

Function NotFound(exception As HandleErrorInfo) As ActionResult
    Response.StatusCode = 404
    ViewData.Add("Title", "404 Error")
    ViewData.Add("Message", "Sorry, the requested page could not be found.")
    Return View("Error", exception)
End Function

Then, on the View, I declared a Model like this:

@ModelType System.Web.Mvc.HandleErrorInfo

Now I can access properties like @Model.Exception.Message but my @ViewData("Title") has disappeared.

The WebViewPage(Of TModel) still has a ViewData property, but it looks like I can't pass anything to it from the controller unless it's explicitly in the model.

Of course, as a workaround, I could create a base class that can strongly type storage for each object, but that seems a little heavy handed when all I want to pass in through the ViewBag is the title.

Is there a way to use both ViewBag AND the Model at the same time?

1

There are 1 answers

0
KyleMit On BEST ANSWER

What was happening in this case was that when the CustomErrors tried to route to the NotFound action on the Error controller, it could only supply the default constructor. Not finding one, it bypassed the controller altogether and went directly to the error page which already had the model it wanted to pass ready.

As a small Proof of Concept, passing both parameters is definitely possible as evidenced by this example

TestModel.vb:

Public Class TestModel
    Public Property ModelInfo As String
End Class

TestController.vb:

Public Class TestController :  Inherits System.Web.Mvc.Controller

    Function Index() As ActionResult
        Dim model As New TestModel With {.ModelInfo = "Hello"}
        ViewData("ViewDataInfo") = "World"
        Return View("Index", model)
    End Function

End Class

Test\Index.vbhtml:

@ModelType TestModel

@Model.ModelInfo @ViewData("ViewDataInfo")