3

I have a partial view with a controller with outputCache on as I need to cache this element.

Then I need to render this PartialView in every page, but first I need to do some string replacement.

So my question is, howdo I get a Partial View in a controller so I can manipulate the content and do some string replacement before returning it to the View?

Thanks

3 Answers 3

8

I use these methods on my custom Controller base.

    public string RenderPartialToString(string partialViewName, object model)
    {
        InvalidateControllerContext();
        IView view = ViewEngines.Engines.FindPartialView(ControllerContext, partialViewName).View;
        string result = RenderViewToString(view, model);
        return result;
    }

    public string RenderViewToString(string viewName, object model)
    {
        InvalidateControllerContext();
        IView view = ViewEngines.Engines.FindView(ControllerContext, viewName, null).View;
        string result = RenderViewToString(view, model);
        return result;
    }

    public string RenderViewToString(IView view, object model)
    {
        InvalidateControllerContext();
        string result = null;
        if (view != null)
        {
            StringBuilder sb = new StringBuilder();
            using (StringWriter writer = new StringWriter(sb))
            {
                ViewContext viewContext = new ViewContext(ControllerContext, view, new ViewDataDictionary(model), new TempDataDictionary(), writer);
                view.Render(viewContext, writer);
                writer.Flush();
            }
            result = sb.ToString();
        }
        return result;
    }

    private void InvalidateControllerContext()
    {
        if (ControllerContext == null)
        {
            ControllerContext context = new ControllerContext(System.Web.HttpContext.Current.Request.RequestContext, this);
            ControllerContext = context;
        }
    }

The InvalidateControllerContext method is meant for the scenario where you need to instance Controllers manually in order to render partials or views outside of the context of a controller.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks - where would you put these methods though?
Like I mentioned, on the base controller
2

No, don't do this. Your controller should not render your View, that's the job of the templating engine.

Pass the "replacement" values as a model to your PartialView.

public ActionResult SomeAction()
{
  SomeModelmodel = new SomeModel(); // your model
  return PartialView(model); // partial view with your model
}

And the Partial View:

@model SomeModel

<div>Replace your values with @Model.Value instead of String.Replace().</div>

4 Comments

yes this would work, but in my case I need to cache the PartialView as is an external component loaded from another website. I don't see how I could keep it cached otherwise...
You can cache by various parameters. See the VaryBy properties.
ah! that might help - I'll give it a go
an observation!!. you've actually really clarified your question in this comment (i.e. that you get the content from another website and can't change the model). why not update your question to reflect the entire use case here and i'm sure the answers will more closely match your requirement!!..
0

Just wanted to share a modification to @Nico's solution, if you want to use ViewBag data from your controller action then change RenderViewToString as follows, I use controller.TempData instead of new TempDataDictionary().

public string RenderViewToString( IView view, object model)
{
    InvalidateControllerContext();
    string result = null;
    if (view != null)
    {
        StringBuilder sb = new StringBuilder();
        using (StringWriter writer = new StringWriter(sb))
        {
            // use TempData from controller
            ViewContext viewContext = new ViewContext(ControllerContext, view, 
                new ViewDataDictionary(model), this.TempData, writer);
            view.Render(viewContext, writer);
            writer.Flush();
        }
        result = sb.ToString();
    }
    return result;
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.