Реализация HtmlHelper MVC 6 vNext

Я работаю с ASP.NET 5/MVC 6. Я использую пользовательский HtmlHelper внутри частичной страницы для регистрации тега скрипта с помощью HttpContext, чтобы я мог отложить рендеринг тега скрипта до конца страницы.

Этот код регистрирует тег скрипта:

    public static HtmlString AddResource(this IHtmlHelper HtmlHelper, PageResourceType resourceType, Func<object, HelperResult> Template)
    {     
            if (HtmlHelper.ViewContext.HttpContext.Items[resourceType] != null)
            {
                ((List<Func<object, HelperResult>>)HtmlHelper.ViewContext.HttpContext.Items[resourceType]).Add(Template);
            }
            else
            {
                HtmlHelper.ViewContext.HttpContext.Items[resourceType] = new List<Func<object, HelperResult>>() { Template };
            }

           return new HtmlString(String.Empty);
    }

Использование для регистрации тега скрипта со страницы Razor с помощью этого помощника:

 @Html.AddResource(PageResourceType.JavaScript ,
                    @<script src='~/js/plugin/sparkline/jquery.sparkline.js'></script>
                    )

Этот код, вызываемый из _Layout.cshtml, отображает все зарегистрированные теги сценария:

    public static HtmlString RenderResources(this IHtmlHelper HtmlHelper, PageResourceType resourceType)
    {
        if (HtmlHelper.ViewContext.HttpContext.Items[resourceType] != null)
        {
            List<Func<object, HelperResult>> Resources = (List<Func<object, HelperResult>>)HtmlHelper.ViewContext.HttpContext.Items[resourceType];

            foreach (var Resource in Resources)
            {
                if (Resource != null)
                {
                    HtmlHelper.ViewContext.Writer.Write(Resource(null));
                }
            }
        }

        return new HtmlString(String.Empty);
    }

Эти два элемента прекрасно работают, однако теперь у меня есть дополнительный HtmlHelper, который я хочу использовать для создания определенного элемента пользовательского интерфейса (в данном случае виджета пользовательского интерфейса Sparkline), который зависит от тега сценария.

    public static HtmlString Sparkline(this IHtmlHelper HtmlHelper, IEnumerable<int> values, string cssClasses)
    {            
        StringBuilder sb = new StringBuilder();
        sb.Append("<div class='sparkline txt-color-blue hidden-mobile hidden-md hidden-sm'>");
        sb.Append(string.Join(",", values));
        sb.Append("</div>");

        HtmlHelper.AddResource(PageResourceType.JavaScript, (x) =>
        {
            return new HelperResult(writer =>
            {
                string script = "<script src='~/js/plugin/sparkline/jquery.sparkline.js'></script>";
                return new Task(() => writer.Write(script));
            });
        });

        return new HtmlString(sb.ToString());
    }

Обратите внимание, что он вызывает предыдущий метод регистрации через

HtmlHelper.AddResource

Проблема в том, что при выполнении кода RenderResources приложение просто зависает на неопределенный срок. У меня это работало в старой системе MVC 5, но мне пришлось внести некоторые изменения для учета новых конструкций MVC 6 (помощники тегов - это то, что вызвало изменение, я думаю), и я как-то испортил это.

Любая идея, как правильно реализовать метод Sparkline, особенно вызов HtmlHelper.AddResource?

ТИА!


person Simon Ordo    schedule 02.12.2015    source источник


Ответы (1)


Конечно, в ту минуту, когда я публикую вопрос, я нахожу ответ. Хотя я не уверен, почему это решает проблему, поскольку я предположил, что обертывание метода .Write внутри Task будет таким же, как вызов .WriteAsync...

    HtmlHelper.AddResource(PageResourceType.JavaScript, (x) =>
    {
        return new HelperResult(writer =>
        {
            string script = "<script src='~/js/plugin/sparkline/jquery.sparkline.js'></script>";
            return new Task(() => writer.Write(script));
        });
    });

должно быть

    HtmlHelper.AddResource(PageResourceType.JavaScript, (x) =>
    {
        return new HelperResult(writer =>
        {
            string script = "<script src='~/js/plugin/sparkline/jquery.sparkline.js'></script>";
            return writer.WriteAsync(script);
        });
    });
person Simon Ordo    schedule 02.12.2015