0

MVC 3 で使用するために asp.net ユーザー コントロールの 1 つを移植する必要がありますが、MVC はユーザー コントロールをサポートするように設定されていないようです。

ユーザー コントロールは MVC のアンチパターンであると主張する投稿を目にします。想定されるフェンスのどちら側にあるかに関係なく、このユーザーコントロールを移植する必要があるという議論には興味がありません。これがhtmlヘルパーであることもわかりません。ヘルパーへのパラメーターとして大量の JavaScript を二重引用符で囲むと、読みやすさ、Intelli-Sense サポート、保守性が失われるため、メリットがなくなります。

コントロールはScriptCompressorと呼ばれます。その目的は、ページ上のすべてのインライン スクリプト タグに取って代わることです。レンダリング中に、最終的に動的ページへの呼び出しを構成するすべてのインライン JavaScript が結合され、ページの下部/上部にある 1 つまたは 2 つのスクリプト「ラッパー」に配置されます。この制御の要点は、すべてのインライン スクリプトを縮小および圧縮することにより、ページ サイズを縮小し、読み込みパフォーマンスを向上させることです。スクリプト タグと 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()

OK、実際のアプリケーションのチェックアウトについては、ASP.NET MVC 4でのバンドルとミニファイのサポート:http://www.beletsky.net/2012/04/new-in-aspnet-mvc4-bundling-and.html

于 2012-07-14T11:08:37.787 に答える