Предупреждение
Это некрасивый некрасивый код, который был взломан без тестирования, кроме как заставить его работать должным образом.
VirtualPathProvider
Поскольку мы не имеем делос реальными представлениями на сервере мы должны добавить нашего собственного поставщика пути, чтобы сообщить MVC, где взять наши динамически сгенерированные шаблоны.Должно быть больше тестов, таких как проверка словаря строк, чтобы увидеть, было ли добавлено представление.
public class StringPathProvider : VirtualPathProvider {
public StringPathProvider()
: base() {
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) {
return null;
}
public override bool FileExists(string virtualPath) {
if (virtualPath.StartsWith("/stringviews") || virtualPath.StartsWith("~/stringviews"))
return true;
return base.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath) {
if (virtualPath.StartsWith("/stringviews") || virtualPath.StartsWith("~/stringviews"))
return new StringVirtualFile(virtualPath);
return base.GetFile(virtualPath);
}
public class StringVirtualFile : System.Web.Hosting.VirtualFile {
string path;
public StringVirtualFile(string path)
: base(path) {
//deal with this later
this.path = path;
}
public override System.IO.Stream Open() {
return new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(RazorViewEngineRender.strings[System.IO.Path.GetFileName(path)]));
}
}
}
Класс визуализации
Этот класс принимает ваш шаблон в качестве параметра конструктора и добавляет его вСтатический словарь, который затем читается VirtualPathProvider
выше.Затем вы звоните Render
и можете при желании передать модель.Это добавит полностью определенный тип модели к @inherits
и добавит его к содержимому файла.
public class RazorViewEngineRender {
internal static Dictionary<string, string> strings { get; set; }
string guid;
static RazorViewEngineRender() {
strings = new Dictionary<string, string>();
}
public RazorViewEngineRender(string Template) {
guid = Guid.NewGuid().ToString() + ".cshtml";
strings.Add(guid, Template);
}
public string Render() {
return Render(null);
}
public string Render(object ViewModel) {
//Register model type
if (ViewModel == null) {
strings[guid] = "@inherits System.Web.Mvc.WebViewPage\r\n" + strings[guid];
} else {
strings[guid] = "@inherits System.Web.Mvc.WebViewPage<" + ViewModel.GetType().FullName + ">\r\n" + strings[guid];
}
CshtmlView view = new CshtmlView("/stringviews/" + guid);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.TextWriter tw = new System.IO.StringWriter(sb);
ControllerContext controller = new ControllerContext();
ViewDataDictionary ViewData = new ViewDataDictionary();
ViewData.Model = ViewModel;
view.Render(new ViewContext(controller, view, ViewData, new TempDataDictionary(), tw), tw);
//view.ExecutePageHierarchy();
strings.Remove(guid);
return sb.ToString();
}
}
Global.asax
В вашем файле global.asax вам придетсядобавьте следующее к Application_Start
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new Controllers.StringPathProvider());
Вызов кода
string Template = "Hello, @Model.Name";
Models.User user = new Models.User() { Name = "Billy Boy" };
RazorViewEngineRender view = new RazorViewEngineRender(Template);
string Results = view.Render(user); //pass in your model
Примечания
Этот только работает с типизированными моделями.Я попытался передать новый {Name = "Billy Boy"}, и он выдает ошибки.Я не уверен, почему, и я не слишком углубился в это.
Это было весело, спасибо, что задали этот вопрос.