3

I'm trying to pass some data into a ControllerRendering from a Razor view. I tried to pass it along as an object:

@model SBJSitecore82.Areas.Editorial.Models.ViewModels.IssueSectionViewModel[]

@foreach (var issueSection in Model)
{
    @Html.Sitecore().ControllerRendering("Module", "IssueSection", new { area = "Editorial", issueSectionViewModel = issueSection })
}

By in my controller, the object properties are always null, even though they are not null in the Razor view where it called the ControllerRendering.

public ActionResult IssueSection(IssueSectionViewModel issueSectionViewModel)
{
    return View(issueSectionViewModel);
}

So I decided to try to pass the object using the Datasource attribute in the Razor view:

@model SBJSitecore82.Areas.Editorial.Models.ViewModels.IssueSectionViewModel[]

@foreach (var issueSection in Model)
{
    @Html.Sitecore().ControllerRendering("Module", "IssueSection", new { area = "Editorial", Datasource = issueSection })
}

But that just passes a string into the RenderingContext.Current.Rendering.Datasource property. I saw an example where someone passed an ID into the Datasource and I presume they just did a GetItem with that ID. I could do the same, but that seems inefficient when I have a dozen of these items to process.

So the question is, how can I pass these objects over, or can I? Or should I just pass the ID over and retrieve the items?

2
  • 2
    I would ask why you are trying to pass this into a Controller Rendering, if you already have the data, why not just use @Html.Partial and pass the model through?
    – Richard Seal
    Nov 11, 2016 at 14:12
  • Excellent question. I'm new to the Sitecore MVC world and kinda new to MVC all together. I didn't realize that we can mix the 2 worlds so easily. That worked for me, thanks. If you make it an answer, I'll mark it as such.
    – Kevin
    Nov 11, 2016 at 14:58

2 Answers 2

7

The problem here is that a controller rendering in the Sitecore world is not the same as a Controller action result in standard MVC.

So you can't pass data through in the same way without custom code.

From your example, it looks like all you really need to do is use an @Html.Partial to render your other razor view and pass the data through like that. Your controller action is not doing anything with the data.

You're razor would become:

@model SBJSitecore82.Areas.Editorial.Models.ViewModels.IssueSectionViewModel[]

@foreach (var issueSection in Model)
{
    @Html.Partial("~/viewpath/IssueSection", issueSection)
}

I do this a lot for renderings where I have a section that is either in a loop or a small view that can be used in multiple other views.

8

The reason your model isn't being populated is because @Html.Sitecore().ControllerRendering("Module", "IssueSection", new { area = "Editorial", issueSectionViewModel = issueSection }) puts the properties of your anonymous object into the properties dictionary for the controller rendering you're calling, not route data.

The built-in MVC model binders only look at things in the current request (e.g., query parameters, body, route data) to build up action parameters, not rendering properties. You would have to write a custom model binder to do that.

I think Richard's approach will best meet your needs, but if you have some requirement that you need to call the Sitecore rendering pipeline, you can pass your model like this:

View

@model SBJSitecore82.Areas.Editorial.Models.ViewModels.IssueSectionViewModel[]

@foreach (var issueSection in Model)
{
    @Html.Sitecore().ControllerRendering("Module", "IssueSection", new { area = "Editorial", issueSection.Property1, issueSection.Property2, issueSection.Property3 })
}

Controller Action

public ActionResult IssueSection()
{
  var rendering = RenderingContext.Current.Rendering;

  var issueSectionViewModel = new IssueSectionViewModel
  {
    Property1 = rendering[nameof(IssueSectionViewModel.Property1)],
    Property2 = rendering[nameof(IssueSectionViewModel.Property2)],
    Property3 = rendering[nameof(IssueSectionViewModel.Property3)],
  };

  return View(issueSectionViewModel);
}

Note that the rendering properties dictionary only stores string values, so you will have to manually cast other property types (e.g., int, bool, etc.).

1
  • 1
    Fantastic answer. This definitely explains the why it doesn't work. I did take Richard's advice and go with that. I'm still stuck in the Sitecore 6 WebForms world, but started a new project in Sitecore 8 MVC and learning lots.
    – Kevin
    Nov 11, 2016 at 17:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.