Kaizen Programmer
Kaizen Programmer

Reputation: 3818

'string' does not contain a definition for helper when looping through ViewBag

I have a unique 'string' does not contain definition problem.

Take following VIew code:

@if (ViewBag.Stories != null)
{
    if (ViewBag.Stories.Count > 0)
    {
    <h2>Stories (@ViewBag.Stories.Count)</h2>
    <ul>
        @foreach (var item in ViewBag.Stories)
        {
            <li>
                @("test".ToString().ToSeoUrl())
                <h2>@(item.Title.ToString().ToSeoUrl())</h2>
            </li>
        }
    </ul>
    }
}

If I remove '.ToString().ToSeoUrl()' from item.Title I get:

If I add it back. I get the excepction

Server Error in '/' Application.

'string' does not contain a definition for 'ToSeoUrl'

I'm using Razor and have the following helper class registered in the View:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;

namespace MyNamespace.Helpers
{    
    public static class StringExtensions
    {
        public static string ToSeoUrl(this string url)
        {
        // make the url lowercase
        string encodedUrl = (url ?? "").ToLower();

        // replace & with and
        encodedUrl = Regex.Replace(encodedUrl, @"\&+", "and");

        // remove characters
        encodedUrl = encodedUrl.Replace("'", "");

        // remove invalid characters
        encodedUrl = Regex.Replace(encodedUrl, @"[^a-z0-9]", "-");

        // remove duplicates
        encodedUrl = Regex.Replace(encodedUrl, @"-+", "-");

        // trim leading & trailing characters
        encodedUrl = encodedUrl.Trim('-');

        return encodedUrl;
        }
    }
}

item is a custom class called Story with a public string Title

Upvotes: 1

Views: 2166

Answers (1)

nemesv
nemesv

Reputation: 139778

Extension methods cannot be dynamically dispatched. Because you are using ViewBag which is dynamic and ToSeoUrl which is an extension method you get an RuntimeBinderException.

There are two ways to solve this:

  1. Use casting: <h2>@(((string)item.Title).ToSeoUrl())</h2> calling ToString() is not enough because it will be also dynamically dispatched.
  2. Call your extension method without the extension method syntax as a normal static method: <h2>@(StringExtensions.ToSeoUrl(item.Title))</h2>

Upvotes: 5

Related Questions