如何将此asp.net usercontrol转换为在MVC 3中工作

时间:2012-07-14 05:29:00

标签: asp.net-mvc-3 user-controls

我需要将我的一个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>

1 个答案:

答案 0 :(得分: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