简体   繁体   English

在 ASP.NET MVC 项目中使用类库中的 Javascript 文件

[英]Using Javascript files from a Class Library in an ASP.NET MVC project

Say I have a Class Library containing a HelloWorld.js file.假设我有一个包含 HelloWorld.js 文件的类库。

This file contains a couple javascript functions, like say:该文件包含几个 javascript 函数,例如:

function Hello_alert() {
   alert("Hello World!!");
}

and

function Hello_console() {
   console.log("Hello World!!");
}

I want to make so I can access the functions inside the HelloWorld.js file individually , on an ASP.NET MVC page, say, the Index.cshtml inside the Home folder.我想让我可以单独访问 HelloWorld.js 文件中的函数,在ASP.NET MVC页面上,比如 Home 文件夹中的 Index.cshtml。 (Failing that, I'd be happy just accessing the .js file at all.) (否则,我很乐意访问 .js 文件。)

I have already changed the .js as EmbeddedResource and added it to the Assembly as such:我已经将 .js 更改为 EmbeddedResource 并将其添加到程序集中,如下所示:

[assembly: WebResource("JSLibrary.Scriptss.HelloWorld.js", "application/x-javascript")]

; ; referenced the DLL on my MVC project, and the DLL namespace shows up on Intellisense so I'm guessing it's linked right.在我的 MVC 项目中引用了 DLL,并且 DLL 命名空间显示在 Intellisense 上,所以我猜它是正确链接的。

Now, I've been googling incessantly the whole day, and I've found a solution that kinda does what I need , but it's for Web Forms , using Page.ClientScript to register the scripts into the page itself, which allows one to call the functions inside the .js file on that page.现在,我一整天都在不停地谷歌搜索,我找到了一种解决方案,可以满足我的需要,但它适用于Web Forms ,使用 Page.ClientScript 将脚本注册到页面本身,这允许人们调用该页面上 .js 文件中的函数。 This is pretty much what I'm trying to do, except I need it in MVC , which doesn't use the "Page" class like that.这几乎就是我想要做的,除了我在MVC 中需要它,它不使用这样的“Page”类。

The closes equivalent I've found has something to do with bundles, but I couldn't find any tutorials that I could viably follow.我发现的 closes 等价物与捆绑包有关,但我找不到任何可以切实遵循的教程。

So again, my question is, how do I somehow register Javascript files from a DLL in order for me to be able to call them from an ASP.NET MVC project?所以,我的问题是,我如何以某种方式从 DLL 注册 Javascript 文件,以便我能够从ASP.NET MVC项目中调用它们?

--------Update:--------- - - - - 更新: - - - - -

Following the tutorial I linked above, my DLL has a class with a method that is used to register the scripts in a Script Manager, that it receives as a parameter.按照我上面链接的教程,我的 DLL 有一个带有方法的类,用于在脚本管理器中注册脚本,它作为参数接收。 Like so像这样

public static void includeHelloWorld(ClientScriptManager manager)
    {
        manager.RegisterClientScriptResource(typeof(JSLibrary.JSAccess), ScriptPath_HelloWorld);
    }//JSLibrary being the DLL namespace and JSAccess being the class

Then, in the main project, using Web Forms , you can call that method and pass it the ClientScript property of the current Page, where the scripts get registered, I assume.然后,在主项目中,使用Web Forms ,您可以调用该方法并将其传递给当前页面的 ClientScript 属性,我假设脚本在其中注册。 Like so:像这样:

protected void Page_Load(object sender, EventArgs e)
    {
        JSLibrary.JSAccess.includeHelloWorld(Page.ClientScript);
    }

I've tried it and it works on Web Forms .我试过了,它适用于Web Forms I need the equivalent of the Page.ClientScript in MVC , that I can send to the method in the DLL that takes in a ClientScriptManager.我需要MVC中的 Page.ClientScript 等价物,我可以将其发送到 DLL 中的方法,该方法接受 ClientScriptManager。

Thanks谢谢

OK I figured it out.好的,我想通了。

Since nobody responded, I figured I would come back and share with the world the solution to my problem, just in case someone else finds it useful.由于没有人回应,我想我会回来与全世界分享我的问题的解决方案,以防其他人发现它有用。

Apparently, MVC has this Blundles feature that allows you to bundle, amongst other stuff, JS scripts for future use.显然,MVC 有这个Blundles功能,允许您捆绑JS 脚本以供将来使用。 Bundles use Virtual Paths to access their files, but the default Virtual Paths can't access DLLs (at least not the files in it), so we have to create a custom Virtual Path in our DLL. Bundle使用Virtual Paths来访问它们的文件,但是默认的Virtual Paths不能访问 DLLs(至少不是其中的文件),所以我们必须在我们的 DLL 中创建一个自定义的Virtual Path After registering this VP in the main program, we can access files on the DLL as if they were on our main program and thus, include the scripts in our bundle.在主程序中注册这个VP后,我们可以访问 DLL 上的文件,就像它们在我们的主程序中一样,因此,将脚本包含在我们的包中。

Notice this probably isn't the best or most efficient method, just something I scrapped together that seems to work.请注意,这可能不是最好或最有效的方法,只是我拼凑起来的似乎有效的方法。


Ok, so here's how we do it:好的,这是我们如何做到的:

First off, install the following NuGet package :首先,安装以下NuGet 包

Install-Package EmbeddedResourceVirtualPathProvider

Then, in our DLL, make sure your .js file is set as embedded resource.然后,在我们的 DLL 中,确保您的 .js 文件被设置为嵌入资源。 Next we create a class in the root of the namespace, which is gonna be our Virtual Path provider and Virtual File.接下来我们在命名空间的根目录中创建一个类,它将成为我们的虚拟路径提供者和虚拟文件。 Basically, just put this code in the root of the namespace:基本上,只需将此代码放在命名空间的根目录中:

public class EmbeddedVirtualPathProvider : VirtualPathProvider
{
    private readonly Assembly assembly = typeof(EmbeddedVirtualPathProvider).Assembly;
    private readonly string[] resourceNames;

    public EmbeddedVirtualPathProvider()
    {
        this.resourceNames = assembly.GetManifestResourceNames();
    }

    private bool IsEmbeddedResourcePath(string virtualPath)
    {
        var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        var resourceName = this.GetType().Namespace + "." + checkPath.Replace("~/", "").Replace("/", ".");
        return this.resourceNames.Contains(resourceName);
    }

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

    public override VirtualFile GetFile(string virtualPath)
    {
        if (IsEmbeddedResourcePath(virtualPath))
        {
            return new EmbeddedVirtualFile(virtualPath);
        }
        return base.GetFile(virtualPath);
    }



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

public class EmbeddedVirtualFile : VirtualFile
{
    private readonly string virtualPath;
    private readonly Assembly assembly;

    public EmbeddedVirtualFile(string virtualPath)
        : base(virtualPath)
    {
        this.assembly = this.GetType().Assembly;
        this.virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
    }

    public override System.IO.Stream Open()
    {
        var resourceName = this.GetType().Namespace + "." + virtualPath.Replace("~/", "").Replace("/", ".");
        return assembly.GetManifestResourceStream(resourceName);
    }
}

That's two classes in the code above.这是上面代码中的两个类。

You will need to include a few libraries such as您将需要包含一些库,例如

using System.Reflection;
using System.Web.Hosting;
using System.Web;
using System.Web.Caching;
using System.Collections;

Now, in our main project , we're going to register this Virtual Path .现在,在我们的主项目中,我们将注册这个Virtual Path If you haven't referenced the DLL in your main: in the solution explorer, under your Main project, right click References -> Add Reference and select your DLL.如果您没有在 main 中引用DLL :在解决方案资源管理器中,在您的 Main 项目下,右键单击 References -> Add Reference 并选择您的 DLL。

In order to register the VP , simply add this line in your main project's Global.asax file ( on the very top of your Application_Start() method):为了注册VP ,只需在主项目的 Global.asax 文件中添加这一行(Application_Start() 方法的最顶部):

HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedVirtualPathProvider());

You will need to include in the Global.asax:您需要在 Global.asax 中包含:

using System.Web.Hosting;
using <your dll namespace>;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

Now to add the script(s) to the bundles.现在将脚本添加到包中。 Inside the App_Start folder should be a BundleConfig.cs file. App_Start 文件夹内应该有一个 BundleConfig.cs 文件。 Inside the RegisterBundles method, you can just write:在 RegisterBundles 方法中,您可以只写:

bundles.Add(new ScriptBundle("~/bundles/external/helloworld").Include(
                    "~/Scripts/HelloWorld.js"));

where the first argument ("~/bundles/external/helloworld") can be anything you want after the ~/, and the second argument ("~/Scripts/HelloWorld.js") has to be the path to your script inside the DLL.其中第一个参数(“~/bundles/external/helloworld”)可以是你在 ~/ 之后想要的任何东西,第二个参数(“~/Scripts/HelloWorld.js”)必须是你的脚本中的路径动态链接库。

To finalize, let's render the scripts in our views.最后,让我们在视图中渲染脚本。 Pick a view, say Index.cshtml, and just include the line:选择一个视图,比如 Index.cshtml,然后只包含以下行:

@Scripts.Render("~/bundles/external/helloworld")

the parameter being whatever you named it when creating the bundle, and now it should work!参数是您在创建包时命名的任何内容,现在它应该可以工作了!

If you implement Zidd's technique and get " Failed to load resource: the server responded with a status of 404 (Not Found) " than add this line:如果您实施 Zidd 的技术并获得“无法加载资源:服务器响应状态为 404(未找到) ”,请添加以下行:

BundleTable.EnableOptimizations = true;

at the end of BundleConfig.RegisterBundles method.BundleConfig.RegisterBundles方法的末尾。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM