2

I'm trying to create my own Html. helper in razor inspired on this answer. I have a problem with the parameter "this HtmlHelper html"

    public static MvcHtmlString ActionImage(this HtmlHelper html, string action, object routeValues, string imagePath, string alt)
{
    var url = new UrlHelper(html.ViewContext.RequestContext);

    // build the <img> tag
    var imgBuilder = new TagBuilder("img");
    imgBuilder.MergeAttribute("src", url.Content(imagePath));
    imgBuilder.MergeAttribute("alt", alt);
    string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

    // build the <a> tag
    var anchorBuilder = new TagBuilder("a");
    anchorBuilder.MergeAttribute("href", url.Action(action, routeValues));
    anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside
    string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

    return MvcHtmlString.Create(anchorHtml);
}

I saw in all the Html helpers the methods also used this parameter. However. i keep getting the error there is no overload for that method i created.

Im fairly sure im placin the method that Lucas provided somewhere wrong. I made a new static class and added the namespace to the web config ( answer provided by umar ).

Could someone help me why im getting this?

thanks in advance

------ Edit Here is my full class

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

namespace SSA_Project.Models.htmlHelper {
    public static class htmlHelperExtension {
        public static MvcHtmlString ActionImage(this HtmlHelper html, string action, object routeValues, string imagePath, string alt) {
            var url = new UrlHelper(html.ViewContext.RequestContext);

            // build the <img> tag
            var imgBuilder = new TagBuilder("img");
            imgBuilder.MergeAttribute("src", url.Content(imagePath));
            imgBuilder.MergeAttribute("alt", alt);
            string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

            // build the <a> tag
            var anchorBuilder = new TagBuilder("a");
            anchorBuilder.MergeAttribute("href", url.Action(action, routeValues));
            anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside
            string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

            return MvcHtmlString.Create(anchorHtml);
        }
    }
}

Web config :

<pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
        <add namespace="SSA_Project.Models.htmlHelper" />
      </namespaces>
    </pages>

And im trying to call it with @Html.ActionImage(..)

I just found out there is also a webconfig file @ the map "views" so i deleted the namespace mentioned before and added it there. code below

 <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="SSA_Project.Models.htmlHelper" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

This is thee area im working in. ( selected one is which im working in ) Area

Whole webconfig file that you can see in the screenshot above.

<?xml version="1.0"?>

<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="SSA_Project.Models.htmlHelper" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

  <appSettings>
    <add key="webpages:Enabled" value="false" />
  </appSettings>

  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
    </httpHandlers>

    <!--
        Enabling request validation in view pages would cause validation to occur
        after the input has already been processed by the controller. By default
        MVC performs request validation before a controller processes the input.
        To change this behavior apply the ValidateInputAttribute to a
        controller or action.
    -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
<handlers>
  <remove name="BlockViewHandler"/>
  <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>

Community
  • 1
  • 1
Mathieu
  • 144
  • 12
  • Is the class made public? Please show me how you are trying to call that method. – tkestowicz Dec 07 '13 at 04:58
  • Yeah the class is made public. I tried it with @Html.ActionImage(..) but that didnt work. I also tried to do use it with naming the whole namespace and then i get the overload error. This is wrong, i just have trouble implementing it into the @Html – Mathieu Dec 07 '13 at 14:49

1 Answers1

2

The changes that you mention you've added to web.config need to be added to the web.config in the Views folder. Please ensure that they're in here rather than just in the web.config in the root of your project.

You can also add a @using statement to the individual view to use it, e.g.

@using SSA_Project.Models.htmlHelper

@Html.ActionImage(....)

If you're using an Area, then the web.config must be in Areas/AreaName/Views. You can also add web.config files to individual folders within the Views folders - the closest existing config file will be used. For example...

|-Areas
|   \-Admin
|     \-Views
|         |-Home
|         |   \-Index.cshtml
|         \-Web.config <-- Will be used by Areas\Admin\Views\Home\Index.cshtml
|-Views
|   |-Account
|   |  |-Login.cshtml
|   |  \-Web.Config     <-- Will be used by Views\Account\Login.cshtml
|   |-Home
|   |  \-Index.cshtml
|   \-Web.config         <-- Will be used by Views\Home\Index.cshtml
\-Web.Config

I've created a project using the code from your question, and this works fine for me. I did the following:

  • Create new MVC project
  • Add folder "htmlHelper" to Models folder
  • Create "htmlHelperExtension.cs" with contents from your question
  • Add <add namespace="WebApplication5.Models.htmlHelper"/> to namespaces section of Views/Web.config
  • Add @Html.ActionImage("Index", "Home", "~/Content/images/blah.png", "aaaa") to Views\Shared_Layout.cshtml

This works for me!

Richard
  • 29,854
  • 11
  • 77
  • 120
  • Yeah. i just found that out but i cant seem to get that to work either. The @using SSA_Project.Models.htmlHelper does work if i put it in there. any solution to the webconfig file in the views? – Mathieu Dec 07 '13 at 15:06
  • If the @using statement works, then it just means you're not getting the web.config bit right. Are you using Areas? If so, the web.config will need to go in there. You can also put a web.config in the individual folder - the closest existing web.config file will be used. – Richard Dec 07 '13 at 15:10
  • So im using the basic internet application project template. and im working in the folder shared ( creating my own website ) Should i copy paste the webconfig file into the folder shared? – Mathieu Dec 07 '13 at 15:12
  • What is the full path within your application to the View in which you're trying to use this helper method? – Richard Dec 07 '13 at 15:15
  • I've added a screenshot at the view where im working ( the highlighted one ) I'm also calling it from the home controller ( index ) So it should be the web.config file right? – Mathieu Dec 07 '13 at 15:21
  • Assuming that your namespace is added to the web.config visible at the bottom of your screenshot (i.e. Views\web.config) then this should work. – Richard Dec 07 '13 at 15:25
  • I've just copied your code into a new project and it works. Perhaps there's something wrong with the way you're calling your helper? @Html.ActionImage("Index", "Home", "~/Content/images/blah.png", "Alt-Blah") works for me – Richard Dec 07 '13 at 15:52
  • Well. since im using it with the using statement on top of my page and it works i dont think so. Im probably calling it wrong in my webconfig page. Ill paste the whole webconfig page into here. give me a second :) Thanks for your dedication btw. It's much appreciated! – Mathieu Dec 07 '13 at 16:30
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/42707/discussion-between-mathieu-and-richard) – Mathieu Dec 07 '13 at 16:32