Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mvc UserControl using HtmlHelper with HelperResult and MvcHtmlString

I'm developing an application in asp mvc, and I want to create some friendly controls for developers, like Server controls in asp.net WebForms . In this case, I want to create a bootstrap panel that has some fixed html and render inside a template of items. I am doing it this way:

public static MvcHtmlString BootPanel<T>(this IEnumerable<T> items, Func<T, HelperResult> template, string title = "")
    {

     StringBuilder sb = new StringBuilder();
     sb.Append("<div class='panel panel-info'>");
     sb.Append("<div class='panel-heading'>");
     sb.Append(title);
     sb.Append("</div>");
     sb.Append("<div class='panel-body'>");
        
     var hr = new HelperResult(writer =>
              {
                 foreach (var item in items)
                {
                  template(item).WriteTo(writer);
                }
       });

      sb.Append(hr.ToHtmlString());
      sb.Append("</div>");
      sb.Append("</div>");
      return MvcHtmlString.Create(sb.ToString());
    }

This is the razor View:

@{
  var videoGames = new[] {
      new VideoGame {nombre = "Shadows of mordor", precio = 66},
      new VideoGame {nombre = "Spiderman", precio = 50}
      };
   }    

  @videoGames.BootPanel(@<div>
                            @item.nombre  &nbsp;  @item.precio
                        </div>
                      , "Titulo")

The output is rendered correctly using the bootstrap classes:

enter image description here

The question is. Is this a correct way of implementing this kind of control?

EDIT:

Following your answers I updated the helper yo use TagBuilder:

public static MvcHtmlString BootPanel<T>(this IEnumerable<T> items, Func<T, HelperResult> template, string title = "")
    {
        TagBuilder PanelDiv = new TagBuilder("div");
        PanelDiv.AddCssClass("panel panel-info");

        TagBuilder PanelHeading = new TagBuilder("div");
        PanelHeading.AddCssClass("panel-heading");
        PanelHeading.SetInnerText(title);

        TagBuilder PanelBody = new TagBuilder("div");
        PanelBody.AddCssClass("panel-body");
       
        var hr = new HelperResult(writer =>
        {


            foreach (var item in items)
            {
                template(item).WriteTo(writer);
            }

        });

        PanelBody.InnerHtml = hr.ToHtmlString();

        PanelDiv.InnerHtml = PanelHeading.ToString() +
                             PanelBody.ToString();

        return MvcHtmlString.Create(PanelDiv.ToString());
    }
like image 531
Carlos Landeras Avatar asked Nov 10 '22 00:11

Carlos Landeras


1 Answers

Make sure you encode the output string before returning since if some one writes a javascript for title then it results in script injection. Apart from that it looks, but instead using hard coded tags you may use TagBuilder class to build your html code. See this example.

like image 87
Venkatesh Avatar answered Nov 14 '22 22:11

Venkatesh