views:

64

answers:

2

Hi,

I have a tricky problem and I'm not sure where in the view rendering process to attempt this. I am building a simple blog/CMS in MVC and I would like to inject a some html (preferably a partial view) into the page if the user is logged in as an admin (and therefore has edit privileges).

I obviously could add render partials to master pages etc. But in my system master pages/views are the "templates" of the CMS and therefore should not contain CMS specific <% %> markup. I would like to hook in to some part of the rendering process and inject the html myself.

Does anyone have any idea how to do this in MVC? Where would be the best point, ViewPage, ViewEngine?

Thanks,

Ian

A: 

You could use Html.RenderPartial to insert an HTML fragment somewhere in the page. If you want to insert it in a place not available to the view but only on the master you could place a <asp:ContentPlaceHolder ID="Admin" runat="server" /> placeholder inside the master and in the view simply override it and insert the partial. If placing such a placeholder is not acceptable you could use AJAX like: $('#adminHolder').load('/home/admin');, but I would probably go with the previous approach as it will work in case the user has javascript disabled.

Darin Dimitrov
But in the CMS the views and masterpages are made by the template creator. I can't rely on them adding the correct Html.RenderPartial. That's why I really need it to be programmatic.
madcapnmckay
The two things are tightly related. I am not aware of any method to achieve this programmatically without touching any of the views. And isn't the template creator to decide where to insert the proper HTML fragments?
Darin Dimitrov
This injected html is not part of the template. It contains an admin interface and just need to be inserted at the end of the body to appear as a modal popup. If this were a classic webforms app, you would add a basepage with an overridden OnPreRender method that inserts a control in the body. There must be a way to do something similar in MVC.
madcapnmckay
A: 

OK this took a bit of messing and the result is a little hacky. But it works and that's all that matters right....

    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
        if (!User.Identity.IsAuthenticated || !User.IsInRole("Admin"))
        {
            // If not admin continue as normal
            base.Render(writer);
            return;
        }

        // Taking a leaf out of the move viewstate to the bottom of page playbook
        var stringWriter = new System.IO.StringWriter();
        var htmlWriter = new HtmlTextWriter(stringWriter);
        base.Render(htmlWriter);
        var html = stringWriter.ToString();
        var endOfBody = html.IndexOf("</body>") - 1;
        if (endOfBody >= 0)
        {
            var adminConsole = Html.RenderPartialAsString("AdminPanel");
            html = html.Insert(endOfBody, adminConsole);
        }
        writer.Write(html);
    }

I implement my own ViewPage overriding the Render method. This checks if the user is logged in as an admin and if they are, it renders a partial at the bottom of the page. Very similar to old skool viewstate hacks in webforms.

Enjoy.

madcapnmckay