views:

518

answers:

2

I want to use the ViewPage/HtmlHelper class in the System.Web.Mvc namespace in a seperate project. I imported the relevant libraries and then tried this:

using System.Web.Mvc;
using System.Web.Mvc.Resources;
using System.Web.Mvc.Html;

public static class Display
{
    public static string CheckBox()
    {
         ViewPage viewPage = new ViewPage();
         return viewPage.Html.CheckBox("Test");
    }
}

Which I call like this in another class that includes my display class:

string Checkbox = Display.CheckBox():

This compiles just fine, however when I run it I get:

System.NullReferenceException: Object reference not set to an instance of an object.

I simply want to use the HtmlHelper's extension methods as is, e.g: page.Html.ActionLink(), page.Html.Radionbutton() etc. How can I resolve this problem?

A: 

The Html helpers require that the ViewContext property of the ViewPage is set. Typically, this is not the case within a controller or other class code.

Could you package this CheckBox within an ASCX file and reference it there by other views with a Html.RenderPartial method call?

David Andres
I don't understand your question, what do you mean?
Mr. Smith
@Mr. Smith: It looks like you want to share a visual thing (a checkbox) with other parts of an MVC website. This concept doesn't have to exist within a specific C# class, and may be better expressed by housing this checkbox within its own, shared partial view. It can still be leveraged by other views/controllers and, better still, you'll have direct access to Html helper methods within the partial view.
David Andres
I've gone with using the TagBuilder class instead. I'm writing a class that generates input tags on the fly based on the Columns in a DataTable or the Properties of a class
Mr. Smith
@Mr. Smith: That's a solid approach.
David Andres
+1  A: 

Are you trying to call your custom CheckBox() from a different place than the view? Please don't do that. The philosophy behind ASP.NET MVC is that your controller should prepare all data for the view, then the view should decide on how to render it.

If you redesign your method to be an extension method, you could do that:

public static class Display // class name really don't matter for extension methods
{
    public static string CheckBox(this HtmlHelper html)
    {
         return html.CheckBox("Test");
    }
}

Within the view:

<%= Html.CheckBox() %>

Note that this may cause a naming conflict with existing extension methods. One way to avoid that is to design something like:

New code in view:

<%= Html.Display().CheckBox() %>

New extension code:

public static DisplayExtension
{
    public static Display(this HtmlHelper html)
    {
        return new Display(html);
    }
}


public class Display // no longer static
{
    private readonly HtmlHelper html;

    public string Display(HtmlHelper html)
    {
         this.html = html;
    }

    public string CheckBox()
    {
         return html.CheckBox("Test");
    }
}
Thomas Eyde