"自定义环境"中的Razor不接受@model指令

Rop*_*tah 5 .net razor

我正在尝试在沙盒环境中解析和编译Razor模板,也就是基于信息的自定义主机(架构见下文).

我有麻烦越来越智能感知工作,所以我指定BuildProvider的规定在这里和接下来的" 解决办法在这个问题的答案提供".

@model MyAssembly.MyModelintellisense上给出以下错误:

无法加载文件或程序集"System.Web.WebPages.Razor"或其中一个依赖项.

(该组件引用和复制的地方,以及所有其他相关的剃刀组件)

解析和编译模板时,会引发以下错误:

行:33列:7错误:当前上下文中不存在名称"model"

任何线索/建议?

ps如果我删除@model指令,模板解析并编译好

建筑:

  • Web应用程序:引用类库,并使用3d方类库中的模型提供.cshtml模板文件.
  • 类库:包含RazorHost和BaseTemplate,并引用3d方库将模型添加到webapplication提供的.cshtml文件中.
  • 3d Party Class:为webapplication提供模型

Bui*_*ted 6

@model是MVC实现Razor非常具体的东西.因此,开箱即用,它不起作用.我已经在codeplex上向RazorEngine上传了一个补丁,它增加@model了对它的引擎的支持,在特定版本之外实现它很容易.http://razorengine.codeplex.com/SourceControl/list/patches

它基本上涉及覆盖razor用来生成它的类文件和覆盖的CodeGenerator TryVisitSpecialSpan

protected override bool TryVisitSpecialSpan(Span span) {
    return TryVisit<ModelSpan>(span, VisitModelSpan); 
      //This is where you would add more special span tests 
      //|| TryVisit<SomeOtherSpan>(span, Method);
}

void VisitModelSpan(ModelSpan span) {
    string modelName = span.ModelTypeName;

    if (DesignTimeMode) {
        WriteHelperVariable(span.Content, "__modelHelper");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你还必须创建自己的CSharpCodeParser

    public class CSharpRazorCodeParser : CSharpCodeParser {
        public string TypeName { get; set; }

        public CSharpRazorCodeParser() {
            RazorKeywords.Add("model", WrapSimpleBlockParser(System.Web.Razor.Parser.SyntaxTree.BlockType.Directive, ParseModelStatement));
        }

        bool ParseModelStatement(CodeBlockInfo block) {
            End(MetaCodeSpan.Create);

            SourceLocation endModelLocation = CurrentLocation;

            Context.AcceptWhiteSpace(includeNewLines: false);

            if (ParserHelpers.IsIdentifierStart(CurrentCharacter)) {
                using (Context.StartTemporaryBuffer()) {
                    AcceptTypeName();
                    Context.AcceptTemporaryBuffer();
                }
            } else {
                OnError(endModelLocation, "Model Keyword Must Be Followed By Type Name");
            }

            End(ModelSpan.Create(Context, TypeName));

            return false;
        }
    }
Run Code Online (Sandbox Code Playgroud)

甚至在此之后你必须覆盖主机以使用你的新类

public class RazorEngineHost : System.Web.Razor.RazorEngineHost {

    public RazorEngineHost(RazorCodeLanguage codeLanguage, Func<MarkupParser> markupParserFactory)
        : base(codeLanguage, markupParserFactory) { }

    public override System.Web.Razor.Generator.RazorCodeGenerator DecorateCodeGenerator(System.Web.Razor.Generator.RazorCodeGenerator generator) {
        if (generator is CSharpRazorCodeGenerator) {
            return new CSharpRazorCodeGenerator(generator.ClassName,
                                                   generator.RootNamespaceName,
                                                   generator.SourceFileName,
                                                   generator.Host, false);
        }

        return base.DecorateCodeGenerator(generator);
    }

    public override ParserBase DecorateCodeParser(ParserBase incomingCodeParser) {
        if (incomingCodeParser is CSharpCodeParser) {
            return new CSharpRazorCodeParser();
        } else {
            return base.DecorateCodeParser(incomingCodeParser);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还必须创建自己的自定义CodeSpan

public class ModelSpan : CodeSpan {
    public ModelSpan(SourceLocation start, string content, string modelTypeName) : base(start, content) {
        this.ModelTypeName = modelTypeName;
    }

    public string ModelTypeName { get; private set; }

    public override int GetHashCode() {
        return base.GetHashCode() ^ (ModelTypeName ?? String.Empty).GetHashCode();
    }

    public override bool Equals(object obj) {
        ModelSpan span = obj as ModelSpan;
        return span != null && Equals(span);
    }

    private bool Equals(ModelSpan span) {
        return base.Equals(span) && string.Equals(ModelTypeName, span.ModelTypeName, StringComparison.Ordinal);
    }

    public new static ModelSpan Create(ParserContext context, string modelTypeName) {
        return new ModelSpan(context.CurrentSpanStart, context.ContentBuffer.ToString(), modelTypeName);
    }
}
Run Code Online (Sandbox Code Playgroud)

除了告诉设计者使用什么模型之外,此实现不做任何其他事情.它根本不应该影响编译,但允许编译器忽略此特定命令.