Selectively remove theme/layout from admin controllers

Topics: Writing modules
Aug 3, 2011 at 2:40 PM

I have a part that pops open a fancybox from the EditorTemplate which renders an action off of one of my admin controllers.  When the action renders the view, it pulls in the admin theme.  Is there a way to suppress the layout for an action or a view so that my content shows up without the header/footer/menu/etc? 

Coordinator
Aug 3, 2011 at 9:44 PM

Could your controller action be returning a ShapeResult?

Aug 4, 2011 at 1:52 AM

Are you saying I should try that? Right now it returns an ActionResult....

Coordinator
Aug 4, 2011 at 2:02 AM
No. Just checking. Is your action themed?

Sent from my TI-99/4A

From: tjans
Sent: Wednesday, August 03, 2011 6:53 PM
To: Bertrand Le Roy
Subject: Re: Selectively remove theme/layout from admin controllers [orchard:267592]

From: tjans

Are you saying I should try that? Right now it returns an ActionResult....

Aug 4, 2011 at 2:11 AM

Nope, there's nothing on the action, just returns an ActionResult...I swear one time I had the opposite effect, it was not theming and I had to do something to make it happen. Now it's the other way around...  

Coordinator
Aug 4, 2011 at 4:00 AM

Can you maybe try to return something a little more specific than ActionResult?

Aug 4, 2011 at 4:37 AM

Like what? It's a controller action, isn't an ActionResult a pretty standard return type? What type of object are you thinking?

Coordinator
Aug 4, 2011 at 6:41 AM

I don't know, I ;m thinking out loud. ActionResult is relatively abstract. You could test a custom result type that executes as a plain string to see if it makes a difference, for debugging purposes. I'm not sure what's going on here. Then again, I *never* use RenderAction.

Aug 4, 2011 at 2:05 PM

I was away from my dev machine last night, so all I could do was post...I just got back and tried to return a string and sure enough, it's not themed...so something with ActionResult causes the theme to be applied, it seems.

Aug 4, 2011 at 2:09 PM

I got it to work using:

public PartialViewResult ReviewRequest(int id)
        {
            var users = _cms
                .Query<UserPart, UserPartRecord>()
                .List();

            var model = new ViewModels.PublishFlow
            {
                UserList = new SelectList(users, "Id", "UserName")
            };
            return PartialView(model);
        }

Aug 4, 2011 at 2:29 PM

Of course, now I don't have my stylesheet, so I'll need a way to reference the stylesheet that resides in my theme....can this popup still do that even though it doesn't really have a "theme" anymore?

Coordinator
Aug 4, 2011 at 6:35 PM

Yes, that will be a problem. You could probably hack something together by accessing the layout and/or resource manager through the WorkContext but that would probably mix concerns a little more than reasonable.

Did you consider the possibility of creating a simple helper that populates a shape, and then call Display on that? It would be much more Orchard-like, would enable you to override templates as usual, and would be much cleaner across the board.

Aug 4, 2011 at 6:48 PM

Can I do that from a controller?

So, build a shape, call display on the shape, and then return the ShapeResult?  Why would I need a helper method?  Is this better because a shape takes on the style from the layout but doesn't include the headers/footers like a full page would?

If I can get a clearer picture of where you're taking this, I can decide if it might actually work for us. I'm all for a cleaner, more orchard-like solution...

Aug 4, 2011 at 6:50 PM

Also, not sure if this matters, but just for the sake of clarity, this is in the admin...

Coordinator
Aug 5, 2011 at 7:55 PM

Well, my question really would be why do you want to use RenderAction for that in the first place?

Aug 8, 2011 at 1:28 PM

I'm not using RenderAction.  Here's what I have:

The editor template for the part:

 

@{
     Style.Require("FancyBox");
     Script.Require("jQuery");
     Script.Require("FancyBox");
}

@using (Script.Foot())
{
<script type="text/javascript">
    $(document).ready(function () {
        $('#SubmitButton').click(function () {
            $.fancybox({
                'width': '200',
                'height' : '200',
                'type': 'iframe',
                'href': '@Url.Action("ReviewRequest", "Admin", new { id = Model.ContentItemRecord.Id, area = "PublishFlow" })'
            });
        });
    });
</script>
}
    
<fieldset class="publish-flow">  
    <legend>@T("Publish flow")</legend>
    <button type="button" id="SubmitButton">Request a Review</button>
    Assigned to: @(Model.AssignedUser != null ? Model.AssignedUser.UserName : "unassigned") 
</fieldset>

The controller/action that the FancyBox opens:

[HttpPost]
        public PartialViewResult ReviewRequest(int id, ViewModels.PublishFlow model)
        {
            if (ModelState.IsValid)
            {
                var user = _orchardService.WorkContext.CurrentUser;
                var contentItem = _contentItemRepository.Get(id);
                var requestUser = _userRepository.Get(model.AssignedUserId);

                CreateNewRecord(model);

                // Send email notification to new reviewer
                if (requestUser.Email != string.Empty) SendEmail(requestUser.Email, model.Note, contentItem.Id);

                return PartialView("ReviewRequestComplete");
            }

            // We only got here if the ModelState was invalid
            var users = _cms
               .Query<UserPart, UserPartRecord>()
               .List();

            model.UserList = new SelectList(users, "Id", "UserName");

            return PartialView(model);
        }

 

@using (Html.BeginFormAntiForgeryPost())
{
    @Html.ValidationSummary(false)
    
    <fieldset>
        <legend>Request a Review</legend>

        <p>Assign to</p>
        @Html.DropDownList("AssignedUserId", Model.UserList, "Select...")
        
        <p>Notes</p>
        @Html.TextArea("Note")

        <p>
            <button type="submit">Save</button>
        </p>
    </fieldset>
}

 

I hope that explains it a little better...

Coordinator
Aug 8, 2011 at 10:15 PM

OK, yes, not at all what I thought you were doing. so what doesn't work?

Aug 9, 2011 at 1:12 PM

Well, the biggest problem is that in the popup, it was putting the admin headers/footers around my content.  I wanted to just pull in my content without a theme. So, when I did a RenderPartial, it removed the theme, but then I wasn't able to pull in my stylesheet.  I opted instead to not use the popup and instead pull everything into my part, so it all does it inline on a save of my content item.

So, the original issue is moot, though I'd still like to know how to accomplish it in case we need it for some other task.  I'm running into some other issues related to this issue, but I'm going to work on them a bit first before I post more details.

Aug 9, 2011 at 2:16 PM

Alright, I can't figure it out, and rather than hijack this post with unrelated subject matter, I've created a new post here:

http://orchard.codeplex.com/discussions/268378