Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File not found exception when using css-files from embedded resources in class library #85

Open
Elimi81 opened this issue Aug 28, 2024 · 5 comments

Comments

@Elimi81
Copy link

Elimi81 commented Aug 28, 2024

Hi!

I'm using Asp.Net Mvc 5 / .net framework.

Testing the library and was unable to get it working in my scenario so I debugged the code a bit. I have a class library that has the css-files as embedded resources and then I use VirtualPathProvider to serve them. This all works with the build in asp.net web optimization but I would like to use this library for modern css-minification. The problem is it does not work as intended with the VirtualPathProvider.

The problem seems to be related to the library removing the tilde in front of the virtual path of the css-file. I include the files like this "~/Content/layout/Common/css/global.css" but when I'm debugging the tilde is gone when in fact if is was there there would be no problem as you can see from my screenshot. See the watches I added at left bottom. The file is found if FileExists is called with tilde and not if it is called without it:
image

So any insight? Why is the tilde removed, is that a bug in this scenario?

@Taritsyn
Copy link
Owner

Hello, Esa!

… but I would like to use this library for modern css-minification.

What modules of the Bundle Transformer do you use?

I have a class library that has the css-files as embedded resources and then I use VirtualPathProvider to serve them.

I would like to look at your VirtualPathProvider. Сorrect implementation of such a provider should process virtual paths both with and without a tilde.

Why is the tilde removed, is that a bug in this scenario?

Tilde is not removed, just the application-relative path is converted to an absolute virtual path. This is a feature of the Bundle Transformer's pipeline implementation.

@Elimi81
Copy link
Author

Elimi81 commented Aug 30, 2024

I'm only using Nuglify to minimize css and nothing more.

Hmm I think you are right and the error resides in our implementation of the VirtualPathProvider since I was able to get things working with minor adjustments. Have to debug some more but thank you for the nudge in the right direction!

@Taritsyn
Copy link
Owner

Hello, Esa!

I'm only using Nuglify to minimize css and nothing more.

Microsoft ASP.NET Web Optimization Framework is an extensible library and such simple functionality can be implemented without a Bundle Transformer. It is enough to write just two new classes:

NUglifyCssMinify.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Optimization;

using NUglify;
using NUglify.Css;

namespace NUglifyExtensions
{
    /// <summary>
    /// Bundle transformation that performs NUglify CSS minification.
    /// </summary>
    public class NUglifyCssMinify : IBundleTransform
    {
        // Not public since in the future we could add instance data to the transforms
        internal static readonly NUglifyCssMinify Instance = new NUglifyCssMinify();

        internal static string CssContentType = "text/css";

        /// <summary>
        /// Minifies the supplied CSS bundle and sets the Http content-type header to 'text/css'
        /// </summary>
        /// <param name="context">The <see cref="BundleContext"/> object that contains state for both the framework configuration and the HTTP request.</param>
        /// <param name="response">A <see cref="BundleResponse"/> object containing the bundle contents.</param>
        public virtual void Process(BundleContext context, BundleResponse response)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            // Don't minify in Instrumentation mode
            if (!context.EnableInstrumentation)
            {
                UglifyResult minifiedResult = Uglify.Css(response.Content, new CssSettings() { CommentMode = CssComment.None });
                if (minifiedResult.HasErrors)
                {
                    GenerateErrorResponse(response, minifiedResult.Errors);
                }
                else
                {
                    response.Content = minifiedResult.Code;
                }
            }

            response.ContentType = CssContentType;
        }

        private static void GenerateErrorResponse(BundleResponse bundle, List<UglifyError> errors)
        {
            StringBuilder errorResponse = new StringBuilder();
            errorResponse.Append("/* ");
            errorResponse.Append("Minification failed. Returning unminified contents.").Append("\r\n");
            foreach (object error in errors)
            {
                errorResponse.Append(error.ToString()).Append("\r\n");
            }
            errorResponse.Append(" */\r\n");
            errorResponse.Append(bundle.Content);
            bundle.Content = errorResponse.ToString();
        }
    }
}

NUglifyStyleBundle.cs

using System.Web.Optimization;

namespace TespAspNetMvc4
{
    /// <summary>
    /// Bundle designed specifically for processing cascading stylesheets (CSS)
    /// </summary>
    public class NUglifyStyleBundle : Bundle
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="NUglifyStyleBundle"/> class.
        /// </summary>
        /// <param name="virtualPath">The virtual path used to reference the <see cref="NUglifyStyleBundle"/> from within a view or Web page.</param>
        public NUglifyStyleBundle(string virtualPath)
            : base(virtualPath, new NUglifyCssMinify())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NUglifyStyleBundle"/> class.
        /// </summary>
        /// <param name="virtualPath">The virtual path used to reference the <see cref="NUglifyStyleBundle"/> from within a view or Web page.</param>
        /// <param name="cdnPath">An alternate url for the bundle when it is stored in a content delivery network.</param>
        public NUglifyStyleBundle(string virtualPath, string cdnPath)
            : base(virtualPath, cdnPath, new NUglifyCssMinify())
        {
        }
    }
}

And then use them instead of the built-in classes: CssMinify and StyleBundle.

@Elimi81
Copy link
Author

Elimi81 commented Sep 2, 2024

You are a lifesaver! Such a simple solution, my implementation was way too compicated.

Can't thank you enough! Much appreciated.

@Taritsyn
Copy link
Owner

Taritsyn commented Sep 2, 2024

Hello, Esa!

This code is based on the source codes of the CssMinify, JsMinify and StyleBundle classes of the Microsoft ASP.NET Web Optimization Framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants