0

我需要移植我的一个 asp.net 用户控件以在 MVC 3 中使用,但看起来 MVC 没有设置为支持用户控件。

我看到声称用户控件是 MVC 的反模式的帖子。我对关于我只需要移植这个用户控件的辩论不感兴趣,而不管你在那个所谓的围栏的哪一边。我也不认为这是一个 html 助手。由于失去可读性、智能感知支持和可维护性,将大量 javascript 放在双引号内作为助手的参数会否定任何好处。

该控件称为ScriptCompressor。它的目的是代替页面上的所有内联脚本标签。在渲染过程中,最终构成对动态页面的调用的所有内联 javascript 被组合并放置在页面底部/顶部的一个或两个脚本“包装器”中。该控制的重点是通过缩小和压缩所有内联脚本来减小页面大小并提高加载性能。不涉及视图状态,它只是输出一个脚本标签和 javascript。

如何在 MVC 3 Razor 页面中调用现有控件?

来自 ASP.net 用法的示例:

<uc:ScriptCompressor Compress="true">
    var myGlobalVar = "something";

</uc:ScriptCompressor>

<uc:ScriptCompressor Compress="true" UseReadyWrapper="true">
    var _registrationViewModel = new RegisterViewModel();
    ...
</uc:ScriptCompressor>

<uc:ScriptCompressor Compress="true" UseReadyWrapper="true">
    var _addNewUserViewModel = new AddNewUserViewModel();
    ...
</uc:ScriptCompressor>

未压缩输出:

<script type="text/javascript">
var myGlobalVar = "something";
$(function () {
    var _registrationViewModel = new RegisterViewModel();
    var _addNewUserViewModel = new AddNewUserViewModel();
});
</script>
4

1 回答 1

0

您可以结合使用 2 个自定义 HTML 帮助程序来替换现有的服务器端控件:

public static class HtmlExtensions
{
    private const string GlobalsQueueKey = "_globals_queue_";
    private const string ReadyWrapperQueueKey = "_ready_wrapper_queue_";

    [Obsolete("Don't use inline scripts, that's what javascript files are meant for. And yeah, there are pretty nifty javascript compressors out there. Not to mention that in ASP.NET MVC 4 there's the bundling and minification functionality built-in. So use this helper just for fun not in a real application that you intend to put in production.")]
    public static IHtmlString RegisterInlineScript(this HtmlHelper htmlHelper, bool compress, bool useReadyWrapper, Func<object, HelperResult> action)
    {
        var queueKey = useReadyWrapper ? ReadyWrapperQueueKey : GlobalsQueueKey;
        var queue = htmlHelper.ViewContext.HttpContext.Items[queueKey] as Queue<Func<object, HelperResult>>;
        if (queue == null)
        {
            queue = new Queue<Func<object, HelperResult>>();
            htmlHelper.ViewContext.HttpContext.Items[queueKey] = queue;
        }
        queue.Enqueue(action);

        return MvcHtmlString.Empty;                
    }

    [Obsolete("Don't use inline scripts, that's what javascript files are meant for. And yeah, there are pretty nifty javascript compressors out there. Not to mention that in ASP.NET MVC 4 there's the bundling and minification functionality built-in. So use this helper just for fun not in a real application that you intend to put in production.")]
    public static IHtmlString InlineScripts(this HtmlHelper htmlHelper)
    {
        var globalsQueue = htmlHelper.ViewContext.HttpContext.Items[GlobalsQueueKey] as Queue<Func<object, HelperResult>> ?? new Queue<Func<object, HelperResult>>();
        var readyWrapperQueue = htmlHelper.ViewContext.HttpContext.Items[ReadyWrapperQueueKey] as Queue<Func<object, HelperResult>> ?? new Queue<Func<object, HelperResult>>();
        if (!globalsQueue.Any() && !readyWrapperQueue.Any())
        {
            // Nothing to compress, nothing to output
            return MvcHtmlString.Empty;
        }

        var writer = htmlHelper.ViewContext.Writer;


        writer.Write("<script type=\"text/javascript\">");

        using (var globalsWriter = new StringWriter())
        {
            foreach (var item in globalsQueue)
            {
                item(null).WriteTo(globalsWriter);
            }
            var globals = globalsWriter.GetStringBuilder().ToString();
            writer.Write(Compress(globals));
        }

        using (var readyWrapperWriter = new StringWriter())
        {
            foreach (var item in readyWrapperQueue)
            {
                item(null).WriteTo(readyWrapperWriter);
            }

            var readyWrapper = readyWrapperWriter.GetStringBuilder().ToString();

            writer.Write(
                string.Format("$(function() {{{0}}});", Compress(readyWrapper))
            );
        }

        writer.Write("</script>");

        return MvcHtmlString.Empty;
    }

    private static string Compress(string script)
    {
        // TODO: wheel reinvention code from your existing
        // server side control to be put here to compress
        return script;
    }
}

然后您可以在其中注册多个内联脚本的视图:

@Html.RegisterInlineScript(true, false, 
    @<text>
        var myGlobalVar = "something";
    </text>
)

@Html.RegisterInlineScript(true, true, 
    @<text>
        var _registrationViewModel = new RegisterViewModel();
    </text>
)

@Html.RegisterInlineScript(true, true, 
    @<text>
        var _addNewUserViewModel = new AddNewUserViewModel();
    </text>
)

在你的_Layout输出中的某个地方:

@Html.InlineScripts()

好的,现在为您的实际应用程序检查 ASP.NET MVC 4 中的捆绑和缩小支持:http ://www.beletsky.net/2012/04/new-in-aspnet-mvc4-bundling-and.html

于 2012-07-14T11:08:37.787 回答