I'm trying to create a re-usable widget in a stand-alone project that I can reference in other solutions in the future.
I would like to achieve the following:
- In my MVC project, I can call out to a helper method contained in my class library (separate project) which will generate the HTML I need. (This is already implemented).
- HTML returned is currently hard-coded in the class (bad). The HTML should not be hard-coded within a class, but instead should use the razor view engine to generate the HTML. It should do this using a .cshtml file contained within the class library itself.
Solution structure is as follows:
Shared-UI (class-library)
/ Views
/ DataGrid
/ _DataGrid.cshtml
/ Models
/ DataGridModel.cs
/ Widgets
/ DataGrid.cs
ViewUtils.cs
Site (Actual MVC site)
/ Controllers
/ HomeController.cs
/ Views
/ Home
/ Index.cshtml
Currently the Index
view in the site project is creating a new instance of the DataGrid
object from the Shared-UI project. Calling ToString()
on this object returns currently some hard-coded HTML.
As the HTML is getting quite complex, I want this to be generated via Razor
using the DataGridModel
and the _DataGrid
partial view, instead of being hard-coded within the class.
I'm trying to use the following method in my ViewUtils
class to achieve this:
public static string RenderPartialToString(string controlName, object viewData)
{
ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
viewPage.ViewData = new ViewDataDictionary(viewData);
viewPage.Controls.Add(viewPage.LoadControl(controlName));
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
viewPage.RenderControl(tw);
}
}
return sb.ToString();
}
I am calling this from the .ToString()
method of my DataGrid
class:
public override string ToString()
{
DataGridModel model = new DataGridModel();
model.Id = this.Id;
string html = ViewUtils.RenderPartialToString("_DataGrid", model);
return html;
}
However this throws an HttpException
when I try and call viewPage.LoadControl(controlName)
, because the _DataGrid
view cannot be found (The file '/_DataGrid' does not exist.
). I have a feeling that it is searching for views in my site project, not in the shared library - but this is just a guess. (I have tried many different combinations of the view path, including/excluding full paths and/or file extensions).
Does anyone know how to get a class library to return HTML generated by Razor using a view contained in it's own library project?