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. そして、モデル、HTML ヘルパーなどの MVC 固有のものはすべて、この基本クラスで定義されています。+

于 2013-01-03T07:09:47.300 に答える
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 に答える
1

「「モデル」という名前は現在のコンテキストには存在しません」という問題に直面しました。私がしたことは、同じ "areas" フォルダー構造 (埋め込み mvc プロジェクトから) をメイン MVC プロジェクト (Areas/AnualReports/Views/) に追加し、web.config (ルートからではなくビューフォルダーからのデフォルトの web.config) をコピーしたことです。 ) を Views フォルダーに移動して、問題を解決しました。これがあなたの場合にうまくいくかどうかはわかりません。

更新: web.config (views フォルダーから) をメイン MVC プロジェクトのルート "areas" フォルダーに追加しても機能します。

于 2013-05-30T05:19:15.743 に答える
0

私の場合、解決策は、通常のビューと同じように、仮想パスを「~Views/」で開始することでした。

機能していません: ~/VIRTUAL/Home/Index.cshtml 機能してい
ます: ~/Views/VIRTUAL/Home/Index.cshtml

これは、~/Views にある web.config と関係があると思います。ビュー用に多くのものを定義しています。たぶん、誰でもより多くの情報を提供できます。

とにかく役立つことを願っています。

于 2013-01-25T09:07:14.840 に答える