10

I want to pass an object Model.AvailableVerticalType along with the expression and templateName in the call to the HTML Helper DisplayFor. Without passing the object, the DisplayFor() syntax looks like this:

@Html.DisplayFor(o => offer, MVC.Shared.Views.DisplayTemplates.OfferDetail)

The OfferDetail template accepts an object of the type Offer only:

@model DGS.DGSAPI.UI.BusinessModels.Offer

So I need a way to send the AvailableVerticleType through the ViewData. Is it possible? What would be the syntax for passing ViewData in DisplayFor()?

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Multi stack
  • 311
  • 3
  • 9
  • 18
  • 1
    Is the object part of your model, or have you added in using `ViewBag` of `ViewData` in the GET method? Note that its [this overload](https://msdn.microsoft.com/en-us/library/system.web.mvc.html.displayextensions.displayfor(v=vs.118).aspx#M:System.Web.Mvc.Html.DisplayExtensions.DisplayFor``2%28System.Web.Mvc.HtmlHelper{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.String,System.Object%29) that you want –  Jun 10 '16 at 07:13
  • `Model.AvailableVerticalType` is part of the model – Multi stack Jun 10 '16 at 07:14
  • 17
    To pass it you would use `@Html.DisplayFor(o => offer, MVC.Shared.Views.DisplayTemplates.OfferDetail, new { data = Model.AvailableVerticalType } )` and then in the template you can access it using `(yourType)ViewData["data"]` –  Jun 10 '16 at 07:18
  • @StephenMuecke Thanks! – Multi stack Jun 10 '16 at 08:05
  • 2
    @StephenMuecke, if that's the answer, please post it as an answer. – Kevin Apr 26 '18 at 14:44

2 Answers2

6

As suggested by user3559349, you can pass an anonymous object into the DisplayFor() method and that get's to be a part of the ViewData dictionary.

In your view:

@Html.DisplayFor(o => offer, "OfferDetail", new {AvailableVerticalType = Model.AvailableVerticalType }

In your OfferDetail template:

(AvailableVerticalType)ViewData["AvailableVerticalType"]

You could also just create a partial view that has a model declared for the AvailableVerticalType and reference that in your main view.

@model AvailableVerticalType

2

You pass it in ViewDataDictionary, example below:

// optional: if you don't want to use "AdditionalData" magic string
public static class ViewDataKeys
{
    public const string AdditionalData = "AdditionalData";
}

We can use the 2nd overload of DisplayFor and pass the additional data in ViewDataDictionary:

@Html.DisplayFor(m => m.MyModel, new ViewDataDictionary { { ViewDataKeys.AdditionalData, "additional-value" } })

And in your DisplayFor template you can access the ViewDataDictionary like this:

@{
    string additionalData = ViewData[ViewDataKeys.AdditionalData];

    /*
     * if you need to cast the data type:
     * var additionalData = (AdditionalDataType)ViewData[ViewDataKeys.AdditionalData];
     */
}

You can also pass multiple additional data, for example:

@Html.DisplayFor(m => m.MyModel, new ViewDataDictionary { 
    { ViewDataKeys.AdditionalData1, "additional-value1" },
    { ViewDataKeys.AdditionalData2, "additional-value2" }
})

Keeping in mind that it is always better to pass the data in a Model.

Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
  • To me, this is a bit of an XY problem, which the last line of your question really gets to the heart of. The OP is asking about the `ViewData` because they don't know _how_ to pass the data as part of their _model_. Given that, is there a way to extend the model while still relying the expression bindings necessary for the `DisplayFor()` template to properly assess e.g. validation attributes on the original target property? (I'm not certain there is, which thus necessitates the use of `ViewData`.) – Jeremy Caney Jun 27 '20 at 21:06