Question

This should hopefully be a simple one.

I would like to add an extension method to the System.Web.Mvc.ViewPage< T > class.

How should this extension method look?

My first intuitive thought is something like this:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle(this ViewPage<Type> v)
        {
            return "";
        }
    }
}

Solution

The general solution is this answer.

The specific solution to extending the System.Web.Mvc.ViewPage class is my answer below, which started from the general solution.

The difference is in the specific case you need both a generically typed method declaration AND a statement to enforce the generic type as a reference type.

Was it helpful?

Solution

I don't have VS installed on my current machine, but I think the syntax would be:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
        {
            return "";
        }
    }
}

OTHER TIPS

Thanks leddt. Doing that yielded the error:

The type 'TModel' must be a reference type in order to use it as parameter 'TModel' in the generic type or method

which pointed me to this page, which yielded this solution:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v) 
          where T : class
        {
            return "";
        }
    }
}

It just needs the generic type specifier on the function:

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v)
        {
            return "";
        }
    }
}

Edit: Just missed it by seconds!

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> view)
            where T : class
        {
            return "";
        }
    }
}

You may also need/wish to add the "new()" qualifier to the generic type (i.e. "where T : class, new()" to enforce that T is both a reference type (class) and has a parameterless constructor.

Glenn Block has a good example of implementing a ForEach extension method to IEnumerable<T>.

From his blog post:

public static class IEnumerableUtils
{
    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach(T item in collection)
            action(item);
    }
}

If you want the extension to only be available for the specified type you simply just need to specify the actual type you will be handling

something like...

public static string GetDefaultPageTitle(this ViewPage<YourSpecificType> v)
{
  ...
}

Note intellisense will then only display the extension method when you declare your (in this case) ViewPage with the matching type.

Also, best not to use the System.Web.Mvc namespace, I know its convenient to not have to include your namespace in the usings section, but its far more maintainable if you create your own extensions namespace for your extension functions.

Here's an example for Razor views:

public static class WebViewPageExtensions
{
    public static string GetFormActionUrl(this WebViewPage view)
    {
        return string.Format("/{0}/{1}/{2}", view.GetController(), view.GetAction(), view.GetId());
    }

    public static string GetController(this WebViewPage view)
    {
        return Get(view, "controller");
    }

    public static string GetAction(this WebViewPage view)
    {
        return Get(view, "action");
    }

    public static string GetId(this WebViewPage view)
    {
        return Get(view, "id");
    }

    private static string Get(WebViewPage view, string key)
    {
        return view.ViewContext.Controller.ValueProvider.GetValue(key).RawValue.ToString();
    }
}

You really don't need to use the Generic version as the generic one extends the non-generic one so just put it in the non-generic base class and you're done :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top