为了账号安全,请及时绑定邮箱和手机立即绑定

ASP.NET MVC中单独程序集中的视图

ASP.NET MVC中单独程序集中的视图

偶然的你 2019-10-08 10:56:16
我正在尝试创建一个Web应用程序,希望能够在其中插入单独的程序集。我将MVC Preview 4与Unity结合使用进行依赖项注入,我使用它从插件程序集创建控制器。我正在使用WebForms(默认aspx)作为视图引擎。如果要使用视图,则由于ASPX部件的动态编译,我将停留在核心项目中定义的视图上。我正在寻找一种将ASPX文件封装在不同程序集中的正确方法,而不必执行整个部署步骤。我是否缺少明显的东西?还是我应该以编程方式创建视图?更新:我更改了接受的答案。即使Dale的答案很彻底,我还是选择了其他虚拟路径提供程序来寻求解决方案。我觉得它像一个咒语一样工作,只占用大约20行代码。
查看完整描述

3 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

我花了很长时间才能从各个部分样本中正常工作,所以这里是从共享库中的Views文件夹获取视图所需的全部代码,该库与常规Views文件夹的结构相同,但所有内容都设置为嵌入式构建资源。如果普通文件不存在,它将仅使用嵌入式文件。


Application_Start的第一行:


HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedViewPathProvider());

虚拟路径提供者


   public class EmbeddedVirtualFile : VirtualFile

{

    public EmbeddedVirtualFile(string virtualPath)

        : base(virtualPath)

    {

    }


    internal static string GetResourceName(string virtualPath)

    {

        if (!virtualPath.Contains("/Views/"))

        {

            return null;

        }




        var resourcename = virtualPath

            .Substring(virtualPath.IndexOf("Views/"))

            .Replace("Views/", "OrangeGuava.Common.Views.")

            .Replace("/", ".");


        return resourcename;


    }



    public override Stream Open()

    {

        Assembly assembly = Assembly.GetExecutingAssembly();



        var resourcename = GetResourceName(this.VirtualPath);

        return assembly.GetManifestResourceStream(resourcename);

    }





}


public class EmbeddedViewPathProvider : VirtualPathProvider

{



    private bool ResourceFileExists(string virtualPath)

    {


        Assembly assembly = Assembly.GetExecutingAssembly();



        var resourcename = EmbeddedVirtualFile.GetResourceName(virtualPath);

        var result = resourcename != null && assembly.GetManifestResourceNames().Contains(resourcename);

        return result;

    }


    public override bool FileExists(string virtualPath)

    {

        return base.FileExists(virtualPath) || ResourceFileExists(virtualPath);

    }



    public override VirtualFile GetFile(string virtualPath)

    {


        if (!base.FileExists(virtualPath))

        {

            return new EmbeddedVirtualFile(virtualPath);

        }

        else

        {

            return base.GetFile(virtualPath);

        }


    }


}

使它工作的最后一步是,根Web.Config必须包含正确的设置才能解析强类型的MVC视图,因为不会使用views文件夹中的视图:


<pages

    validateRequest="false"

    pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"

    pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"

    userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">

  <controls>

    <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />

  </controls>

</pages>

要使其与Mono一起使用,还需要执行几个附加步骤。首先,您需要实现GetDirectory,因为views文件夹中的所有文件都是在应用启动时加载的,而不是根据需要加载的:


public override VirtualDirectory GetDirectory(string virtualDir)

    {

        Log.LogInfo("GetDirectory - " + virtualDir);

        var b = base.GetDirectory(virtualDir);

        return new EmbeddedVirtualDirectory(virtualDir, b);

    }


public class EmbeddedVirtualDirectory : VirtualDirectory

{

    private VirtualDirectory FileDir { get; set; } 


    public EmbeddedVirtualDirectory(string virtualPath, VirtualDirectory filedir)

        : base(virtualPath)

    {

        FileDir = filedir;

    }


    public override System.Collections.IEnumerable Children

    {

        get { return FileDir.Children; }

    }


    public override System.Collections.IEnumerable Directories

    {

        get { return FileDir.Directories; }

    }


    public override System.Collections.IEnumerable Files

    {

        get {


            if (!VirtualPath.Contains("/Views/") || VirtualPath.EndsWith("/Views/"))

            {

                return FileDir.Files;

            }


            var fl = new List<VirtualFile>();


            foreach (VirtualFile f in FileDir.Files)

            {

                fl.Add(f);

            }



            var resourcename = VirtualPath.Substring(VirtualPath.IndexOf("Views/"))

.Replace("Views/", "OrangeGuava.Common.Views.")

.Replace("/", ".");


            Assembly assembly = Assembly.GetExecutingAssembly();


            var rfl = assembly.GetManifestResourceNames()

                .Where(s => s.StartsWith(resourcename))

                .Select(s => VirtualPath + s.Replace(resourcename, ""))

                .Select(s => new EmbeddedVirtualFile(s));

            fl.AddRange(rfl);


            return fl;

        }

    }

}

最后,强类型视图将几乎但不是很完美。模型将被视为未类型化的对象,因此要进行强类型化输入,您需要使用类似以下内容来启动共享视图


<% var Model2 = Model as IEnumerable<AppModel>;  %>


查看完整回答
反对 回复 2019-10-08
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

protected void Application_Start()

{

    WebFormViewEngine engine = new WebFormViewEngine();


    engine.ViewLocationFormats = new[] { "~/bin/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" };

    engine.PartialViewLocationFormats = engine.ViewLocationFormats;


    ViewEngines.Engines.Clear();

    ViewEngines.Engines.Add(engine);


    RegisterRoutes(RouteTable.Routes);

}

将视图的“复制到输出”属性设置为“始终复制”


查看完整回答
反对 回复 2019-10-08
  • 3 回答
  • 0 关注
  • 419 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信