Использование Razor View Engine по-другому - PullRequest
18 голосов
/ 28 сентября 2010

Я подумал, что было бы интересно использовать новый движок MVC Razor View в качестве технологии слияния. Он по-прежнему может быть частью веб-сайта MVC и не обязательно должен быть автономным консольным приложением.

Пример:

string  myTemplate = "Hello @Name,  How are you today?";
ViewModel.Name = "Billy Boy";
string output = RazorViewEngineRender( myTemplate, ViewModel );

Тогда string output = "Hello Billy Boy, How are you today?"

Главное, я хочу, чтобы шаблон управлялся из строки, а не из представления или частичного представления.

Кто-нибудь знает, возможно ли это?

UPDATE:

Бен и Мэтт создали проект на codeplex: http://razorengine.codeplex.com/

Ответы [ 2 ]

17 голосов
/ 28 сентября 2010

Предупреждение

Это некрасивый некрасивый код, который был взломан без тестирования, кроме как заставить его работать должным образом.

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"}, и он выдает ошибки.Я не уверен, почему, и я не слишком углубился в это.

Это было весело, спасибо, что задали этот вопрос.

5 голосов
/ 28 сентября 2010

Бритва была разработана с учетом автономной работы. Об этом режиме пока нет много документации (так как он все еще находится в стадии разработки), но посмотрите на это сообщение в блоге Эндрю Медсестра: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...