web-dev-qa-db-ja.com

ASP.NET MVC:RazorのカスタムHtmlヘルパー

Razorで使用すると、Htmlヘルパーで問題が発生します。これらのヘルパーは、Webフォームビューエンジンを備えたMVC 2で正常に機能しました。しかし、かみそりではありません。実行時に表示されるエラーは次のとおりです。

Compiler Error Message: CS1502: The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments

Source Error:


Line 1:  @using Wingspan.Web.Mvc;
Line 2:  @Html.IncrementalMenu(MenuBlock.Site)

Show Detailed Compiler Outputを展開すると、次のことがわかります。

d:\...\Views\Shared\MenuTop.cshtml(2,1): error CS1502: The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments
d:\...\Views\Shared\MenuTop.cshtml(2,7): error CS1503: Argument 1: cannot convert from 'void' to 'System.Web.WebPages.HelperResult'

これは、カミソリが私のヘルパーIncrementalMenuを嫌い、voidを返すことを示しています(MVC 2 Webフォームエンジンビューでは正常に機能します)。

コードの行(@ Html.IncrementalMenu(...))には次のメッセージが下線が引かれていますが、コンパイル時にエラーは発生しません。

Cannot implicitly convert type 'void' to 'object'

IncrementalMenuはWingspan.Web.Mvc名前空間にあります。署名は次のとおりです。

public static void IncrementalMenu(this HtmlHelper html, MenuBlock menuBlock)
{
    // Uses an HtmlTextWriter to render a menu from the sitemap
}

何がおかしいのか知っていると息が詰まる...

PS:

MenuBlockパラメーターは、メニューのレンダリング方法を識別する単なる列挙です。これに固執しないでください。

63
awrigley

次のようにヘルパーを呼び出すことができます。

@{ Html.IncrementalMenu(MenuBlock.Site); }

WebFormsの構文

<% Html.IncrementalMenu(MenuBlock.Site); %>

メソッドを呼び出すだけで、戻り値(ある場合)は無視されます。

このようなコードは戻り値を予期し、戻り値をhtmlストリームに書き込みます。

@Html.YourHelper()

Webformsの構文:

<%: Html.YourHelper() %>

同じ、結果値!= IHtmlStringの場合:

<%= Server.HtmlEncode(Html.YourHelper()) %>
85
GvS

補遺:

@ Html.RenderPartialを使用して、同じまたは類似のエラーを取得できます。この場合、RenderPartialは応答に直接レンダリングされるため、文字列ではないため、「Razor code block」内にコーディングする必要があります。

@{
   Html.RenderPartial(...);
}

これが、MicrosoftがASP.NET MVCに新しいHtml.Partialを含めた理由の1つだと思います。 Html.Partialは文字列を返すので、次のように記述してもかまいません。

@Html.Partial

それはずっと良く見えます。 Razorの宣言された目標の1つが目にやさしいことであることを考えると、これはおそらく真実です。

また、少なくとも、私はより快適に感じることができます。文字列を返すことを知っています、私はいつもそれをします。しかし、「応答に戻る」には、考えるたびにさらに数回の脳サイクルが必要です。

そして、Microsoftが最終的にバージョン3で製品を入手したという古い格言に適合しています。たとえば、Access 97。

それは憂鬱な直mileです。 Cos彼らはバージョン4で物事を台無しにした、すなわち、Access 2000 ...

49
awrigley

HTMLヘルパーは、Razor(およびWebFormsViewEngineではない他のビューエンジン)で適切に動作するために、htmlを表すMvcHtmlStringを返す必要があります。

public static MvcHtmlString Label(this HtmlHelper html, string expression)
{
    return MvcHtmlString.Create("<label>" + expression + "</label>");
}
22
Atanas Korchev