November Happy Hour will be moved to Thursday December 5th.

Block template selection when using a controller

Vote:
 

Another question for you guys!

Say I have defined a NewsBlock which has its own NewsBlockController. This controller fetches some pages, does some logic etc and maps the data to a simple view model, NewsViewModel, which is rendered in a Views/NewsBlock/Index.cshtml (typed to NewsViewModel). This works fine, everything as expected.


Now, on some pages (where I have the NewsBlock as a local property), I would like render the block slightly different, using another template. All I want to do is to trigger the use of another .cshtml-file (but still go via the same controller and view model). I thought I could solve this by introducing a tag like this:

@Html.PropertyFor(m => m.NewsBlock, new { Tag = "Condensed" })

and register another template (I'm using the TemplateCoordinator class as in the Alloy project) something like this:

...

viewTemplateModelRegistrator.Add(typeof(NewsBlock), new TemplateModel
{
Name = "NewsCondensed,
Inherited = true,
Tags = new[] { "Condensed" },
AvailableWithoutTag = false,
Path = "~/Views/NewsBlock/Condensed.cshtml"
});

But obviously, this isn't quite right! First of all, if I trigger this specific template (by using the "Condensed" tag), it wouldn't involve the NewsBlockController, it goes directly for partial view. Secondly, the Condensed.cshtml expects a NewsViewModel, not a NewsBlock type (resulting in an exception).


Any suggestions how to solve this? Do I need to duplicate the controller (and decorate it with another tag using the TemplateDescriptor attribute)? :/ 

 

 

 

#80953
Feb 05, 2014 16:27
Vote:
 

In a block controller you can get the view data from the "main" view (a block controller is called through a child action call). So you could have a view like eg:

@Html.PropertyFor(m => m.CurrentPage.MyBlock, new { View = "Condensed" })

then in the block controller you could check if the parent context has a value for the property (View in this case) as:

 public override ActionResult Index(TestBlock currentBlock)
        {
            var parentContext = this.RouteData.DataTokens["ParentActionViewContext"] as ViewContext;
            if (parentContext != null)
            {
                var viewName = parentContext.ViewData["View"] as string;
                if (!String.IsNullOrEmpty(viewName))
                {
                    return PartialView(viewName, currentBlock);
                }
            }

            return PartialView(currentBlock);
        }

    

#80972
Feb 06, 2014 9:50
Vote:
 

Thanks,

Yes, I figured I could pass the viewdata myself. I was hoping for a more "built-in" way of doing it, but this will be good enough!

#80977
Feb 06, 2014 11:31
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.