4

我正在努力从图书馆获得一些观点到主要项目。我开始在这里阅读有关创建自己的 VirtualPathProvider 实现的信息:Using VirtualPathProvider to load ASP.NET MVC views from DLLs

我必须设置我的 view = EmbbebedResource 才能从库中获取资源。但是现在又抛出了另一个错误。

在我的部分视图的标题中,我有以下内容:

@model Contoso.ExercisesLibrary.AbsoluteArithmetic.Problem1

并且错误说:外部组件已引发异常。c:\Users\Oscar\AppData\Local\Temp\Temporary ASP.NET Files\root\4f78c765\7f9a47c6\App_Web_contoso.exerciseslibrary.absolutearithmetic.view1.cshtml.38e14c22.y-yjyt6g.0.cs(46):错误 CS0103 :当前上下文中不存在名称“模型”

我不知道为什么编译器会说无法识别我的模型。当我处于设计模式时,我可以看到编译器检查正常。

检查图像

在此处输入图像描述

我做错了什么或者我错过了什么?提前致谢。

4

4 回答 4

7

尝试将@inherits指令添加到剃刀视图的顶部:

@inherits System.Web.Mvc.WebViewPage
@model Contoso.ExercisesLibrary.AbsoluteArithmetic.Problem1

您需要这样做的原因是您的视图来自嵌入式资源,而不是来自标准~/Views位置。如您所知,里面~/Views有一个名为 web.config 的文件。在这个文件里面有一个pageBaseType="System.Web.Mvc.WebViewPage"指令,指示里面的所有 Razor 文件~/Views都应该从这个基类型继承。但是由于您的视图现在来自未知位置,因此您没有指定它应该是System.Web.Mvc.WebViewPage. 并且所有 MVC 特定的东西,例如模型、HTML 助手,......都在这个基类中定义。+

于 2013-01-03T07:09:47.300 回答
1

我遇到了这个问题“当前上下文中不存在名称'模型'”。我所做的是将相同的“区域”文件夹结构(来自我的嵌入式 mvc 项目)添加到我的主 MVC 项目(Areas/AnualReports/Views/)并复制 web.config(默认 web.config 来自视图文件夹,而不是来自根目录的那个) ) 到解决问题的 Views 文件夹。我不确定这是否适用于您的情况。

更新:将 web.config(从视图文件夹)添加到主 MVC 项目中的根“区域”文件夹也可以。

于 2013-05-30T05:19:15.743 回答
1

我和你有同样的问题,所以在所有搜索之后我得到了有效的解决方案

创建您自己的基于 WebViewPage 的抽象类(模型通用和非通用)

public abstract class MyOwnViewPage<TModel> : WebViewPage<TModel> { }

public abstract class MyOwnViewPage : WebViewPage {   }

接下来创建基于 VirtualFile 的类或嵌入式视图

class AssemblyResourceFile : VirtualFile
    {
        private readonly IDictionary<string, Assembly> _nameAssemblyCache;
        private readonly string _assemblyPath;
        private readonly string _webViewPageClassName;
        public string LayoutPath { get; set; }
        public string ViewStartPath { get; set; }

        public AssemblyResourceFile(IDictionary<string, Assembly> nameAssemblyCache, string virtualPath) :
            base(virtualPath)
        {
            _nameAssemblyCache = nameAssemblyCache;
            _assemblyPath = VirtualPathUtility.ToAppRelative(virtualPath);
            LayoutPath = "~/Views/Shared/_Layout.cshtml";
            ViewStartPath = "~/Views/_ViewStart.cshtml";
            _webViewPageClassName = typeofMyOwnViewPage).ToString();
        }

        // Please change Open method for your scenario
        public override Stream Open()
        {
            string[] parts = _assemblyPath.Split(new[] { '/' }, 4);    

            string assemblyName = parts[2];
            string resourceName = parts[3].Replace('/', '.');

            Assembly assembly;

            lock (_nameAssemblyCache)
            {
                if (!_nameAssemblyCache.TryGetValue(assemblyName, out assembly))
                {
                    var assemblyPath = Path.Combine(HttpRuntime.BinDirectory, assemblyName);
                    assembly = Assembly.LoadFrom(assemblyPath);

                    _nameAssemblyCache[assemblyName] = assembly;
                }
            }

            Stream resourceStream = null;

            if (assembly != null)
            {
                 resourceStream = assembly.GetManifestResourceStream(resourceName);

                if (resourceName.EndsWith(".cshtml"))
                {
                    //the trick is here. We must correct our embedded view
                    resourceStream = CorrectView(resourceName, resourceStream);
                }
            }

            return resourceStream;
        }

        public Stream CorrectView(string virtualPath, Stream stream)
        {
            var reader = new StreamReader(stream, Encoding.UTF8);
            var view = reader.ReadToEnd();
            stream.Close();
            var ourStream = new MemoryStream();
            var writer = new StreamWriter(ourStream, Encoding.UTF8);

            var modelString = "";
            var modelPos = view.IndexOf("@model");
            if (modelPos != -1)
            {
                writer.Write(view.Substring(0, modelPos));
                var modelEndPos = view.IndexOfAny(new[] { '\r', '\n' }, modelPos);
                modelString = view.Substring(modelPos, modelEndPos - modelPos);
                view = view.Remove(0, modelEndPos);
            }

            writer.WriteLine("@using System.Web.Mvc");
            writer.WriteLine("@using System.Web.Mvc.Ajax");
            writer.WriteLine("@using System.Web.Mvc.Html");
            writer.WriteLine("@using System.Web.Routing");

            var basePrefix = "@inherits " + _webViewPageClassName;

            if (virtualPath.ToLower().Contains("_viewstart"))
            {
                writer.WriteLine("@inherits System.Web.WebPages.StartPage");
            }
            else if (modelString == "@model object")
            {
                writer.WriteLine(basePrefix + "<dynamic>");
            }
            else if (!string.IsNullOrEmpty(modelString))
            {
                writer.WriteLine(basePrefix + "<" + modelString.Substring(7) + ">");
            }
            else
            {
                writer.WriteLine(basePrefix);
            }


            writer.Write(view);
            writer.Flush();
            ourStream.Position = 0;
            return ourStream;
        }
    }

接下来创建基于 VirtualPathProvider 的类(根据您的目的对其进行修改)

public class AssemblyResPathProvider : VirtualPathProvider
    {
        private readonly Dictionary<string, Assembly> _nameAssemblyCache;

        private string _layoutPath;
        private string _viewstartPath;

        public AssemblyResPathProvider(string layout, string viewstart)
        {
            _layoutPath = layout;
            _viewstartPath = viewstart;

            _nameAssemblyCache = new Dictionary<string, Assembly>(StringComparer.InvariantCultureIgnoreCase);
        }

      private bool IsAppResourcePath(string virtualPath)
        {
            string checkPath = VirtualPathUtility.ToAppRelative(virtualPath);



            bool bres1 = checkPath.StartsWith("~/App_Resource/",
                                         StringComparison.InvariantCultureIgnoreCase);


            bool bres2 = checkPath.StartsWith("/App_Resource/",
                                         StringComparison.InvariantCultureIgnoreCase);

        //todo: fix this    
            if (checkPath.EndsWith("_ViewStart.cshtml"))
            {
                return false;
            }

            if (checkPath.EndsWith("_ViewStart.vbhtml"))
            {
                return false;
            }

            return ((bres1 || bres2));

        }

        public override bool FileExists(string virtualPath)
        {
            return (IsAppResourcePath(virtualPath) ||
                    base.FileExists(virtualPath));
        }


        public override VirtualFile GetFile(string virtualPath)
        {
            if (IsAppResourcePath(virtualPath))
            {
        // creating AssemblyResourceFile instance
                return new AssemblyResourceFile(_nameAssemblyCache, virtualPath,_layoutPath,virtualPath);
            }

            return base.GetFile(virtualPath);
        }

        public override CacheDependency GetCacheDependency(
            string virtualPath,
            IEnumerable virtualPathDependencies,
            DateTime utcStart)
        {
            if (IsAppResourcePath(virtualPath))
            {
                return null;
            }

            return base.GetCacheDependency(virtualPath,
                                           virtualPathDependencies, utcStart);
        }

    }

最后在 global.asax 中注册您的 AssemblyResPathProvider

string  _layoutPath = "~/Views/Shared/_Layout.cshtml";
string  _viewstarPath = "~/Views/_ViewStart.cshtml";
HostingEnvironment.RegisterVirtualPathProvider(new AssemblyResPathProvider(_layoutPath,_viewstarPath));

这不是理想的解决方案,但它对我有用。干杯!

于 2013-07-03T07:08:35.103 回答
0

就我而言,解决方案是让虚拟路径以“~Views/”开头——就像任何普通视图一样。

不工作:~/VIRTUAL/Home/Index.cshtml
工作:~/Views/VIRTUAL/Home/Index.cshtml

我认为,这与位于 ~/Views 中的 web.config 并为视图定义了很多东西有关。也许任何人都可以提供更多信息。

希望无论如何都会有所帮助。

于 2013-01-25T09:07:14.840 回答